diff options
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/getopt32.c | 61 |
1 files changed, 42 insertions, 19 deletions
diff --git a/libbb/getopt32.c b/libbb/getopt32.c index 80d5d2822..46807a3b6 100644 --- a/libbb/getopt32.c +++ b/libbb/getopt32.c @@ -220,6 +220,14 @@ Special characters: "x--x" Variation of the above, it means that -x option should occur at most once. + "a+:" A plus after a char in opt_complementary means that the parameter + for this option is a nonnegative integer. It will be processed + with xatoi_u() - allowed range is 0..INT_MAX. + + int param; // "unsigned param;" will also work + opt_complementary = "p+"; + getopt32(argv, "p:", ¶m); + "a::" A double colon after a char in opt_complementary means that the option can occur multiple times. Each occurrence will be saved as a llist_t element instead of char*. @@ -275,14 +283,20 @@ Special characters: const char *opt_complementary; +enum { + PARAM_STRING, + PARAM_LIST, + PARAM_INT, +}; + typedef struct { - int opt; - int list_flg; + unsigned char opt_char; + smallint param_type; unsigned switch_on; unsigned switch_off; unsigned incongruously; unsigned requires; - void **optarg; /* char **optarg or llist_t **optarg */ + void **optarg; /* char**, llist_t** or int *. */ int *counter; } t_complementary; @@ -337,12 +351,14 @@ getopt32(char **argv, const char *applet_opts, ...) if (*s == '+' || *s == '-') s++; while (*s) { - if (c >= 32) break; - on_off->opt = *s; + if (c >= 32) + break; + on_off->opt_char = *s; on_off->switch_on = (1 << c); if (*++s == ':') { on_off->optarg = va_arg(p, void **); - while (*++s == ':') /* skip */; + while (*++s == ':') + continue; } on_off++; c++; @@ -375,11 +391,12 @@ getopt32(char **argv, const char *applet_opts, ...) for (l_o = long_options; l_o->name; l_o++) { if (l_o->flag) continue; - for (on_off = complementary; on_off->opt != 0; on_off++) - if (on_off->opt == l_o->val) + for (on_off = complementary; on_off->opt_char; on_off++) + if (on_off->opt_char == l_o->val) goto next_long; - if (c >= 32) break; - on_off->opt = l_o->val; + if (c >= 32) + break; + on_off->opt_char = l_o->val; on_off->switch_on = (1 << c); if (l_o->has_arg != no_argument) on_off->optarg = va_arg(p, void **); @@ -422,11 +439,15 @@ getopt32(char **argv, const char *applet_opts, ...) s++; continue; } - for (on_off = complementary; on_off->opt; on_off++) - if (on_off->opt == *s) + for (on_off = complementary; on_off->opt_char; on_off++) + if (on_off->opt_char == *s) break; if (c == ':' && s[2] == ':') { - on_off->list_flg++; + on_off->param_type = PARAM_LIST; + continue; + } + if (c == '+' && (s[2] == ':' || s[2] == '\0')) { + on_off->param_type = PARAM_INT; continue; } if (c == ':' || c == '\0') { @@ -454,8 +475,8 @@ getopt32(char **argv, const char *applet_opts, ...) else pair_switch = &(pair->switch_off); } else { - for (on_off = complementary; on_off->opt; on_off++) - if (on_off->opt == *s) { + for (on_off = complementary; on_off->opt_char; on_off++) + if (on_off->opt_char == *s) { *pair_switch |= on_off->switch_on; break; } @@ -508,9 +529,9 @@ getopt32(char **argv, const char *applet_opts, ...) #endif c &= 0xff; /* fight libc's sign extension */ loop_arg_is_opt: - for (on_off = complementary; on_off->opt != c; on_off++) { + for (on_off = complementary; on_off->opt_char != c; on_off++) { /* c==0 if long opt have non NULL flag */ - if (on_off->opt == 0 && c != 0) + if (on_off->opt_char == '\0' && c != '\0') bb_show_usage(); } if (flags & on_off->incongruously) @@ -521,8 +542,10 @@ getopt32(char **argv, const char *applet_opts, ...) flags ^= trigger; if (on_off->counter) (*(on_off->counter))++; - if (on_off->list_flg) { + if (on_off->param_type == PARAM_LIST) { llist_add_to_end((llist_t **)(on_off->optarg), optarg); + } else if (on_off->param_type == PARAM_INT) { + *(unsigned*)(on_off->optarg) = xatoi_u(optarg); } else if (on_off->optarg) { *(char **)(on_off->optarg) = optarg; } @@ -550,7 +573,7 @@ getopt32(char **argv, const char *applet_opts, ...) free(argv[1]); #endif /* check depending requires for given options */ - for (on_off = complementary; on_off->opt; on_off++) { + for (on_off = complementary; on_off->opt_char; on_off++) { if (on_off->requires && (flags & on_off->switch_on) && (flags & on_off->requires) == 0) bb_show_usage(); |