ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
core.h File Reference

Internal helper functions and data for registry implementation. More...

Go to the source code of this file.

Functions

void registry_init_from_builders (void)
 Initialize registry from category builders Populates g_options_registry by concatenating all category arrays.
 
asciichat_error_t registry_validate_unique_options (void)
 Validate that no short or long options appear more than once in the registry.
 
void registry_init_size (void)
 Initialize registry size and metadata.
 
const registry_entry_t * registry_find_entry_by_name (const char *long_name)
 Get a registry entry by long name.
 
const registry_entry_t * registry_find_entry_by_short (char short_name)
 Get a registry entry by short name.
 
option_descriptor_t registry_entry_to_descriptor (const registry_entry_t *entry)
 Convert registry entry to option descriptor.
 
bool registry_entry_applies_to_mode (const registry_entry_t *entry, asciichat_mode_t mode, bool for_binary_help)
 Check if an option applies to the given mode for display purposes.
 

Variables

registry_entry_t g_options_registry [2048]
 
size_t g_registry_size
 
bool g_metadata_populated
 
category_builder_t g_category_builders []
 

Detailed Description

Internal helper functions and data for registry implementation.

This header declares internal helper functions and global registry data that are used by core.c and public_api.c. These are NOT part of the public API.

Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
January 2026

Definition in file core.h.

Function Documentation

◆ registry_entry_applies_to_mode()

bool registry_entry_applies_to_mode ( const registry_entry_t *  entry,
asciichat_mode_t  mode,
bool  for_binary_help 
)

Check if an option applies to the given mode for display purposes.

This implements the same filtering logic as the help system's option_applies_to_mode(). Used by options_registry_get_for_display() to ensure completions match help output.

Parameters
entryRegistry entry to check
modeMode to check (use MODE_DISCOVERY for binary help)
for_binary_helpIf true, show all options for any mode; if false, filter by mode
Returns
true if option should be displayed for this mode

Definition at line 200 of file core.c.

200 {
201 if (!entry) {
202 SET_ERRNO(ERROR_INVALID_PARAM, "Entry is NULL");
203 return false;
204 }
205
206 // Hardcoded list of options to hide from binary help (matches builder.c line 752)
207 // These are options that have hide_from_binary_help=true set in builder.c
208 const char *hidden_from_binary[] = {NULL};
209
210 // When for_binary_help is true (i.e., for 'ascii-chat --help'),
211 // we want to show all options that apply to any mode, plus binary-level options.
212 if (for_binary_help) {
213 // Check if this option is explicitly hidden from binary help
214 for (int i = 0; hidden_from_binary[i] != NULL; i++) {
215 if (strcmp(entry->long_name, hidden_from_binary[i]) == 0) {
216 return false; // Hidden from binary help
217 }
218 }
219
220 // An option applies if its mode_bitmask has any bit set for any valid mode.
221 // OPTION_MODE_ALL is a bitmask of all modes (including OPTION_MODE_BINARY).
222 return (entry->mode_bitmask & OPTION_MODE_ALL) != 0;
223 }
224
225 // For mode-specific help, show only options for that mode.
226 // Do not show binary options here unless it also specifically applies to the mode.
227 if (mode < 0 || mode > MODE_DISCOVERY) {
228 return false;
229 }
230 option_mode_bitmask_t mode_bit = (1 << mode);
231
232 // Check if it's a binary option. If so, only show if it also explicitly applies to this mode.
233 if ((entry->mode_bitmask & OPTION_MODE_BINARY) && !(entry->mode_bitmask & mode_bit)) {
234 return false; // Binary options not shown in mode-specific help unless also mode-specific
235 }
236
237 return (entry->mode_bitmask & mode_bit) != 0;
238}
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it, returning the error code.
@ ERROR_INVALID_PARAM
option_mode_bitmask_t
Option mode bitmask.
@ MODE_DISCOVERY
Discovery mode - participant that can dynamically become host.
@ OPTION_MODE_ALL
All modes + binary.
@ OPTION_MODE_BINARY
Binary-level options (parsed before mode detection)
const char * long_name
option_mode_bitmask_t mode_bitmask

References ERROR_INVALID_PARAM, registry_entry_t::long_name, registry_entry_t::mode_bitmask, MODE_DISCOVERY, OPTION_MODE_ALL, OPTION_MODE_BINARY, and SET_ERRNO.

Referenced by options_registry_get_for_display().

◆ registry_entry_to_descriptor()

option_descriptor_t registry_entry_to_descriptor ( const registry_entry_t *  entry)

