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 )