GCC Code Coverage Report


Directory: lib/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 90.5% 314 / 0 / 347
Functions: 100.0% 13 / 0 / 13
Branches: 86.0% 296 / 0 / 344

format_help.c
Line Branch Exec Source
1 #include <stdarg.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 #include "ap_internal.h"
7
8 extern int ap_test_sb_before_appendf(void) __attribute__((weak));
9 extern int ap_test_sb_before_free(void) __attribute__((weak));
10
11 5014 void ap_sb_init(ap_string_builder *sb) {
12 5014 sb->data = NULL;
13 5014 sb->len = 0;
14 5014 sb->cap = 0;
15 5014 }
16
17 4698 void ap_sb_free(ap_string_builder *sb) {
18
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4696 times.
4698 if (!sb) {
19 2 return;
20 }
21
3/4
✓ Branch 0 taken 4696 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 4694 times.
✓ Branch 4 taken 2 times.
4696 if (!(ap_test_sb_before_free && ap_test_sb_before_free() != 0)) {
22 4694 free(sb->data);
23 }
24 4696 sb->data = NULL;
25 4696 sb->len = 0;
26 4696 sb->cap = 0;
27 }
28
29 824858 int ap_sb_appendf(ap_string_builder *sb, const char *fmt, ...) {
30 va_list ap;
31 va_list ap_copy;
32 int needed;
33 size_t required;
34 char *next;
35
36
4/4
✓ Branch 0 taken 824854 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 824850 times.
824858 if (!sb || !fmt) {
37 8 return -1;
38 }
39
4/4
✓ Branch 0 taken 821244 times.
✓ Branch 1 taken 3606 times.
✓ Branch 3 taken 4666 times.
✓ Branch 4 taken 816578 times.
824850 if (ap_test_sb_before_appendf && ap_test_sb_before_appendf() != 0) {
40 4666 return -1;
41 }
42
43 820184 va_start(ap, fmt);
44 820184 va_copy(ap_copy, ap);
45 820184 needed = vsnprintf(NULL, 0, fmt, ap);
46 820184 va_end(ap);
47
48
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 820182 times.
820184 if (needed < 0) {
49 2 va_end(ap_copy);
50 2 return -1;
51 }
52
53 820182 required = sb->len + (size_t)needed + 1;
54
2/2
✓ Branch 0 taken 17724 times.
✓ Branch 1 taken 802458 times.
820182 if (required > sb->cap) {
55
2/2
✓ Branch 0 taken 12770 times.
✓ Branch 1 taken 4954 times.
17724 size_t next_cap = sb->cap == 0 ? 128 : sb->cap;
56
2/2
✓ Branch 0 taken 14576 times.
✓ Branch 1 taken 17724 times.
32300 while (next_cap < required) {
57 14576 next_cap *= 2;
58 }
59 17724 next = realloc(sb->data, next_cap);
60
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17722 times.
17724 if (!next) {
61 2 va_end(ap_copy);
62 2 return -1;
63 }
64 17722 sb->data = next;
65 17722 sb->cap = next_cap;
66 }
67
68 820180 vsnprintf(sb->data + sb->len, sb->cap - sb->len, fmt, ap_copy);
69 820180 va_end(ap_copy);
70 820180 sb->len += (size_t)needed;
71 820180 return 0;
72 }
73
74 914 static const char *metavar_for(const ap_arg_def *def) {
75 static char fallback[64];
76 size_t i;
77
3/4
✓ Branch 0 taken 354 times.
✓ Branch 1 taken 560 times.
✓ Branch 2 taken 354 times.
✗ Branch 3 not taken.
914 if (def->opts.metavar && def->opts.metavar[0] != '\0') {
78 354 return def->opts.metavar;
79 }
80
3/4
✓ Branch 0 taken 3392 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2832 times.
✓ Branch 3 taken 560 times.
3392 for (i = 0; i < sizeof(fallback) - 1 && def->dest[i] != '\0'; i++) {
81 2832 char c = def->dest[i];
82
3/4
✓ Branch 0 taken 2816 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 2816 times.
✗ Branch 3 not taken.
2832 if (c >= 'a' && c <= 'z') {
83 2816 fallback[i] = (char)(c - 'a' + 'A');
84
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
16 } else if (c == '_') {
85 12 fallback[i] = '-';
86 } else {
87 4 fallback[i] = c;
88 }
89 }
90 560 fallback[i] = '\0';
91 560 return fallback;
92 }
93
94 464 static int append_optional_usage(ap_string_builder *sb, const ap_arg_def *def) {
95 464 const char *mv = metavar_for(def);
96 int i;
97
98
2/2
✓ Branch 0 taken 264 times.
✓ Branch 1 taken 200 times.
464 if (def->opts.action == AP_ACTION_STORE_TRUE ||
99
2/2
✓ Branch 0 taken 262 times.
✓ Branch 1 taken 2 times.
264 def->opts.action == AP_ACTION_STORE_FALSE ||
100
2/2
✓ Branch 0 taken 166 times.
✓ Branch 1 taken 96 times.
262 def->opts.action == AP_ACTION_COUNT ||
101
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 162 times.
166 def->opts.action == AP_ACTION_STORE_CONST) {
102 302 return ap_sb_appendf(sb, def->opts.required ? " %s" : " [%s]",
103
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 298 times.
302 def->flags[0]);
104 }
105
106
6/6
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 4 times.
162 switch (def->opts.nargs) {
107 118 case AP_NARGS_ONE:
108 118 return ap_sb_appendf(sb, def->opts.required ? " %s %s" : " [%s %s]",
109
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 20 times.
118 def->flags[0], mv);
110 10 case AP_NARGS_OPTIONAL:
111 10 return ap_sb_appendf(sb, def->opts.required ? " %s [%s]" : " [%s [%s]]",
112
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
10 def->flags[0], mv);
113 10 case AP_NARGS_ZERO_OR_MORE:
114 10 return ap_sb_appendf(sb,
115 10 def->opts.required ? " %s [%s ...]" : " [%s [%s ...]]",
116
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
10 def->flags[0], mv);
117 6 case AP_NARGS_ONE_OR_MORE:
118 6 return ap_sb_appendf(
119 6 sb, def->opts.required ? " %s %s [%s ...]" : " [%s %s [%s ...]]",
120
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 def->flags[0], mv, mv);
121 14 case AP_NARGS_FIXED:
122
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
14 if (ap_sb_appendf(sb, def->opts.required ? " %s" : " [%s", def->flags[0]) !=
123 0) {
124 return -1;
125 }
126
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 14 times.
48 for (i = 0; i < def->opts.nargs_count; i++) {
127
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 34 times.
34 if (ap_sb_appendf(sb, " %s", mv) != 0) {
128 return -1;
129 }
130 }
131
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 4 times.
14 return ap_sb_appendf(sb, def->opts.required ? "" : "]");
132 }
133 4 return 0;
134 }
135
136 112 static int append_positional_usage(ap_string_builder *sb,
137 const ap_arg_def *def) {
138 112 const char *mv = metavar_for(def);
139 int i;
140
6/6
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 90 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 4 times.
112 switch (def->opts.nargs) {
141 6 case AP_NARGS_ONE:
142 6 return ap_sb_appendf(sb, " %s", mv);
143 4 case AP_NARGS_OPTIONAL:
144 4 return ap_sb_appendf(sb, " [%s]", mv);
145 2 case AP_NARGS_ZERO_OR_MORE:
146 2 return ap_sb_appendf(sb, " [%s ...]", mv);
147 90 case AP_NARGS_ONE_OR_MORE:
148 90 return ap_sb_appendf(sb, " %s [%s ...]", mv, mv);
149 6 case AP_NARGS_FIXED:
150
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
18 for (i = 0; i < def->opts.nargs_count; i++) {
151
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 if (ap_sb_appendf(sb, " %s", mv) != 0) {
152 return -1;
153 }
154 }
155 6 return 0;
156 }
157 4 return 0;
158 }
159
160 typedef struct {
161 bool raw_text;
162 bool show_defaults;
163 } ap_help_render_options;
164
165 338 static bool help_line_has_meta(const ap_arg_def *def) {
166 512 return (def->opts.action == AP_ACTION_STORE ||
167
4/4
✓ Branch 0 taken 174 times.
✓ Branch 1 taken 164 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 170 times.
506 def->opts.action == AP_ACTION_APPEND) &&
168
2/2
✓ Branch 0 taken 114 times.
✓ Branch 1 taken 54 times.
168 (def->opts.nargs == AP_NARGS_ONE ||
169
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 12 times.
114 def->opts.nargs == AP_NARGS_OPTIONAL ||
170
2/2
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 10 times.
102 def->opts.nargs == AP_NARGS_ZERO_OR_MORE ||
171
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 74 times.
92 def->opts.nargs == AP_NARGS_ONE_OR_MORE ||
172
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 4 times.
18 def->opts.nargs == AP_NARGS_FIXED);
173 }
174
175 294 static int append_choices_line(ap_string_builder *sb, const ap_arg_def *def,
176 const char *prefix) {
177 int i;
178
179
3/4
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 262 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
294 if (!def->opts.choices.items || def->opts.choices.count <= 0) {
180 262 return 0;
181 }
182
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 30 times.
32 if (ap_sb_appendf(sb, "%schoices: ", prefix) != 0) {
183 2 return -1;
184 }
185
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 24 times.
82 for (i = 0; i < def->opts.choices.count; i++) {
186
4/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 30 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 26 times.
58 if (i > 0 && ap_sb_appendf(sb, ", ") != 0) {
187 2 return -1;
188 }
189
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 52 times.
56 if (ap_sb_appendf(sb, "%s", def->opts.choices.items[i]) != 0) {
190 4 return -1;
191 }
192 }
193 24 return 0;
194 }
195
196 324 static int append_help_line_standard(ap_string_builder *sb,
197 const ap_arg_def *def,
198 bool show_defaults) {
199 324 const char *mv = metavar_for(def);
200 324 bool has_meta = help_line_has_meta(def);
201 int i;
202
203
2/2
✓ Branch 0 taken 238 times.
✓ Branch 1 taken 86 times.
324 if (def->is_optional) {
204
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 230 times.
238 if (ap_sb_appendf(sb, " ") != 0) {
205 8 return -1;
206 }
207
2/2
✓ Branch 0 taken 378 times.
✓ Branch 1 taken 210 times.
588 for (i = 0; i < def->flags_count; i++) {
208
4/4
✓ Branch 0 taken 148 times.
✓ Branch 1 taken 230 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 142 times.
378 if (i > 0 && ap_sb_appendf(sb, ", ") != 0) {
209 6 return -1;
210 }
211
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 358 times.
372 if (ap_sb_appendf(sb, "%s", def->flags[i]) != 0) {
212 14 return -1;
213 }
214 }
215
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 144 times.
210 if (has_meta) {
216
5/6
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
66 switch (def->opts.nargs) {
217 44 case AP_NARGS_ONE:
218
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 42 times.
44 if (ap_sb_appendf(sb, " %s", mv) != 0) {
219 2 return -1;
220 }
221 42 break;
222 6 case AP_NARGS_OPTIONAL:
223
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (ap_sb_appendf(sb, " [%s]", mv) != 0) {
224 return -1;
225 }
226 6 break;
227 6 case AP_NARGS_ZERO_OR_MORE:
228
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (ap_sb_appendf(sb, " [%s ...]", mv) != 0) {
229 return -1;
230 }
231 6 break;
232 4 case AP_NARGS_ONE_OR_MORE:
233
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (ap_sb_appendf(sb, " %s [%s ...]", mv, mv) != 0) {
234 return -1;
235 }
236 4 break;
237 6 case AP_NARGS_FIXED: {
238 int idx;
239
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 6 times.
20 for (idx = 0; idx < def->opts.nargs_count; idx++) {
240
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 if (ap_sb_appendf(sb, " %s", mv) != 0) {
241 return -1;
242 }
243 }
244 6 break;
245 }
246 }
247 }
248
4/4
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 8 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 192 times.
208 if (def->opts.help && ap_sb_appendf(sb, "\n %s", def->opts.help) != 0) {
249 8 return -1;
250 }
251
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 192 times.
200 if (append_choices_line(sb, def, "\n ") != 0) {
252 8 return -1;
253 }
254
5/6
✓ Branch 0 taken 192 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 168 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 22 times.
216 if (show_defaults && def->opts.default_value &&
255 24 ap_sb_appendf(sb, "\n default: %s", def->opts.default_value) != 0) {
256 2 return -1;
257 }
258
4/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 162 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 26 times.
190 if (def->opts.required && ap_sb_appendf(sb, "\n required: true") != 0) {
259 2 return -1;
260 }
261 188 return ap_sb_appendf(sb, "\n");
262 }
263
264
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 84 times.
86 if (ap_sb_appendf(sb, " %s", mv) != 0) {
265 2 return -1;
266 }
267
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 2 times.
84 if (has_meta) {
268
5/6
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 68 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
82 switch (def->opts.nargs) {
269 4 case AP_NARGS_ONE:
270 4 break;
271 4 case AP_NARGS_OPTIONAL:
272
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (ap_sb_appendf(sb, " [%s]", mv) != 0) {
273 return -1;
274 }
275 4 break;
276 2 case AP_NARGS_ZERO_OR_MORE:
277
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (ap_sb_appendf(sb, " [%s ...]", mv) != 0) {
278 return -1;
279 }
280 2 break;
281 68 case AP_NARGS_ONE_OR_MORE:
282
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 66 times.
68 if (ap_sb_appendf(sb, " [%s ...]", mv) != 0) {
283 2 return -1;
284 }
285 66 break;
286 4 case AP_NARGS_FIXED: {
287 int idx;
288
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 for (idx = 1; idx < def->opts.nargs_count; idx++) {
289
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (ap_sb_appendf(sb, " %s", mv) != 0) {
290 return -1;
291 }
292 }
293 4 break;
294 }
295 }
296 }
297
4/4
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 6 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 74 times.
82 if (def->opts.help && ap_sb_appendf(sb, "\n %s", def->opts.help) != 0) {
298 2 return -1;
299 }
300
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
80 if (append_choices_line(sb, def, "\n ") != 0) {
301 return -1;
302 }
303
4/6
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 78 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
82 if (show_defaults && def->opts.default_value &&
304 2 ap_sb_appendf(sb, "\n default: %s", def->opts.default_value) != 0) {
305 return -1;
306 }
307
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 78 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
80 if (def->opts.required && ap_sb_appendf(sb, "\n required: true") != 0) {
308 return -1;
309 }
310 80 return ap_sb_appendf(sb, "\n");
311 }
312
313 14 static int append_help_line_raw(ap_string_builder *sb, const ap_arg_def *def,
314 bool show_defaults) {
315 14 const char *mv = metavar_for(def);
316 14 bool has_meta = help_line_has_meta(def);
317 int i;
318
319
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 if (ap_sb_appendf(sb, " ") != 0) {
320 return -1;
321 }
322
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 2 times.
14 if (def->is_optional) {
323
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 12 times.
28 for (i = 0; i < def->flags_count; i++) {
324
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
16 if (i > 0 && ap_sb_appendf(sb, ", ") != 0) {
325 return -1;
326 }
327
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
16 if (ap_sb_appendf(sb, "%s", def->flags[i]) != 0) {
328 return -1;
329 }
330 }
331
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 } else if (ap_sb_appendf(sb, "%s", mv) != 0) {
332 return -1;
333 }
334
335
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 4 times.
14 if (has_meta) {
336
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
10 if (def->opts.nargs == AP_NARGS_ONE && ap_sb_appendf(sb, " %s", mv) != 0) {
337 return -1;
338 }
339
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
12 if (def->opts.nargs == AP_NARGS_OPTIONAL &&
340 2 ap_sb_appendf(sb, " [%s]", mv) != 0) {
341 return -1;
342 }
343
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
12 if (def->opts.nargs == AP_NARGS_ZERO_OR_MORE &&
344 2 ap_sb_appendf(sb, " [%s ...]", mv) != 0) {
345 return -1;
346 }
347
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
10 if (def->opts.nargs == AP_NARGS_ONE_OR_MORE &&
348 ap_sb_appendf(sb, " %s [%s ...]", mv, mv) != 0) {
349 return -1;
350 }
351
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
10 if (def->opts.nargs == AP_NARGS_FIXED) {
352 4 int start = def->is_optional ? 0 : 1;
353
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (i = start; i < def->opts.nargs_count; i++) {
354
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (ap_sb_appendf(sb, " %s", mv) != 0) {
355 return -1;
356 }
357 }
358 }
359 }
360
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
14 if (def->opts.help && ap_sb_appendf(sb, " - %s", def->opts.help) != 0) {
361 return -1;
362 }
363
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 if (append_choices_line(sb, def, " | ") != 0) {
364 return -1;
365 }
366
4/6
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
18 if (show_defaults && def->opts.default_value &&
367 4 ap_sb_appendf(sb, " | default: %s", def->opts.default_value) != 0) {
368 return -1;
369 }
370
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
14 if (def->opts.required && ap_sb_appendf(sb, " | required: true") != 0) {
371 return -1;
372 }
373 14 return ap_sb_appendf(sb, "\n");
374 }
375
376 338 static int append_help_line(ap_string_builder *sb, const ap_arg_def *def,
377 ap_help_render_options opts) {
378
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 324 times.
338 if (opts.raw_text) {
379 14 return append_help_line_raw(sb, def, opts.show_defaults);
380 }
381 324 return append_help_line_standard(sb, def, opts.show_defaults);
382 }
383
384 212 char *ap_usage_build(const ap_parser *parser) {
385 ap_string_builder sb;
386 int i;
387
388
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 210 times.
212 if (!parser) {
389 2 return NULL;
390 }
391
392 210 ap_sb_init(&sb);
393
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 196 times.
210 if (ap_sb_appendf(&sb, "usage: %s", parser->prog) != 0) {
394 14 ap_sb_free(&sb);
395 14 return NULL;
396 }
397
398
2/2
✓ Branch 0 taken 576 times.
✓ Branch 1 taken 174 times.
750 for (i = 0; i < parser->defs_count; i++) {
399 576 const ap_arg_def *def = &parser->defs[i];
400 464 int rc = def->is_optional ? append_optional_usage(&sb, def)
401
2/2
✓ Branch 0 taken 464 times.
✓ Branch 1 taken 112 times.
576 : append_positional_usage(&sb, def);
402
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 554 times.
576 if (rc != 0) {
403 22 ap_sb_free(&sb);
404 22 return NULL;
405 }
406 }
407
408
4/4
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 84 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 86 times.
264 if (parser->subcommands_count > 0 &&
409 90 ap_sb_appendf(&sb, " <%s>", "subcommand") != 0) {
410 4 ap_sb_free(&sb);
411 4 return NULL;
412 }
413
414
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 162 times.
170 if (ap_sb_appendf(&sb, "\n") != 0) {
415 8 ap_sb_free(&sb);
416 8 return NULL;
417 }
418 162 return sb.data;
419 }
420
421 162 char *ap_help_build(const ap_parser *parser) {
422 ap_string_builder sb;
423 int i;
424 int j;
425 162 ap_help_render_options render_opts = {0};
426 162 bool has_positionals = false;
427 162 bool has_optionals = false;
428 162 bool has_argument_groups = false;
429 162 bool has_subcommands = false;
430
431
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 160 times.
162 if (!parser) {
432 2 return NULL;
433 }
434
435 160 ap_sb_init(&sb);
436 160 render_opts.show_defaults = true;
437
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 156 times.
160 if (parser->help_formatter_mode == AP_HELP_FORMATTER_RAW_TEXT) {
438 4 render_opts.raw_text = true;
439
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 154 times.
156 } else if (parser->help_formatter_mode == AP_HELP_FORMATTER_STANDARD ||
440
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 parser->help_formatter_mode == AP_HELP_FORMATTER_SHOW_DEFAULTS) {
441 156 render_opts.raw_text = false;
442 }
443
444 {
445 160 char *usage = ap_usage_build(parser);
446
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 138 times.
160 if (!usage) {
447 22 ap_sb_free(&sb);
448 22 return NULL;
449 }
450
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 134 times.
138 if (ap_sb_appendf(&sb, "%s", usage) != 0) {
451 4 free(usage);
452 4 ap_sb_free(&sb);
453 4 return NULL;
454 }
455 134 free(usage);
456 }
457
458
4/4
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 116 times.
252 if (parser->description[0] != '\0' &&
459 118 ap_sb_appendf(&sb, "\n%s\n", parser->description) != 0) {
460 2 ap_sb_free(&sb);
461 2 return NULL;
462 }
463
464
2/2
✓ Branch 0 taken 414 times.
✓ Branch 1 taken 132 times.
546 for (i = 0; i < parser->defs_count; i++) {
465
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 410 times.
414 if (parser->defs[i].arg_group_index >= 0) {
466 4 has_argument_groups = true;
467 4 continue;
468 }
469
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 88 times.
410 if (parser->defs[i].is_optional) {
470 322 has_optionals = true;
471 } else {
472 88 has_positionals = true;
473 }
474 }
475 132 has_subcommands = parser->subcommands_count > 0;
476
477
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 48 times.
132 if (has_positionals) {
478
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 82 times.
84 if (ap_sb_appendf(&sb, "\npositional arguments:\n") != 0) {
479 2 ap_sb_free(&sb);
480 2 return NULL;
481 }
482
2/2
✓ Branch 0 taken 326 times.
✓ Branch 1 taken 74 times.
400 for (i = 0; i < parser->defs_count; i++) {
483
5/6
✓ Branch 0 taken 326 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 86 times.
✓ Branch 3 taken 240 times.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 78 times.
412 if (parser->defs[i].arg_group_index < 0 && !parser->defs[i].is_optional &&
484 86 append_help_line(&sb, &parser->defs[i], render_opts) != 0) {
485 8 ap_sb_free(&sb);
486 8 return NULL;
487 }
488 }
489 }
490
491
1/2
✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
122 if (has_optionals) {
492
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 118 times.
122 if (ap_sb_appendf(&sb, "\noptional arguments:\n") != 0) {
493 4 ap_sb_free(&sb);
494 4 return NULL;
495 }
496
2/2
✓ Branch 0 taken 282 times.
✓ Branch 1 taken 60 times.
342 for (i = 0; i < parser->defs_count; i++) {
497
6/6
✓ Branch 0 taken 278 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 248 times.
✓ Branch 3 taken 30 times.
✓ Branch 4 taken 58 times.
✓ Branch 5 taken 190 times.
530 if (parser->defs[i].arg_group_index < 0 && parser->defs[i].is_optional &&
498 248 append_help_line(&sb, &parser->defs[i], render_opts) != 0) {
499 58 ap_sb_free(&sb);
500 58 return NULL;
501 }
502 }
503 }
504
505
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 58 times.
60 if (has_argument_groups) {
506
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (i = 0; i < parser->arg_groups_count; i++) {
507
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (ap_sb_appendf(&sb, "\n%s:\n", parser->arg_groups[i].title) != 0) {
508 ap_sb_free(&sb);
509 return NULL;
510 }
511
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (parser->arg_groups[i].description &&
512
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
4 parser->arg_groups[i].description[0] != '\0' &&
513 2 ap_sb_appendf(&sb, " %s\n", parser->arg_groups[i].description) !=
514 0) {
515 ap_sb_free(&sb);
516 return NULL;
517 }
518
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (j = 0; j < parser->defs_count; j++) {
519
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
10 if (parser->defs[j].arg_group_index == i &&
520 4 append_help_line(&sb, &parser->defs[j], render_opts) != 0) {
521 ap_sb_free(&sb);
522 return NULL;
523 }
524 }
525 }
526 }
527
528
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 44 times.
60 if (has_subcommands) {
529
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 14 times.
16 if (ap_sb_appendf(&sb, "\nsubcommands:\n") != 0) {
530 2 ap_sb_free(&sb);
531 2 return NULL;
532 }
533
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 8 times.
22 for (i = 0; i < parser->subcommands_count; i++) {
534
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 12 times.
14 if (ap_sb_appendf(&sb, " %s", parser->subcommands[i].name) != 0) {
535 2 ap_sb_free(&sb);
536 2 return NULL;
537 }
538
3/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 10 times.
24 if (parser->subcommands[i].help[0] != '\0' &&
539 12 ap_sb_appendf(&sb, "\n %s", parser->subcommands[i].help) != 0) {
540 2 ap_sb_free(&sb);
541 2 return NULL;
542 }
543
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 8 times.
10 if (ap_sb_appendf(&sb, "\n") != 0) {
544 2 ap_sb_free(&sb);
545 2 return NULL;
546 }
547 }
548 }
549
550 52 return sb.data;
551 }
552