Convert registry entry to option descriptor.

Definition at line 161 of file core.c.

161 {
162 option_descriptor_t desc = {0};
163 if (entry) {
164 desc.long_name = entry->long_name;
165 desc.short_name = entry->short_name;
166 desc.type = entry->type;
167 desc.offset = entry->offset;
168 desc.help_text = entry->help_text;
169 desc.group = entry->group;
170 desc.arg_placeholder = entry->arg_placeholder;
171 desc.hide_from_mode_help = false;
172 // Hide discovery service options from binary-level help (they're for discovery-service mode only)
174 desc.default_value = entry->default_value;
175 desc.required = entry->required;
176 desc.env_var_name = entry->env_var_name;
177 desc.validate = entry->validate_fn;
178 desc.parse_fn = entry->parse_fn;
179 desc.action_fn = NULL;
180 desc.owns_memory = entry->owns_memory;
181 desc.optional_arg = entry->optional_arg;
182 desc.mode_bitmask = entry->mode_bitmask;
183 desc.metadata = entry->metadata;
185 }
186 return desc;
187}
@ OPTION_MODE_DISCOVERY_SVC
Discovery server mode (bit 3)
Option descriptor.
Definition builder.h:241
bool(* validate)(const void *options_struct, char **error_msg)
Definition builder.h:263
option_mode_bitmask_t mode_bitmask
Which modes this option applies to.
Definition builder.h:278
const char * help_text
Description for –help.
Definition builder.h:251
bool hide_from_mode_help
If true, don't show in mode-specific help (binary-level only)
Definition builder.h:254
size_t offset
offsetof(struct, field) - where to store value
Definition builder.h:248
bool hide_from_binary_help
If true, don't show in binary-level help (e.g., in release builds)
Definition builder.h:255
const char * env_var_name
Environment variable fallback (or NULL)
Definition builder.h:260
const char * arg_placeholder
Custom argument placeholder (e.g., "SHELL [FILE]" instead of "STR")
Definition builder.h:253
const char * group
Group name for help sections (e.g., "NETWORK OPTIONS")
Definition builder.h:252
const void * default_value
Pointer to default value (or NULL if required)
Definition builder.h:258
bool required
If true, option must be provided.
Definition builder.h:259
bool(* parse_fn)(const char *arg, void *dest, char **error_msg)
Definition builder.h:266
bool owns_memory
If true, strings are strdup'd and freed on cleanup.
Definition builder.h:272
const char * long_name
Long option name (e.g., "port")
Definition builder.h:243
const void *(* mode_default_getter)(asciichat_mode_t mode)
Get mode-specific default value (NULL if not mode-aware)
Definition builder.h:284
char short_name
Short option char (e.g., 'p', or '\0' if none)
Definition builder.h:244
void(* action_fn)(void)
Action to execute (may call exit)
Definition builder.h:269
option_metadata_t metadata
Metadata for shell completions (enums, ranges, examples, etc.)
Definition builder.h:281
option_type_t type
Value type.
Definition builder.h:247
bool optional_arg
If true, argument is optional (for callbacks like –verbose)
Definition builder.h:275
option_type_t type
bool optional_arg
const char * group
bool required
bool owns_memory
bool(* validate_fn)(const void *options_struct, char **error_msg)
mode_default_getter_fn mode_default_getter
Mode-aware default getter (NULL if using default_value) - LAST for backward compat.
const char * env_var_name
bool(* parse_fn)(const char *arg, void *dest, char **error_msg)
const void * default_value
Default value (single value for all modes, or NULL if mode_default_getter is set)
const char * arg_placeholder
Custom argument placeholder (e.g., "SHELL [FILE]" instead of "STR")
option_metadata_t metadata
Enum values, numeric ranges, examples.
char short_name
const char * help_text
size_t offset

References option_descriptor_t::action_fn, option_descriptor_t::arg_placeholder, registry_entry_t::arg_placeholder, option_descriptor_t::default_value, registry_entry_t::default_value, option_descriptor_t::env_var_name, registry_entry_t::env_var_name, option_descriptor_t::group, registry_entry_t::group, option_descriptor_t::help_text, registry_entry_t::help_text, option_descriptor_t::hide_from_binary_help, option_descriptor_t::hide_from_mode_help, option_descriptor_t::long_name, registry_entry_t::long_name, option_descriptor_t::metadata, registry_entry_t::metadata, option_descriptor_t::mode_bitmask, registry_entry_t::mode_bitmask, option_descriptor_t::mode_default_getter, registry_entry_t::mode_default_getter, option_descriptor_t::offset, registry_entry_t::offset, OPTION_MODE_DISCOVERY_SVC, option_descriptor_t::optional_arg, registry_entry_t::optional_arg, option_descriptor_t::owns_memory, registry_entry_t::owns_memory, option_descriptor_t::parse_fn, registry_entry_t::parse_fn, option_descriptor_t::required, registry_entry_t::required, option_descriptor_t::short_name, registry_entry_t::short_name, option_descriptor_t::type, registry_entry_t::type, option_descriptor_t::validate, and registry_entry_t::validate_fn.

