Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/libbb/getopt32.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 532 by niro, Sat Sep 1 22:45:15 2007 UTC revision 816 by niro, Fri Apr 24 18:33:46 2009 UTC
# Line 7  Line 7 
7   * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.   * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
8   */   */
9    
 #include "libbb.h"  
10  #include <getopt.h>  #include <getopt.h>
11    #include "libbb.h"
12    
13  /*      Documentation  /*      Documentation
14    
15  uint32_t  uint32_t
16  getopt32(int argc, char **argv, const char *applet_opts, ...)  getopt32(char **argv, const char *applet_opts, ...)
17    
18          The command line options must be declared in const char          The command line options must be declared in const char
19          *applet_opts as a string of chars, for example:          *applet_opts as a string of chars, for example:
20    
21          flags = getopt32(argc, argv, "rnug");          flags = getopt32(argv, "rnug");
22    
23          If one of the given options is found, a flag value is added to          If one of the given options is found, a flag value is added to
24          the return value (an unsigned long).          the return value (an unsigned long).
# Line 26  getopt32(int argc, char **argv, const ch Line 26  getopt32(int argc, char **argv, const ch
26          The flag value is determined by the position of the char in          The flag value is determined by the position of the char in
27          applet_opts string.  For example, in the above case:          applet_opts string.  For example, in the above case:
28    
29          flags = getopt32(argc, argv, "rnug");          flags = getopt32(argv, "rnug");
30    
31          "r" will add 1    (bit 0)          "r" will add 1    (bit 0)
32          "n" will add 2    (bit 1)          "n" will add 2    (bit 1)
33          "u  will add 4    (bit 2)          "u" will add 4    (bit 2)
34          "g" will add 8    (bit 3)          "g" will add 8    (bit 3)
35    
36          and so on.  You can also look at the return value as a bit          and so on.  You can also look at the return value as a bit
# Line 52  getopt32(int argc, char **argv, const ch Line 52  getopt32(int argc, char **argv, const ch
52          char *pointer_to_arg_for_c;          char *pointer_to_arg_for_c;
53          char *pointer_to_arg_for_d;          char *pointer_to_arg_for_d;
54    
55          flags = getopt32(argc, argv, "a:b:c:d:",          flags = getopt32(argv, "a:b:c:d:",
56           &pointer_to_arg_for_a, &pointer_to_arg_for_b,                          &pointer_to_arg_for_a, &pointer_to_arg_for_b,
57           &pointer_to_arg_for_c, &pointer_to_arg_for_d);                          &pointer_to_arg_for_c, &pointer_to_arg_for_d);
58    
59          The type of the pointer (char* or llist_t*) may be controlled          The type of the pointer (char* or llist_t*) may be controlled
60          by the "::" special separator that is set in the external string          by the "::" special separator that is set in the external string
# Line 72  getopt32(int argc, char **argv, const ch Line 72  getopt32(int argc, char **argv, const ch
72          env -i ls -d /          env -i ls -d /
73          Here we want env to process just the '-i', not the '-d'.          Here we want env to process just the '-i', not the '-d'.
74    
75  const struct option *applet_long_options  const char *applet_long_options
76    
77            This struct allows you to define long options:
78    
79          This struct allows you to define long options.  The syntax for          static const char applet_longopts[] ALIGN1 =
80          declaring the array is just like that of getopt's longopts.   //"name\0" has_arg val
81          (see getopt(3))   "verbose\0" No_argument "v"
82     ;
83          static const struct option applet_long_options[] = {          applet_long_options = applet_longopts;
          //name,has_arg,flag,val  
          { "verbose", 0, 0, 'v' },  
          { 0, 0, 0, 0 }  
         };  
         applet_long_options = applet_long_options;  
84    
85          The last member of struct option (val) typically is set to          The last member of struct option (val) typically is set to
86          matching short option from applet_opts. If there is no matching          matching short option from applet_opts. If there is no matching
87          char in applet_opts, then:          char in applet_opts, then:
88          - return bit have next position after short options          - return bit have next position after short options
89          - if has_arg is not "no_argument", use ptr for arg also          - if has_arg is not "No_argument", use ptr for arg also
90          - opt_complementary affects it too          - opt_complementary affects it too
91    
92          Note: a good applet will make long options configurable via the          Note: a good applet will make long options configurable via the
# Line 108  const char *opt_complementary Line 105  const char *opt_complementary
105          if they are not specifed on the command line.  For example:          if they are not specifed on the command line.  For example:
106    
107          opt_complementary = "abc";          opt_complementary = "abc";
108          flags = getopt32(argc, argv, "abcd")          flags = getopt32(argv, "abcd")
109    
110          If getopt() finds "-a" on the command line, then          If getopt() finds "-a" on the command line, then
111          getopt32's return value will be as if "-a -b -c" were          getopt32's return value will be as if "-a -b -c" were
# Line 120  const char *opt_complementary Line 117  const char *opt_complementary
117          if w is given once, GNU ps sets the width to 132,          if w is given once, GNU ps sets the width to 132,
118          if w is given more than once, it is "unlimited"          if w is given more than once, it is "unlimited"
119    
120          int w_counter = 0;          int w_counter = 0; // must be initialized!
121          opt_complementary = "ww";          opt_complementary = "ww";
122          getopt32(argc, argv, "w", &w_counter);          getopt32(argv, "w", &w_counter);
123          if (w_counter)          if (w_counter)
124           width = (w_counter == 1) ? 132 : INT_MAX;                  width = (w_counter == 1) ? 132 : INT_MAX;
125          else          else
126           get_terminal_width(...&width...);                  get_terminal_width(...&width...);
127    
128          w_counter is a pointer to an integer. It has to be passed to          w_counter is a pointer to an integer. It has to be passed to
129          getopt32() after all other option argument sinks.          getopt32() after all other option argument sinks.
# Line 138  const char *opt_complementary Line 135  const char *opt_complementary
135          llist_t *my_b = NULL;          llist_t *my_b = NULL;
136          int verbose_level = 0;          int verbose_level = 0;
137          opt_complementary = "vv:b::b-c:c-b";          opt_complementary = "vv:b::b-c:c-b";
138          f = getopt32(argc, argv, "vb:c", &my_b, &verbose_level);          f = getopt32(argv, "vb:c", &my_b, &verbose_level);
139          if (f & 2)       // -c after -b unsets -b flag          if (f & 2)       // -c after -b unsets -b flag
140           while (my_b) { dosomething_with(my_b->data); my_b = my_b->link; }                  while (my_b) dosomething_with(llist_pop(&my_b));
141          if (my_b)        // but llist is stored if -b is specified          if (my_b)        // but llist is stored if -b is specified
142           free_llist(my_b);                  free_llist(my_b);
143          if (verbose_level) printf("verbose level is %d\n", verbose_level);          if (verbose_level) printf("verbose level is %d\n", verbose_level);
144    
145  Special characters:  Special characters:
# Line 153  Special characters: Line 150  Special characters:
150          use ':' or end of line. For example:          use ':' or end of line. For example:
151    
152          opt_complementary = "-:w-x:x-w";          opt_complementary = "-:w-x:x-w";
153          getopt32(argc, argv, "wx");          getopt32(argv, "wx");
154    
155          Allows any arguments to be given without a dash (./program w x)          Allows any arguments to be given without a dash (./program w x)
156          as well as with a dash (./program -x).          as well as with a dash (./program -x).
157    
158     NB: getopt32() will leak a small amount of memory if you use
159     this option! Do not use it if there is a possibility of recursive
160     getopt32() calls.
161    
162   "--"   A double dash at the beginning of opt_complementary means the   "--"   A double dash at the beginning of opt_complementary means the
163          argv[1] string should always be treated as options, even if it isn't          argv[1] string should always be treated as options, even if it isn't
164          prefixed with a "-".  This is useful for special syntax in applets          prefixed with a "-".  This is useful for special syntax in applets
165          such as "ar" and "tar":          such as "ar" and "tar":
166          tar xvf foo.tar          tar xvf foo.tar
167    
168     NB: getopt32() will leak a small amount of memory if you use
169     this option! Do not use it if there is a possibility of recursive
170     getopt32() calls.
171    
172   "-N"   A dash as the first char in a opt_complementary group followed   "-N"   A dash as the first char in a opt_complementary group followed
173          by a single digit (0-9) means that at least N non-option          by a single digit (0-9) means that at least N non-option
174          arguments must be present on the command line          arguments must be present on the command line
# Line 177  Special characters: Line 182  Special characters:
182          on the command line.          on the command line.
183    
184   "V-"   An option with dash before colon or end-of-line results in   "V-"   An option with dash before colon or end-of-line results in
185          bb_show_usage being called if this option is encountered.          bb_show_usage() being called if this option is encountered.
186          This is typically used to implement "print verbose usage message          This is typically used to implement "print verbose usage message
187          and exit" option.          and exit" option.
188    
189   "-"    A dash between two options causes the second of the two   "a-b"  A dash between two options causes the second of the two
190          to be unset (and ignored) if it is given on the command line.          to be unset (and ignored) if it is given on the command line.
191    
192          [FIXME: what if they are the same? like "x-x"? Is it ever useful?]          [FIXME: what if they are the same? like "x-x"? Is it ever useful?]
# Line 200  Special characters: Line 205  Special characters:
205          char *smax_print_depth;          char *smax_print_depth;
206    
207          opt_complementary = "s-d:d-s:x-x";          opt_complementary = "s-d:d-s:x-x";
208          opt = getopt32(argc, argv, "sd:x", &smax_print_depth);          opt = getopt32(argv, "sd:x", &smax_print_depth);
209    
210          if (opt & 2)          if (opt & 2)
211           max_print_depth = atoi(smax_print_depth);                  max_print_depth = atoi(smax_print_depth);
212          if (opt & 4)          if (opt & 4)
213           printf("Detected odd -x usage\n");                  printf("Detected odd -x usage\n");
214    
215   "--"   A double dash between two options, or between an option and a group   "a--b" A double dash between two options, or between an option and a group
216          of options, means that they are mutually exclusive.  Unlike          of options, means that they are mutually exclusive.  Unlike
217          the "-" case above, an error will be forced if the options          the "-" case above, an error will be forced if the options
218          are used together.          are used together.
219    
220          For example:          For example:
221          The cut applet must have only one type of list specified, so          The cut applet must have only one type of list specified, so
222          -b, -c and -f are mutally exclusive and should raise an error          -b, -c and -f are mutually exclusive and should raise an error
223          if specified together.  In this case you must set          if specified together.  In this case you must set
224          opt_complementary = "b--cf:c--bf:f--bc".  If two of the          opt_complementary = "b--cf:c--bf:f--bc".  If two of the
225          mutually exclusive options are found, getopt32's          mutually exclusive options are found, getopt32 will call
226          return value will have the error flag set (BB_GETOPT_ERROR) so   bb_show_usage() and die.
         that we can check for it:  
   
         if (flags & BB_GETOPT_ERROR)  
          bb_show_usage();  
227    
228   "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
229          at most once.          at most once.
230    
231   "?"    A "?" as the first char in a opt_complementary group means:   "a+"   A plus after a char in opt_complementary means that the parameter
232          if BB_GETOPT_ERROR is detected, don't return, call bb_show_usage          for this option is a nonnegative integer. It will be processed
233          and exit instead. Next char after '?' can't be a digit.          with xatoi_u() - allowed range is 0..INT_MAX.
234    
235            int param;  // "unsigned param;" will also work
236            opt_complementary = "p+";
237            getopt32(argv, "p:", &param);
238    
239   "::"   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
240          option can occur multiple times. Each occurrence will be saved as          option can occur multiple times. Each occurrence will be saved as
241          a llist_t element instead of char*.          a llist_t element instead of char*.
242    
# Line 242  Special characters: Line 247  Special characters:
247          llist_t *patterns = NULL;          llist_t *patterns = NULL;
248    
249          (this pointer must be initializated to NULL if the list is empty          (this pointer must be initializated to NULL if the list is empty
250          as required by *llist_add_to(llist_t *old_head, char *new_item).)          as required by llist_add_to_end(llist_t **old_head, char *new_item).)
251    
252          opt_complementary = "e::";          opt_complementary = "e::";
253    
254          getopt32(argc, argv, "e:", &patterns);          getopt32(argv, "e:", &patterns);
255          $ grep -e user -e root /etc/passwd          $ grep -e user -e root /etc/passwd
256          root:x:0:0:root:/root:/bin/bash          root:x:0:0:root:/root:/bin/bash
257          user:x:500:500::/home/user:/bin/bash          user:x:500:500::/home/user:/bin/bash
258    
259   "?"    An "?" between an option and a group of options means that   "a?b"  A "?" between an option and a group of options means that
260          at least one of them is required to occur if the first option          at least one of them is required to occur if the first option
261          occurs in preceding command line arguments.          occurs in preceding command line arguments.
262    
263          For example from "id" applet:          For example from "id" applet:
264    
265          // Don't allow -n -r -rn -ug -rug -nug -rnug          // Don't allow -n -r -rn -ug -rug -nug -rnug
266          opt_complementary = "r?ug:n?ug:?u--g:g--u";          opt_complementary = "r?ug:n?ug:u--g:g--u";
267          flags = getopt32(argc, argv, "rnug");          flags = getopt32(argv, "rnug");
268    
269          This example allowed only:          This example allowed only:
270          $ id; id -u; id -g; id -ru; id -nu; id -rg; id -ng; id -rnu; id -rng          $ id; id -u; id -g; id -ru; id -nu; id -rg; id -ng; id -rnu; id -rng
# Line 270  Special characters: Line 275  Special characters:
275          For example from "start-stop-daemon" applet:          For example from "start-stop-daemon" applet:
276    
277          // Don't allow -KS -SK, but -S or -K is required          // Don't allow -KS -SK, but -S or -K is required
278          opt_complementary = "K:S:?K--S:S--K";          opt_complementary = "K:S:K--S:S--K";
279          flags = getopt32(argc, argv, "KS...);          flags = getopt32(argv, "KS...);
280    
281    
282          Don't forget to use ':'. For example, "?322-22-23X-x-a"          Don't forget to use ':'. For example, "?322-22-23X-x-a"
# Line 279  Special characters: Line 284  Special characters:
284          max 3 args; count uses of '-2'; min 2 args; if there is          max 3 args; count uses of '-2'; min 2 args; if there is
285          a '-2' option then unset '-3', '-X' and '-a'; if there is          a '-2' option then unset '-3', '-X' and '-a'; if there is
286          a '-2' and after it a '-x' then error out.          a '-2' and after it a '-x' then error out.
287            But it's far too obfuscated. Use ':' to separate groups.
288  */  */
289    
290  /* Code here assumes that 'unsigned' is at least 32 bits wide */  /* Code here assumes that 'unsigned' is at least 32 bits wide */
291    
292    const char *const bb_argv_dash[] = { "-", NULL };
293    
294  const char *opt_complementary;  const char *opt_complementary;
295    
296    enum {
297     PARAM_STRING,
298     PARAM_LIST,
299     PARAM_INT,
300    };
301    
302  typedef struct {  typedef struct {
303   int opt;   unsigned char opt_char;
304   int list_flg;   smallint param_type;
305   unsigned switch_on;   unsigned switch_on;
306   unsigned switch_off;   unsigned switch_off;
307   unsigned incongruously;   unsigned incongruously;
308   unsigned requires;   unsigned requires;
309   void **optarg;               /* char **optarg or llist_t **optarg */   void **optarg;  /* char**, llist_t** or int *. */
310   int *counter;   int *counter;
311  } t_complementary;  } t_complementary;
312    
313  /* You can set applet_long_options for parse called long options */  /* You can set applet_long_options for parse called long options */
314  #if ENABLE_GETOPT_LONG  #if ENABLE_GETOPT_LONG
315  static const struct option bb_default_long_options[] = {  static const struct option bb_null_long_options[1] = {
 /*      { "help", 0, NULL, '?' }, */  
316   { 0, 0, 0, 0 }   { 0, 0, 0, 0 }
317  };  };
318    const char *applet_long_options;
 const struct option *applet_long_options = bb_default_long_options;  
