ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
examples.c
Go to the documentation of this file.
1
9#include <ascii-chat/common.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <sodium.h>
15
19typedef struct {
21 const char *name;
23
24static const mode_bit_name_t mode_bit_names[] = {
25 {(1 << 0), "server"}, // MODE_SERVER
26 {(1 << 1), "client"}, // MODE_CLIENT
27 {(1 << 2), "mirror"}, // MODE_MIRROR
28 {(1 << 3), "discovery-service"}, // MODE_DISCOVERY_SERVICE
29 {(1 << 4), NULL}, // MODE_DISCOVERY (no mode prefix)
30 {0, NULL} // Terminator
31};
32
43static const char **get_all_mode_names_from_bitmask(uint32_t mode_bitmask, size_t *count) {
44 // Skip binary-only examples (OPTION_MODE_BINARY = 0x100)
45 if (mode_bitmask & 0x100 && !(mode_bitmask & 0x1F)) {
46 *count = 0;
47 return NULL; // Binary-level example, no mode name
48 }
49
50 // Count how many mode bits are set
51 size_t num_modes = 0;
52 for (size_t i = 0; mode_bit_names[i].bit != 0; i++) {
53 if ((mode_bitmask & mode_bit_names[i].bit) && mode_bit_names[i].name) {
54 num_modes++;
55 }
56 }
57
58 if (num_modes == 0) {
59 *count = 0;
60 return NULL;
61 }
62
63 // Allocate array for mode names (plus NULL terminator)
64 const char **names = SAFE_MALLOC((num_modes + 1) * sizeof(char *), const char **);
65
66 // Fill in mode names
67 size_t idx = 0;
68 for (size_t i = 0; mode_bit_names[i].bit != 0; i++) {
69 if ((mode_bitmask & mode_bit_names[i].bit) && mode_bit_names[i].name) {
70 names[idx++] = mode_bit_names[i].name;
71 }
72 }
73 names[idx] = NULL;
74
75 *count = num_modes;
76 return names;
77}
78
80 if (!config) {
81 char *buffer = SAFE_MALLOC(1, char *);
82 buffer[0] = '\0';
83 return buffer;
84 }
85
86 if (config->num_examples == 0) {
87 // Generate fallback content when no examples are defined
88 size_t buffer_capacity = 256;
89 char *buffer = SAFE_MALLOC(buffer_capacity, char *);
90 size_t offset = 0;
91 offset += safe_snprintf(buffer + offset, buffer_capacity - offset, ".PP\nNo examples available for this mode.\n");
92 log_debug("Generated EXAMPLES section (fallback - no examples found)");
93 return buffer;
94 }
95
96 // Allocate growing buffer for examples section
97 size_t buffer_capacity = 8192;
98 char *buffer = SAFE_MALLOC(buffer_capacity, char *);
99 size_t offset = 0;
100
101 for (size_t i = 0; i < config->num_examples; i++) {
102 const example_descriptor_t *example = &config->examples[i];
103
104 // Get all mode names from bitmask (examples can apply to multiple modes)
105 // For man pages, we only show each example once, randomly selecting one mode
106 size_t num_modes = 0;
107 const char **mode_names = get_all_mode_names_from_bitmask(example->mode_bitmask, &num_modes);
108
109 // Ensure buffer is large enough
110 if (offset + 512 >= buffer_capacity) {
111 buffer_capacity *= 2;
112 buffer = SAFE_REALLOC(buffer, buffer_capacity, char *);
113 }
114
115 offset += safe_snprintf(buffer + offset, buffer_capacity - offset, ".TP\n");
116 offset += safe_snprintf(buffer + offset, buffer_capacity - offset, ".B ascii-chat");
117
118 // Add mode name if applicable (randomly select one mode for multi-mode examples)
119 if (num_modes > 0) {
120 size_t selected_mode = randombytes_uniform((uint32_t)num_modes);
121 if (mode_names[selected_mode]) {
122 offset += safe_snprintf(buffer + offset, buffer_capacity - offset, " %s", mode_names[selected_mode]);
123 }
124 }
125
126 if (example->args) {
127 offset += safe_snprintf(buffer + offset, buffer_capacity - offset, " %s", example->args);
128 }
129 offset += safe_snprintf(buffer + offset, buffer_capacity - offset, "\n");
130
131 if (example->description) {
132 offset +=
133 safe_snprintf(buffer + offset, buffer_capacity - offset, "%s\n", escape_groff_special(example->description));
134 }
135
136 // Free mode names array
137 if (mode_names) {
138 SAFE_FREE(mode_names);
139 }
140 }
141
142 offset += safe_snprintf(buffer + offset, buffer_capacity - offset, "\n");
143
144 return buffer;
145}
146
147void manpage_content_free_examples(char *content) {
148 if (content) {
149 SAFE_FREE(content);
150 }
151}
⚙️ Common definitions, error codes, macros, and types shared throughout the application
char * manpage_content_generate_examples(const options_config_t *config)
Generate EXAMPLES section content.
Definition examples.c:79
void manpage_content_free_examples(char *content)
Free generated examples content.
Definition examples.c:147
EXAMPLES section generator for man pages.
#define SAFE_REALLOC(ptr, size, cast)
Definition common.h:284
unsigned int uint32_t
Definition common.h:58
#define SAFE_FREE(ptr)
Definition common.h:376
#define SAFE_MALLOC(size, cast)
Definition common.h:264
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:548
const char * escape_groff_special(const char *str)
Escape special groff/troff characters in text.
int safe_snprintf(char *buffer, size_t buffer_size, const char *format,...)
Safe formatted string printing to buffer.
Definition system.c:148
📝 Logging API with multiple log levels and terminal output control
Man page template generation from options builder.
Example descriptor for programmatic EXAMPLES generation.
Definition builder.h:310
uint32_t mode_bitmask
Bitmask of modes (OPTION_MODE_SERVER, OPTION_MODE_CLIENT, etc.)
Definition builder.h:311
const char * description
Definition builder.h:313
const char * args
Command-line arguments part of the example.
Definition builder.h:312
Mode name mapping for bitmask extraction.
Definition examples.c:19
const char * name
Definition examples.c:21
uint32_t bit
Definition examples.c:20
Options configuration.
Definition builder.h:401
size_t num_examples
Number of examples.
Definition builder.h:420
example_descriptor_t * examples
Array of example descriptors.
Definition builder.h:419