*/
typedef struct {
unlang_function_t func; //!< To call when going down the stack.
+ char const *func_name; //!< Debug name for the function.
unlang_function_t repeat; //!< To call when going back up the stack.
+ char const *repeat_name; //!< Debug name for the repeat function.
unlang_function_signal_t signal; //!< Signal function to call.
+ char const *signal_name; //!< Debug name for the signal function.
void *uctx; //!< Uctx to pass to function.
} unlang_frame_state_func_t;
*/
caller = request->module;
request->module = NULL;
- RDEBUG4("Calling repeat function %p", state->repeat);
+ RDEBUG4("Calling repeat function %p (%s)", state->repeat, state->repeat_name);
ua = state->repeat(p_result, &frame->priority, request, state->uctx);
request->module = caller;
caller = request->module;
request->module = NULL;
- RDEBUG4("Calling function %p", state->func);
+ RDEBUG4("Calling function %p (%s)", state->func, state->func_name);
ua = state->func(p_result, &frame->priority, request, state->uctx);
switch (ua) {
case UNLANG_ACTION_STOP_PROCESSING:
*
* The function frame being modified must be at the top of the stack.
*
- * @param[in] request The current request.
- * @param[in] repeat the repeat function to set.
+ * @param[in] request The current request.
+ * @param[in] repeat the repeat function to set.
+ * @param[in] repeat_name Name of the repeat function call (for debugging).
* @return
* - 0 on success.
* - -1 on failure.
*/
-int unlang_function_repeat(request_t *request, unlang_function_t repeat)
+int _unlang_function_repeat(request_t *request, unlang_function_t repeat, char const *repeat_name)
{
unlang_stack_t *stack = request->stack;
unlang_stack_frame_t *frame = &stack->frame[stack->depth];
* once the current function returns.
*/
state->repeat = repeat;
+ state->repeat_name = repeat_name;
+ repeatable_set(frame);
return 0;
}
* These can be pushed by any other type of unlang op to allow a submodule or function
* deeper in the C call stack to establish a new resumption point.
*
- * @param[in] request The current request.
- * @param[in] func to call going up the stack.
- * @param[in] repeat function to call going back down the stack (may be NULL).
- * This may be the same as func.
- * @param[in] signal function to call if the request is signalled.
- * @param[in] uctx to pass to func.
+ * @param[in] request The current request.
+ * @param[in] func to call going up the stack.
+ * @param[in] func_name Name of the function call (for debugging).
+ * @param[in] repeat function to call going back down the stack (may be NULL).
+ * This may be the same as func.
+ * @param[in] repeat_name Name of the repeat function call (for debugging).
+ * @param[in] signal function to call if the request is signalled.
+ * @param[in] signal_name Name of the signal function call (for debugging).
+ * @param[in] uctx to pass to func(s).
* @return
* - 0 on success.
* - -1 on failure.
*/
-unlang_action_t unlang_function_push(request_t *request, unlang_function_t func, unlang_function_t repeat,
- unlang_function_signal_t signal, bool top_frame, void *uctx)
+unlang_action_t _unlang_function_push(request_t *request,
+ unlang_function_t func, char const *func_name,
+ unlang_function_t repeat, char const *repeat_name,
+ unlang_function_signal_t signal, char const *signal_name,
+ bool top_frame, void *uctx)
{
unlang_stack_t *stack = request->stack;
unlang_stack_frame_t *frame;
*/
state = frame->state;
state->func = func;
+ state->func_name = func_name;
state->repeat = repeat;
+ state->repeat_name = repeat_name;
state->signal = signal;
+ state->signal_name = signal_name;
state->uctx = uctx;
/*
return UNLANG_ACTION_PUSHED_CHILD;
}
+/** Custom frame state dumper
+ *
+ */
+static void unlang_function_dump(request_t *request, unlang_stack_frame_t *frame)
+{
+ unlang_frame_state_func_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_func_t);
+
+ RDEBUG2("frame state");
+ if (state->func) RDEBUG2("function %p (%s)", state->func, state->func_name);
+ if (state->repeat) RDEBUG2("repeat %p (%s)", state->repeat, state->repeat_name);
+ if (state->signal) RDEBUG2("signal %p (%s)", state->signal, state->signal_name);
+}
+
void unlang_function_init(void)
{
unlang_register(UNLANG_TYPE_FUNCTION,
.name = "function",
.interpret = unlang_function_call,
.signal = unlang_function_signal,
+ .dump = unlang_function_dump,
.debug_braces = false,
.frame_state_size = sizeof(unlang_frame_state_func_t),
.frame_state_name = "unlang_frame_state_func_t",
int unlang_function_clear(request_t *request) CC_HINT(warn_unused_result);
-int unlang_function_repeat(request_t *request, unlang_function_t repeat) CC_HINT(warn_unused_result);
+int _unlang_function_repeat(request_t *request, unlang_function_t repeat, char const *name) CC_HINT(warn_unused_result);
-unlang_action_t unlang_function_push(request_t *request,
- unlang_function_t func, unlang_function_t repeat,
- unlang_function_signal_t signal, bool top_frame, void *uctx)
- CC_HINT(warn_unused_result);
+/** Set a new repeat function for an existing function frame
+ *
+ * The function frame being modified must be at the top of the stack.
+ *
+ * @param[in] _request The current request.
+ * @param[in] _repeat the repeat function to set.
+ * @return
+ * - 0 on success.
+ * - -1 on failure.
+ */
+#define unlang_function_repeat(_request, _repeat) \
+ _unlang_function_repeat(_request, _repeat, STRINGIFY(_repeat))
+
+unlang_action_t _unlang_function_push(request_t *request,
+ unlang_function_t func, char const *func_name,
+ unlang_function_t repeat, char const *repeat_name,
+ unlang_function_signal_t signal, char const *signal_name,
+ bool top_frame, void *uctx)
+ CC_HINT(warn_unused_result);
+
+/** Push a generic function onto the unlang stack
+ *
+ * These can be pushed by any other type of unlang op to allow a submodule or function
+ * deeper in the C call stack to establish a new resumption point.
+ *
+ * @param[in] _request The current request.
+ * @param[in] _func to call going up the stack.
+ * @param[in] _repeat function to call going back down the stack (may be NULL).
+ * This may be the same as func.
+ * @param[in] _signal function to call if the request is signalled.
+ * @param[in] _uctx to pass to func(s).
+ * @return
+ * - 0 on success.
+ * - -1 on failure.
+ */
+#define unlang_function_push(_request, _func, _repeat, _signal, _top_frame, _uctx) \
+ _unlang_function_push(_request, \
+ _func, STRINGIFY(_func), \
+ _repeat, STRINGIFY(_repeat), \
+ _signal, STRINGIFY(_signal), \
+ _top_frame, _uctx)
#ifdef __cplusplus
}
static _Thread_local unlang_interpret_t *intp_thread_default;
static fr_table_num_ordered_t const unlang_action_table[] = {
- { L("unwind"), UNLANG_ACTION_UNWIND },
+ { L("unwind"), UNLANG_ACTION_UNWIND },
{ L("calculate-result"), UNLANG_ACTION_CALCULATE_RESULT },
- { L("next"), UNLANG_ACTION_EXECUTE_NEXT },
- { L("pushed-child"), UNLANG_ACTION_PUSHED_CHILD },
- { L("stop"), UNLANG_ACTION_STOP_PROCESSING },
- { L("yield"), UNLANG_ACTION_YIELD }
+ { L("next"), UNLANG_ACTION_EXECUTE_NEXT },
+ { L("pushed-child"), UNLANG_ACTION_PUSHED_CHILD },
+ { L("stop"), UNLANG_ACTION_STOP_PROCESSING },
+ { L("yield"), UNLANG_ACTION_YIELD }
};
static size_t unlang_action_table_len = NUM_ELEMENTS(unlang_action_table);
static fr_table_num_ordered_t const unlang_frame_action_table[] = {
- { L("pop"), UNLANG_FRAME_ACTION_POP },
- { L("next"), UNLANG_FRAME_ACTION_NEXT },
- { L("yield"), UNLANG_FRAME_ACTION_YIELD }
+ { L("pop"), UNLANG_FRAME_ACTION_POP },
+ { L("next"), UNLANG_FRAME_ACTION_NEXT },
+ { L("yield"), UNLANG_FRAME_ACTION_YIELD }
};
static size_t unlang_frame_action_table_len = NUM_ELEMENTS(unlang_frame_action_table);
static void frame_dump(request_t *request, unlang_stack_frame_t *frame)
{
+ unlang_op_t *op = NULL;
+
+ if (frame->instruction) op = &unlang_ops[frame->instruction->type];
+
instruction_dump(request, frame->instruction);
RINDENT();
RDEBUG2("break_point %s", is_break_point(frame) ? "yes" : "no");
RDEBUG2("return_point %s", is_return_point(frame) ? "yes" : "no");
RDEBUG2("resumable %s", is_yielded(frame) ? "yes" : "no");
+
+ /*
+ * Call the custom frame dump function
+ */
+ if (op && op->dump) op->dump(request, frame);
+
REXDENT();
}
typedef void (*unlang_signal_t)(request_t *request,
unlang_stack_frame_t *frame, fr_state_signal_t action);
+/** Custom callback for dumping information about frame state
+ *
+ * @param[in] request The current request.
+ * @param[in] frame to provide additional information for.
+ */
+typedef void (*unlang_dump_t)(request_t *request, unlang_stack_frame_t *frame);
+
/** An unlang operation
*
* These are like the opcodes in other interpreters. Each operation, when executed
unlang_signal_t signal; //!< Function to signal stop / dup / whatever
+ unlang_dump_t dump; //!< Dump additional information about the frame state.
+
bool debug_braces; //!< Whether the operation needs to print braces
///< in debug mode.