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:
Denis Vlasenko 2008-02-10 19:44:20 +00:00
parent 9304d6ea92
commit 04e11c9209
3 changed files with 55 additions and 44 deletions

View File

@ -220,6 +220,14 @@ Special characters:
"x--x" Variation of the above, it means that -x option should occur "x--x" Variation of the above, it means that -x option should occur
at most once. 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:", &param);
"a::" A double colon after a char in opt_complementary means that the "a::" A double colon after a char in opt_complementary means that the
option can occur multiple times. Each occurrence will be saved as option can occur multiple times. Each occurrence will be saved as
a llist_t element instead of char*. a llist_t element instead of char*.
@ -275,14 +283,20 @@ Special characters:
const char *opt_complementary; const char *opt_complementary;
enum {
PARAM_STRING,
PARAM_LIST,
PARAM_INT,
};
typedef struct { typedef struct {
int opt; unsigned char opt_char;
int list_flg; smallint param_type;
unsigned switch_on; unsigned switch_on;
unsigned switch_off; unsigned switch_off;
unsigned incongruously; unsigned incongruously;
unsigned requires; unsigned requires;
void **optarg; /* char **optarg or llist_t **optarg */ void **optarg; /* char**, llist_t** or int *. */
int *counter; int *counter;
} t_complementary; } t_complementary;
@ -337,12 +351,14 @@ getopt32(char **argv, const char *applet_opts, ...)
if (*s == '+' || *s == '-') if (*s == '+' || *s == '-')
s++; s++;
while (*s) { while (*s) {
if (c >= 32) break; if (c >= 32)
on_off->opt = *s; break;
on_off->opt_char = *s;
on_off->switch_on = (1 << c); on_off->switch_on = (1 << c);
if (*++s == ':') { if (*++s == ':') {
on_off->optarg = va_arg(p, void **); on_off->optarg = va_arg(p, void **);
while (*++s == ':') /* skip */; while (*++s == ':')
continue;
} }
on_off++; on_off++;
c++; c++;
@ -375,11 +391,12 @@ getopt32(char **argv, const char *applet_opts, ...)
for (l_o = long_options; l_o->name; l_o++) { for (l_o = long_options; l_o->name; l_o++) {
if (l_o->flag) if (l_o->flag)
continue; continue;
for (on_off = complementary; on_off->opt != 0; on_off++) for (on_off = complementary; on_off->opt_char; on_off++)
if (on_off->opt == l_o->val) if (on_off->opt_char == l_o->val)
goto next_long; goto next_long;
if (c >= 32) break; if (c >= 32)
on_off->opt = l_o->val; break;
on_off->opt_char = l_o->val;
on_off->switch_on = (1 << c); on_off->switch_on = (1 << c);
if (l_o->has_arg != no_argument) if (l_o->has_arg != no_argument)
on_off->optarg = va_arg(p, void **); on_off->optarg = va_arg(p, void **);
@ -422,11 +439,15 @@ getopt32(char **argv, const char *applet_opts, ...)
s++; s++;
continue; continue;
} }
for (on_off = complementary; on_off->opt; on_off++) for (on_off = complementary; on_off->opt_char; on_off++)
if (on_off->opt == *s) if (on_off->opt_char == *s)
break; break;
if (c == ':' && s[2] == ':') { 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; continue;
} }
if (c == ':' || c == '\0') { if (c == ':' || c == '\0') {
@ -454,8 +475,8 @@ getopt32(char **argv, const char *applet_opts, ...)
else else
pair_switch = &(pair->switch_off); pair_switch = &(pair->switch_off);
} else { } else {
for (on_off = complementary; on_off->opt; on_off++) for (on_off = complementary; on_off->opt_char; on_off++)
if (on_off->opt == *s) { if (on_off->opt_char == *s) {
*pair_switch |= on_off->switch_on; *pair_switch |= on_off->switch_on;
break; break;
} }
@ -508,9 +529,9 @@ getopt32(char **argv, const char *applet_opts, ...)
#endif #endif
c &= 0xff; /* fight libc's sign extension */ c &= 0xff; /* fight libc's sign extension */
loop_arg_is_opt: 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 */ /* 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(); bb_show_usage();
} }
if (flags & on_off->incongruously) if (flags & on_off->incongruously)
@ -521,8 +542,10 @@ getopt32(char **argv, const char *applet_opts, ...)
flags ^= trigger; flags ^= trigger;
if (on_off->counter) if (on_off->counter)
(*(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); 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) { } else if (on_off->optarg) {
*(char **)(on_off->optarg) = optarg; *(char **)(on_off->optarg) = optarg;
} }
@ -550,7 +573,7 @@ getopt32(char **argv, const char *applet_opts, ...)
free(argv[1]); free(argv[1]);
#endif #endif
/* check depending requires for given options */ /* 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) && if (on_off->requires && (flags & on_off->switch_on) &&
(flags & on_off->requires) == 0) (flags & on_off->requires) == 0)
bb_show_usage(); bb_show_usage();

View File

@ -740,7 +740,7 @@ int top_main(int argc, char **argv)
int count, lines, col; int count, lines, col;
unsigned interval; unsigned interval;
int iterations; int iterations;
char *sinterval, *siterations; char *sinterval;
SKIP_FEATURE_TOPMEM(const) unsigned scan_mask = TOP_MASK; SKIP_FEATURE_TOPMEM(const) unsigned scan_mask = TOP_MASK;
#if ENABLE_FEATURE_USE_TERMIOS #if ENABLE_FEATURE_USE_TERMIOS
struct termios new_settings; struct termios new_settings;
@ -757,15 +757,12 @@ int top_main(int argc, char **argv)
iterations = 0; /* infinite */ iterations = 0; /* infinite */
/* do normal option parsing */ /* do normal option parsing */
opt_complementary = "-"; opt_complementary = "-:n+";
getopt32(argv, "d:n:b", &sinterval, &siterations); getopt32(argv, "d:n:b", &sinterval, &iterations);
if (option_mask32 & 0x1) { if (option_mask32 & 0x1) {
/* Need to limit it to not overflow poll timeout */ /* Need to limit it to not overflow poll timeout */
interval = xatou16(sinterval); // -d interval = xatou16(sinterval); // -d
} }
if (option_mask32 & 0x2)
iterations = xatoi_u(siterations); // -n
//if (option_mask32 & 0x4) // -b
/* change to /proc */ /* change to /proc */
xchdir("/proc"); xchdir("/proc");

View File

@ -2754,7 +2754,6 @@ unknown_command(int c)
int fdisk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int fdisk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int fdisk_main(int argc, char **argv) int fdisk_main(int argc, char **argv)
{ {
char *str_b, *str_C, *str_H, *str_S;
unsigned opt; unsigned opt;
/* /*
* fdisk -v * fdisk -v
@ -2776,8 +2775,9 @@ int fdisk_main(int argc, char **argv)
INIT_G(); INIT_G();
opt_complementary = "b+:C+:H+:S+"; /* numeric params */
opt = getopt32(argv, "b:C:H:lS:u" USE_FEATURE_FDISK_BLKSIZE("s"), opt = getopt32(argv, "b:C:H:lS:u" USE_FEATURE_FDISK_BLKSIZE("s"),
&str_b, &str_C, &str_H, &str_S); &sector_size, &user_cylinders, &user_heads, &user_sectors);
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (opt & OPT_b) { // -b if (opt & OPT_b) { // -b
@ -2785,27 +2785,18 @@ int fdisk_main(int argc, char **argv)
so cannot be combined with multiple disks, so cannot be combined with multiple disks,
and the same goes for the C/H/S options. and the same goes for the C/H/S options.
*/ */
sector_size = xatoi_u(str_b); if (sector_size != 512 && sector_size != 1024
if (sector_size != 512 && sector_size != 1024 && && sector_size != 2048)
sector_size != 2048)
bb_show_usage(); bb_show_usage();
sector_offset = 2; sector_offset = 2;
user_set_sector_size = 1; user_set_sector_size = 1;
} }
if (opt & OPT_C) user_cylinders = xatoi_u(str_C); // -C if (user_heads <= 0 || user_heads >= 256)
if (opt & OPT_H) { // -H user_heads = 0;
user_heads = xatoi_u(str_H); if (user_sectors <= 0 || user_sectors >= 64)
if (user_heads <= 0 || user_heads >= 256) user_sectors = 0;
user_heads = 0; if (opt & OPT_u)
} display_in_cyl_units = 0; // -u
//if (opt & OPT_l) // -l
if (opt & OPT_S) { // -S
user_sectors = xatoi_u(str_S);
if (user_sectors <= 0 || user_sectors >= 64)
user_sectors = 0;
}
if (opt & OPT_u) display_in_cyl_units = 0; // -u
//if (opt & OPT_s) // -s
if (user_set_sector_size && argc != 1) if (user_set_sector_size && argc != 1)
printf("Warning: the -b (set sector size) option should" printf("Warning: the -b (set sector size) option should"