The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
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 */
25RCSID("$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:483
#define UNUSED
Definition build.h:315
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
#define fr_assert(_expr)
Definition rad_assert.h:38
static bool cleanup
Definition radsniff.c:60
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
#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).
#define UNLANG_NEXT_SIBLING
Definition unlang_priv.h:93
static void frame_cleanup(unlang_stack_frame_t *frame)
Cleanup any lingering frame state.
@ 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.
unlang_t const * instruction
The unlang node we're evaluating.
rlm_rcode_t result
The result from executing the instruction.
unlang_t const * next
The next unlang node we will evaluate.
unlang_type_t type
The specialisation of this node.
An unlang operation.
A node in a graph of unlang_op_t (s) that we execute.
Our interpreter stack, as distinct from the C stack.