db81d1c3d76b6eb004082d3caec29be8d3872129
[oweals/gnunet.git] / src / util / getopt.c
1 /* Getopt for GNU.
2    NOTE: getopt is now part of the C library, so if you don't know what
3    "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
4    before changing it!
5
6    Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97
7      Free Software Foundation, Inc.
8
9 NOTE: The canonical source of this file is maintained with the GNU C Library.
10 Bugs can be reported to bug-glibc@prep.ai.mit.edu.
11
12 This program is free software; you can redistribute it and/or modify it
13 under the terms of the GNU General Public License as published by the
14 Free Software Foundation; either version 2, or (at your option) any
15 later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25 USA.
26
27
28 This code was heavily modified for GNUnet.
29 Copyright (C) 2006 Christian Grothoff
30 */
31
32 /**
33  * @file util/getopt.c
34  * @brief GNU style option parsing
35  *
36  * TODO: get rid of statics (make reentrant) and
37  * replace main GNU getopt parser with one that
38  * actually fits our API.
39  */
40
41 #include "platform.h"
42 #include "gnunet_common.h"
43 #include "gnunet_getopt_lib.h"
44
45 #ifdef VMS
46 #include <unixlib.h>
47 #if HAVE_STRING_H - 0
48 #include <string.h>
49 #endif
50 #endif
51
52 #if defined (WIN32) && !defined (__CYGWIN32__)
53 /* It's not Unix, really.  See?  Capital letters.  */
54 #include <windows.h>
55 #define getpid() GetCurrentProcessId()
56 #endif
57
58 #ifndef _
59 /* This is for other GNU distributions with internationalized messages.
60    When compiling libc, the _ macro is predefined.  */
61 #ifdef HAVE_LIBINTL_H
62 #include <libintl.h>
63 #define _(msgid)  gettext (msgid)
64 #else
65 #define _(msgid)  (msgid)
66 #endif
67 #endif
68
69 /* Describe the long-named options requested by the application.
70    The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
71    of `struct GNoption' terminated by an element containing a name which is
72    zero.
73
74    The field `has_arg' is:
75    no_argument          (or 0) if the option does not take an argument,
76    required_argument  (or 1) if the option requires an argument,
77    optional_argument   (or 2) if the option takes an optional argument.
78
79    If the field `flag' is not NULL, it points to a variable that is set
80    to the value given in the field `val' when the option is found, but
81    left unchanged if the option is not found.
82
83    To have a long-named option do something other than set an `int' to
84    a compiled-in constant, such as set a value from `GNoptarg', set the
85    option's `flag' field to zero and its `val' field to a nonzero
86    value (the equivalent single-letter option character, if there is
87    one).  For long options that have a zero `flag' field, `getopt'
88    returns the contents of the `val' field.  */
89
90 struct GNoption
91 {
92   const char *name;
93   /* has_arg can't be an enum because some compilers complain about
94    * type mismatches in all the code that assumes it is an int.  */
95   int has_arg;
96   int *flag;
97   int val;
98 };
99
100
101 /* This version of `getopt' appears to the caller like standard Unix `getopt'
102    but it behaves differently for the user, since it allows the user
103    to intersperse the options with the other arguments.
104
105    As `getopt' works, it permutes the elements of ARGV so that,
106    when it is done, all the options precede everything else.  Thus
107    all application programs are extended to handle flexible argument order.
108
109    Setting the environment variable POSIXLY_CORRECT disables permutation.
110    Then the behavior is completely standard.
111
112    GNU application programs can use a third alternative mode in which
113    they can distinguish the relative order of options and other arguments.  */
114
115 /* For communication from `getopt' to the caller.
116    When `getopt' finds an option that takes an argument,
117    the argument value is returned here.
118    Also, when `ordering' is RETURN_IN_ORDER,
119    each non-option ARGV-element is returned here.  */
120
121 static char *GNoptarg = NULL;
122
123 /* Index in ARGV of the next element to be scanned.
124    This is used for communication to and from the caller
125    and for communication between successive calls to `getopt'.
126
127    On entry to `getopt', zero means this is the first call; initialize.
128
129    When `getopt' returns -1, this is the index of the first of the
130    non-option elements that the caller should itself scan.
131
132    Otherwise, `GNoptind' communicates from one call to the next
133    how much of ARGV has been scanned so far.  */
134
135 /* 1003.2 says this must be 1 before any call.  */
136 static int GNoptind = 1;
137
138 /* The next char to be scanned in the option-element
139    in which the last option character we returned was found.
140    This allows us to pick up the scan where we left off.
141
142    If this is zero, or a null string, it means resume the scan
143    by advancing to the next ARGV-element.  */
144
145 static char *nextchar;
146
147
148 /* Describe how to deal with options that follow non-option ARGV-elements.
149
150    If the caller did not specify anything,
151    the default is REQUIRE_ORDER if the environment variable
152    POSIXLY_CORRECT is defined, PERMUTE otherwise.
153
154    REQUIRE_ORDER means don't recognize them as options;
155    stop option processing when the first non-option is seen.
156    This is what Unix does.
157    This mode of operation is selected by either setting the environment
158    variable POSIXLY_CORRECT, or using `+' as the first character
159    of the list of option characters.
160
161    PERMUTE is the default.  We GNUNET_CRYPTO_random_permute the contents of ARGV as we scan,
162    so that eventually all the non-options are at the end.  This allows options
163    to be given in any order, even with programs that were not written to
164    expect this.
165
166    RETURN_IN_ORDER is an option available to programs that were written
167    to expect GNoptions and other ARGV-elements in any order and that care about
168    the ordering of the two.  We describe each non-option ARGV-element
169    as if it were the argument of an option with character code 1.
170    Using `-' as the first character of the list of option characters
171    selects this mode of operation.
172
173    The special argument `--' forces an end of option-scanning regardless
174    of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
175    `--' can cause `getopt' to return -1 with `GNoptind' != ARGC.  */
176
177 static enum
178 {
179   REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
180 } ordering;
181
182 /* Value of POSIXLY_CORRECT environment variable.  */
183 static char *posixly_correct;
184
185 #ifdef  __GNU_LIBRARY__
186 /* We want to avoid inclusion of string.h with non-GNU libraries
187    because there are many ways it can cause trouble.
188    On some systems, it contains special magic macros that don't work
189    in GCC.  */
190 #include <string.h>
191 #define  my_index       strchr
192 #else
193
194 /* Avoid depending on library functions or files
195    whose names are inconsistent.  */
196
197 char *getenv ();
198
199 static char *
200 my_index (str, chr)
201   const char *str;
202   int chr;
203 {
204   while (*str)
205   {
206     if (*str == chr)
207       return (char *) str;
208     str++;
209   }
210   return 0;
211 }
212
213 /* If using GCC, we can safely declare strlen this way.
214    If not using GCC, it is ok not to declare it.  */
215 #ifdef __GNUC__
216 /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
217    That was relevant to code that was here before.  */
218 #if !defined (__STDC__) || !__STDC__
219 /* gcc with -traditional declares the built-in strlen to return int,
220    and has done so at least since version 2.4.5. -- rms.  */
221 extern int strlen (const char *);
222 #endif /* not __STDC__ */
223 #endif /* __GNUC__ */
224
225 #endif /* not __GNU_LIBRARY__ */
226
227 /* Handle permutation of arguments.  */
228
229 /* Describe the part of ARGV that contains non-options that have
230    been skipped.  `first_nonopt' is the index in ARGV of the first of them;
231    `last_nonopt' is the index after the last of them.  */
232
233 static int first_nonopt;
234 static int last_nonopt;
235
236 #ifdef _LIBC
237 /* Bash 2.0 gives us an environment variable containing flags
238    indicating ARGV elements that should not be considered arguments.  */
239
240 /* Defined in getopt_init.c  */
241 extern char *__getopt_nonoption_flags;
242
243 static int nonoption_flags_max_len;
244 static int nonoption_flags_len;
245
246 static int original_argc;
247 static char *const *original_argv;
248
249 extern pid_t __libc_pid;
250
251 /* Make sure the environment variable bash 2.0 puts in the environment
252    is valid for the getopt call we must make sure that the ARGV passed
253    to getopt is that one passed to the process.  */
254 static void
255     __attribute__ ((unused)) store_args_and_env (int argc, char *const *argv)
256 {
257   /* XXX This is no good solution.  We should rather copy the args so
258    * that we can compare them later.  But we must not use malloc(3).  */
259   original_argc = argc;
260   original_argv = argv;
261 }
262
263 text_set_element (__libc_subinit, store_args_and_env);
264
265 #define SWAP_FLAGS(ch1, ch2) \
266   if (nonoption_flags_len > 0)                                                \
267     {                                                                 \
268       char __tmp = __getopt_nonoption_flags[ch1];                     \
269       __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2];        \
270       __getopt_nonoption_flags[ch2] = __tmp;                          \
271     }
272 #else /* !_LIBC */
273 #define SWAP_FLAGS(ch1, ch2)
274 #endif /* _LIBC */
275
276 /* Exchange two adjacent subsequences of ARGV.
277    One subsequence is elements [first_nonopt,last_nonopt)
278    which contains all the non-options that have been skipped so far.
279    The other is elements [last_nonopt,GNoptind), which contains all
280    the options processed since those non-options were skipped.
281
282    `first_nonopt' and `last_nonopt' are relocated so that they describe
283    the new indices of the non-options in ARGV after they are moved.  */
284
285 #if defined (__STDC__) && __STDC__
286 static void exchange (char **);
287 #endif
288
289 static void
290 exchange (argv)
291   char **argv;
292 {
293   int bottom = first_nonopt;
294   int middle = last_nonopt;
295   int top = GNoptind;
296   char *tem;
297
298   /* Exchange the shorter segment with the far end of the longer segment.
299    * That puts the shorter segment into the right place.
300    * It leaves the longer segment in the right place overall,
301    * but it consists of two parts that need to be swapped next.  */
302
303 #ifdef _LIBC
304   /* First make sure the handling of the `__getopt_nonoption_flags'
305    * string can work normally.  Our top argument must be in the range
306    * of the string.  */
307   if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
308   {
309     /* We must extend the array.  The user plays games with us and
310      * presents new arguments.  */
311     char *new_str = malloc (top + 1);
312
313     if (new_str == NULL)
314       nonoption_flags_len = nonoption_flags_max_len = 0;
315     else
316     {
317       memcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len);
318       memset (&new_str[nonoption_flags_max_len], '\0',
319               top + 1 - nonoption_flags_max_len);
320       nonoption_flags_max_len = top + 1;
321       __getopt_nonoption_flags = new_str;
322     }
323   }
324 #endif
325
326   while (top > middle && middle > bottom)
327   {
328     if (top - middle > middle - bottom)
329     {
330       /* Bottom segment is the short one.  */
331       int len = middle - bottom;
332       register int i;
333
334       /* Swap it with the top part of the top segment.  */
335       for (i = 0; i < len; i++)
336       {
337         tem = argv[bottom + i];
338         argv[bottom + i] = argv[top - (middle - bottom) + i];
339         argv[top - (middle - bottom) + i] = tem;
340         SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
341       }
342       /* Exclude the moved bottom segment from further swapping.  */
343       top -= len;
344     }
345     else
346     {
347       /* Top segment is the short one.  */
348       int len = top - middle;
349       register int i;
350
351       /* Swap it with the bottom part of the bottom segment.  */
352       for (i = 0; i < len; i++)
353       {
354         tem = argv[bottom + i];
355         argv[bottom + i] = argv[middle + i];
356         argv[middle + i] = tem;
357         SWAP_FLAGS (bottom + i, middle + i);
358       }
359       /* Exclude the moved top segment from further swapping.  */
360       bottom += len;
361     }
362   }
363
364   /* Update records for the slots the non-options now occupy.  */
365
366   first_nonopt += (GNoptind - last_nonopt);
367   last_nonopt = GNoptind;
368 }
369
370 /* Initialize the internal data when the first call is made.  */
371
372 #if defined (__STDC__) && __STDC__
373 static const char *_getopt_initialize (int, char *const *, const char *);
374 #endif
375 static const char *
376 _getopt_initialize (argc, argv, optstring)
377   int argc;
378   char *const *argv;
379   const char *optstring;
380 {
381   /* Start processing options with ARGV-element 1 (since ARGV-element 0
382    * is the program name); the sequence of previously skipped
383    * non-option ARGV-elements is empty.  */
384
385   first_nonopt = last_nonopt = GNoptind;
386
387   nextchar = NULL;
388
389   posixly_correct = getenv ("POSIXLY_CORRECT");
390
391   /* Determine how to handle the ordering of options and nonoptions.  */
392
393   if (optstring[0] == '-')
394   {
395     ordering = RETURN_IN_ORDER;
396     ++optstring;
397   }
398   else if (optstring[0] == '+')
399   {
400     ordering = REQUIRE_ORDER;
401     ++optstring;
402   }
403   else if (posixly_correct != NULL)
404     ordering = REQUIRE_ORDER;
405   else
406     ordering = PERMUTE;
407
408 #ifdef _LIBC
409   if (posixly_correct == NULL && argc == original_argc && argv == original_argv)
410   {
411     if (nonoption_flags_max_len == 0)
412     {
413       if (__getopt_nonoption_flags == NULL ||
414           __getopt_nonoption_flags[0] == '\0')
415         nonoption_flags_max_len = -1;
416       else
417       {
418         const char *orig_str = __getopt_nonoption_flags;
419         int len = nonoption_flags_max_len = strlen (orig_str);
420
421         if (nonoption_flags_max_len < argc)
422           nonoption_flags_max_len = argc;
423         __getopt_nonoption_flags = (char *) malloc (nonoption_flags_max_len);
424         if (__getopt_nonoption_flags == NULL)
425           nonoption_flags_max_len = -1;
426         else
427         {
428           memcpy (__getopt_nonoption_flags, orig_str, len);
429           memset (&__getopt_nonoption_flags[len], '\0',
430                   nonoption_flags_max_len - len);
431         }
432       }
433     }
434     nonoption_flags_len = nonoption_flags_max_len;
435   }
436   else
437     nonoption_flags_len = 0;
438 #endif
439
440   return optstring;
441 }
442 \f
443 /* Scan elements of ARGV (whose length is ARGC) for option characters
444    given in OPTSTRING.
445
446    If an element of ARGV starts with '-', and is not exactly "-" or "--",
447    then it is an option element.  The characters of this element
448    (aside from the initial '-') are option characters.  If `getopt'
449    is called repeatedly, it returns successively each of the option characters
450    from each of the option elements.
451
452    If `getopt' finds another option character, it returns that character,
453    updating `GNoptind' and `nextchar' so that the next call to `getopt' can
454    resume the scan with the following option character or ARGV-element.
455
456    If there are no more option characters, `getopt' returns -1.
457    Then `GNoptind' is the index in ARGV of the first ARGV-element
458    that is not an option.  (The ARGV-elements have been permuted
459    so that those that are not options now come last.)
460
461    OPTSTRING is a string containing the legitimate option characters.
462    If an option character is seen that is not listed in OPTSTRING,
463    return '?' after printing an error message.  If you set `GNopterr' to
464    zero, the error message is suppressed but we still return '?'.
465
466    If a char in OPTSTRING is followed by a colon, that means it wants an arg,
467    so the following text in the same ARGV-element, or the text of the following
468    ARGV-element, is returned in `GNoptarg'.  Two colons mean an option that
469    wants an optional arg; if there is text in the current ARGV-element,
470    it is returned in `GNoptarg', otherwise `GNoptarg' is set to zero.
471
472    If OPTSTRING starts with `-' or `+', it requests different methods of
473    handling the non-option ARGV-elements.
474    See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
475
476    Long-named options begin with `--' instead of `-'.
477    Their names may be abbreviated as long as the abbreviation is unique
478    or is an exact match for some defined option.  If they have an
479    argument, it follows the option name in the same ARGV-element, separated
480    from the option name by a `=', or else the in next ARGV-element.
481    When `getopt' finds a long-named option, it returns 0 if that option's
482    `flag' field is nonzero, the value of the option's `val' field
483    if the `flag' field is zero.
484
485    The elements of ARGV aren't really const, because we GNUNET_CRYPTO_random_permute them.
486    But we pretend they're const in the prototype to be compatible
487    with other systems.
488
489    LONGOPTS is a vector of `struct GNoption' terminated by an
490    element containing a name which is zero.
491
492    LONGIND returns the index in LONGOPT of the long-named option found.
493    It is only valid when a long-named option has been found by the most
494    recent call.
495
496    If LONG_ONLY is nonzero, '-' as well as '--' can introduce
497    long-named options.  */
498
499 static int
500 GN_getopt_internal (int argc, char *const *argv, const char *optstring,
501                     const struct GNoption *longopts, int *longind,
502                     int long_only)
503 {
504   static int __getopt_initialized = 0;
505   static int GNopterr = 1;
506
507   GNoptarg = NULL;
508
509   if (GNoptind == 0 || !__getopt_initialized)
510   {
511     if (GNoptind == 0)
512       GNoptind = 1;             /* Don't scan ARGV[0], the program name.  */
513     optstring = _getopt_initialize (argc, argv, optstring);
514     __getopt_initialized = 1;
515   }
516
517   /* Test whether ARGV[GNoptind] points to a non-option argument.
518    * Either it does not have option syntax, or there is an environment flag
519    * from the shell indicating it is not an option.  The later information
520    * is only used when the used in the GNU libc.  */
521 #ifdef _LIBC
522 #define NONOPTION_P (argv[GNoptind][0] != '-' || argv[GNoptind][1] == '\0'        \
523              || (GNoptind < nonoption_flags_len                       \
524                  && __getopt_nonoption_flags[GNoptind] == '1'))
525 #else
526 #define NONOPTION_P (argv[GNoptind][0] != '-' || argv[GNoptind][1] == '\0')
527 #endif
528
529   if (nextchar == NULL || *nextchar == '\0')
530   {
531     /* Advance to the next ARGV-element.  */
532
533     /* Give FIRST_NONOPT & LAST_NONOPT rational values if GNoptind has been
534      * moved back by the user (who may also have changed the arguments).  */
535     if (last_nonopt > GNoptind)
536       last_nonopt = GNoptind;
537     if (first_nonopt > GNoptind)
538       first_nonopt = GNoptind;
539
540     if (ordering == PERMUTE)
541     {
542       /* If we have just processed some options following some non-options,
543        * exchange them so that the options come first.  */
544
545       if (first_nonopt != last_nonopt && last_nonopt != GNoptind)
546         exchange ((char **) argv);
547       else if (last_nonopt != GNoptind)
548         first_nonopt = GNoptind;
549
550       /* Skip any additional non-options
551        * and extend the range of non-options previously skipped.  */
552
553       while (GNoptind < argc && NONOPTION_P)
554         GNoptind++;
555       last_nonopt = GNoptind;
556     }
557
558     /* The special ARGV-element `--' means premature end of options.
559      * Skip it like a null option,
560      * then exchange with previous non-options as if it were an option,
561      * then skip everything else like a non-option.  */
562     if (GNoptind != argc && !strcmp (argv[GNoptind], "--"))
563     {
564       GNoptind++;
565
566       if (first_nonopt != last_nonopt && last_nonopt != GNoptind)
567         exchange ((char **) argv);
568       else if (first_nonopt == last_nonopt)
569         first_nonopt = GNoptind;
570       last_nonopt = argc;
571
572       GNoptind = argc;
573     }
574
575     /* If we have done all the ARGV-elements, stop the scan
576      * and back over any non-options that we skipped and permuted.  */
577
578     if (GNoptind == argc)
579     {
580       /* Set the next-arg-index to point at the non-options
581        * that we previously skipped, so the caller will digest them.  */
582       if (first_nonopt != last_nonopt)
583         GNoptind = first_nonopt;
584       return -1;
585     }
586
587     /* If we have come to a non-option and did not permute it,
588      * either stop the scan or describe it to the caller and pass it by.  */
589
590     if (NONOPTION_P)
591     {
592       if (ordering == REQUIRE_ORDER)
593         return -1;
594       GNoptarg = argv[GNoptind++];
595       return 1;
596     }
597
598     /* We have found another option-ARGV-element.
599      * Skip the initial punctuation.  */
600
601     nextchar =
602         (argv[GNoptind] + 1 + (longopts != NULL && argv[GNoptind][1] == '-'));
603   }
604
605   /* Decode the current option-ARGV-element.  */
606
607   /* Check whether the ARGV-element is a long option.
608    * 
609    * If long_only and the ARGV-element has the form "-f", where f is
610    * a valid short option, don't consider it an abbreviated form of
611    * a long option that starts with f.  Otherwise there would be no
612    * way to give the -f short option.
613    * 
614    * On the other hand, if there's a long option "fubar" and
615    * the ARGV-element is "-fu", do consider that an abbreviation of
616    * the long option, just like "--fu", and not "-f" with arg "u".
617    * 
618    * This distinction seems to be the most useful approach.  */
619
620   if (longopts != NULL &&
621       (argv[GNoptind][1] == '-' ||
622        (long_only &&
623         (argv[GNoptind][2] || !my_index (optstring, argv[GNoptind][1])))))
624   {
625     char *nameend;
626     const struct GNoption *p;
627     const struct GNoption *pfound = NULL;
628     int exact = 0;
629     int ambig = 0;
630     int indfound = -1;
631     int option_index;
632
633     for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
634       /* Do nothing.  */ ;
635
636     /* Test all long options for either exact match
637      * or abbreviated matches.  */
638     for (p = longopts, option_index = 0; p->name; p++, option_index++)
639       if (!strncmp (p->name, nextchar, nameend - nextchar))
640       {
641         if ((unsigned int) (nameend - nextchar) ==
642             (unsigned int) strlen (p->name))
643         {
644           /* Exact match found.  */
645           pfound = p;
646           indfound = option_index;
647           exact = 1;
648           break;
649         }
650         else if (pfound == NULL)
651         {
652           /* First nonexact match found.  */
653           pfound = p;
654           indfound = option_index;
655         }
656         else
657           /* Second or later nonexact match found.  */
658           ambig = 1;
659       }
660
661     if (ambig && !exact)
662     {
663       if (GNopterr)
664         fprintf (stderr, _("%s: option `%s' is ambiguous\n"), argv[0],
665                  argv[GNoptind]);
666       nextchar += strlen (nextchar);
667       GNoptind++;
668       return '?';
669     }
670
671     if (pfound != NULL)
672     {
673       option_index = indfound;
674       GNoptind++;
675       if (*nameend)
676       {
677         /* Don't test has_arg with >, because some C compilers don't
678          * allow it to be used on enums.  */
679         if (pfound->has_arg)
680           GNoptarg = nameend + 1;
681         else
682         {
683           if (GNopterr)
684           {
685             if (argv[GNoptind - 1][1] == '-')
686               /* --option */
687               fprintf (stderr,
688                        _("%s: option `--%s' does not allow an argument\n"),
689                        argv[0], pfound->name);
690             else
691               /* +option or -option */
692               fprintf (stderr,
693                        _("%s: option `%c%s' does not allow an argument\n"),
694                        argv[0], argv[GNoptind - 1][0], pfound->name);
695           }
696           nextchar += strlen (nextchar);
697           return '?';
698         }
699       }
700       else if (pfound->has_arg == 1)
701       {
702         if (GNoptind < argc)
703         {
704           GNoptarg = argv[GNoptind++];
705         }
706         else
707         {
708           if (GNopterr)
709           {
710             fprintf (stderr, _("%s: option `%s' requires an argument\n"),
711                      argv[0], argv[GNoptind - 1]);
712           }
713           nextchar += strlen (nextchar);
714           return (optstring[0] == ':') ? ':' : '?';
715         }
716       }
717       nextchar += strlen (nextchar);
718       if (longind != NULL)
719         *longind = option_index;
720       if (pfound->flag)
721       {
722         *(pfound->flag) = pfound->val;
723         return 0;
724       }
725       return pfound->val;
726     }
727
728     /* Can't find it as a long option.  If this is not getopt_long_only,
729      * or the option starts with '--' or is not a valid short
730      * option, then it's an error.
731      * Otherwise interpret it as a short option.  */
732     if (!long_only || argv[GNoptind][1] == '-' ||
733         my_index (optstring, *nextchar) == NULL)
734     {
735       if (GNopterr)
736       {
737         if (argv[GNoptind][1] == '-')
738           /* --option */
739           fprintf (stderr, _("%s: unrecognized option `--%s'\n"), argv[0],
740                    nextchar);
741         else
742           /* +option or -option */
743           fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), argv[0],
744                    argv[GNoptind][0], nextchar);
745       }
746       nextchar = (char *) "";
747       GNoptind++;
748       return '?';
749     }
750   }
751
752   /* Look at and handle the next short option-character.  */
753
754   {
755     char c = *nextchar++;
756     char *temp = my_index (optstring, c);
757
758     /* Increment `GNoptind' when we start to process its last character.  */
759     if (*nextchar == '\0')
760       ++GNoptind;
761
762     if (temp == NULL || c == ':')
763     {
764       if (GNopterr)
765       {
766         if (posixly_correct)
767           /* 1003.2 specifies the format of this message.  */
768           fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c);
769         else
770           fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c);
771       }
772       return '?';
773     }
774     /* Convenience. Treat POSIX -W foo same as long option --foo */
775     if (temp[0] == 'W' && temp[1] == ';')
776     {
777       char *nameend;
778       const struct GNoption *p;
779       const struct GNoption *pfound = NULL;
780       int exact = 0;
781       int ambig = 0;
782       int indfound = 0;
783       int option_index;
784
785       /* This is an option that requires an argument.  */
786       if (*nextchar != '\0')
787       {
788         GNoptarg = nextchar;
789         /* If we end this ARGV-element by taking the rest as an arg,
790          * we must advance to the next element now.  */
791         GNoptind++;
792       }
793       else if (GNoptind == argc)
794       {
795         if (GNopterr)
796         {
797           /* 1003.2 specifies the format of this message.  */
798           fprintf (stderr, _("%s: option requires an argument -- %c\n"),
799                    argv[0], c);
800         }
801         if (optstring[0] == ':')
802           c = ':';
803         else
804           c = '?';
805         return c;
806       }
807       else
808         /* We already incremented `GNoptind' once;
809          * increment it again when taking next ARGV-elt as argument.  */
810         GNoptarg = argv[GNoptind++];
811
812       /* GNoptarg is now the argument, see if it's in the
813        * table of longopts.  */
814
815       for (nextchar = nameend = GNoptarg; *nameend && *nameend != '=';
816            nameend++)
817         /* Do nothing.  */ ;
818
819       /* Test all long options for either exact match
820        * or abbreviated matches.  */
821       if (longopts != NULL)
822         for (p = longopts, option_index = 0; p->name; p++, option_index++)
823           if (!strncmp (p->name, nextchar, nameend - nextchar))
824           {
825             if ((unsigned int) (nameend - nextchar) == strlen (p->name))
826             {
827               /* Exact match found.  */
828               pfound = p;
829               indfound = option_index;
830               exact = 1;
831               break;
832             }
833             else if (pfound == NULL)
834             {
835               /* First nonexact match found.  */
836               pfound = p;
837               indfound = option_index;
838             }
839             else
840               /* Second or later nonexact match found.  */
841               ambig = 1;
842           }
843       if (ambig && !exact)
844       {
845         if (GNopterr)
846           fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), argv[0],
847                    argv[GNoptind]);
848         nextchar += strlen (nextchar);
849         GNoptind++;
850         return '?';
851       }
852       if (pfound != NULL)
853       {
854         option_index = indfound;
855         if (*nameend)
856         {
857           /* Don't test has_arg with >, because some C compilers don't
858            * allow it to be used on enums.  */
859           if (pfound->has_arg)
860             GNoptarg = nameend + 1;
861           else
862           {
863             if (GNopterr)
864               fprintf (stderr, _("\
865 %s: option `-W %s' does not allow an argument\n"), argv[0], pfound->name);
866
867             nextchar += strlen (nextchar);
868             return '?';
869           }
870         }
871         else if (pfound->has_arg == 1)
872         {
873           if (GNoptind < argc)
874             GNoptarg = argv[GNoptind++];
875           else
876           {
877             if (GNopterr)
878               fprintf (stderr, _("%s: option `%s' requires an argument\n"),
879                        argv[0], argv[GNoptind - 1]);
880             nextchar += strlen (nextchar);
881             return optstring[0] == ':' ? ':' : '?';
882           }
883         }
884         nextchar += strlen (nextchar);
885         if (longind != NULL)
886           *longind = option_index;
887         if (pfound->flag)
888         {
889           *(pfound->flag) = pfound->val;
890           return 0;
891         }
892         return pfound->val;
893       }
894       nextchar = NULL;
895       return 'W';               /* Let the application handle it.   */
896     }
897     if (temp[1] == ':')
898     {
899       if (temp[2] == ':')
900       {
901         /* This is an option that accepts an argument optionally.  */
902         if (*nextchar != '\0')
903         {
904           GNoptarg = nextchar;
905           GNoptind++;
906         }
907         else
908           GNoptarg = NULL;
909         nextchar = NULL;
910       }
911       else
912       {
913         /* This is an option that requires an argument.  */
914         if (*nextchar != '\0')
915         {
916           GNoptarg = nextchar;
917           /* If we end this ARGV-element by taking the rest as an arg,
918            * we must advance to the next element now.  */
919           GNoptind++;
920         }
921         else if (GNoptind == argc)
922         {
923           if (GNopterr)
924           {
925             /* 1003.2 specifies the format of this message.  */
926             fprintf (stderr, _("%s: option requires an argument -- %c\n"),
927                      argv[0], c);
928           }
929           if (optstring[0] == ':')
930             c = ':';
931           else
932             c = '?';
933         }
934         else
935           /* We already incremented `GNoptind' once;
936            * increment it again when taking next ARGV-elt as argument.  */
937           GNoptarg = argv[GNoptind++];
938         nextchar = NULL;
939       }
940     }
941     return c;
942   }
943 }
944
945 static int
946 GNgetopt_long (int argc, char *const *argv, const char *options,
947                const struct GNoption *long_options, int *opt_index)
948 {
949   return GN_getopt_internal (argc, argv, options, long_options, opt_index, 0);
950 }
951
952 /* ******************** now the GNUnet specific modifications... ********************* */
953
954 /**
955  * Parse the command line.
956  *
957  * @param binaryOptions Name of application with option summary
958  * @param allOptions defined options and handlers
959  * @param argc number of arguments
960  * @param argv actual arguments
961  * @return index into argv with first non-option
962  *   argument, or -1 on error
963  */
964 int
965 GNUNET_GETOPT_run (const char *binaryOptions,
966                    const struct GNUNET_GETOPT_CommandLineOption *allOptions,
967                    unsigned int argc, char *const *argv)
968 {
969   struct GNoption *long_options;
970   struct GNUNET_GETOPT_CommandLineProcessorContext clpc;
971   int count;
972   int i;
973   char *shorts;
974   int spos;
975   int cont;
976   int c;
977
978   GNUNET_assert (argc > 0);
979   GNoptind = 0;
980   clpc.binaryName = argv[0];
981   clpc.binaryOptions = binaryOptions;
982   clpc.allOptions = allOptions;
983   clpc.argv = argv;
984   clpc.argc = argc;
985   count = 0;
986   while (allOptions[count].name != NULL)
987     count++;
988   long_options = GNUNET_malloc (sizeof (struct GNoption) * (count + 1));
989   shorts = GNUNET_malloc (count * 2 + 1);
990   spos = 0;
991   for (i = 0; i < count; i++)
992   {
993     long_options[i].name = allOptions[i].name;
994     long_options[i].has_arg = allOptions[i].require_argument;
995     long_options[i].flag = NULL;
996     long_options[i].val = allOptions[i].shortName;
997     shorts[spos++] = allOptions[i].shortName;
998     if (allOptions[i].require_argument != 0)
999       shorts[spos++] = ':';
1000   }
1001   long_options[count].name = NULL;
1002   long_options[count].has_arg = 0;
1003   long_options[count].flag = NULL;
1004   long_options[count].val = '\0';
1005   shorts[spos] = '\0';
1006   cont = GNUNET_OK;
1007   /* main getopt loop */
1008   while (cont == GNUNET_OK)
1009   {
1010     int option_index = 0;
1011
1012     c = GNgetopt_long (argc, argv, shorts, long_options, &option_index);
1013
1014     if (c == GNUNET_SYSERR)
1015       break;                    /* No more flags to process */
1016
1017     for (i = 0; i < count; i++)
1018     {
1019       clpc.currentArgument = GNoptind - 1;
1020       if ((char) c == allOptions[i].shortName)
1021       {
1022         cont =
1023             allOptions[i].processor (&clpc, allOptions[i].scls,
1024                                      allOptions[i].name, GNoptarg);
1025         break;
1026       }
1027     }
1028     if (i == count)
1029     {
1030       fprintf (stderr, _("Use --help to get a list of options.\n"));
1031       cont = GNUNET_SYSERR;
1032     }
1033   }
1034
1035   GNUNET_free (shorts);
1036   GNUNET_free (long_options);
1037   if (cont == GNUNET_SYSERR)
1038     return GNUNET_SYSERR;
1039   return GNoptind;
1040 }
1041
1042 /* end of getopt.c */