From bdc88fdc6844ee6890e31ba4cf56800becc8c682 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Mon, 23 Jul 2007 17:14:14 +0000 Subject: rework long option handling. saves ~1.2k function old new delta tar_longopts - 222 +222 static.udhcpc_longopts - 192 +192 start_stop_daemon_longopts - 150 +150 getopt32 1045 1185 +140 static.wget_longopts - 111 +111 static.od_longopts - 105 +105 getopt_longopts - 96 +96 install_longopts - 67 +67 ipcalc_longopts - 63 +63 static.hwclock_longopts - 54 +54 ftpgetput_longopts - 52 +52 static.dumpleases_longopts - 32 +32 env_longopts - 31 +31 runparts_longopts - 30 +30 mv_longopts - 24 +24 mkdir_longopts - 19 +19 find_pair 164 180 +16 bb_null_long_options - 16 +16 setconsole_longopts - 10 +10 display_speed 91 98 +7 collect_blk 467 474 +7 show_color 4 1 -3 ls_main 913 904 -9 bb_default_long_options 16 - -16 ls_color_opt 32 10 -22 setconsole_long_options 32 - -32 arith 2077 2030 -47 mv_long_options 48 - -48 mkdir_long_options 48 - -48 env_long_options 48 - -48 static.options 248 184 -64 runparts_long_options 80 - -80 ftpgetput_long_options 96 - -96 static.hwclock_long_options 112 - -112 install_long_options 112 - -112 static.long_options 144 - -144 static.wget_long_options 160 - -160 longopts 160 - -160 static.arg_options 304 - -304 tar_long_options 320 - -320 long_options 384 - -384 ------------------------------------------------------------------------------ (add/remove: 17/15 grow/shrink: 4/5 up/down: 1444/-2209) Total: -765 bytes text data bss dec hex filename 782618 1328 11900 795846 c24c6 busybox_old 781354 1328 11900 794582 c1fd6 busybox_unstripped --- libbb/getopt32.c | 78 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 28 deletions(-) (limited to 'libbb') diff --git a/libbb/getopt32.c b/libbb/getopt32.c index f5aaa70df..e5d97e98c 100644 --- a/libbb/getopt32.c +++ b/libbb/getopt32.c @@ -72,24 +72,21 @@ getopt32(int argc, char **argv, const char *applet_opts, ...) env -i ls -d / Here we want env to process just the '-i', not the '-d'. -const struct option *applet_long_options +const char *applet_long_options - This struct allows you to define long options. The syntax for - declaring the array is just like that of getopt's longopts. - (see getopt(3)) + This struct allows you to define long options: - static const struct option applet_long_options[] = { - //name,has_arg,flag,val - { "verbose", 0, 0, 'v' }, - { 0, 0, 0, 0 } - }; - applet_long_options = applet_long_options; + static const char applet_longopts[] = + //"name\0" has_arg val + "verbose\0" No_argument "v" + "\0"; + applet_long_options = applet_longopts; The last member of struct option (val) typically is set to matching short option from applet_opts. If there is no matching char in applet_opts, then: - return bit have next position after short options - - if has_arg is not "no_argument", use ptr for arg also + - if has_arg is not "No_argument", use ptr for arg also - opt_complementary affects it too Note: a good applet will make long options configurable via the @@ -290,12 +287,10 @@ typedef struct { /* You can set applet_long_options for parse called long options */ #if ENABLE_GETOPT_LONG -static const struct option bb_default_long_options[] = { -/* { "help", 0, NULL, '?' }, */ +static const struct option bb_null_long_options[1] = { { 0, 0, 0, 0 } }; - -const struct option *applet_long_options = bb_default_long_options; +const char *applet_long_options; #endif uint32_t option_mask32; @@ -312,6 +307,7 @@ getopt32(int argc, char **argv, const char *applet_opts, ...) va_list p; #if ENABLE_GETOPT_LONG const struct option *l_o; + struct option *long_options = NULL; #endif unsigned trigger; char **pargv = NULL; @@ -347,19 +343,42 @@ getopt32(int argc, char **argv, const char *applet_opts, ...) } #if ENABLE_GETOPT_LONG - for (l_o = applet_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) - goto next_long; - if (c >= 32) break; - on_off->opt = l_o->val; - on_off->switch_on = (1 << c); - if (l_o->has_arg != no_argument) - on_off->optarg = va_arg(p, void **); - c++; + if (applet_long_options) { + const char *optstr; + unsigned i, count; + + count = 1; + optstr = applet_long_options; + while (optstr[0]) { + optstr += strlen(optstr) + 3; /* skip \0, has_arg, val */ + count++; + } + /* count == no. of longopts + 1 */ + long_options = xzalloc(count * sizeof(*long_options)); + i = 0; + optstr = applet_long_options; + while (--count) { + long_options[i].name = optstr; + optstr += strlen(optstr) + 1; + long_options[i].has_arg = (unsigned char)(*optstr++); + /* long_options[i].flag = NULL; */ + long_options[i].val = (unsigned char)(*optstr++); + i++; + } + 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) + goto next_long; + if (c >= 32) break; + on_off->opt = l_o->val; + on_off->switch_on = (1 << c); + if (l_o->has_arg != no_argument) + on_off->optarg = va_arg(p, void **); + c++; next_long: ; + } } #endif /* ENABLE_GETOPT_LONG */ for (s = (const unsigned char *)opt_complementary; s && *s; s++) { @@ -457,7 +476,7 @@ getopt32(int argc, char **argv, const char *applet_opts, ...) * (supposed to act as --header, but doesn't) */ #if ENABLE_GETOPT_LONG while ((c = getopt_long(argc, argv, applet_opts, - applet_long_options, NULL)) != -1) { + long_options ? long_options : bb_null_long_options, NULL)) != -1) { #else while ((c = getopt(argc, argv, applet_opts)) != -1) { #endif @@ -516,6 +535,9 @@ getopt32(int argc, char **argv, const char *applet_opts, ...) if (argc < min_arg || (max_arg >= 0 && argc > max_arg)) bb_show_usage(); +#if ENABLE_GETOPT_LONG + free(long_options); +#endif option_mask32 = flags; return flags; } -- cgit v1.2.3