getpot: add support for "a+" specifier for nonnegative int parameters.
By Vladimir Dronnikov <dronnikov at gmail.com>. fdisk and top are converted as an example. function old new delta getopt32 1340 1370 +30 top_main 1137 1120 -17 fdisk_main 3033 2949 -84 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/2 up/down: 30/-101) Total: -71 bytes
This commit is contained in:
@ -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();
|
||||
|
Reference in New Issue
Block a user