aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2016-07-06 21:58:02 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2016-07-06 21:58:02 +0200
commit237bedd499c58034a1355484d6d4d906f0180308 (patch)
tree42a789f8867ba3bc6ef0cea30fb18f5553d447a0 /libbb
parent0844b5afe2cd60d46b7f2ad0fac8c2818d0780b3 (diff)
downloadbusybox-w32-237bedd499c58034a1355484d6d4d906f0180308.tar.gz
busybox-w32-237bedd499c58034a1355484d6d4d906f0180308.tar.bz2
busybox-w32-237bedd499c58034a1355484d6d4d906f0180308.zip
getopt32: add new syntax of 'o:+' and 'o:*' for -o NUM and -o LIST
In many cases, this aqllows to drop use of opt_complementary. Approximately -400 bytes: function old new delta getopt32 1423 1502 +79 opt_string 17 18 +1 OPT_STR 24 25 +1 uniq_main 416 406 -10 timeout_main 279 269 -10 sulogin_main 270 260 -10 readprofile_main 1825 1815 -10 ps_main 543 533 -10 pidof_main 245 235 -10 pgrep_main 611 601 -10 od_main 2600 2590 -10 mkfs_minix_main 2684 2674 -10 mkfs_ext2_main 2603 2593 -10 microcom_main 712 702 -10 makemime_main 315 305 -10 ionice_main 282 272 -10 inetd_main 2074 2064 -10 ifplugd_main 1144 1134 -10 halt_main 353 343 -10 getopt_main 636 626 -10 fdisk_main 2854 2844 -10 env_main 206 196 -10 dmesg_main 319 309 -10 conspy_main 1214 1204 -10 awk_main 981 971 -10 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/22 up/down: 81/-220) Total: -139 bytes text data bss dec hex filename 919373 906 14060 934339 e41c3 busybox_old 918969 906 14060 933935 e402f busybox_unstripped Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'libbb')
-rw-r--r--libbb/getopt32.c82
-rw-r--r--libbb/parse_config.c4
2 files changed, 61 insertions, 25 deletions
diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index d0e83d88e..15b6efc09 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -17,23 +17,20 @@
17uint32_t 17uint32_t
18getopt32(char **argv, const char *applet_opts, ...) 18getopt32(char **argv, const char *applet_opts, ...)
19 19
20 The command line options must be declared in const char 20 The command line options are passed as the applet_opts string.
21 *applet_opts as a string of chars, for example:
22
23 flags = getopt32(argv, "rnug");
24 21
25 If one of the given options is found, a flag value is added to 22 If one of the given options is found, a flag value is added to
26 the return value (an unsigned long). 23 the return value.
27 24
28 The flag value is determined by the position of the char in 25 The flag value is determined by the position of the char in
29 applet_opts string. For example, in the above case: 26 applet_opts string. For example:
30 27
31 flags = getopt32(argv, "rnug"); 28 flags = getopt32(argv, "rnug");
32 29
33 "r" will add 1 (bit 0) 30 "r" will set 1 (bit 0)
34 "n" will add 2 (bit 1) 31 "n" will set 2 (bit 1)
35 "u" will add 4 (bit 2) 32 "u" will set 4 (bit 2)
36 "g" will add 8 (bit 3) 33 "g" will set 8 (bit 3)
37 34
38 and so on. You can also look at the return value as a bit 35 and so on. You can also look at the return value as a bit
39 field and each option sets one bit. 36 field and each option sets one bit.
@@ -45,7 +42,7 @@ getopt32(char **argv, const char *applet_opts, ...)
45 (options and their parameters will be moved into argv[] 42 (options and their parameters will be moved into argv[]
46 positions prior to argv[optind]). 43 positions prior to argv[optind]).
47 44
48 ":" If one of the options requires an argument, then add a ":" 45 "o:" If one of the options requires an argument, then add a ":"
49 after the char in applet_opts and provide a pointer to store 46 after the char in applet_opts and provide a pointer to store
50 the argument. For example: 47 the argument. For example:
51 48
@@ -58,15 +55,39 @@ getopt32(char **argv, const char *applet_opts, ...)
58 &pointer_to_arg_for_a, &pointer_to_arg_for_b, 55 &pointer_to_arg_for_a, &pointer_to_arg_for_b,
59 &pointer_to_arg_for_c, &pointer_to_arg_for_d); 56 &pointer_to_arg_for_c, &pointer_to_arg_for_d);
60 57
61 The type of the pointer (char* or llist_t*) may be controlled 58 The type of the pointer may be controlled by "o::" or "o+" in
62 by the "::" special separator that is set in the external string 59 the external string opt_complementary (see below for more info).
63 opt_complementary (see below for more info).
64 60
65 "::" If option can have an *optional* argument, then add a "::" 61 "o::" If option can have an *optional* argument, then add a "::"
66 after its char in applet_opts and provide a pointer to store 62 after its char in applet_opts and provide a pointer to store
67 the argument. Note that optional arguments _must_ 63 the argument. Note that optional arguments _must_
68 immediately follow the option: -oparam, not -o param. 64 immediately follow the option: -oparam, not -o param.
69 65
66 "o:+" This means that the parameter for this option is a nonnegative integer.
67 It will be processed with xatoi_positive() - allowed range
68 is 0..INT_MAX.
69
70 int param; // "unsigned param;" will also work
71 getopt32(argv, "p:+", &param);
72
73 "o:*" This means that the option can occur multiple times. Each occurrence
74 will be saved as a llist_t element instead of char*.
75
76 For example:
77 The grep applet can have one or more "-e pattern" arguments.
78 In this case you should use getopt32() as follows:
79
80 llist_t *patterns = NULL;
81
82 (this pointer must be initializated to NULL if the list is empty
83 as required by llist_add_to_end(llist_t **old_head, char *new_item).)
84
85 getopt32(argv, "e:*", &patterns);
86
87 $ grep -e user -e root /etc/passwd
88 root:x:0:0:root:/root:/bin/bash
89 user:x:500:500::/home/user:/bin/bash
90
70 "+" If the first character in the applet_opts string is a plus, 91 "+" If the first character in the applet_opts string is a plus,
71 then option processing will stop as soon as a non-option is 92 then option processing will stop as soon as a non-option is
72 encountered in the argv array. Useful for applets like env 93 encountered in the argv array. Useful for applets like env
@@ -82,7 +103,7 @@ const char *applet_long_options
82 This struct allows you to define long options: 103 This struct allows you to define long options:
83 104
84 static const char applet_longopts[] ALIGN1 = 105 static const char applet_longopts[] ALIGN1 =
85 //"name\0" has_arg val 106 //"name\0" has_arg val
86 "verbose\0" No_argument "v" 107 "verbose\0" No_argument "v"
87 ; 108 ;
88 applet_long_options = applet_longopts; 109 applet_long_options = applet_longopts;
@@ -90,7 +111,7 @@ const char *applet_long_options
90 The last member of struct option (val) typically is set to 111 The last member of struct option (val) typically is set to
91 matching short option from applet_opts. If there is no matching 112 matching short option from applet_opts. If there is no matching
92 char in applet_opts, then: 113 char in applet_opts, then:
93 - return bit have next position after short options 114 - return bit has next position after short options
94 - if has_arg is not "No_argument", use ptr for arg also 115 - if has_arg is not "No_argument", use ptr for arg also
95 - opt_complementary affects it too 116 - opt_complementary affects it too
96 117
@@ -139,8 +160,8 @@ const char *opt_complementary
139 160
140 llist_t *my_b = NULL; 161 llist_t *my_b = NULL;
141 int verbose_level = 0; 162 int verbose_level = 0;
142 opt_complementary = "vv:b::b-c:c-b"; 163 opt_complementary = "vv:b-c:c-b";
143 f = getopt32(argv, "vb:c", &my_b, &verbose_level); 164 f = getopt32(argv, "vb:*c", &my_b, &verbose_level);
144 if (f & 2) // -c after -b unsets -b flag 165 if (f & 2) // -c after -b unsets -b flag
145 while (my_b) dosomething_with(llist_pop(&my_b)); 166 while (my_b) dosomething_with(llist_pop(&my_b));
146 if (my_b) // but llist is stored if -b is specified 167 if (my_b) // but llist is stored if -b is specified
@@ -233,7 +254,7 @@ Special characters:
233 "x--x" Variation of the above, it means that -x option should occur 254 "x--x" Variation of the above, it means that -x option should occur
234 at most once. 255 at most once.
235 256
236 "a+" A plus after a char in opt_complementary means that the parameter 257 "o+" A plus after a char in opt_complementary means that the parameter
237 for this option is a nonnegative integer. It will be processed 258 for this option is a nonnegative integer. It will be processed
238 with xatoi_positive() - allowed range is 0..INT_MAX. 259 with xatoi_positive() - allowed range is 0..INT_MAX.
239 260
@@ -241,7 +262,7 @@ Special characters:
241 opt_complementary = "p+"; 262 opt_complementary = "p+";
242 getopt32(argv, "p:", &param); 263 getopt32(argv, "p:", &param);
243 264
244 "a::" A double colon after a char in opt_complementary means that the 265 "o::" A double colon after a char in opt_complementary means that the
245 option can occur multiple times. Each occurrence will be saved as 266 option can occur multiple times. Each occurrence will be saved as
246 a llist_t element instead of char*. 267 a llist_t element instead of char*.
247 268
@@ -255,12 +276,17 @@ Special characters:
255 as required by llist_add_to_end(llist_t **old_head, char *new_item).) 276 as required by llist_add_to_end(llist_t **old_head, char *new_item).)
256 277
257 opt_complementary = "e::"; 278 opt_complementary = "e::";
258
259 getopt32(argv, "e:", &patterns); 279 getopt32(argv, "e:", &patterns);
280
260 $ grep -e user -e root /etc/passwd 281 $ grep -e user -e root /etc/passwd
261 root:x:0:0:root:/root:/bin/bash 282 root:x:0:0:root:/root:/bin/bash
262 user:x:500:500::/home/user:/bin/bash 283 user:x:500:500::/home/user:/bin/bash
263 284
285 "o+" and "o::" can be handled by "o:+" and "o:*" specifiers
286 in option string (and it is preferred), but this does not work
287 for "long options only" cases, such as tar --exclude=PATTERN,
288 wget --header=HDR cases.
289
264 "a?b" A "?" between an option and a group of options means that 290 "a?b" A "?" between an option and a group of options means that
265 at least one of them is required to occur if the first option 291 at least one of them is required to occur if the first option
266 occurs in preceding command line arguments. 292 occurs in preceding command line arguments.
@@ -359,10 +385,11 @@ getopt32(char **argv, const char *applet_opts, ...)
359 385
360 va_start(p, applet_opts); 386 va_start(p, applet_opts);
361 387
362 c = 0;
363 on_off = complementary; 388 on_off = complementary;
364 memset(on_off, 0, sizeof(complementary)); 389 memset(on_off, 0, sizeof(complementary));
365 390
391 applet_opts = strcpy(alloca(strlen(applet_opts) + 1), applet_opts);
392
366 /* skip bbox extension */ 393 /* skip bbox extension */
367 first_char = applet_opts[0]; 394 first_char = applet_opts[0];
368 if (first_char == '!') 395 if (first_char == '!')
@@ -372,6 +399,7 @@ getopt32(char **argv, const char *applet_opts, ...)
372 s = (const unsigned char *)applet_opts; 399 s = (const unsigned char *)applet_opts;
373 if (*s == '+' || *s == '-') 400 if (*s == '+' || *s == '-')
374 s++; 401 s++;
402 c = 0;
375 while (*s) { 403 while (*s) {
376 if (c >= 32) 404 if (c >= 32)
377 break; 405 break;
@@ -379,6 +407,13 @@ getopt32(char **argv, const char *applet_opts, ...)
379 on_off->switch_on = (1 << c); 407 on_off->switch_on = (1 << c);
380 if (*++s == ':') { 408 if (*++s == ':') {
381 on_off->optarg = va_arg(p, void **); 409 on_off->optarg = va_arg(p, void **);
410 if (s[1] == '+' || s[1] == '*') {
411 /* 'o:+' or 'o:*' */
412 on_off->param_type = (s[1] == '+') ?
413 PARAM_INT : PARAM_LIST;
414 overlapping_strcpy((char*)s + 1, (char*)s + 2);
415 }
416 /* skip possible 'o::' (or 'o:+:' !) */
382 while (*++s == ':') 417 while (*++s == ':')
383 continue; 418 continue;
384 } 419 }
@@ -431,6 +466,7 @@ getopt32(char **argv, const char *applet_opts, ...)
431 applet_long_options = NULL; 466 applet_long_options = NULL;
432 } 467 }
433#endif /* ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG */ 468#endif /* ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG */
469
434 for (s = (const unsigned char *)opt_complementary; s && *s; s++) { 470 for (s = (const unsigned char *)opt_complementary; s && *s; s++) {
435 t_complementary *pair; 471 t_complementary *pair;
436 unsigned *pair_switch; 472 unsigned *pair_switch;
diff --git a/libbb/parse_config.c b/libbb/parse_config.c
index 1590d9a4c..408439766 100644
--- a/libbb/parse_config.c
+++ b/libbb/parse_config.c
@@ -42,8 +42,8 @@ int parse_main(int argc UNUSED_PARAM, char **argv)
42 int mintokens = 0, ntokens = 128; 42 int mintokens = 0, ntokens = 128;
43 unsigned noout; 43 unsigned noout;
44 44
45 opt_complementary = "-1:n+:m+:f+"; 45 opt_complementary = "-1";
46 noout = 1 & getopt32(argv, "xn:m:d:f:", &ntokens, &mintokens, &delims, &flags); 46 noout = 1 & getopt32(argv, "xn:+m:+d:f:+", &ntokens, &mintokens, &delims, &flags);
47 //argc -= optind; 47 //argc -= optind;
48 argv += optind; 48 argv += optind;
49 49