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