Affix
view release on metacpan or search on metacpan
infix/src/core/signature.c view on Meta::CPAN
size_t * out_num_fixed_args,
infix_registry_t * registry) {
_infix_clear_error();
//
if (!signature) {
_infix_set_error(INFIX_CATEGORY_GENERAL, INFIX_CODE_NULL_POINTER, 0);
return INFIX_ERROR_INVALID_ARGUMENT;
}
if (*signature == '\0') {
_infix_set_error(INFIX_CATEGORY_PARSER, INFIX_CODE_EMPTY_SIGNATURE, 0);
return INFIX_ERROR_INVALID_ARGUMENT;
}
if (!out_arena || !out_ret_type || !out_args || !out_num_args || !out_num_fixed_args) {
_infix_set_error(INFIX_CATEGORY_GENERAL, INFIX_CODE_NULL_POINTER, 0);
return INFIX_ERROR_INVALID_ARGUMENT;
}
g_infix_last_signature_context = signature;
// Parse stage
infix_type * raw_func_type = nullptr;
infix_arena_t * parser_arena = nullptr;
infix_status status = _infix_parse_type_internal(&raw_func_type, &parser_arena, signature);
if (status != INFIX_SUCCESS)
return status;
if (raw_func_type->category != INFIX_TYPE_REVERSE_TRAMPOLINE) {
infix_arena_destroy(parser_arena);
_infix_set_error(INFIX_CATEGORY_PARSER, INFIX_CODE_UNEXPECTED_TOKEN, 0);
return INFIX_ERROR_INVALID_ARGUMENT;
}
// Create final arena
*out_arena = infix_arena_create(8192);
if (!*out_arena) {
infix_arena_destroy(parser_arena);
_infix_set_error(INFIX_CATEGORY_ALLOCATION, INFIX_CODE_OUT_OF_MEMORY, 0);
return INFIX_ERROR_ALLOCATION_FAILED;
}
// "Copy" stage
infix_type * final_func_type = _copy_type_graph_to_arena(*out_arena, raw_func_type);
infix_arena_destroy(parser_arena);
if (!final_func_type) {
infix_arena_destroy(*out_arena);
*out_arena = nullptr;
_infix_set_error(INFIX_CATEGORY_ALLOCATION, INFIX_CODE_OUT_OF_MEMORY, 0);
return INFIX_ERROR_ALLOCATION_FAILED;
}
// Resolve and layout stages
status = _infix_resolve_type_graph_inplace(&final_func_type, registry);
if (status != INFIX_SUCCESS) {
infix_arena_destroy(*out_arena);
*out_arena = nullptr;
return INFIX_ERROR_INVALID_ARGUMENT;
}
_infix_type_recalculate_layout(final_func_type);
// Unpack the results for the caller from the final, processed function type object.
*out_ret_type = final_func_type->meta.func_ptr_info.return_type;
*out_args = final_func_type->meta.func_ptr_info.args;
*out_num_args = final_func_type->meta.func_ptr_info.num_args;
*out_num_fixed_args = final_func_type->meta.func_ptr_info.num_fixed_args;
return INFIX_SUCCESS;
}
// Type Printing Logic
/**
* @internal
* @struct printer_state
* @brief Holds the state for the recursive type-to-string printer.
*/
typedef struct {
char * p; /**< The current write position in the output buffer. */
size_t remaining; /**< The number of bytes remaining in the buffer. */
infix_status status; /**< The current status, set to an error if the buffer is too small. */
// Itanium mangling state
const void * itanium_subs[64]; /**< Dictionary of substitutable components. */
size_t itanium_sub_count; /**< Number of components in the dictionary. */
// MSVC mangling state
const infix_type * msvc_types[10]; /**< First 10 encountered types for back-referencing. */
size_t msvc_type_count; /**< Number of types encountered. */
} printer_state;
/**
* @internal
* @brief A safe `vsnprintf` wrapper for building the signature string.
* Updates the printer state and sets an error on buffer overflow.
* @param[in,out] state The printer state.
* @param[in] fmt The `printf`-style format string.
* @param[in] ... Arguments for the format string.
*/
static void _print(printer_state * state, const char * fmt, ...) {
if (state->status != INFIX_SUCCESS)
return;
va_list args;
va_start(args, fmt);
int written = vsnprintf(state->p, state->remaining, fmt, args);
va_end(args);
if (written < 0 || (size_t)written >= state->remaining)
// If snprintf failed or would have overflowed, mark an error.
state->status = INFIX_ERROR_INVALID_ARGUMENT;
else {
state->p += written;
state->remaining -= written;
}
}
// Forward declaration for mutual recursion in printers.
static void _infix_type_print_signature_recursive(printer_state * state, const infix_type * type);
static void _infix_type_print_itanium_recursive(printer_state * state, const infix_type * type);
static void _infix_type_print_msvc_recursive(printer_state * state, const infix_type * type);
// Itanium Mangling Helpers
static bool _find_itanium_sub(printer_state * state, const void * component, size_t * index) {
for (size_t i = 0; i < state->itanium_sub_count; i++) {
if (state->itanium_subs[i] == component) {
*index = i;
return true;
}
}
( run in 1.266 second using v1.01-cache-2.11-cpan-437f7b0c052 )