Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2024 HiSilicon Limited
3 : : */
4 : :
5 : : #include <errno.h>
6 : : #include <stdlib.h>
7 : : #include <string.h>
8 : :
9 : : #include <rte_log.h>
10 : :
11 : : #include "rte_argparse.h"
12 : :
13 [ - + ]: 238 : RTE_LOG_REGISTER_DEFAULT(rte_argparse_logtype, INFO);
14 : : #define RTE_LOGTYPE_ARGPARSE rte_argparse_logtype
15 : : #define ARGPARSE_LOG(level, ...) \
16 : : RTE_LOG_LINE(level, ARGPARSE, "" __VA_ARGS__)
17 : :
18 : : #define ARG_ATTR_HAS_VAL_MASK RTE_GENMASK64(1, 0)
19 : : #define ARG_ATTR_VAL_TYPE_MASK RTE_GENMASK64(9, 2)
20 : : #define ARG_ATTR_SUPPORT_MULTI_MASK RTE_BIT64(10)
21 : : #define ARG_ATTR_FLAG_PARSED_MASK RTE_BIT64(63)
22 : :
23 : : static inline bool
24 : : is_arg_optional(const struct rte_argparse_arg *arg)
25 : : {
26 : 58 : return arg->name_long[0] == '-';
27 : : }
28 : :
29 : : static inline bool
30 : : is_arg_positional(const struct rte_argparse_arg *arg)
31 : : {
32 : 93 : return arg->name_long[0] != '-';
33 : : }
34 : :
35 : : static inline uint32_t
36 : : arg_attr_has_val(const struct rte_argparse_arg *arg)
37 : : {
38 : 118 : return RTE_FIELD_GET64(ARG_ATTR_HAS_VAL_MASK, arg->flags);
39 : : }
40 : :
41 : : static inline uint32_t
42 : : arg_attr_val_type(const struct rte_argparse_arg *arg)
43 : : {
44 : 78 : return RTE_FIELD_GET64(ARG_ATTR_VAL_TYPE_MASK, arg->flags);
45 : : }
46 : :
47 : : static inline bool
48 : : arg_attr_flag_multi(const struct rte_argparse_arg *arg)
49 : : {
50 : 0 : return RTE_FIELD_GET64(ARG_ATTR_SUPPORT_MULTI_MASK, arg->flags);
51 : : }
52 : :
53 : : static inline uint32_t
54 : : arg_attr_unused_bits(const struct rte_argparse_arg *arg)
55 : : {
56 : : #define USED_BIT_MASK (ARG_ATTR_HAS_VAL_MASK | ARG_ATTR_VAL_TYPE_MASK | \
57 : : ARG_ATTR_SUPPORT_MULTI_MASK)
58 : 39 : return arg->flags & ~USED_BIT_MASK;
59 : : }
60 : :
61 : : static int
62 : 58 : verify_arg_name(const struct rte_argparse_arg *arg)
63 : : {
64 [ + + ]: 58 : if (is_arg_optional(arg)) {
65 [ + + ]: 46 : if (strlen(arg->name_long) <= 3) {
66 : 1 : ARGPARSE_LOG(ERR, "optional long name %s too short!", arg->name_long);
67 : 1 : return -EINVAL;
68 : : }
69 [ + + ]: 45 : if (arg->name_long[1] != '-') {
70 : 1 : ARGPARSE_LOG(ERR, "optional long name %s must only start with '--'",
71 : : arg->name_long);
72 : 1 : return -EINVAL;
73 : : }
74 [ + + ]: 44 : if (arg->name_long[2] == '-') {
75 : 1 : ARGPARSE_LOG(ERR, "optional long name %s should not start with '---'",
76 : : arg->name_long);
77 : 1 : return -EINVAL;
78 : : }
79 : : }
80 : :
81 [ + + ]: 55 : if (arg->name_short == NULL)
82 : : return 0;
83 : :
84 [ + + ]: 44 : if (!is_arg_optional(arg)) {
85 : 1 : ARGPARSE_LOG(ERR, "short name %s corresponding long name must be optional!",
86 : : arg->name_short);
87 : 1 : return -EINVAL;
88 : : }
89 : :
90 [ + + + + ]: 43 : if (strlen(arg->name_short) != 2 || arg->name_short[0] != '-' ||
91 [ - + ]: 40 : arg->name_short[1] == '-') {
92 : 3 : ARGPARSE_LOG(ERR, "short name %s must start with a hyphen (-) followed by an English letter",
93 : : arg->name_short);
94 : 3 : return -EINVAL;
95 : : }
96 : :
97 : : return 0;
98 : : }
99 : :
100 : : static int
101 : : verify_arg_help(const struct rte_argparse_arg *arg)
102 : : {
103 [ + + ]: 51 : if (arg->help == NULL) {
104 : 1 : ARGPARSE_LOG(ERR, "argument %s must have help info!", arg->name_long);
105 : : return -EINVAL;
106 : : }
107 : :
108 : : return 0;
109 : : }
110 : :
111 : : static int
112 : 50 : verify_arg_has_val(const struct rte_argparse_arg *arg)
113 : : {
114 : : uint32_t has_val = arg_attr_has_val(arg);
115 : :
116 [ + + ]: 50 : if (is_arg_positional(arg)) {
117 [ + + ]: 11 : if (has_val == RTE_ARGPARSE_ARG_REQUIRED_VALUE)
118 : : return 0;
119 : 3 : ARGPARSE_LOG(ERR, "argument %s is positional, should has zero or required-val!",
120 : : arg->name_long);
121 : 3 : return -EINVAL;
122 : : }
123 : :
124 [ + + ]: 39 : if (has_val == 0) {
125 : 1 : ARGPARSE_LOG(ERR, "argument %s is optional, has-val config wrong!",
126 : : arg->name_long);
127 : 1 : return -EINVAL;
128 : : }
129 : :
130 : : return 0;
131 : : }
132 : :
133 : : static int
134 : 46 : verify_arg_saver(const struct rte_argparse *obj, uint32_t index)
135 : : {
136 : : uint32_t cmp_max = RTE_FIELD_GET64(ARG_ATTR_VAL_TYPE_MASK, RTE_ARGPARSE_ARG_VALUE_MAX);
137 : : const struct rte_argparse_arg *arg = &obj->args[index];
138 : : uint32_t val_type = arg_attr_val_type(arg);
139 : : uint32_t has_val = arg_attr_has_val(arg);
140 : :
141 [ + + ]: 46 : if (arg->val_saver == NULL) {
142 [ + + ]: 18 : if (val_type != 0) {
143 : 1 : ARGPARSE_LOG(ERR, "argument %s parse by callback, val-type must be zero!",
144 : : arg->name_long);
145 : 1 : return -EINVAL;
146 : : }
147 : :
148 [ + + ]: 17 : if (obj->callback == NULL) {
149 : 2 : ARGPARSE_LOG(ERR, "argument %s parse by callback, but callback is NULL!",
150 : : arg->name_long);
151 : 2 : return -EINVAL;
152 : : }
153 : :
154 : : return 0;
155 : : }
156 : :
157 [ + + ]: 28 : if (val_type == 0 || val_type >= cmp_max) {
158 : 2 : ARGPARSE_LOG(ERR, "argument %s val-type config wrong!", arg->name_long);
159 : 2 : return -EINVAL;
160 : : }
161 : :
162 [ + + + + ]: 26 : if (has_val == RTE_ARGPARSE_ARG_REQUIRED_VALUE && arg->val_set != NULL) {
163 : 2 : ARGPARSE_LOG(ERR, "argument %s has required value, val-set should be NULL!",
164 : : arg->name_long);
165 : 2 : return -EINVAL;
166 : : }
167 : :
168 : : return 0;
169 : : }
170 : :
171 : : static int
172 : 39 : verify_arg_flags(const struct rte_argparse *obj, uint32_t index)
173 : : {
174 : : const struct rte_argparse_arg *arg = &obj->args[index];
175 : : uint32_t unused_bits = arg_attr_unused_bits(arg);
176 : :
177 [ + + ]: 39 : if (unused_bits != 0) {
178 : 1 : ARGPARSE_LOG(ERR, "argument %s flags set wrong!", arg->name_long);
179 : 1 : return -EINVAL;
180 : : }
181 : :
182 [ + + ]: 38 : if (!(arg->flags & RTE_ARGPARSE_ARG_SUPPORT_MULTI))
183 : : return 0;
184 : :
185 [ - + ]: 1 : if (is_arg_positional(arg)) {
186 : 0 : ARGPARSE_LOG(ERR, "argument %s is positional, don't support multiple times!",
187 : : arg->name_long);
188 : 0 : return -EINVAL;
189 : : }
190 : :
191 [ + - ]: 1 : if (arg->val_saver != NULL) {
192 : 1 : ARGPARSE_LOG(ERR, "argument %s could occur multiple times, should use callback to parse!",
193 : : arg->name_long);
194 : 1 : return -EINVAL;
195 : : }
196 : :
197 [ # # ]: 0 : if (obj->callback == NULL) {
198 : 0 : ARGPARSE_LOG(ERR, "argument %s should use callback to parse, but callback is NULL!",
199 : : arg->name_long);
200 : 0 : return -EINVAL;
201 : : }
202 : :
203 : : return 0;
204 : : }
205 : :
206 : : static int
207 : 37 : verify_arg_repeat(const struct rte_argparse *self, uint32_t index)
208 : : {
209 : : const struct rte_argparse_arg *arg = &self->args[index];
210 : : uint32_t i;
211 : :
212 [ + + ]: 42 : for (i = 0; i < index; i++) {
213 [ + + ]: 6 : if (!strcmp(arg->name_long, self->args[i].name_long)) {
214 : 1 : ARGPARSE_LOG(ERR, "argument %s repeat!", arg->name_long);
215 : 1 : return -EINVAL;
216 : : }
217 : : }
218 : :
219 [ + + ]: 36 : if (arg->name_short == NULL)
220 : : return 0;
221 : :
222 [ + + ]: 31 : for (i = 0; i < index; i++) {
223 [ - + ]: 3 : if (self->args[i].name_short == NULL)
224 : 0 : continue;
225 [ + + ]: 3 : if (!strcmp(arg->name_short, self->args[i].name_short)) {
226 : 1 : ARGPARSE_LOG(ERR, "argument %s repeat!", arg->name_short);
227 : 1 : return -EINVAL;
228 : : }
229 : : }
230 : :
231 : : return 0;
232 : : }
233 : :
234 : : static int
235 : 58 : verify_argparse_arg(const struct rte_argparse *obj, uint32_t index)
236 : : {
237 : 58 : const struct rte_argparse_arg *arg = &obj->args[index];
238 : : int ret;
239 : :
240 : 58 : ret = verify_arg_name(arg);
241 [ + + ]: 58 : if (ret != 0)
242 : : return ret;
243 : :
244 : : ret = verify_arg_help(arg);
245 : : if (ret != 0)
246 : 1 : return ret;
247 : :
248 : 50 : ret = verify_arg_has_val(arg);
249 [ + + ]: 50 : if (ret != 0)
250 : : return ret;
251 : :
252 : 46 : ret = verify_arg_saver(obj, index);
253 [ + + ]: 46 : if (ret != 0)
254 : : return ret;
255 : :
256 : 39 : ret = verify_arg_flags(obj, index);
257 [ + + ]: 39 : if (ret != 0)
258 : : return ret;
259 : :
260 : 37 : ret = verify_arg_repeat(obj, index);
261 [ + + ]: 37 : if (ret != 0)
262 : 2 : return ret;
263 : :
264 : : return 0;
265 : : }
266 : :
267 : : static int
268 : 54 : verify_argparse(const struct rte_argparse *obj)
269 : : {
270 : : uint32_t idx;
271 : : int ret;
272 : :
273 [ + + ]: 54 : if (obj->prog_name == NULL) {
274 : 1 : ARGPARSE_LOG(ERR, "program name is NULL!");
275 : 1 : return -EINVAL;
276 : : }
277 : :
278 [ + + ]: 53 : if (obj->usage == NULL) {
279 : 1 : ARGPARSE_LOG(ERR, "usage is NULL!");
280 : 1 : return -EINVAL;
281 : : }
282 : :
283 [ + + ]: 884 : for (idx = 0; idx < RTE_DIM(obj->reserved); idx++) {
284 [ - + ]: 832 : if (obj->reserved[idx] != 0) {
285 : 0 : ARGPARSE_LOG(ERR, "reserved field must be zero!");
286 : 0 : return -EINVAL;
287 : : }
288 : : }
289 : :
290 : : idx = 0;
291 [ + + ]: 87 : while (obj->args[idx].name_long != NULL) {
292 : 58 : ret = verify_argparse_arg(obj, idx);
293 [ + + ]: 58 : if (ret != 0)
294 : 23 : return ret;
295 : 35 : idx++;
296 : : }
297 : :
298 : : return 0;
299 : : }
300 : :
301 : : static uint32_t
302 : : calc_position_count(const struct rte_argparse *obj)
303 : : {
304 : : const struct rte_argparse_arg *arg;
305 : : uint32_t count = 0;
306 : : uint32_t i;
307 : :
308 : 33 : for (i = 0; /* NULL */; i++) {
309 : 33 : arg = &obj->args[i];
310 [ - - + + ]: 62 : if (obj->args[i].name_long == NULL)
311 : : break;
312 [ - - + + ]: 33 : if (is_arg_positional(arg))
313 : 7 : count++;
314 : : }
315 : :
316 : : return count;
317 : : }
318 : :
319 : : static struct rte_argparse_arg *
320 : : find_position_arg(struct rte_argparse *obj, uint32_t index)
321 : : {
322 : : struct rte_argparse_arg *arg;
323 : : uint32_t count = 0;
324 : : uint32_t i;
325 : :
326 : 2 : for (i = 0; /* NULL */; i++) {
327 : 9 : arg = &obj->args[i];
328 [ + - ]: 9 : if (arg->name_long == NULL)
329 : : break;
330 [ - + ]: 9 : if (!is_arg_positional(arg))
331 : 0 : continue;
332 : 9 : count++;
333 [ + + ]: 9 : if (count == index)
334 : : return arg;
335 : : }
336 : :
337 : : return NULL;
338 : : }
339 : :
340 : : static bool
341 : 24 : is_arg_match(struct rte_argparse_arg *arg, const char *curr_argv, uint32_t len)
342 : : {
343 [ + + - + ]: 24 : if (strlen(arg->name_long) == len && strncmp(arg->name_long, curr_argv, len) == 0)
344 : : return true;
345 : :
346 [ + - ]: 15 : if (arg->name_short == NULL)
347 : : return false;
348 : :
349 [ + + + - ]: 15 : if (strlen(arg->name_short) == len && strncmp(arg->name_short, curr_argv, len) == 0)
350 : 13 : return true;
351 : :
352 : : return false;
353 : : }
354 : :
355 : : static struct rte_argparse_arg *
356 : 23 : find_option_arg(struct rte_argparse *obj, const char *curr_argv, const char *has_equal,
357 : : const char **arg_name)
358 : : {
359 [ + + ]: 23 : uint32_t len = strlen(curr_argv) - (has_equal != NULL ? strlen(has_equal) : 0);
360 : : struct rte_argparse_arg *arg;
361 : : uint32_t i;
362 : : bool match;
363 : :
364 : 2 : for (i = 0; /* nothing */; i++) {
365 : 25 : arg = &obj->args[i];
366 [ + + ]: 25 : if (arg->name_long == NULL)
367 : : break;
368 : 24 : match = is_arg_match(arg, curr_argv, len);
369 [ + + ]: 24 : if (match) {
370 : : /* Obtains the exact matching name (long or short). */
371 [ + + ]: 22 : *arg_name = len > 2 ? arg->name_long : arg->name_short;
372 : 22 : return arg;
373 : : }
374 : : }
375 : :
376 : : return NULL;
377 : : }
378 : :
379 : : static int
380 : 17 : parse_arg_int(struct rte_argparse_arg *arg, const char *value)
381 : : {
382 : 17 : char *s = NULL;
383 : :
384 [ + + ]: 17 : if (value == NULL) {
385 : 4 : *(int *)arg->val_saver = (int)(intptr_t)arg->val_set;
386 : 4 : return 0;
387 : : }
388 : :
389 : 13 : errno = 0;
390 : 13 : *(int *)arg->val_saver = strtol(value, &s, 0);
391 [ + + ]: 13 : if (errno == ERANGE) {
392 : 1 : ARGPARSE_LOG(ERR, "argument %s numerical out of range!", arg->name_long);
393 : 1 : return -EINVAL;
394 : : }
395 : :
396 [ + + ]: 12 : if (s[0] != '\0') {
397 : 5 : ARGPARSE_LOG(ERR, "argument %s expect an integer value!", arg->name_long);
398 : 5 : return -EINVAL;
399 : : }
400 : :
401 : : return 0;
402 : : }
403 : :
404 : : static int
405 : 4 : parse_arg_u8(struct rte_argparse_arg *arg, const char *value)
406 : : {
407 : : unsigned long val;
408 : 4 : char *s = NULL;
409 : :
410 [ - + ]: 4 : if (value == NULL) {
411 : 0 : *(uint8_t *)arg->val_saver = (uint8_t)(intptr_t)arg->val_set;
412 : 0 : return 0;
413 : : }
414 : :
415 : 4 : errno = 0;
416 : 4 : val = strtoul(value, &s, 0);
417 [ + + + + ]: 4 : if (errno == ERANGE || val > UINT8_MAX) {
418 : 2 : ARGPARSE_LOG(ERR, "argument %s numerical out of range!", arg->name_long);
419 : 2 : return -EINVAL;
420 : : }
421 : :
422 [ + + ]: 2 : if (s[0] != '\0') {
423 : 1 : ARGPARSE_LOG(ERR, "argument %s expect an uint8 value!", arg->name_long);
424 : 1 : return -EINVAL;
425 : : }
426 : :
427 : 1 : *(uint8_t *)arg->val_saver = val;
428 : :
429 : 1 : return 0;
430 : : }
431 : :
432 : : static int
433 : 4 : parse_arg_u16(struct rte_argparse_arg *arg, const char *value)
434 : : {
435 : : unsigned long val;
436 : 4 : char *s = NULL;
437 : :
438 [ - + ]: 4 : if (value == NULL) {
439 : 0 : *(uint16_t *)arg->val_saver = (uint16_t)(intptr_t)arg->val_set;
440 : 0 : return 0;
441 : : }
442 : :
443 : 4 : errno = 0;
444 : 4 : val = strtoul(value, &s, 0);
445 [ + + + + ]: 4 : if (errno == ERANGE || val > UINT16_MAX) {
446 : 2 : ARGPARSE_LOG(ERR, "argument %s numerical out of range!", arg->name_long);
447 : 2 : return -EINVAL;
448 : : }
449 : :
450 [ + + ]: 2 : if (s[0] != '\0') {
451 : 1 : ARGPARSE_LOG(ERR, "argument %s expect an uint16 value!", arg->name_long);
452 : 1 : return -EINVAL;
453 : : }
454 : :
455 : 1 : *(uint16_t *)arg->val_saver = val;
456 : :
457 : 1 : return 0;
458 : : }
459 : :
460 : : static int
461 : 4 : parse_arg_u32(struct rte_argparse_arg *arg, const char *value)
462 : : {
463 : : unsigned long val;
464 : 4 : char *s = NULL;
465 : :
466 [ - + ]: 4 : if (value == NULL) {
467 : 0 : *(uint32_t *)arg->val_saver = (uint32_t)(intptr_t)arg->val_set;
468 : 0 : return 0;
469 : : }
470 : :
471 : 4 : errno = 0;
472 : 4 : val = strtoul(value, &s, 0);
473 [ + + + + ]: 4 : if (errno == ERANGE || val > UINT32_MAX) {
474 : 2 : ARGPARSE_LOG(ERR, "argument %s numerical out of range!", arg->name_long);
475 : 2 : return -EINVAL;
476 : : }
477 : :
478 [ + + ]: 2 : if (s[0] != '\0') {
479 : 1 : ARGPARSE_LOG(ERR, "argument %s expect an uint32 value!", arg->name_long);
480 : 1 : return -EINVAL;
481 : : }
482 : :
483 : 1 : *(uint32_t *)arg->val_saver = val;
484 : :
485 : 1 : return 0;
486 : : }
487 : :
488 : : static int
489 : 3 : parse_arg_u64(struct rte_argparse_arg *arg, const char *value)
490 : : {
491 : : unsigned long val;
492 : 3 : char *s = NULL;
493 : :
494 [ - + ]: 3 : if (value == NULL) {
495 : 0 : *(uint64_t *)arg->val_saver = (uint64_t)(intptr_t)arg->val_set;
496 : 0 : return 0;
497 : : }
498 : :
499 : 3 : errno = 0;
500 : 3 : val = strtoull(value, &s, 0);
501 [ + + ]: 3 : if (errno == ERANGE) {
502 : 1 : ARGPARSE_LOG(ERR, "argument %s numerical out of range!", arg->name_long);
503 : 1 : return -EINVAL;
504 : : }
505 : :
506 [ + + ]: 2 : if (s[0] != '\0') {
507 : 1 : ARGPARSE_LOG(ERR, "argument %s expect an uint64 value!", arg->name_long);
508 : 1 : return -EINVAL;
509 : : }
510 : :
511 : 1 : *(uint64_t *)arg->val_saver = val;
512 : :
513 : 1 : return 0;
514 : : }
515 : :
516 : : static int
517 : : parse_arg_autosave(struct rte_argparse_arg *arg, const char *value)
518 : : {
519 : : static struct {
520 : : int (*f_parse_type)(struct rte_argparse_arg *arg, const char *value);
521 : : } map[] = {
522 : : /* Sort by RTE_ARGPARSE_ARG_VALUE_XXX. */
523 : : { NULL },
524 : : { parse_arg_int },
525 : : { parse_arg_u8 },
526 : : { parse_arg_u16 },
527 : : { parse_arg_u32 },
528 : : { parse_arg_u64 },
529 : : };
530 : : uint32_t index = arg_attr_val_type(arg);
531 : : int ret = -EINVAL;
532 : :
533 [ + - ]: 14 : if (index > 0 && index < RTE_DIM(map))
534 : 32 : ret = map[index].f_parse_type(arg, value);
535 : :
536 : : return ret;
537 : : }
538 : :
539 : : static int
540 : 28 : parse_arg_val(struct rte_argparse *obj, struct rte_argparse_arg *arg, char *value)
541 : : {
542 : : int ret;
543 : :
544 [ + + ]: 28 : if (arg->val_saver == NULL)
545 : 14 : ret = obj->callback((uint32_t)(uintptr_t)arg->val_set, value, obj->opaque);
546 : : else
547 : : ret = parse_arg_autosave(arg, value);
548 [ + + ]: 28 : if (ret != 0) {
549 : 7 : ARGPARSE_LOG(ERR, "argument %s parse value fail!", arg->name_long);
550 : 7 : return ret;
551 : : }
552 : :
553 : : return 0;
554 : : }
555 : :
556 : : static bool
557 : 23 : is_help(const char *curr_argv)
558 : : {
559 [ + - + - ]: 23 : return strcmp(curr_argv, "-h") == 0 || strcmp(curr_argv, "--help") == 0;
560 : : }
561 : :
562 : : static int
563 : 29 : parse_args(struct rte_argparse *obj, int argc, char **argv, bool *show_help)
564 : : {
565 : : uint32_t position_count = calc_position_count(obj);
566 : : struct rte_argparse_arg *arg;
567 : : uint32_t position_index = 0;
568 : : const char *arg_name;
569 : : char *curr_argv;
570 : : char *has_equal;
571 : : char *value;
572 : : int ret;
573 : : int i;
574 : :
575 [ + + ]: 50 : for (i = 1; i < argc; i++) {
576 : 32 : curr_argv = argv[i];
577 [ + + ]: 32 : if (curr_argv[0] != '-') {
578 : : /* process positional parameters. */
579 : 9 : position_index++;
580 [ + + ]: 9 : if (position_index > position_count) {
581 : 2 : ARGPARSE_LOG(ERR, "too much positional argument %s!", curr_argv);
582 : 2 : return -EINVAL;
583 : : }
584 : : arg = find_position_arg(obj, position_index);
585 : 7 : ret = parse_arg_val(obj, arg, curr_argv);
586 [ + + ]: 7 : if (ret != 0)
587 : 2 : return ret;
588 : 5 : continue;
589 : : }
590 : :
591 : : /* process optional parameters. */
592 [ - + ]: 23 : if (is_help(curr_argv)) {
593 : 0 : *show_help = true;
594 : 0 : continue;
595 : : }
596 : :
597 : 23 : has_equal = strchr(curr_argv, '=');
598 : 23 : arg_name = NULL;
599 : 23 : arg = find_option_arg(obj, curr_argv, has_equal, &arg_name);
600 [ + + - + ]: 23 : if (arg == NULL || arg_name == NULL) {
601 : 1 : ARGPARSE_LOG(ERR, "unknown argument %s!", curr_argv);
602 : 1 : return -EINVAL;
603 : : }
604 : :
605 [ - + - - ]: 22 : if ((arg->flags & ARG_ATTR_FLAG_PARSED_MASK) && !arg_attr_flag_multi(arg)) {
606 : 0 : ARGPARSE_LOG(ERR, "argument %s should not occur multiple!",
607 : : arg_name);
608 : 0 : return -EINVAL;
609 : : }
610 : :
611 [ + + ]: 22 : value = (has_equal != NULL ? has_equal + 1 : NULL);
612 [ + + ]: 22 : if (arg_attr_has_val(arg) == RTE_ARGPARSE_ARG_NO_VALUE) {
613 [ - + ]: 4 : if (value != NULL) {
614 : 0 : ARGPARSE_LOG(ERR, "argument %s should not take value!",
615 : : arg_name);
616 : 0 : return -EINVAL;
617 : : }
618 [ + + ]: 18 : } else if (arg_attr_has_val(arg) == RTE_ARGPARSE_ARG_REQUIRED_VALUE) {
619 [ + - ]: 7 : if (value == NULL) {
620 [ + + ]: 7 : if (i >= argc - 1) {
621 : 1 : ARGPARSE_LOG(ERR, "argument %s doesn't have value!",
622 : : arg_name);
623 : 1 : return -EINVAL;
624 : : }
625 : : /* Set value and make i move next. */
626 : 6 : value = argv[++i];
627 : : }
628 : : } else {
629 : : /* Do nothing, because it's optional value, only support arg=val or arg. */
630 : : }
631 : :
632 : 21 : ret = parse_arg_val(obj, arg, value);
633 [ + + ]: 21 : if (ret != 0)
634 : 5 : return ret;
635 : :
636 : : /* This argument parsed success! then mark it parsed. */
637 : 16 : arg->flags |= ARG_ATTR_FLAG_PARSED_MASK;
638 : : }
639 : :
640 : : return 0;
641 : : }
642 : :
643 : : static uint32_t
644 : 0 : calc_help_align(const struct rte_argparse *obj)
645 : : {
646 : : const struct rte_argparse_arg *arg;
647 : : uint32_t width = 12; /* Default "-h, --help " len. */
648 : : uint32_t len;
649 : : uint32_t i;
650 : :
651 : 0 : for (i = 0; /* NULL */; i++) {
652 : 0 : arg = &obj->args[i];
653 [ # # ]: 0 : if (arg->name_long == NULL)
654 : : break;
655 : 0 : len = strlen(arg->name_long);
656 [ # # # # ]: 0 : if (is_arg_optional(arg) && arg->name_short != NULL) {
657 : 0 : len += strlen(", ");
658 : 0 : len += strlen(arg->name_short);
659 : : }
660 : 0 : width = RTE_MAX(width, 1 + len + 2); /* start with 1 & end with 2 space. */
661 : : }
662 : :
663 : 0 : return width;
664 : : }
665 : :
666 : : static void
667 : 0 : show_oneline_help(const struct rte_argparse_arg *arg, uint32_t width)
668 : : {
669 : : uint32_t len = 0;
670 : : uint32_t i;
671 : :
672 [ # # ]: 0 : if (arg->name_short != NULL)
673 : 0 : len = printf(" %s,", arg->name_short);
674 : 0 : len += printf(" %s", arg->name_long);
675 : :
676 [ # # ]: 0 : for (i = len; i < width; i++)
677 : : printf(" ");
678 : :
679 : 0 : printf("%s\n", arg->help);
680 : 0 : }
681 : :
682 : : static void
683 : 0 : show_args_pos_help(const struct rte_argparse *obj, uint32_t align)
684 : : {
685 : : uint32_t position_count = calc_position_count(obj);
686 : : const struct rte_argparse_arg *arg;
687 : : uint32_t i;
688 : :
689 [ # # ]: 0 : if (position_count == 0)
690 : : return;
691 : :
692 : : printf("\npositional arguments:\n");
693 : 0 : for (i = 0; /* NULL */; i++) {
694 : 0 : arg = &obj->args[i];
695 [ # # ]: 0 : if (arg->name_long == NULL)
696 : : break;
697 [ # # ]: 0 : if (!is_arg_positional(arg))
698 : 0 : continue;
699 : 0 : show_oneline_help(arg, align);
700 : : }
701 : : }
702 : :
703 : : static void
704 : 0 : show_args_opt_help(const struct rte_argparse *obj, uint32_t align)
705 : : {
706 : : static const struct rte_argparse_arg help = {
707 : : .name_long = "--help",
708 : : .name_short = "-h",
709 : : .help = "show this help message and exit.",
710 : : };
711 : : const struct rte_argparse_arg *arg;
712 : : uint32_t i;
713 : :
714 : : printf("\noptions:\n");
715 : 0 : show_oneline_help(&help, align);
716 : 0 : for (i = 0; /* NULL */; i++) {
717 : 0 : arg = &obj->args[i];
718 [ # # ]: 0 : if (arg->name_long == NULL)
719 : : break;
720 [ # # ]: 0 : if (!is_arg_optional(arg))
721 : 0 : continue;
722 : 0 : show_oneline_help(arg, align);
723 : : }
724 : 0 : }
725 : :
726 : : static void
727 : 0 : show_args_help(const struct rte_argparse *obj)
728 : : {
729 : 0 : uint32_t align = calc_help_align(obj);
730 : :
731 : 0 : printf("usage: %s %s\n", obj->prog_name, obj->usage);
732 [ # # ]: 0 : if (obj->descriptor != NULL)
733 : : printf("\ndescriptor: %s\n", obj->descriptor);
734 : :
735 : 0 : show_args_pos_help(obj, align);
736 : 0 : show_args_opt_help(obj, align);
737 : :
738 [ # # ]: 0 : if (obj->epilog != NULL)
739 : : printf("\n%s\n", obj->epilog);
740 : : else
741 : : printf("\n");
742 : 0 : }
743 : :
744 : : int
745 : 54 : rte_argparse_parse(struct rte_argparse *obj, int argc, char **argv)
746 : : {
747 : 54 : bool show_help = false;
748 : : int ret;
749 : :
750 : 54 : ret = verify_argparse(obj);
751 [ + + ]: 54 : if (ret != 0)
752 : 25 : goto error;
753 : :
754 : 29 : ret = parse_args(obj, argc, argv, &show_help);
755 [ + + ]: 29 : if (ret != 0)
756 : 11 : goto error;
757 : :
758 [ - + ]: 18 : if (show_help) {
759 : 0 : show_args_help(obj);
760 : 0 : exit(0);
761 : : }
762 : :
763 : : return 0;
764 : :
765 : 36 : error:
766 [ - + ]: 36 : if (obj->exit_on_error)
767 : 0 : exit(ret);
768 : : return ret;
769 : : }
770 : :
771 : : int
772 : 18 : rte_argparse_parse_type(const char *str, uint64_t val_type, void *val)
773 : : {
774 : : uint32_t cmp_max = RTE_FIELD_GET64(ARG_ATTR_VAL_TYPE_MASK, RTE_ARGPARSE_ARG_VALUE_MAX);
775 : 18 : struct rte_argparse_arg arg = {
776 : : .name_long = str,
777 : : .name_short = NULL,
778 : : .val_saver = val,
779 : : .val_set = NULL,
780 : : .flags = val_type,
781 : : };
782 : : uint32_t value_type = arg_attr_val_type(&arg);
783 : :
784 [ + - ]: 18 : if (value_type == 0 || value_type >= cmp_max)
785 : : return -EINVAL;
786 : :
787 : 18 : return parse_arg_autosave(&arg, str);
788 : : }
|