Referenced by options_registry_get_binary_options(), options_registry_get_for_display(), and options_registry_get_for_mode().

◆ registry_find_entry_by_name()

const registry_entry_t * registry_find_entry_by_name ( const char *  long_name)

Get a registry entry by long name.

Note
This is used internally for option lookup

Definition at line 127 of file core.c.

127 {
128 if (!long_name) {
129 SET_ERRNO(ERROR_INVALID_PARAM, "Long name is NULL");
130 return NULL;
131 }
132
133 for (size_t i = 0; g_options_registry[i].long_name != NULL; i++) {
134 if (strcmp(g_options_registry[i].long_name, long_name) == 0) {
135 return &g_options_registry[i];
136 }
137 }
138 return NULL;
139}
registry_entry_t g_options_registry[2048]
Definition registry.c:51

References ERROR_INVALID_PARAM, g_options_registry, registry_entry_t::long_name, and SET_ERRNO.

Referenced by options_registry_find_by_name().

◆ registry_find_entry_by_short()

const registry_entry_t * registry_find_entry_by_short ( char  short_name)

Get a registry entry by short name.

Note
This is used internally for option lookup

Definition at line 145 of file core.c.

145 {
146 if (short_name == '\0') {
147 return NULL;
148 }
149
150 for (size_t i = 0; g_options_registry[i].long_name != NULL; i++) {
151 if (g_options_registry[i].short_name == short_name) {
152 return &g_options_registry[i];
153 }
154 }
155 return NULL;
156}

References g_options_registry, and registry_entry_t::long_name.

Referenced by options_registry_find_by_short().

◆ registry_init_from_builders()

void registry_init_from_builders ( void  )

Initialize registry from category builders Populates g_options_registry by concatenating all category arrays.

Definition at line 23 of file core.c.

23 {
24 static bool initialized = false;
25 if (initialized) {
26 return;
27 }
28
29 size_t offset = 0;
30 for (int i = 0; g_category_builders[i].entries != NULL; i++) {
31 // Count entries in this category (until sentinel terminator)
32 size_t count = 0;
33 for (const registry_entry_t *e = g_category_builders[i].entries; e->long_name != NULL; e++) {
34 count++;
35 }
36
37 // Copy category entries (count already excludes sentinel)
38 if (offset + count <= 2048) {
39 memcpy(&g_options_registry[offset], g_category_builders[i].entries, count * sizeof(registry_entry_t));
40 offset += count;
41 }
42 }
43
44 // Add final null terminator
45 if (offset < 2048) {
47 .short_name = '\0',
48 .type = OPTION_TYPE_BOOL,
49 .offset = 0,
50 .default_value = NULL,
51 .default_value_size = 0,
52 .help_text = NULL,
53 .group = NULL,
54 .required = false,
55 .env_var_name = NULL,
56 .validate_fn = NULL,
57 .parse_fn = NULL,
58 .owns_memory = false,
59 .optional_arg = false,
60 .mode_bitmask = OPTION_MODE_NONE,
61 .metadata = {0}};
62 }
63
64 initialized = true;
65}
@ OPTION_TYPE_BOOL
Boolean flag (–flag, no value)
Definition builder.h:162
@ OPTION_MODE_NONE
No modes (invalid)
bool initialized
Definition mmap.c:38
category_builder_t g_category_builders[]
Definition registry.c:27
const registry_entry_t * entries
Registry entry - stores option definition with mode bitmask and metadata.

References category_builder_t::entries, g_category_builders, g_options_registry, initialized, registry_entry_t::long_name, OPTION_MODE_NONE, and OPTION_TYPE_BOOL.

Referenced by registry_init_size().

◆ registry_init_size()

void registry_init_size ( void  )

Initialize registry size and metadata.

Definition at line 108 of file core.c.

