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


diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index f5aaa70..e5d97e9 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -72,24 +72,21 @@
         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 @@
 
 /* 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 @@
 	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 @@
 	}
 
 #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 @@
 	 * (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 @@
 	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;
 }