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: a5f5934e1452ce4ec498fb3e7a611cf6466787a6 $
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: a5f5934e1452ce4ec498fb3e7a611cf6466787a6 $")
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  REDEBUG("Failed to 'catch' error %s",
100  fr_table_str_by_value(mod_rcode_table, *p_result, "<invalid>"));
102  }
103 
104  c = unlang_generic_to_catch(unlang);
105  if (c->catching[*p_result]) break;
106  }
107 
108  fr_assert(unlang != NULL);
109 
110  return cleanup(frame, unlang);
111 }
112 
114 {
116  &(unlang_op_t){
117  .name = "catch",
118  .interpret = unlang_catch,
119  .debug_braces = true
120  });
121 }
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:444
#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:113
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:72
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
void unlang_register(int type, unlang_op_t *op)
Register an operation with the interpreter.
Definition: base.c:65
#define REDEBUG(fmt,...)
Definition: radclient.h:52
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:253
unlang_t * next
Next node (executed on UNLANG_ACTION_EXECUTE_NEXT et al).
Definition: unlang_priv.h:124
#define UNLANG_NEXT_SIBLING
Definition: unlang_priv.h:103
static void frame_cleanup(unlang_stack_frame_t *frame)
Cleanup any lingering frame state.
Definition: unlang_priv.h:456
@ UNLANG_TYPE_TRY
try / catch blocks
Definition: unlang_priv.h:81
@ UNLANG_TYPE_CATCH
catch a previous try
Definition: unlang_priv.h:82
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:526
unlang_t const * instruction
The unlang node we're evaluating.
Definition: unlang_priv.h:289
rlm_rcode_t result
The result from executing the instruction.
Definition: unlang_priv.h:308
unlang_t const * next
The next unlang node we will evaluate.
Definition: unlang_priv.h:290
unlang_type_t type
The specialisation of this node.
Definition: unlang_priv.h:127
An unlang operation.
Definition: unlang_priv.h:214
A node in a graph of unlang_op_t (s) that we execute.
Definition: unlang_priv.h:122
Our interpreter stack, as distinct from the C stack.
Definition: unlang_priv.h:288