26RCSIDH(cf_parse_h,
"$Id: 6d8ca220cf7ad2ad78b764313ebfee9a6906cf24 $")
32#include <freeradius-devel/util/rb.h>
33#include <freeradius-devel/util/table.h>
34#include <freeradius-devel/util/value.h>
35#include <freeradius-devel/server/cf_util.h>
41#ifdef HAVE_BUILTIN_CHOOSE_EXPR
42typedef void _mismatch_abinary_m;
43typedef void _mismatch_abinary;
44typedef void _mismatch_bool_m;
45typedef void _mismatch_bool;
46typedef void _mismatch_char_m;
47typedef void _mismatch_char;
48typedef void _mismatch_double_m;
49typedef void _mismatch_double;
50typedef void _mismatch_ethernet_m;
51typedef void _mismatch_ethernet;
52typedef void _mismatch_float_m;
53typedef void _mismatch_float;
54typedef void _mismatch_fripaddr_m;
55typedef void _mismatch_fripaddr;
56typedef void _mismatch_ifid_m;
57typedef void _mismatch_ifid;
58typedef void _mismatch_int32_m;
59typedef void _mismatch_int32;
60typedef void _mismatch_size_m;
61typedef void _mismatch_size;
62typedef void _mismatch_time_delta_m;
63typedef void _mismatch_time_delta;
64typedef void _mismatch_time_m;
65typedef void _mismatch_time;
66typedef void _mismatch_uint16_m;
67typedef void _mismatch_uint16;
68typedef void _mismatch_uint32_m;
69typedef void _mismatch_uint32;
70typedef void _mismatch_uint64_m;
71typedef void _mismatch_uint64;
72typedef void _mismatch_uint8_m_m;
73typedef void _mismatch_uint8_m;
74typedef void _mismatch_uint8;
75typedef void _mismatch_void_m;
76typedef void _mismatch_void;
77typedef void _mismatch_tmpl_m;
78typedef void _mismatch_vp_tmpl;
81typedef void _mismatch_default;
82typedef void conf_type_mismatch;
83typedef void conf_type_invalid;
100# define FR_CONF_FLAG_CHECK(_t, _f, _ct, _p) \
101__builtin_choose_expr(((_f) & CONF_FLAG_SUBSECTION), _p, \
102__builtin_choose_expr((_t == FR_TYPE_VOID), _p, \
103__builtin_choose_expr((_t == FR_TYPE_SIZE) && !((_f) & CONF_FLAG_MULTI), \
104 __builtin_choose_expr(IS_COMPATIBLE((_ct), size_t *), _p, (_mismatch_size) 0), \
105__builtin_choose_expr((_t == FR_TYPE_SIZE) && ((_f) & CONF_FLAG_MULTI), \
106 __builtin_choose_expr(IS_COMPATIBLE((_ct), size_t **), _p, (_mismatch_size_m) 0), \
108 fr_time_t * : __builtin_choose_expr((_t == FR_TYPE_DATE) && !((_f) & CONF_FLAG_MULTI), \
109 _p, (_mismatch_time) 0), \
110 fr_time_t ** : __builtin_choose_expr((_t == FR_TYPE_DATE) && ((_f) & CONF_FLAG_MULTI), \
111 _p, (_mismatch_time_m) 0), \
112 fr_ethernet_t * : __builtin_choose_expr((_t == FR_TYPE_ETHERNET) && !((_f) & CONF_FLAG_MULTI), \
113 _p, (_mismatch_ethernet) 0), \
114 fr_ethernet_t ** : __builtin_choose_expr((_t == FR_TYPE_ETHERNET) && ((_f) & CONF_FLAG_MULTI), \
115 _p, (_mismatch_ethernet_m) 0), \
116 fr_ifid_t * : __builtin_choose_expr((_t == FR_TYPE_IFID) && !((_f) & CONF_FLAG_MULTI), \
117 _p, (_mismatch_ifid) 0), \
118 fr_ifid_t ** : __builtin_choose_expr((_t == FR_TYPE_IFID) && ((_f) & CONF_FLAG_MULTI), \
119 _p, (_mismatch_ifid_m) 0), \
120 fr_time_delta_t *: __builtin_choose_expr((_t == FR_TYPE_TIME_DELTA) && !((_f) & CONF_FLAG_MULTI), \
121 _p, (_mismatch_time_delta) 0), \
122 fr_time_delta_t **: __builtin_choose_expr((_t == FR_TYPE_TIME_DELTA) && ((_f) & CONF_FLAG_MULTI), \
123 _p, (_mismatch_time_delta_m) 0), \
124 tmpl_t ** : __builtin_choose_expr(((_f) & CONF_FLAG_TMPL) && !((_f) & CONF_FLAG_MULTI), \
125 _p, (_mismatch_vp_tmpl) 0), \
126 tmpl_t *** : __builtin_choose_expr(((_f) & CONF_FLAG_TMPL) && ((_f) & CONF_FLAG_MULTI), \
127 _p, (_mismatch_tmpl_m) 0), \
128 char const ** : __builtin_choose_expr((_t == FR_TYPE_STRING) && !((_f) & CONF_FLAG_MULTI), \
129 _p, (_mismatch_char) 0), \
130 char const *** : __builtin_choose_expr((_t == FR_TYPE_STRING) && ((_f) & CONF_FLAG_MULTI), \
131 _p, (_mismatch_char_m) 0), \
132 bool * : __builtin_choose_expr((_t == FR_TYPE_BOOL) && !((_f) & CONF_FLAG_MULTI), \
133 _p, (_mismatch_bool) 0), \
134 bool ** : __builtin_choose_expr((_t == FR_TYPE_BOOL) && ((_f) & CONF_FLAG_MULTI), \
135 _p, (_mismatch_bool_m) 0), \
136 uint32_t * : __builtin_choose_expr((_t == FR_TYPE_UINT32) && !((_f) & CONF_FLAG_MULTI), \
137 _p, (_mismatch_uint32) 0), \
138 uint32_t ** : __builtin_choose_expr((_t == FR_TYPE_UINT32) && ((_f) & CONF_FLAG_MULTI), \
139 _p, (_mismatch_uint32_m) 0), \
140 fr_ipaddr_t * : __builtin_choose_expr(((_t == FR_TYPE_IPV4_ADDR) || \
141 (_t == FR_TYPE_IPV4_PREFIX) || \
142 (_t == FR_TYPE_IPV6_ADDR) || \
143 (_t == FR_TYPE_IPV6_PREFIX) || \
144 (_t == FR_TYPE_COMBO_IP_PREFIX) || \
145 (_t == FR_TYPE_COMBO_IP_ADDR)) || \
146 !((_f) & CONF_FLAG_MULTI), _p, (_mismatch_fripaddr) 0), \
147 fr_ipaddr_t ** : __builtin_choose_expr(((_t == FR_TYPE_IPV4_ADDR) || \
148 (_t == FR_TYPE_IPV4_PREFIX) || \
149 (_t == FR_TYPE_IPV6_ADDR) || \
150 (_t == FR_TYPE_IPV6_PREFIX) || \
151 (_t == FR_TYPE_COMBO_IP_PREFIX) || \
152 (_t == FR_TYPE_COMBO_IP_ADDR)) && \
153 ((_f) & CONF_FLAG_MULTI), _p, (_mismatch_fripaddr_m) 0), \
154 uint8_t const ** : __builtin_choose_expr((_t == FR_TYPE_OCTETS) && !((_f) & CONF_FLAG_MULTI), \
155 _p, (_mismatch_uint8) 0), \
156 uint8_t const ***: __builtin_choose_expr((_t == FR_TYPE_OCTETS) && ((_f) & CONF_FLAG_MULTI), \
157 _p, (_mismatch_uint8_m) 0), \
158 uint8_t * : __builtin_choose_expr((_t == FR_TYPE_UINT8) && !((_f) & CONF_FLAG_MULTI), \
159 _p, (_mismatch_uint8) 0), \
160 uint8_t ** : __builtin_choose_expr((_t == FR_TYPE_UINT8) && ((_f) & CONF_FLAG_MULTI), \
161 _p, (_mismatch_uint8_m) 0), \
162 uint16_t * : __builtin_choose_expr((_t == FR_TYPE_UINT16) && !((_f) & CONF_FLAG_MULTI), \
163 _p, (_mismatch_uint16) 0), \
164 uint16_t ** : __builtin_choose_expr((_t == FR_TYPE_UINT16) && ((_f) & CONF_FLAG_MULTI), \
165 _p, (_mismatch_uint16_m) 0), \
166 int32_t * : __builtin_choose_expr((_t == FR_TYPE_INT32) && !((_f) & CONF_FLAG_MULTI), \
167 _p, (_mismatch_int32) 0), \
168 int32_t ** : __builtin_choose_expr((_t == FR_TYPE_INT32) && ((_f) & CONF_FLAG_MULTI), \
169 _p, (_mismatch_int32_m) 0), \
170 uint64_t * : __builtin_choose_expr((_t == FR_TYPE_UINT64) && !((_f) & CONF_FLAG_MULTI), \
171 _p, (_mismatch_uint64) 0), \
172 uint64_t ** : __builtin_choose_expr((_t == FR_TYPE_UINT64) && ((_f) & CONF_FLAG_MULTI), \
173 _p, (_mismatch_uint64_m) 0), \
174 float * : __builtin_choose_expr((_t == FR_TYPE_FLOAT32) && !((_f) & CONF_FLAG_MULTI), \
175 _p, (_mismatch_float) 0), \
176 float ** : __builtin_choose_expr((_t == FR_TYPE_FLOAT32) && ((_f) & CONF_FLAG_MULTI), \
177 _p, (_mismatch_float_m) 0), \
178 double * : __builtin_choose_expr((_t == FR_TYPE_FLOAT64) && !((_f) & CONF_FLAG_MULTI), \
179 _p, (_mismatch_double) 0), \
180 double ** : __builtin_choose_expr((_t == FR_TYPE_FLOAT64) && ((_f) & CONF_FLAG_MULTI), \
181 _p, (_mismatch_double_m) 0), \
182 default: (conf_type_mismatch)0)))))
184# define FR_CONF_FLAG_CHECK(_type, _flags, _c_type, _ptr_or_offset) _ptr_or_offset
187#define CONF_CTYPE_TO_FLAGS(_ct) \
189 tmpl_t ** : CONF_FLAG_TMPL, \
190 tmpl_t *** : CONF_FLAG_TMPL | CONF_FLAG_MULTI, \
191 xlat_t ** : CONF_FLAG_XLAT, \
192 xlat_t *** : CONF_FLAG_XLAT | CONF_FLAG_MULTI, \
193 fr_ethernet_t * : 0, \
194 fr_ethernet_t ** : CONF_FLAG_MULTI, \
196 fr_ifid_t ** : CONF_FLAG_MULTI, \
198 fr_time_t ** : CONF_FLAG_MULTI, \
199 fr_time_delta_t * : 0, \
200 fr_time_delta_t ** : CONF_FLAG_MULTI, \
202 char const *** : CONF_FLAG_MULTI, \
204 bool ** : CONF_FLAG_MULTI, \
205 uint8_t const ** : 0, \
206 uint8_t const *** : CONF_FLAG_MULTI, \
208 uint8_t ** : CONF_FLAG_MULTI, \
210 uint16_t ** : CONF_FLAG_MULTI, \
212 uint32_t ** : CONF_FLAG_MULTI, \
214 uint64_t ** : CONF_FLAG_MULTI, \
216 int8_t ** : CONF_FLAG_MULTI, \
218 int16_t ** : CONF_FLAG_MULTI, \
220 int32_t ** : CONF_FLAG_MULTI, \
222 int64_t ** : CONF_FLAG_MULTI, \
224 float ** : CONF_FLAG_MULTI, \
226 double ** : CONF_FLAG_MULTI)
238# define FR_CONF_OFFSET_TYPE_FLAGS(_name, _type, _flags, _struct, _field) \
242 .offset = FR_CONF_FLAG_CHECK((_type), (_flags), &(((_struct *)NULL)->_field), offsetof(_struct, _field))
253# define FR_CONF_OFFSET_HINT_TYPE(_name, _type, _struct, _field) \
256 .flags = CONF_FLAG_TMPL, \
257 .offset = FR_CONF_FLAG_CHECK(FR_TYPE_VOID, CONF_FLAG_TMPL, &(((_struct *)NULL)->_field), offsetof(_struct, _field))
268# define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field) \
269 FR_CONF_OFFSET_TYPE_FLAGS(_name, \
270 FR_CTYPE_TO_TYPE((((_struct *)NULL)->_field)), \
271 (_flags) | CONF_CTYPE_TO_FLAGS((((_struct *)NULL)->_field)),\
280# define FR_CONF_OFFSET(_name, _struct, _field) \
281 FR_CONF_OFFSET_TYPE_FLAGS(_name, \
282 FR_CTYPE_TO_TYPE((((_struct *)NULL)->_field)), \
283 CONF_CTYPE_TO_FLAGS((((_struct *)NULL)->_field)),\
294# define FR_CONF_OFFSET_IS_SET(_name, _type, _flags, _struct, _field) \
297 .flags = CONF_FLAG_IS_SET | (_flags), \
298 .offset = FR_CONF_FLAG_CHECK((_type), (_flags), &(((_struct *)NULL)->_field), offsetof(_struct, _field)), \
299 .is_set_offset = offsetof(_struct, _field ## _is_set)
309# define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs) \
311 .flags = CONF_FLAG_SUBSECTION | (_flags), \
312 .offset = offsetof(_struct, _field), \
321# define FR_CONF_OFFSET_REF(_struct, _field, _subcs) \
322 .name1 = CF_IDENT_ANY, \
323 .flags = CONF_FLAG_REF, \
324 .offset = offsetof(_struct, _field), \
334# define FR_CONF_POINTER(_name, _type, _flags, _res_p) \
338 .data = FR_CONF_FLAG_CHECK((_type), (_flags), (_res_p), _res_p)
349# define FR_CONF_POINTER_IS_SET(_name, _type, _flags, _res_p) \
352 .flags = CONF_FLAG_IS_SET | (_flags), \
353 .data = FR_CONF_FLAG_CHECK((_type), (_flags), (_res_p), _res_p), \
354 .is_set_ptr = _res_p ## _is_set
355# define FR_ITEM_POINTER(_type, _res_p) _type, FR_CONF_FLAG_CHECK((_type), 0, (_res_p), _res_p)
369# define FR_CONF_SUBSECTION_ALLOC(_name, _type, _flags, _struct, _field, _subcs) \
373 .offset = FR_CONF_FLAG_CHECK((_type), (_flags), &(((_struct *)NULL)->_field), offsetof(_struct, _field)), \
375 .subcs_size = sizeof(**(((_struct *)0)->_field))
385# define FR_CONF_FUNC(_name, _type, _flags, _func, _dflt_func) \
390 .dflt_func = _dflt_func
398# define FR_CONF_SUBSECTION_GLOBAL(_name, _flags, _subcs) \
400 .flags = CONF_FLAG_SUBSECTION | (_flags), \
409#define FR_CONF_DEPRECATED(_name, _struct, _field) \
411 .flags = CONF_FLAG_DEPRECATED
421typedef enum CC_HINT(flag_enum) {
468#define fr_rule_deprecated(_rule) ((_rule)->flags & CONF_FLAG_DEPRECATED)
470#define fr_rule_required(_rule) ((_rule)->flags & CONF_FLAG_REQUIRED)
472#define fr_rule_secret(_rule) ((_rule)->flags & CONF_FLAG_SECRET)
474#define fr_rule_file_readable(_rule) ((_rule)->flags & CONF_FLAG_FILE_READABLE)
476#define fr_rule_file_writable(_rule) ((_rule)->flags & CONF_FLAG_FILE_WRITABLE)
478#define fr_rule_file_socket(_rule) ((_rule)->flags & CONF_FLAG_FILE_SOCKET)
480#define fr_rule_file_exists(_rule) ((_rule)->flags & CONF_FLAG_FILE_EXISTS)
482#define fr_rule_multi(_rule) ((_rule)->flags & CONF_FLAG_MULTI)
484#define fr_rule_not_empty(_rule) ((_rule)->flags & CONF_FLAG_NOT_EMPTY)
486#define fr_rule_is_set(_rule) ((_rule)->flags & CONF_FLAG_IS_SET)
488#define fr_rule_ok_missing(_rule) ((_rule)->flags & CONF_FLAG_OK_MISSING)
490#define fr_rule_dflt(_rule) ((_rule)->dflt || (_rule)->dflt_func)
492#define fr_rule_is_attribute(_rule) ((_rule)->flags & CONF_FLAG_ATTRIBUTE)
494#define fr_rule_is_xlat(_rule) ((_rule)->flags & CONF_FLAG_XLAT)
496#define fr_rule_is_tmpl(_rule) ((_rule)->flags & CONF_FLAG_TMPL)
499#define FR_SIZE_COND_CHECK(_name, _var, _cond, _new)\
502 WARN("Ignoring \"" _name " = %zu\", forcing to \"" _name " = %zu\"", _var, _new);\
507#define FR_SIZE_BOUND_CHECK(_name, _var, _op, _bound) FR_SIZE_COND_CHECK(_name, _var, (_var _op _bound), _bound)
509#define FR_INTEGER_COND_CHECK(_name, _var, _cond, _new)\
512 WARN("Ignoring \"" _name " = %u\", forcing to \"" _name " = %u\"", (unsigned int) (_var), (unsigned int) (_new));\
517#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound) FR_INTEGER_COND_CHECK(_name, _var, (_var _op _bound), _bound)
519#define FR_TIME_DELTA_COND_CHECK(_name, _var, _cond, _new)\
522 WARN("Ignoring \"" _name " = %pV\", forcing to \"" _name " = %pV\"", \
523 fr_box_time_delta(_var), fr_box_time_delta(_new));\
528#define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)\
530 if (!fr_time_delta_cond(_var, _op, _bound)) { \
531 WARN("Ignoring \"" _name " = %pV\", forcing to \"" _name " = %pV\"",\
532 fr_box_time_delta(_var),\
533 fr_box_time_delta(_bound));\
626 size_t is_set_offset;
645 char const *subcs_type;
657#define CONF_PARSER_TERMINATOR { .name1 = NULL, .type = ~(UINT32_MAX - 1), \
658 .offset = 0, .data = NULL, .dflt = NULL, .quote = T_INVALID }
660#define CONF_PARSER_PARTIAL_TERMINATOR { .name1 = NULL, .type = ~(UINT32_MAX - 1), \
661 .offset = 1, .data = NULL, .dflt = NULL, .quote = T_INVALID }
663#define CF_FILE_NONE (0)
664#define CF_FILE_ERROR (1)
665#define CF_FILE_CONFIG (1 << 2)
666#define CF_FILE_MODULE (1 << 3)
687#define cf_section_rule_push(_cs, _rule) _cf_section_rule_push(_cs, _rule, __FILE__, __LINE__)
689#define cf_section_rules_push(_cs, _rule) _cf_section_rules_push(_cs, _rule, __FILE__, __LINE__)
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
int cf_table_parse_uint32(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int32_t (FR_TYPE_UINT32)
int(* cf_dflt_t)(CONF_PAIR **out, void *parent, CONF_SECTION *cs, fr_token_t quote, conf_parser_t const *rule)
Callback for producing dynamic defaults from 3rd party libraries.
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
void const * uctx
User data accessible by the cf_parse_t func.
void * data
Pointer to a static variable to write the parsed value to.
int cf_table_parse_int32(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int32_t (FR_TYPE_INT32)
int cf_pair_parse(TALLOC_CTX *ctx, CONF_SECTION *cs, char const *name, unsigned int type, void *data, char const *dflt, fr_token_t dflt_quote))
Parses a CONF_PAIR into a C data type, with a default value.
int cf_parse_uid(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
conf_parser_flags_t flags
Flags which control parsing behaviour.
int cf_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int.
int cf_parse_permissions(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
fr_type_t type
An fr_type_t value, controls the output type.
size_t offset
Relative offset of field or structure to write the parsed value to.
char const * name2
Second identifier for CONF_SECTION.
void cf_pair_debug_log(CONF_SECTION const *cs, CONF_PAIR *cp, conf_parser_t const *rule)
fr_token_t quote
Quoting around the default value. Only used for templates.
fr_table_num_sorted_t const * table
int(* cf_parse_t)(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Callback for performing custom parsing of a CONF_SECTION or CONF_PAIR.
int cf_null_on_read(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
int cf_pair_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *out, CONF_PAIR *cp, conf_parser_t const *rule))
Parses a CONF_PAIR into a boxed value.
char const * name1
Name of the CONF_ITEM to parse.
int cf_parse_gid(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
int cf_section_parse_pass2(void *base, CONF_SECTION *cs)
Fixup xlat expansions and attributes.
int _cf_section_rule_push(CONF_SECTION *cs, conf_parser_t const *rule, char const *filename, int lineno)
Add a single rule to a CONF_SECTION.
int _cf_section_rules_push(CONF_SECTION *cs, conf_parser_t const *rules, char const *filename, int lineno)
Add an array of parse rules to a CONF_SECTION.
cf_parse_t on_read
Function to call as the item is being read, just after it has been allocated and initialized.
int cf_pair_parse_value(TALLOC_CTX *ctx, void *out, void *base, CONF_ITEM *ci, conf_parser_t const *rule))
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
@ CONF_FLAG_FILE_SOCKET
File matching value must exist, and must be a unix socket.
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
@ CONF_FLAG_REF
reference another conf_parser_t inline in this one
@ CONF_FLAG_SECRET
Only print value if debug level >= 3.
@ CONF_FLAG_IS_SET
Write whether this config item was left as the default to is_set_offset or is_set_ptr.
@ CONF_FLAG_ATTRIBUTE
Value must resolve to attribute in dict (deprecated, use CONF_FLAG_TMPL).
@ CONF_FLAG_DEPRECATED
If a matching CONF_PAIR is found, error out with a deprecated message.
@ CONF_FLAG_NONE
No special flags.
@ CONF_FLAG_NOT_EMPTY
CONF_PAIR is required to have a non zero length value.
@ CONF_FLAG_XLAT
string will be dynamically expanded.
@ CONF_FLAG_OPTIONAL
subsection is pushed only if a non-optional matching one is pushed
@ CONF_FLAG_FILE_READABLE
File matching value must exist, and must be readable.
@ CONF_FLAG_OK_MISSING
OK if it's missing.
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
@ CONF_FLAG_FILE_EXISTS
File matching value must exist.
@ CONF_FLAG_TMPL
CONF_PAIR should be parsed as a template.
@ CONF_FLAG_HIDDEN
Used by scripts to omit items from the generated documentation.
@ CONF_FLAG_FILE_WRITABLE
File matching value must exist, and must be writable.
Defines a CONF_PAIR to C data type mapping.
Common header for all CONF_* types.
Configuration AVP similar to a fr_pair_t.
A section grouping multiple CONF_PAIR.
fr_aka_sim_id_type_t type
An element in a lexicographically sorted array of name to num mappings.
static size_t char ** out