47#define MAX_RECURSION_DEPTH 32
64 size_t * out_num_args,
65 size_t * out_num_fixed_args);
83 while (isspace((
unsigned char)*state->
p))
86 while (*state->
p !=
'\n' && *state->
p !=
'\0')
100 const char *
start = state->
p;
102 unsigned long long val = strtoull(
start, &
end, 10);
107 *out_val = (size_t)val;
121 const char *
start = state->
p;
122 if (!isalpha((
unsigned char)*
start) && *
start !=
'_')
124 while (isalnum((
unsigned char)*state->
p) || *state->
p ==
'_' || *state->
p ==
':') {
125 if (*state->
p ==
':' && state->
p[1] !=
':')
127 if (*state->
p ==
':')
131 size_t len = state->
p -
start;
155 size_t len = strlen(keyword);
156 if (strncmp(state->
p, keyword, len) == 0) {
158 if (isalnum((
unsigned char)state->
p[len]) || state->
p[len] ==
'_')
178 const char * p_before = state->
p;
182 if (*state->
p ==
':') {
206 const char * p = state->
p;
212 while (*p !=
'\0' && depth > 0) {
222 while (isspace((
unsigned char)*p) || *p ==
'#') {
224 while (*p !=
'\n' && *p !=
'\0')
230 return (p[0] ==
'-' && p[1] ==
'>');
246 typedef struct member_node {
248 struct member_node * next;
250 member_node *head =
nullptr, *tail =
nullptr;
251 size_t num_members = 0;
253 if (*state->
p != end_char) {
255 const char * p_before_member = state->
p;
258 if (name && (*state->
p ==
',' || *state->
p == end_char)) {
259 state->
p = p_before_member + strlen(name);
273 uint8_t bit_width = 0;
274 bool is_bitfield =
false;
276 if (*state->
p ==
':') {
279 size_t width_val = 0;
282 if (width_val > 255) {
286 bit_width = (uint8_t)width_val;
303 node->next =
nullptr;
314 if (*state->
p ==
',') {
318 if (*state->
p == end_char) {
323 else if (*state->
p == end_char)
326 if (*state->
p ==
'\0') {
335 *out_num_members = num_members;
336 if (num_members == 0)
345 member_node * current = head;
346 for (
size_t i = 0; i < num_members; i++) {
348 current = current->next;
366 if (*state->
p != start_char) {
372 size_t num_members = 0;
379 if (*state->
p != end_char) {
402 size_t alignment = 1;
403 if (*state->
p ==
'!') {
405 if (isdigit((
unsigned char)*state->
p)) {
409 if (*state->
p !=
':') {
417 if (*state->
p !=
'{') {
422 size_t num_members = 0;
426 if (*state->
p !=
'}') {
437 size_t total_size = 0;
438 for (
size_t i = 0; i < num_members; ++i)
439 total_size +=
members[i].type->size;
592 const char * p_before_type = state->
p;
593 if (*state->
p ==
'@') {
603 result_type =
nullptr;
605 else if (*state->
p ==
'*') {
614 result_type =
nullptr;
616 else if (*state->
p ==
'(') {
620 size_t num_args = 0, num_fixed = 0;
634 func_type->
size =
sizeof(
void *);
642 result_type = func_type;
653 if (*state->
p !=
')') {
655 result_type =
nullptr;
661 else if (*state->
p ==
'[') {
664 size_t num_elements = 0;
665 bool is_flexible =
false;
667 if (*state->
p ==
'?') {
678 if (*state->
p !=
':') {
696 if (*state->
p !=
']') {
705 result_type =
nullptr;
709 result_type =
nullptr;
712 else if (*state->
p ==
'!')
714 else if (*state->
p ==
'{')
716 else if (*state->
p ==
'<')
718 else if (*state->
p ==
'e' && state->
p[1] ==
':') {
728 result_type =
nullptr;
730 else if (*state->
p ==
'c' && state->
p[1] ==
'[') {
739 if (*state->
p !=
']') {
746 result_type =
nullptr;
748 else if (*state->
p ==
'v' && state->
p[1] ==
'[') {
756 if (*state->
p !=
':') {
767 if (*state->
p !=
']') {
774 result_type =
nullptr;
781 state->
p = p_before_type;
782 if (isalpha((
unsigned char)*state->
p) || *state->
p ==
'_')
808 size_t * out_num_args,
809 size_t * out_num_fixed_args) {
810 if (*state->
p !=
'(') {
817 typedef struct arg_node {
819 struct arg_node * next;
821 arg_node *head =
nullptr, *tail =
nullptr;
824 if (*state->
p !=
')' && *state->
p !=
';') {
827 if (*state->
p ==
')' || *state->
p ==
';')
839 node->arg.type = arg_type;
840 node->arg.name = name;
841 node->next =
nullptr;
850 if (*state->
p ==
',') {
853 if (*state->
p ==
')' || *state->
p ==
';') {
858 else if (*state->
p !=
')' && *state->
p !=
';') {
866 *out_num_fixed_args = num_args;
868 if (*state->
p ==
';') {
870 if (*state->
p !=
')') {
873 if (*state->
p ==
')')
885 node->arg.type = arg_type;
886 node->arg.name = name;
887 node->next =
nullptr;
896 if (*state->
p ==
',') {
899 if (*state->
p ==
')') {
904 else if (*state->
p !=
')') {
914 if (*state->
p !=
')') {
921 if (state->
p[0] !=
'-' || state->
p[1] !=
'>') {
933 if (num_args > 0 && !
args) {
937 arg_node * current = head;
938 for (
size_t i = 0; i < num_args; i++) {
939 args[i] = current->arg;
940 current = current->next;
943 *out_num_args = num_args;
965 const char * signature) {
966 if (!out_type || !out_arena || !signature || *signature ==
'\0') {
976 parser_state state = {.
p = signature, .start = signature, .arena = *out_arena, .depth = 0};
981 if (state.
p[0] !=
'\0') {
989 *out_arena =
nullptr;
1011 const char * signature,
1033 *out_arena =
nullptr;
1041 *out_arena =
nullptr;
1042 *out_type =
nullptr;
1047 *out_type = final_type;
1072 size_t * out_num_args,
1073 size_t * out_num_fixed_args,
1076 if (!signature || !out_arena || !out_ret_type || !out_args || !out_num_args || !out_num_fixed_args) {
1102 if (!final_func_type) {
1104 *out_arena =
nullptr;
1112 *out_arena =
nullptr;
1146 va_start(
args, fmt);
1149 if (written < 0 || (
size_t)written >= state->
remaining)
1153 state->
p += written;
1278 bool printed_alias =
false;
1280 if (num_elements == 8 &&
is_double(element_type)) {
1282 printed_alias =
true;
1284 else if (num_elements == 16 &&
is_float(element_type)) {
1286 printed_alias =
true;
1290 printed_alias =
true;
1292 else if (num_elements == 4 &&
is_double(element_type)) {
1294 printed_alias =
true;
1296 else if (num_elements == 8 &&
is_float(element_type)) {
1298 printed_alias =
true;
1301 if (!printed_alias) {
1302 _print(state,
"v[%zu:", num_elements);
1338 _print(state,
"sint128");
1341 _print(state,
"uint128");
1350 _print(state,
"longdouble");
1476 _print(state,
"sint128");
1479 _print(state,
"uint128");
1488 _print(state,
"longdouble");
1520 buffer[buffer_size - 1] =
'\0';
1536 if (!buffer || buffer_size == 0 || !type) {
1546 _print(&state,
"unsupported_dialect");
1554 buffer[buffer_size - 1] =
'\0';
1558 else if (buffer_size > 0)
1560 buffer[buffer_size - 1] =
'\0';
1577 const char * function_name,
1581 size_t num_fixed_args,
1584 if (!buffer || buffer_size == 0 || !
ret_type || (num_args > 0 && !
args)) {
1590 (void)function_name;
1593 for (
size_t i = 0; i < num_fixed_args; ++i) {
1598 if (num_args > num_fixed_args) {
1600 for (
size_t i = num_fixed_args; i < num_args; ++i) {
1601 if (i > num_fixed_args)
1610 _print(&state,
"unsupported_dialect");
1617 if (buffer_size > 0)
1618 buffer[buffer_size - 1] =
'\0';
1622 else if (buffer_size > 0)
1623 buffer[buffer_size - 1] =
'\0';
1641 if (!buffer || buffer_size == 0 || !
registry)
1649 if (entry->type && !entry->is_forward_declaration) {
1650 char type_body_buffer[1024];
1655 goto end_print_loop;
1657 _print(&state,
"@%s = %s;\n", entry->name, type_body_buffer);
1659 goto end_print_loop;
infix_registry_t * registry
Definition 008_registry_introspection.c:32
infix_status status
Definition 103_unions.c:59
infix_struct_member * members
Definition 103_unions.c:53
void * args[]
Definition 202_in_structs.c:57
clock_t start
Definition 901_call_overhead.c:47
infix_type * ret_type
Definition 901_call_overhead.c:60
clock_t end
Definition 901_call_overhead.c:47
#define c23_nodiscard
A compatibility macro for the C23 [[nodiscard]] attribute.
Definition compat_c23.h:106
#define INFIX_TLS
Definition error.c:68
infix_error_code_t
Enumerates specific error codes.
Definition infix.h:1223
infix_error_details_t infix_get_last_error(void)
Retrieves detailed information about the last error that occurred on the current thread.
Definition error.c:271
@ INFIX_CODE_SUCCESS
Definition infix.h:1225
@ INFIX_CODE_INVALID_MEMBER_TYPE
Definition infix.h:1243
@ INFIX_CODE_TYPE_TOO_LARGE
Definition infix.h:1241
@ INFIX_CODE_UNEXPECTED_TOKEN
Definition infix.h:1232
@ INFIX_CODE_MISSING_RETURN_TYPE
Definition infix.h:1235
@ INFIX_CODE_UNKNOWN
Definition infix.h:1226
@ INFIX_CODE_RECURSION_DEPTH_EXCEEDED
Definition infix.h:1237
@ INFIX_CODE_UNTERMINATED_AGGREGATE
Definition infix.h:1233
@ INFIX_CODE_INVALID_KEYWORD
Definition infix.h:1234
@ INFIX_CODE_OUT_OF_MEMORY
Definition infix.h:1228
@ INFIX_CATEGORY_ALLOCATION
Definition infix.h:1216
@ INFIX_CATEGORY_GENERAL
Definition infix.h:1215
@ INFIX_CATEGORY_PARSER
Definition infix.h:1217
struct infix_type_t::@0::@1 pointer_info
Metadata for INFIX_TYPE_POINTER.
union infix_type_t::@0 meta
A union containing metadata specific to the type's category.
bool is_packed
Definition infix.h:213
struct infix_type_t::@0::@7 vector_info
Metadata for INFIX_TYPE_VECTOR.
infix_type * type
Definition infix.h:266
struct infix_type_t::@0::@4 func_ptr_info
Metadata for INFIX_TYPE_REVERSE_TRAMPOLINE.
c23_nodiscard infix_status infix_type_from_signature(infix_type **out_type, infix_arena_t **out_arena, const char *signature, infix_registry_t *registry)
Parses a signature string representing a single data type.
Definition signature.c:1009
size_t num_elements
Definition infix.h:218
size_t size
Definition infix.h:197
size_t alignment
Definition infix.h:198
infix_struct_member * members
Definition infix.h:211
struct infix_type_t::@0::@6 complex_info
Metadata for INFIX_TYPE_COMPLEX.
const char * name
Definition infix.h:195
infix_function_argument * args
Definition infix.h:224
infix_status
Enumerates the possible status codes returned by infix API functions.
Definition infix.h:352
const char * name
Definition infix.h:265
const char * name
Definition infix.h:253
infix_type_category category
Definition infix.h:196
struct infix_type_t::@0::@2 aggregate_info
Metadata for INFIX_TYPE_STRUCT and INFIX_TYPE_UNION.
struct infix_type_t::@0::@3 array_info
Metadata for INFIX_TYPE_ARRAY.
struct infix_type_t * pointee_type
Definition infix.h:207
infix_type * type
Definition infix.h:254
struct infix_type_t * element_type
Definition infix.h:217
bool is_flexible
Definition infix.h:219
struct infix_type_t * return_type
Definition infix.h:223
c23_nodiscard infix_status infix_signature_parse(const char *signature, infix_arena_t **out_arena, infix_type **out_ret_type, infix_function_argument **out_args, size_t *out_num_args, size_t *out_num_fixed_args, infix_registry_t *registry)
Parses a full function signature string into its constituent parts.
Definition signature.c:1068
struct infix_type_t::@0::@5 enum_info
Metadata for INFIX_TYPE_ENUM.
struct infix_type_t * base_type
Definition infix.h:234
uint8_t bit_width
Definition infix.h:256
size_t num_members
Definition infix.h:212
struct infix_type_t * underlying_type
Definition infix.h:230
struct infix_type_t::@0::@8 named_reference
Metadata for INFIX_TYPE_NAMED_REFERENCE.
size_t num_fixed_args
Definition infix.h:226
infix_primitive_type_id primitive_id
Metadata for INFIX_TYPE_PRIMITIVE.
Definition infix.h:204
size_t num_args
Definition infix.h:225
bool is_arena_allocated
Definition infix.h:199
@ INFIX_ERROR_ALLOCATION_FAILED
Definition infix.h:354
@ INFIX_SUCCESS
Definition infix.h:353
@ INFIX_ERROR_INVALID_ARGUMENT
Definition infix.h:355
c23_nodiscard infix_status infix_type_print(char *buffer, size_t buffer_size, const infix_type *type, infix_print_dialect_t dialect)
Serializes an infix_type object graph back into a signature string.
Definition signature.c:1531
c23_nodiscard infix_status infix_function_print(char *buffer, size_t buffer_size, const char *function_name, const infix_type *ret_type, const infix_function_argument *args, size_t num_args, size_t num_fixed_args, infix_print_dialect_t dialect)
Serializes a function signature's components into a string.
Definition signature.c:1575
infix_print_dialect_t
Specifies the output format for printing types and function signatures.
Definition infix.h:1038
@ INFIX_DIALECT_SIGNATURE
Definition infix.h:1039
void infix_arena_destroy(infix_arena_t *)
Destroys an arena and frees all memory allocated from it.
Definition arena.c:83
#define infix_memcpy
A macro that can be defined to override the default memcpy function.
Definition infix.h:305
c23_nodiscard void * infix_arena_calloc(infix_arena_t *, size_t, size_t, size_t)
Allocates and zero-initializes a block of memory from an arena.
Definition arena.c:179
c23_nodiscard infix_arena_t * infix_arena_create(size_t)
Creates a new memory arena.
Definition arena.c:52
c23_nodiscard infix_status infix_registry_print(char *buffer, size_t buffer_size, const infix_registry_t *registry)
Serializes all defined types within a registry into a single, human-readable string.
Definition signature.c:1640
c23_nodiscard infix_status infix_type_create_packed_struct(infix_arena_t *, infix_type **, size_t, size_t, infix_struct_member *, size_t)
Creates a new packed struct type with a user-specified layout.
Definition types.c:744
infix_status infix_type_create_flexible_array(infix_arena_t *, infix_type **, infix_type *)
Creates a flexible array member type ([?:type]).
Definition types.c:493
c23_nodiscard infix_type * infix_type_create_void(void)
Creates a static descriptor for the void type.
Definition types.c:183
c23_nodiscard infix_status infix_type_create_union(infix_arena_t *, infix_type **, infix_struct_member *, size_t)
Creates a new union type from an array of members.
Definition types.c:638
c23_nodiscard infix_status infix_type_create_enum(infix_arena_t *, infix_type **, infix_type *)
Creates a new enum type with a specified underlying integer type.
Definition types.c:536
c23_nodiscard infix_status infix_type_create_vector(infix_arena_t *, infix_type **, infix_type *, size_t)
Creates a new SIMD vector type.
Definition types.c:600
c23_nodiscard infix_status infix_type_create_complex(infix_arena_t *, infix_type **, infix_type *)
Creates a new _Complex number type.
Definition types.c:570
c23_nodiscard infix_status infix_type_create_array(infix_arena_t *, infix_type **, infix_type *, size_t)
Creates a new fixed-size array type.
Definition types.c:455
c23_nodiscard infix_status infix_type_create_pointer_to(infix_arena_t *, infix_type **, infix_type *)
Creates a new pointer type that points to a specific type.
Definition types.c:425
infix_struct_member infix_type_create_bitfield_member(const char *, infix_type *, size_t, uint8_t)
A factory function to create a bitfield infix_struct_member.
Definition types.c:202
c23_nodiscard infix_status infix_type_create_struct(infix_arena_t *, infix_type **, infix_struct_member *, size_t)
Creates a new struct type from an array of members, calculating layout automatically.
Definition types.c:685
c23_nodiscard infix_status infix_type_create_named_reference(infix_arena_t *, infix_type **, const char *, infix_aggregate_category_t)
Creates a placeholder for a named type to be resolved by a registry.
Definition types.c:792
c23_nodiscard infix_type * infix_type_create_primitive(infix_primitive_type_id)
Creates a static descriptor for a primitive C type.
Definition types.c:130
infix_struct_member infix_type_create_member(const char *, infix_type *, size_t)
A factory function to create an infix_struct_member.
Definition types.c:191
@ INFIX_PRIMITIVE_UINT16
Definition infix.h:168
@ INFIX_PRIMITIVE_UINT32
Definition infix.h:170
@ INFIX_PRIMITIVE_LONG_DOUBLE
Definition infix.h:178
@ INFIX_PRIMITIVE_FLOAT
Definition infix.h:176
@ INFIX_PRIMITIVE_DOUBLE
Definition infix.h:177
@ INFIX_PRIMITIVE_SINT16
Definition infix.h:169
@ INFIX_PRIMITIVE_SINT64
Definition infix.h:173
@ INFIX_PRIMITIVE_SINT32
Definition infix.h:171
@ INFIX_PRIMITIVE_UINT8
Definition infix.h:166
@ INFIX_PRIMITIVE_UINT128
Definition infix.h:174
@ INFIX_PRIMITIVE_BOOL
Definition infix.h:165
@ INFIX_PRIMITIVE_UINT64
Definition infix.h:172
@ INFIX_PRIMITIVE_SINT128
Definition infix.h:175
@ INFIX_PRIMITIVE_SINT8
Definition infix.h:167
@ INFIX_TYPE_UNION
Definition infix.h:152
@ INFIX_TYPE_PRIMITIVE
Definition infix.h:149
@ INFIX_TYPE_COMPLEX
Definition infix.h:156
@ INFIX_TYPE_ARRAY
Definition infix.h:153
@ INFIX_TYPE_VECTOR
Definition infix.h:157
@ INFIX_TYPE_VOID
Definition infix.h:159
@ INFIX_TYPE_POINTER
Definition infix.h:150
@ INFIX_TYPE_NAMED_REFERENCE
Definition infix.h:158
@ INFIX_TYPE_REVERSE_TRAMPOLINE
Definition infix.h:154
@ INFIX_TYPE_ENUM
Definition infix.h:155
@ INFIX_TYPE_STRUCT
Definition infix.h:151
@ INFIX_AGGREGATE_STRUCT
Definition infix.h:184
Internal data structures, function prototypes, and constants.
void _infix_set_error(infix_error_category_t category, infix_error_code_t code, size_t position)
Sets the thread-local error state with detailed information.
Definition error.c:165
void _infix_type_recalculate_layout(infix_type *type)
Recalculates the layout of a fully resolved type graph.
Definition types.c:938
infix_type * _copy_type_graph_to_arena(infix_arena_t *, const infix_type *)
Performs a deep copy of a type graph into a destination arena.
Definition types.c:1125
c23_nodiscard infix_status _infix_resolve_type_graph_inplace(infix_type **type_ptr, infix_registry_t *registry)
Resolves all named type references in a type graph in-place.
Definition type_registry.c:335
static bool is_double(const infix_type *type)
A fast inline check to determine if an infix_type is a double.
Definition infix_internals.h:743
void _infix_clear_error(void)
Clears the thread-local error state.
Definition error.c:258
static bool is_float(const infix_type *type)
A fast inline check to determine if an infix_type is a float.
Definition infix_internals.h:735
static void _print(printer_state *state, const char *fmt,...)
Definition signature.c:1142
static infix_struct_member * parse_aggregate_members(parser_state *state, char end_char, size_t *out_num_members)
Definition signature.c:244
static bool is_function_signature_ahead(const parser_state *state)
Definition signature.c:205
static void _infix_type_print_body_only_recursive(printer_state *state, const infix_type *type)
Definition signature.c:1371
c23_nodiscard infix_status _infix_type_print_body_only(char *buffer, size_t buffer_size, const infix_type *type, infix_print_dialect_t dialect)
An internal-only function to serialize a type's body without its registered name.
Definition signature.c:1508
#define MAX_RECURSION_DEPTH
Definition signature.c:47
static bool parse_size_t(parser_state *state, size_t *out_val)
Definition signature.c:99
c23_nodiscard infix_status _infix_parse_type_internal(infix_type **out_type, infix_arena_t **out_arena, const char *signature)
The internal core of the signature parser.
Definition signature.c:963
static void set_parser_error(parser_state *state, infix_error_code_t code)
Definition signature.c:73
static infix_type * parse_primitive(parser_state *state)
Definition signature.c:457
static infix_status parse_function_signature_details(parser_state *state, infix_type **out_ret_type, infix_function_argument **out_args, size_t *out_num_args, size_t *out_num_fixed_args)
Definition signature.c:805
static bool consume_keyword(parser_state *state, const char *keyword)
Definition signature.c:153
static infix_type * parse_type(parser_state *state)
Definition signature.c:584
static infix_type * parse_packed_struct(parser_state *state)
Definition signature.c:401
static infix_type * parse_aggregate(parser_state *state, char start_char, char end_char)
Definition signature.c:360
static const char * parse_identifier(parser_state *state)
Definition signature.c:119
static void _infix_type_print_signature_recursive(printer_state *state, const infix_type *type)
Definition signature.c:1171
static const char * parse_optional_name_prefix(parser_state *state)
Definition signature.c:175
INFIX_TLS const char * g_infix_last_signature_context
A thread-local pointer to the full signature string being parsed.
Definition error.c:99
static void skip_whitespace(parser_state *state)
Definition signature.c:81
A single entry in the registry's hash table.
Definition infix_internals.h:152
Internal definition of a memory arena.
Definition infix_internals.h:138
Describes a single argument to a C function.
Definition infix.h:264
Internal definition of a named type registry.
Definition infix_internals.h:165
_infix_registry_entry_t ** buckets
Definition infix_internals.h:170
size_t num_buckets
Definition infix_internals.h:168
Describes a single member of a C struct or union.
Definition infix.h:252
A semi-opaque structure that describes a C type.
Definition infix.h:194
Definition signature.c:53
const char * start
Definition signature.c:55
infix_arena_t * arena
Definition signature.c:56
int depth
Definition signature.c:57
const char * p
Definition signature.c:54
Definition signature.c:1129
char * p
Definition signature.c:1130
size_t remaining
Definition signature.c:1131
infix_status status
Definition signature.c:1132