319  #endif  #endif
320    
321  uint32_t option_mask32;  uint32_t option_mask32;
322    
323  uint32_t  uint32_t FAST_FUNC
324  getopt32(int argc, char **argv, const char *applet_opts, ...)  getopt32(char **argv, const char *applet_opts, ...)
325  {  {
326     int argc;
327   unsigned flags = 0;   unsigned flags = 0;
328   unsigned requires = 0;   unsigned requires = 0;
329   t_complementary complementary[33];   t_complementary complementary[33]; /* last stays zero-filled */
330   int c;   int c;
331   const unsigned char *s;   const unsigned char *s;
332   t_complementary *on_off;   t_complementary *on_off;
333   va_list p;   va_list p;
334  #if ENABLE_GETOPT_LONG  #if ENABLE_GETOPT_LONG
335   const struct option *l_o;   const struct option *l_o;
336     struct option *long_options = (struct option *) &bb_null_long_options;
337  #endif  #endif
338   unsigned trigger;   unsigned trigger;
339   char **pargv = NULL;   char **pargv;
340   int min_arg = 0;   int min_arg = 0;
341   int max_arg = -1;   int max_arg = -1;
342    
343  #define SHOW_USAGE_IF_ERROR     1  #define SHOW_USAGE_IF_ERROR     1
344  #define ALL_ARGV_IS_OPTS        2  #define ALL_ARGV_IS_OPTS        2
345  #define FIRST_ARGV_IS_OPT       4  #define FIRST_ARGV_IS_OPT       4
346  #define FREE_FIRST_ARGV_IS_OPT  8  
347   int spec_flgs = 0;   int spec_flgs = 0;
348    
349     /* skip 0: some applets cheat: they do not actually HAVE argv[0] */
350     argc = 1;
351     while (argv[argc])
352     argc++;
353    
354   va_start(p, applet_opts);   va_start(p, applet_opts);
355    
356   c = 0;   c = 0;
# Line 343  getopt32(int argc, char **argv, const ch Line 362  getopt32(int argc, char **argv, const ch
362   if (*s == '+' || *s == '-')   if (*s == '+' || *s == '-')
363   s++;   s++;
364   while (*s) {   while (*s) {
365   if (c >= 32) break;   if (c >= 32)
366   on_off->opt = *s;   break;
367     on_off->opt_char = *s;
368   on_off->switch_on = (1 << c);   on_off->switch_on = (1 << c);
369   if (*++s == ':') {   if (*++s == ':') {
370   on_off->optarg = va_arg(p, void **);   on_off->optarg = va_arg(p, void **);
371   while (*++s == ':') /* skip */;   while (*++s == ':')
372     continue;
373   }   }
374   on_off++;   on_off++;
375   c++;   c++;
376   }   }
377    
378  #if ENABLE_GETOPT_LONG  #if ENABLE_GETOPT_LONG
379   for (l_o = applet_long_options; l_o->name; l_o++) {   if (applet_long_options) {
380   if (l_o->flag)   const char *optstr;
381   continue;   unsigned i, count;
382   for (on_off = complementary; on_off->opt != 0; on_off++)  
383   if (on_off->opt == l_o->val)   count = 1;
384   goto next_long;   optstr = applet_long_options;
385   if (c >= 32) break;   while (optstr[0]) {
386   on_off->opt = l_o->val;   optstr += strlen(optstr) + 3; /* skip NUL, has_arg, val */
387   on_off->switch_on = (1 << c);   count++;
388   if (l_o->has_arg != no_argument)   }
389   on_off->optarg = va_arg(p, void **);   /* count == no. of longopts + 1 */
390   c++;   long_options = alloca(count * sizeof(*long_options));
391     memset(long_options, 0, count * sizeof(*long_options));
392     i = 0;
393     optstr = applet_long_options;
394     while (--count) {
395     long_options[i].name = optstr;
396     optstr += strlen(optstr) + 1;
397     long_options[i].has_arg = (unsigned char)(*optstr++);
398     /* long_options[i].flag = NULL; */
399     long_options[i].val = (unsigned char)(*optstr++);
400     i++;
401     }
402     for (l_o = long_options; l_o->name; l_o++) {
403     if (l_o->flag)
404     continue;
405     for (on_off = complementary; on_off->opt_char; on_off++)
406     if (on_off->opt_char == l_o->val)
407     goto next_long;
408     if (c >= 32)
409     break;
410     on_off->opt_char = l_o->val;
411     on_off->switch_on = (1 << c);
412     if (l_o->has_arg != no_argument)
413     on_off->optarg = va_arg(p, void **);
414     c++;
415   next_long: ;   next_long: ;
416     }
417   }   }
418  #endif /* ENABLE_GETOPT_LONG */  #endif /* ENABLE_GETOPT_LONG */
419   for (s = (const unsigned char *)opt_complementary; s && *s; s++) {   for (s = (const unsigned char *)opt_complementary; s && *s; s++) {
# Line 404  getopt32(int argc, char **argv, const ch Line 450  getopt32(int argc, char **argv, const ch
450   s++;   s++;
451   continue;   continue;
452   }   }
453   for (on_off = complementary; on_off->opt; on_off++)   for (on_off = complementary; on_off->opt_char; on_off++)
454   if (on_off->opt == *s)   if (on_off->opt_char == *s)
455   break;   break;
456   if (c == ':' && s[2] == ':') {   if (c == ':' && s[2] == ':') {
457   on_off->list_flg++;   on_off->param_type = PARAM_LIST;
458     continue;
459     }
460     if (c == '+' && (s[2] == ':' || s[2] == '\0')) {
461     on_off->param_type = PARAM_INT;
462   continue;   continue;
463   }   }
464   if (c == ':' || c == '\0') {   if (c == ':' || c == '\0') {
# Line 436  getopt32(int argc, char **argv, const ch Line 486  getopt32(int argc, char **argv, const ch
486   else   else
487   pair_switch = &(pair->switch_off);   pair_switch = &(pair->switch_off);
488   } else {   } else {
489   for (on_off = complementary; on_off->opt; on_off++)   for (on_off = complementary; on_off->opt_char; on_off++)
490   if (on_off->opt == *s) {   if (on_off->opt_char == *s) {
491   *pair_switch |= on_off->switch_on;   *pair_switch |= on_off->switch_on;
492   break;   break;
493   }   }
# Line 445  getopt32(int argc, char **argv, const ch Line 495  getopt32(int argc, char **argv, const ch
495   }   }
496   s--;   s--;
497   }   }
498   va_end (p);   va_end(p);
499    
500   if (spec_flgs & FIRST_ARGV_IS_OPT) {   if (spec_flgs & (FIRST_ARGV_IS_OPT | ALL_ARGV_IS_OPTS)) {
501   if (argv[1] && argv[1][0] != '-' && argv[1][0] != '\0') {   pargv = argv + 1;
502   argv[1] = xasprintf("-%s", argv[1]);   while (*pargv) {
503   if (ENABLE_FEATURE_CLEAN_UP)   if (pargv[0][0] != '-' && pargv[0][0] != '\0') {
504   spec_flgs |= FREE_FIRST_ARGV_IS_OPT;   /* Can't use alloca: opts with params will
505     * return pointers to stack!
506     * NB: we leak these allocations... */
507     char *pp = xmalloc(strlen(*pargv) + 2);
508     *pp = '-';
509     strcpy(pp + 1, *pargv);
510     *pargv = pp;
511     }
512     if (!(spec_flgs & ALL_ARGV_IS_OPTS))
513     break;
514     pargv++;
515   }   }
516   }   }
517   /* Note: just "getopt() <= 0" will not work good for  
518     /* In case getopt32 was already called:
519     * reset the libc getopt() function, which keeps internal state.
520     * run_nofork_applet_prime() does this, but we might end up here
521     * also via gunzip_main() -> gzip_main(). Play safe.
522     */
523    #ifdef __GLIBC__
524     optind = 0;
525    #else /* BSD style */
526     optind = 1;
527     /* optreset = 1; */
528    #endif
529     /* optarg = NULL; opterr = 0; optopt = 0; - do we need this?? */
530    
531     pargv = NULL;
532    
533     /* Note: just "getopt() <= 0" will not work well for
534   * "fake" short options, like this one:   * "fake" short options, like this one:
535   * wget $'-\203' "Test: test" http://kernel.org/   * wget $'-\203' "Test: test" http://kernel.org/
536   * (supposed to act as --header, but doesn't) */   * (supposed to act as --header, but doesn't) */
537  #if ENABLE_GETOPT_LONG  #if ENABLE_GETOPT_LONG
538   while ((c = getopt_long(argc, argv, applet_opts,   while ((c = getopt_long(argc, argv, applet_opts,
539   applet_long_options, NULL)) != -1) {   long_options, NULL)) != -1) {
540  #else  #else
541   while ((c = getopt(argc, argv, applet_opts)) != -1) {   while ((c = getopt(argc, argv, applet_opts)) != -1) {
542  #endif /* ENABLE_GETOPT_LONG */  #endif
543   c &= 0xff; /* fight libc's sign extends */   /* getopt prints "option requires an argument -- X"
544  loop_arg_is_opt:   * and returns '?' if an option has no arg, but one is reqd */
545   for (on_off = complementary; on_off->opt != c; on_off++) {   c &= 0xff; /* fight libc's sign extension */
546   /* c==0 if long opt have non NULL flag */   for (on_off = complementary; on_off->opt_char != c; on_off++) {
547   if (on_off->opt == 0 && c != 0)   /* c can be NUL if long opt has non-NULL ->flag,
548   bb_show_usage();   * but we construct long opts so that flag
549   }   * is always NULL (see above) */
550   if (flags & on_off->incongruously) {   if (on_off->opt_char == '\0' /* && c != '\0' */) {
551   if ((spec_flgs & SHOW_USAGE_IF_ERROR))   /* c is probably '?' - "bad option" */
552   bb_show_usage();   bb_show_usage();
553   flags |= BB_GETOPT_ERROR;   }
554   }   }
555     if (flags & on_off->incongruously)
556     bb_show_usage();
557   trigger = on_off->switch_on & on_off->switch_off;   trigger = on_off->switch_on & on_off->switch_off;
558   flags &= ~(on_off->switch_off ^ trigger);   flags &= ~(on_off->switch_off ^ trigger);
559   flags |= on_off->switch_on ^ trigger;   flags |= on_off->switch_on ^ trigger;
560   flags ^= trigger;   flags ^= trigger;
561   if (on_off->counter)   if (on_off->counter)
562   (*(on_off->counter))++;   (*(on_off->counter))++;
563   if (on_off->list_flg) {   if (on_off->param_type == PARAM_LIST) {
564   llist_add_to((llist_t **)(on_off->optarg), optarg);   if (optarg)
565     llist_add_to_end((llist_t **)(on_off->optarg), optarg);
566     } else if (on_off->param_type == PARAM_INT) {
567     if (optarg)
568    //TODO: xatoi_u indirectly pulls in printf machinery
569     *(unsigned*)(on_off->optarg) = xatoi_u(optarg);
570   } else if (on_off->optarg) {   } else if (on_off->optarg) {
571   *(char **)(on_off->optarg) = optarg;   if (optarg)
572     *(char **)(on_off->optarg) = optarg;
573   }   }
574   if (pargv != NULL)   if (pargv != NULL)
575   break;   break;
576   }   }
577    
  if (spec_flgs & ALL_ARGV_IS_OPTS) {  
  /* process argv is option, for example "ps" applet */  
  if (pargv == NULL)  
  pargv = argv + optind;  
  while (*pargv) {  
  c = **pargv;  
  if (c == '\0') {  
  pargv++;  
  } else {  
  (*pargv)++;  
  goto loop_arg_is_opt;  
  }  
  }  
  }  
   
 #if (ENABLE_AR || ENABLE_TAR) && ENABLE_FEATURE_CLEAN_UP  
  if (spec_flgs & FREE_FIRST_ARGV_IS_OPT)  
  free(argv[1]);  
 #endif  
578   /* check depending requires for given options */   /* check depending requires for given options */
579   for (on_off = complementary; on_off->opt; on_off++) {   for (on_off = complementary; on_off->opt_char; on_off++) {
580   if (on_off->requires && (flags & on_off->switch_on) &&   if (on_off->requires && (flags & on_off->switch_on) &&
581   (flags & on_off->requires) == 0)   (flags & on_off->requires) == 0)
582   bb_show_usage();   bb_show_usage();

Legend:
Removed from v.532  
changed lines
  Added in v.816