108 {
110
111 if (g_registry_size == 0) {
112 for (size_t i = 0; g_options_registry[i].long_name != NULL; i++) {
114 }
115 // Validate that all options have unique short and long names
117 // DEPRECATED: Metadata is now initialized compile-time in registry entries
118 // registry_populate_metadata_for_critical_options();
120 }
121}
void registry_init_from_builders(void)
Initialize registry from category builders Populates g_options_registry by concatenating all category...
Definition core.c:23
asciichat_error_t registry_validate_unique_options(void)
Validate that no short or long options appear more than once in the registry.
Definition core.c:71
bool g_metadata_populated
Definition registry.c:54
size_t g_registry_size
Definition registry.c:53

References g_metadata_populated, g_options_registry, g_registry_size, registry_entry_t::long_name, registry_init_from_builders(), and registry_validate_unique_options().

Referenced by options_get_help_text(), options_registry_add_all_to_builder(), options_registry_find_by_name(), options_registry_find_by_short(), options_registry_get_binary_options(), options_registry_get_count(), options_registry_get_for_display(), options_registry_get_for_mode(), options_registry_get_metadata(), options_registry_get_raw(), and options_state_init().

◆ registry_validate_unique_options()

asciichat_error_t registry_validate_unique_options ( void  )

Validate that no short or long options appear more than once in the registry.

Returns
Result of SET_ERRNO if duplicates found, ASCIICHAT_OK if valid

Definition at line 71 of file core.c.

71 {
72 // Check for duplicate long options
73 for (size_t i = 0; g_options_registry[i].long_name != NULL; i++) {
74 const char *long_name = g_options_registry[i].long_name;
75 if (!long_name || long_name[0] == '\0') {
76 continue; // Skip empty long names
77 }
78
79 for (size_t j = i + 1; g_options_registry[j].long_name != NULL; j++) {
80 if (strcmp(g_options_registry[j].long_name, long_name) == 0) {
81 return SET_ERRNO(ERROR_CONFIG, "Duplicate long option '--%s' at registry indices %zu and %zu", long_name, i, j);
82 }
83 }
84 }
85
86 // Check for duplicate short options (skip if '\0')
87 for (size_t i = 0; g_options_registry[i].long_name != NULL; i++) {
88 char short_name = g_options_registry[i].short_name;
89 if (short_name == '\0') {
90 continue; // Skip if no short option
91 }
92
93 for (size_t j = i + 1; g_options_registry[j].long_name != NULL; j++) {
94 if (g_options_registry[j].short_name == short_name) {
96 "Duplicate short option '-%c' for '--%s' and '--%s' at registry indices %zu and %zu",
97 short_name, g_options_registry[i].long_name, g_options_registry[j].long_name, i, j);
98 }
99 }
100 }
101
102 return ASCIICHAT_OK;
103}
@ ASCIICHAT_OK
Definition error_codes.h:51
@ ERROR_CONFIG
Definition error_codes.h:57

References ASCIICHAT_OK, ERROR_CONFIG, g_options_registry, registry_entry_t::long_name, SET_ERRNO, and registry_entry_t::short_name.

Referenced by registry_init_size().

Variable Documentation

◆ g_category_builders

category_builder_t g_category_builders[]
extern

Definition at line 27 of file registry.c.

27 {{g_general_entries, "GENERAL"},
28 {g_logging_entries, "LOGGING"},
29 {g_terminal_entries, "TERMINAL"},
30 {g_configuration_entries, "CONFIGURATION"},
31 {g_display_entries, "DISPLAY"},
32 {g_webcam_entries, "WEBCAM"},
33 {g_audio_entries, "AUDIO"},
34 {g_media_entries, "MEDIA"},
35 {g_network_entries, "NETWORK"},
36 {g_security_entries, "SECURITY"},
37 {g_database_entries, "DATABASE"},
38 {g_debug_entries, "DEBUG"},
39 {NULL, NULL}};
const registry_entry_t g_configuration_entries[]
const registry_entry_t g_debug_entries[]
Definition debug.c:14
const registry_entry_t g_general_entries[]
Definition general.c:18
const registry_entry_t g_audio_entries[]
const registry_entry_t g_display_entries[]
const registry_entry_t g_media_entries[]
Definition media.c:37
const registry_entry_t g_database_entries[]
const registry_entry_t g_logging_entries[]
const registry_entry_t g_network_entries[]
const registry_entry_t g_terminal_entries[]
const registry_entry_t g_webcam_entries[]
const registry_entry_t g_security_entries[]
Definition security.c:18

Referenced by registry_init_from_builders().

◆ g_metadata_populated

bool g_metadata_populated
extern

Definition at line 54 of file registry.c.

Referenced by registry_init_size().

◆ g_options_registry

◆ g_registry_size