2a35ab278852dcc5004e43143b7af31ef08e4c77
[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,
501                     char *const *argv,
502                     const char *optstring,
503                     const struct GNoption *longopts,
504                     int *longind, int long_only)
505 {
506   static int __getopt_initialized = 0;
507   static int GNopterr = 1;
508
509   GNoptarg = NULL;
510
511   if (GNoptind == 0 || !__getopt_initialized)
512   {
513     if (GNoptind == 0)
514       GNoptind = 1;             /* Don't scan ARGV[0], the program name.  */
515     optstring = _getopt_initialize (argc, argv, optstring);
516     __getopt_initialized = 1;
517   }
518
519   /* Test whether ARGV[GNoptind] points to a non-option argument.
520    * Either it does not have option syntax, or there is an environment flag
521    * from the shell indicating it is not an option.  The later information
522    * is only used when the used in the GNU libc.  */
523 #ifdef _LIBC
524 #define NONOPTION_P (argv[GNoptind][0] != '-' || argv[GNoptind][1] == '\0'        \
525              || (GNoptind < nonoption_flags_len                       \
526                  && __getopt_nonoption_flags[GNoptind] == '1'))
527 #else
528 #define NONOPTION_P (argv[GNoptind][0] != '-' || argv[GNoptind][1] == '\0')
529 #endif
530
531   if (nextchar == NULL || *nextchar == '\0')
532   {
533     /* Advance to the next ARGV-element.  */
534
535     /* Give FIRST_NONOPT & LAST_NONOPT rational values if GNoptind has been
536      * moved back by the user (who may also have changed the arguments).  */
537     if (last_nonopt > GNoptind)
538       last_nonopt = GNoptind;
539     if (first_nonopt > GNoptind)
540       first_nonopt = GNoptind;
541
542     if (ordering == PERMUTE)
543     {
544       /* If we have just processed some options following some non-options,
545        * exchange them so that the options come first.  */
546
547       if (first_nonopt != last_nonopt && last_nonopt != GNoptind)
548         exchange ((char **) argv);
549       else if (last_nonopt != GNoptind)
550         first_nonopt = GNoptind;
551
552       /* Skip any additional non-options
553        * and extend the range of non-options previously skipped.  */
554
555       while (GNoptind < argc && NONOPTION_P)
556         GNoptind++;
557       last_nonopt = GNoptind;
558     }
559
560     /* The special ARGV-element `--' means premature end of options.
561      * Skip it like a null option,
562      * then exchange with previous non-options as if it were an option,
563      * then skip everything else like a non-option.  */
564     if (GNoptind != argc && !strcmp (argv[GNoptind], "--"))
565     {
566       GNoptind++;
567
568       if (first_nonopt != last_nonopt && last_nonopt != GNoptind)
569         exchange ((char **) argv);
570       else if (first_nonopt == last_nonopt)
571         first_nonopt = GNoptind;
572       last_nonopt = argc;
573
574       GNoptind = argc;
575     }
576
577     /* If we have done all the ARGV-elements, stop the scan
578      * and back over any non-options that we skipped and permuted.  */
579
580     if (GNoptind == argc)
581     {
582       /* Set the next-arg-index to point at the non-options
583        * that we previously skipped, so the caller will digest them.  */
584       if (first_nonopt != last_nonopt)
585         GNoptind = first_nonopt;
586       return -1;
587     }
588
589     /* If we have come to a non-option and did not permute it,
590      * either stop the scan or describe it to the caller and pass it by.  */
591
592     if (NONOPTION_P)
593     {
594       if (ordering == REQUIRE_ORDER)
595         return -1;
596       GNoptarg = argv[GNoptind++];
597       return 1;
598     }
599
600     /* We have found another option-ARGV-element.
601      * Skip the initial punctuation.  */
602
603     nextchar = (argv[GNoptind] + 1
604                 + (longopts != NULL && argv[GNoptind][1] == '-'));
605   }
606
607   /* Decode the current option-ARGV-element.  */
608
609   /* Check whether the ARGV-element is a long option.
610    * 
611    * If long_only and the ARGV-element has the form "-f", where f is
612    * a valid short option, don't consider it an abbreviated form of
613    * a long option that starts with f.  Otherwise there would be no
614    * way to give the -f short option.
615    * 
616    * On the other hand, if there's a long option "fubar" and
617    * the ARGV-element is "-fu", do consider that an abbreviation of
618    * the long option, just like "--fu", and not "-f" with arg "u".
619    * 
620    * This distinction seems to be the most useful approach.  */
621
622   if (longopts != NULL
623       && (argv[GNoptind][1] == '-'
624           || (long_only
625               && (argv[GNoptind][2]
626                   || !my_index (optstring, argv[GNoptind][1])))))
627   {
628     char *nameend;
629     const struct GNoption *p;
630     const struct GNoption *pfound = NULL;
631     int exact = 0;
632     int ambig = 0;
633     int indfound = -1;
634     int option_index;
635
636     for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
637       /* Do nothing.  */ ;
638
639     /* Test all long options for either exact match
640      * or abbreviated matches.  */
641     for (p = longopts, option_index = 0; p->name; p++, option_index++)
642       if (!strncmp (p->name, nextchar, nameend - nextchar))
643       {
644         if ((unsigned int) (nameend - nextchar)
645             == (unsigned int) strlen (p->name))
646         {
647           /* Exact match found.  */
648           pfound = p;
649           indfound = option_index;
650           exact = 1;
651           break;
652         }
653         else if (pfound == NULL)
654         {
655           /* First nonexact match found.  */
656           pfound = p;
657           indfound = option_index;
658         }
659         else
660           /* Second or later nonexact match found.  */
661           ambig = 1;
662       }
663
664     if (ambig && !exact)
665     {
666       if (GNopterr)
667         fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
668                  argv[0], argv[GNoptind]);
669       nextchar += strlen (nextchar);
670       GNoptind++;
671       return '?';
672     }
673
674     if (pfound != NULL)
675     {
676       option_index = indfound;
677       GNoptind++;
678       if (*nameend)
679       {
680         /* Don't test has_arg with >, because some C compilers don't
681          * allow it to be used on enums.  */
682         if (pfound->has_arg)
683           GNoptarg = nameend + 1;
684         else
685         {
686           if (GNopterr)
687           {
688             if (argv[GNoptind - 1][1] == '-')
689               /* --option */
690               fprintf (stderr,
691                        _
692                        ("%s: option `--%s' does not allow an argument\n"),
693                        argv[0], pfound->name);
694             else
695               /* +option or -option */
696               fprintf (stderr,
697                        _
698                        ("%s: option `%c%s' does not allow an argument\n"),
699                        argv[0], argv[GNoptind - 1][0], pfound->name);
700           }
701           nextchar += strlen (nextchar);
702           return '?';
703         }
704       }
705       else if (pfound->has_arg == 1)
706       {
707         if (GNoptind < argc)
708         {
709           GNoptarg = argv[GNoptind++];
710         }
711         else
712         {
713           if (GNopterr)
714           {
715             fprintf (stderr,
716                      _("%s: option `%s' requires an argument\n"),
717                      argv[0], argv[GNoptind - 1]);
718           }
719           nextchar += strlen (nextchar);
720           return (optstring[0] == ':') ? ':' : '?';
721         }
722       }
723       nextchar += strlen (nextchar);
724       if (longind != NULL)
725         *longind = option_index;
726       if (pfound->flag)
727       {
728         *(pfound->flag) = pfound->val;
729         return 0;
730       }
731       return pfound->val;
732     }
733
734     /* Can't find it as a long option.  If this is not getopt_long_only,
735      * or the option starts with '--' or is not a valid short
736      * option, then it's an error.
737      * Otherwise interpret it as a short option.  */
738     if (!long_only || argv[GNoptind][1] == '-'
739         || my_index (optstring, *nextchar) == NULL)
740     {
741       if (GNopterr)
742       {
743         if (argv[GNoptind][1] == '-')
744           /* --option */
745           fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
746                    argv[0], nextchar);
747         else
748           /* +option or -option */
749           fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
750                    argv[0], argv[GNoptind][0], nextchar);
751       }
752       nextchar = (char *) "";
753       GNoptind++;
754       return '?';
755     }
756   }
757
758   /* Look at and handle the next short option-character.  */
759
760   {
761     char c = *nextchar++;
762     char *temp = my_index (optstring, c);
763
764     /* Increment `GNoptind' when we start to process its last character.  */
765     if (*nextchar == '\0')
766       ++GNoptind;
767
768     if (temp == NULL || c == ':')
769     {
770       if (GNopterr)
771       {
772         if (posixly_correct)
773           /* 1003.2 specifies the format of this message.  */
774           fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c);
775         else
776           fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c);
777       }
778       return '?';
779     }
780     /* Convenience. Treat POSIX -W foo same as long option --foo */
781     if (temp[0] == 'W' && temp[1] == ';')
782     {
783       char *nameend;
784       const struct GNoption *p;
785       const struct GNoption *pfound = NULL;
786       int exact = 0;
787       int ambig = 0;
788       int indfound = 0;
789       int option_index;
790
791       /* This is an option that requires an argument.  */
792       if (*nextchar != '\0')
793       {
794         GNoptarg = nextchar;
795         /* If we end this ARGV-element by taking the rest as an arg,
796          * we must advance to the next element now.  */
797         GNoptind++;
798       }
799       else if (GNoptind == argc)
800       {
801         if (GNopterr)
802         {
803           /* 1003.2 specifies the format of this message.  */
804           fprintf (stderr, _("%s: option requires an argument -- %c\n"),
805                    argv[0], c);
806         }
807         if (optstring[0] == ':')
808           c = ':';
809         else
810           c = '?';
811         return c;
812       }
813       else
814         /* We already incremented `GNoptind' once;
815          * increment it again when taking next ARGV-elt as argument.  */
816         GNoptarg = argv[GNoptind++];
817
818       /* GNoptarg is now the argument, see if it's in the
819        * table of longopts.  */
820
821       for (nextchar = nameend = GNoptarg; *nameend && *nameend != '=';
822            nameend++)
823         /* Do nothing.  */ ;
824
825       /* Test all long options for either exact match
826        * or abbreviated matches.  */
827       if (longopts != NULL)
828         for (p = longopts, option_index = 0; p->name; p++, option_index++)
829           if (!strncmp (p->name, nextchar, nameend - nextchar))
830           {
831             if ((unsigned int) (nameend - nextchar) == strlen (p->name))
832             {
833               /* Exact match found.  */
834               pfound = p;
835               indfound = option_index;
836               exact = 1;
837               break;
838             }
839             else if (pfound == NULL)
840             {
841               /* First nonexact match found.  */
842               pfound = p;
843               indfound = option_index;
844             }
845             else
846               /* Second or later nonexact match found.  */
847               ambig = 1;
848           }
849       if (ambig && !exact)
850       {
851         if (GNopterr)
852           fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
853                    argv[0], argv[GNoptind]);
854         nextchar += strlen (nextchar);
855         GNoptind++;
856         return '?';
857       }
858       if (pfound != NULL)
859       {
860         option_index = indfound;
861         if (*nameend)
862         {
863           /* Don't test has_arg with >, because some C compilers don't
864            * allow it to be used on enums.  */
865           if (pfound->has_arg)
866             GNoptarg = nameend + 1;
867           else
868           {
869             if (GNopterr)
870               fprintf (stderr, _("\
871 %s: option `-W %s' does not allow an argument\n"), argv[0], pfound->name);
872
873             nextchar += strlen (nextchar);
874             return '?';
875           }
876         }
877         else if (pfound->has_arg == 1)
878         {
879           if (GNoptind < argc)
880             GNoptarg = argv[GNoptind++];
881           else
882           {
883             if (GNopterr)
884               fprintf (stderr,
885                        _("%s: option `%s' requires an argument\n"),
886                        argv[0], argv[GNoptind - 1]);
887             nextchar += strlen (nextchar);
888             return optstring[0] == ':' ? ':' : '?';
889           }
890         }
891         nextchar += strlen (nextchar);
892         if (longind != NULL)
893           *longind = option_index;
894         if (pfound->flag)
895         {
896           *(pfound->flag) = pfound->val;
897           return 0;
898         }
899         return pfound->val;
900       }
901       nextchar = NULL;
902       return 'W';               /* Let the application handle it.   */
903     }
904     if (temp[1] == ':')
905     {
906       if (temp[2] == ':')
907       {
908         /* This is an option that accepts an argument optionally.  */
909         if (*nextchar != '\0')
910         {
911           GNoptarg = nextchar;
912           GNoptind++;
913         }
914         else
915           GNoptarg = NULL;
916         nextchar = NULL;
917       }
918       else
919       {
920         /* This is an option that requires an argument.  */
921         if (*nextchar != '\0')
922         {
923           GNoptarg = nextchar;
924           /* If we end this ARGV-element by taking the rest as an arg,
925            * we must advance to the next element now.  */
926           GNoptind++;
927         }
928         else if (GNoptind == argc)
929         {
930           if (GNopterr)
931           {
932             /* 1003.2 specifies the format of this message.  */
933             fprintf (stderr,
934                      _("%s: option requires an argument -- %c\n"), argv[0], c);
935           }
936           if (optstring[0] == ':')
937             c = ':';
938           else
939             c = '?';
940         }
941         else
942           /* We already incremented `GNoptind' once;
943            * increment it again when taking next ARGV-elt as argument.  */
944           GNoptarg = argv[GNoptind++];
945         nextchar = NULL;
946       }
947     }
948     return c;
949   }
950 }
951
952 static int
953 GNgetopt_long (int argc,
954                char *const *argv,
955                const char *options,
956                const struct GNoption *long_options, int *opt_index)
957 {
958   return GN_getopt_internal (argc, argv, options, long_options, opt_index, 0);
959 }
960
961 /* ******************** now the GNUnet specific modifications... ********************* */
962
963 /**
964  * Parse the command line.
965  *
966  * @param binaryOptions Name of application with option summary
967  * @param allOptions defined options and handlers
968  * @param argc number of arguments
969  * @param argv actual arguments
970  * @return index into argv with first non-option
971  *   argument, or -1 on error
972  */
973 int
974 GNUNET_GETOPT_run (const char *binaryOptions,
975                    const struct GNUNET_GETOPT_CommandLineOption *allOptions,
976                    unsigned int argc, char *const *argv)
977 {
978   struct GNoption *long_options;
979   struct GNUNET_GETOPT_CommandLineProcessorContext clpc;
980   int count;
981   int i;
982   char *shorts;
983   int spos;
984   int cont;
985   int c;
986
987   GNUNET_assert (argc > 0);
988   GNoptind = 0;
989   clpc.binaryName = argv[0];
990   clpc.binaryOptions = binaryOptions;
991   clpc.allOptions = allOptions;
992   clpc.argv = argv;
993   clpc.argc = argc;
994   count = 0;
995   while (allOptions[count].name != NULL)
996     count++;
997   long_options = GNUNET_malloc (sizeof (struct GNoption) * (count + 1));
998   shorts = GNUNET_malloc (count * 2 + 1);
999   spos = 0;
1000   for (i = 0; i < count; i++)
1001   {
1002     long_options[i].name = allOptions[i].name;
1003     long_options[i].has_arg = allOptions[i].require_argument;
1004     long_options[i].flag = NULL;
1005     long_options[i].val = allOptions[i].shortName;
1006     shorts[spos++] = allOptions[i].shortName;
1007     if (allOptions[i].require_argument != 0)
1008       shorts[spos++] = ':';
1009   }
1010   long_options[count].name = NULL;
1011   long_options[count].has_arg = 0;
1012   long_options[count].flag = NULL;
1013   long_options[count].val = '\0';
1014   shorts[spos] = '\0';
1015   cont = GNUNET_OK;
1016   /* main getopt loop */
1017   while (cont == GNUNET_OK)
1018   {
1019     int option_index = 0;
1020
1021     c = GNgetopt_long (argc, argv, shorts, long_options, &option_index);
1022
1023     if (c == GNUNET_SYSERR)
1024       break;                    /* No more flags to process */
1025
1026     for (i = 0; i < count; i++)
1027     {
1028       clpc.currentArgument = GNoptind - 1;
1029       if ((char) c == allOptions[i].shortName)
1030       {
1031         cont = allOptions[i].processor (&clpc,
1032                                         allOptions[i].scls,
1033                                         allOptions[i].name, GNoptarg);
1034         break;
1035       }
1036     }
1037     if (i == count)
1038     {
1039       fprintf (stderr, _("Use --help to get a list of options.\n"));
1040       cont = GNUNET_SYSERR;
1041     }
1042   }
1043
1044   GNUNET_free (shorts);
1045   GNUNET_free (long_options);
1046   if (cont == GNUNET_SYSERR)
1047     return GNUNET_SYSERR;
1048   return GNoptind;
1049 }
1050
1051 /* end of getopt.c */