The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
catch.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * $Id: 1fd47f7ef55647047ca3281240cd16f8c3a61273 $
19  *
20  * @file unlang/catch.c
21  * @brief Unlang "catch" keyword evaluation.
22  *
23  * @copyright 2023 Network RADIUS SAS (legal@networkradius.com)
24  */
25 RCSID("$Id: 1fd47f7ef55647047ca3281240cd16f8c3a61273 $")
26 
27 #include "unlang_priv.h"
28 #include "catch_priv.h"
29 
31 {
32 
33  /*
34  * Clean up this frame now, so that stats, etc. will be
35  * processed using the correct frame.
36  */
37  frame_cleanup(frame);
38 
39  /*
40  * frame_next() will call cleanup *before* resetting the frame->instruction.
41  * but since the instruction is NULL, no duplicate cleanups will happen.
42  *
43  * frame_next() will then set frame->instruction = frame->next, and everything will be OK.
44  */
45  frame->instruction = NULL;
46  frame->next = unlang;
48 }
49 
51 {
52  unlang_t *unlang;
53 
55 
56  for (unlang = frame->instruction->next;
57  unlang != NULL;
58  unlang = unlang->next) {
59  if (unlang->type == UNLANG_TYPE_CATCH) continue;
60 
61  break;
62  }
63 
64  return cleanup(frame, unlang);
65 }
66 
68 {
69 #ifndef NDEBUG
71 
72  fr_assert(c->catching[*p_result]);
73 #endif
74 
75  /*
76  * Skip over any "catch" statementa after this one.
77  */
79 
80  return unlang_interpret_push_children(p_result, request, frame->result, UNLANG_NEXT_SIBLING);
81 }
82 
83 
84 /** Skip ahead to a particular "catch" instruction.
85  *
86  */
88 {
89  unlang_t *unlang;
90 
92 
93  for (unlang = frame->instruction->next;
94  unlang != NULL;
95  unlang = unlang->next) {
96  unlang_catch_t const *c;
97 
98  if (unlang->type != UNLANG_TYPE_CATCH) {
99  RWDEBUG2("Failed to 'catch' error %s",
100  fr_table_str_by_value(mod_rcode_table, *p_result, "<invalid>"));
101  frame->next = unlang;
103  }
104 
105  c = unlang_generic_to_catch(unlang);
106  if (c->catching[*p_result]) break;
107  }
108 
109  fr_assert(unlang != NULL);
110 
111  return cleanup(frame, unlang);
112 }
113 
115 {
117  &(unlang_op_t){
118  .name = "catch",
119  .interpret = unlang_catch,
120  .debug_braces = true
121  });
122 }
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition: action.h:35
@ UNLANG_ACTION_EXECUTE_NEXT
Execute the next unlang_t.
Definition: action.h:38
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
Definition: action.h:37
#define RCSID(id)
Definition: build.h:481
#define UNUSED
Definition: build.h:313
static unlang_action_t cleanup(unlang_stack_frame_t *frame, unlang_t *unlang)
Definition: catch.c:30
static unlang_action_t unlang_catch(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
Definition: catch.c:67
static unlang_action_t catch_skip_to_next(UNUSED rlm_rcode_t *p_result, UNUSED request_t *request, unlang_stack_frame_t *frame)
Definition: catch.c:50
void unlang_catch_init(void)
Definition: catch.c:114
unlang_action_t unlang_interpret_skip_to_catch(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
Skip ahead to a particular "catch" instruction.
Definition: catch.c:87
Declarations for the "catch" keyword.
static unlang_catch_t const * unlang_generic_to_catch(unlang_t const *g)
Cast a generic structure to the catch keyword extension.
Definition: catch_priv.h:51
bool catching[RLM_MODULE_NUMCODES]
Definition: catch_priv.h:35
fr_table_num_sorted_t const mod_rcode_table[]
Definition: compile.c:82
unlang_action_t unlang_interpret_push_children(rlm_rcode_t *p_result, request_t *request, rlm_rcode_t default_rcode, bool do_next_sibling)
Push the children of the current frame onto a new frame onto the stack.
Definition: interpret.c:243
#define RWDEBUG2(fmt,...)
Definition: log.h:362
void unlang_register(int type, unlang_op_t *op)
Register an operation with the interpreter.
Definition: base.c:63
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
fr_assert(0)
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition: table.h:772
unlang_t * next
Next node (executed on UNLANG_ACTION_EXECUTE_NEXT et al).
Definition: unlang_priv.h:114
#define UNLANG_NEXT_SIBLING
Definition: unlang_priv.h:93
static void frame_cleanup(unlang_stack_frame_t *frame)
Cleanup any lingering frame state.
Definition: unlang_priv.h:448
@ UNLANG_TYPE_TRY
try / catch blocks
Definition: unlang_priv.h:71
@ UNLANG_TYPE_CATCH
catch a previous try
Definition: unlang_priv.h:72
static void frame_repeat(unlang_stack_frame_t *frame, unlang_process_t process)
Mark the current stack frame up for repeat, and set a new process function.
Definition: unlang_priv.h:518
unlang_t const * instruction
The unlang node we're evaluating.
Definition: unlang_priv.h:281
rlm_rcode_t result
The result from executing the instruction.
Definition: unlang_priv.h:300
unlang_t const * next
The next unlang node we will evaluate.
Definition: unlang_priv.h:282
unlang_type_t type
The specialisation of this node.
Definition: unlang_priv.h:117
An unlang operation.
Definition: unlang_priv.h:204
A node in a graph of unlang_op_t (s) that we execute.
Definition: unlang_priv.h:112
Our interpreter stack, as distinct from the C stack.
Definition: unlang_priv.h:280