blob: 6edf186a390974a9b53e366b457a5c91ce014d01 [file] [log] [blame]
Tristan Matthews0a329cc2013-07-17 13:20:14 -04001/* $Id$ */
2/*
3 * pj_getopt entry points
4 *
5 * modified by Mike Borella <mike_borella@mw.3com.com>
6 */
7
8#include <pjlib-util/getopt.h>
9#include <pj/string.h>
10
11/* Internal only. Users should not call this directly. */
12static
13int _getopt_internal (int argc, char *const *argv,
14 const char *shortopts,
15 const struct pj_getopt_option *longopts, int *longind,
16 int long_only);
17
18/* pj_getopt_long and pj_getopt_long_only entry points for GNU pj_getopt.
19 Copyright (C) 1987,88,89,90,91,92,93,94,96,97 Free Software Foundation, Inc.
20 This file is part of the GNU C Library.
21
22 The GNU C Library is free software; you can redistribute it and/or
23 modify it under the terms of the GNU Library General Public License as
24 published by the Free Software Foundation; either version 2 of the
25 License, or (at your option) any later version.
26
27 The GNU C Library is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 Library General Public License for more details.
31
32 You should have received a copy of the GNU Library General Public
33 License along with the GNU C Library; see the file COPYING.LIB. If not,
34 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
35 Boston, MA 02111-1307, USA. */
36
37
38/* Comment out all this code if we are using the GNU C Library, and are not
39 actually compiling the library itself. This code is part of the GNU C
40 Library, but also included in many other GNU distributions. Compiling
41 and linking in this code is a waste when using the GNU C library
42 (especially if it is a shared library). Rather than having every GNU
43 program understand `configure --with-gnu-libc' and omit the object files,
44 it is simpler to just do this in the source for each such file. */
45
46# define GETOPT_INTERFACE_VERSION 2
47
48
49int
50pj_getopt_long (int argc, char *const *argv, const char *options,
51 const struct pj_getopt_option *long_options, int *opt_index)
52{
53 return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
54}
55
56/* Like pj_getopt_long, but '-' as well as '--' can indicate a long option.
57 If an option that starts with '-' (not '--') doesn't match a long option,
58 but does match a short option, it is parsed as a short option
59 instead. */
60
61int
62pj_getopt (int argc, char * const * argv, const char * optstring)
63{
64 return _getopt_internal (argc, argv, optstring,
65 (const struct pj_getopt_option *) 0,
66 (int *) 0,
67 0);
68}
69
70
71#define _(msgid) (msgid)
72
73/* This version of `pj_getopt' appears to the caller like standard Unix `pj_getopt'
74 but it behaves differently for the user, since it allows the user
75 to intersperse the options with the other arguments.
76
77 As `pj_getopt' works, it permutes the elements of ARGV so that,
78 when it is done, all the options precede everything else. Thus
79 all application programs are extended to handle flexible argument order.
80
81 Setting the environment variable POSIXLY_CORRECT disables permutation.
82 Then the behavior is completely standard.
83
84 GNU application programs can use a third alternative mode in which
85 they can distinguish the relative order of options and other arguments. */
86
87/* For communication from `pj_getopt' to the caller.
88 When `pj_getopt' finds an option that takes an argument,
89 the argument value is returned here.
90 Also, when `ordering' is RETURN_IN_ORDER,
91 each non-option ARGV-element is returned here. */
92
93char *pj_optarg = NULL;
94
95/* Index in ARGV of the next element to be scanned.
96 This is used for communication to and from the caller
97 and for communication between successive calls to `pj_getopt'.
98
99 On entry to `pj_getopt', zero means this is the first call; initialize.
100
101 When `pj_getopt' returns -1, this is the index of the first of the
102 non-option elements that the caller should itself scan.
103
104 Otherwise, `pj_optind' communicates from one call to the next
105 how much of ARGV has been scanned so far. */
106
107/* 1003.2 says this must be 1 before any call. */
108int pj_optind = 1;
109
110/* Formerly, initialization of pj_getopt depended on pj_optind==0, which
111 causes problems with re-calling pj_getopt as programs generally don't
112 know that. */
113
114int __getopt_initialized = 0;
115
116/* The next char to be scanned in the option-element
117 in which the last option character we returned was found.
118 This allows us to pick up the scan where we left off.
119
120 If this is zero, or a null string, it means resume the scan
121 by advancing to the next ARGV-element. */
122
123static char *nextchar;
124
125/* Set to an option character which was unrecognized.
126 This must be initialized on some systems to avoid linking in the
127 system's own pj_getopt implementation. */
128
129int pj_optopt = '?';
130
131/* Describe how to deal with options that follow non-option ARGV-elements.
132
133 If the caller did not specify anything,
134 the default is REQUIRE_ORDER if the environment variable
135 POSIXLY_CORRECT is defined, PERMUTE otherwise.
136
137 REQUIRE_ORDER means don't recognize them as options;
138 stop option processing when the first non-option is seen.
139 This is what Unix does.
140 This mode of operation is selected by either setting the environment
141 variable POSIXLY_CORRECT, or using `+' as the first character
142 of the list of option characters.
143
144 PERMUTE is the default. We permute the contents of ARGV as we scan,
145 so that eventually all the non-options are at the end. This allows options
146 to be given in any order, even with programs that were not written to
147 expect this.
148
149 RETURN_IN_ORDER is an option available to programs that were written
150 to expect options and other ARGV-elements in any order and that care about
151 the ordering of the two. We describe each non-option ARGV-element
152 as if it were the argument of an option with character code 1.
153 Using `-' as the first character of the list of option characters
154 selects this mode of operation.
155
156 The special argument `--' forces an end of option-scanning regardless
157 of the value of `ordering'. In the case of RETURN_IN_ORDER, only
158 `--' can cause `pj_getopt' to return -1 with `pj_optind' != ARGC. */
159
160static enum
161{
162 REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
163} ordering;
164
165/* Value of POSIXLY_CORRECT environment variable. */
166static char *posixly_correct;
167
168static char *
169my_index (const char *str, int chr)
170{
171 while (*str)
172 {
173 if (*str == chr)
174 return (char *) str;
175 str++;
176 }
177 return 0;
178}
179
180
181/* Handle permutation of arguments. */
182
183/* Describe the part of ARGV that contains non-options that have
184 been skipped. `first_nonopt' is the index in ARGV of the first of them;
185 `last_nonopt' is the index after the last of them. */
186
187static int first_nonopt;
188static int last_nonopt;
189
190# define SWAP_FLAGS(ch1, ch2)
191
192/* Exchange two adjacent subsequences of ARGV.
193 One subsequence is elements [first_nonopt,last_nonopt)
194 which contains all the non-options that have been skipped so far.
195 The other is elements [last_nonopt,pj_optind), which contains all
196 the options processed since those non-options were skipped.
197
198 `first_nonopt' and `last_nonopt' are relocated so that they describe
199 the new indices of the non-options in ARGV after they are moved. */
200
201static void
202exchange (char **argv)
203{
204 int bottom = first_nonopt;
205 int middle = last_nonopt;
206 int top = pj_optind;
207 char *tem;
208
209 /* Exchange the shorter segment with the far end of the longer segment.
210 That puts the shorter segment into the right place.
211 It leaves the longer segment in the right place overall,
212 but it consists of two parts that need to be swapped next. */
213
214 while (top > middle && middle > bottom)
215 {
216 if (top - middle > middle - bottom)
217 {
218 /* Bottom segment is the short one. */
219 int len = middle - bottom;
220 register int i;
221
222 /* Swap it with the top part of the top segment. */
223 for (i = 0; i < len; i++)
224 {
225 tem = argv[bottom + i];
226 argv[bottom + i] = argv[top - (middle - bottom) + i];
227 argv[top - (middle - bottom) + i] = tem;
228 SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
229 }
230 /* Exclude the moved bottom segment from further swapping. */
231 top -= len;
232 }
233 else
234 {
235 /* Top segment is the short one. */
236 int len = top - middle;
237 register int i;
238
239 /* Swap it with the bottom part of the bottom segment. */
240 for (i = 0; i < len; i++)
241 {
242 tem = argv[bottom + i];
243 argv[bottom + i] = argv[middle + i];
244 argv[middle + i] = tem;
245 SWAP_FLAGS (bottom + i, middle + i);
246 }
247 /* Exclude the moved top segment from further swapping. */
248 bottom += len;
249 }
250 }
251
252 /* Update records for the slots the non-options now occupy. */
253
254 first_nonopt += (pj_optind - last_nonopt);
255 last_nonopt = pj_optind;
256}
257
258/* Initialize the internal data when the first call is made. */
259
260static const char *_getopt_initialize (int argc, char *const *argv,
261 const char *optstring)
262{
263 PJ_UNUSED_ARG(argc);
264 PJ_UNUSED_ARG(argv);
265
266 /* Start processing options with ARGV-element 1 (since ARGV-element 0
267 is the program name); the sequence of previously skipped
268 non-option ARGV-elements is empty. */
269
270 first_nonopt = last_nonopt = pj_optind;
271
272 nextchar = NULL;
273
274 //posixly_correct = getenv ("POSIXLY_CORRECT");
275 posixly_correct = NULL;
276
277 /* Determine how to handle the ordering of options and nonoptions. */
278
279 if (optstring[0] == '-')
280 {
281 ordering = RETURN_IN_ORDER;
282 ++optstring;
283 }
284 else if (optstring[0] == '+')
285 {
286 ordering = REQUIRE_ORDER;
287 ++optstring;
288 }
289 else if (posixly_correct != NULL)
290 ordering = REQUIRE_ORDER;
291 else
292 ordering = PERMUTE;
293
294 return optstring;
295}
296
297/* Scan elements of ARGV (whose length is ARGC) for option characters
298 given in OPTSTRING.
299
300 If an element of ARGV starts with '-', and is not exactly "-" or "--",
301 then it is an option element. The characters of this element
302 (aside from the initial '-') are option characters. If `pj_getopt'
303 is called repeatedly, it returns successively each of the option characters
304 from each of the option elements.
305
306 If `pj_getopt' finds another option character, it returns that character,
307 updating `pj_optind' and `nextchar' so that the next call to `pj_getopt' can
308 resume the scan with the following option character or ARGV-element.
309
310 If there are no more option characters, `pj_getopt' returns -1.
311 Then `pj_optind' is the index in ARGV of the first ARGV-element
312 that is not an option. (The ARGV-elements have been permuted
313 so that those that are not options now come last.)
314
315 OPTSTRING is a string containing the legitimate option characters.
316 If an option character is seen that is not listed in OPTSTRING,
317 return '?' after printing an error message. If you set `pj_opterr' to
318 zero, the error message is suppressed but we still return '?'.
319
320 If a char in OPTSTRING is followed by a colon, that means it wants an arg,
321 so the following text in the same ARGV-element, or the text of the following
322 ARGV-element, is returned in `pj_optarg'. Two colons mean an option that
323 wants an optional arg; if there is text in the current ARGV-element,
324 it is returned in `pj_optarg', otherwise `pj_optarg' is set to zero.
325
326 If OPTSTRING starts with `-' or `+', it requests different methods of
327 handling the non-option ARGV-elements.
328 See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
329
330 Long-named options begin with `--' instead of `-'.
331 Their names may be abbreviated as long as the abbreviation is unique
332 or is an exact match for some defined option. If they have an
333 argument, it follows the option name in the same ARGV-element, separated
334 from the option name by a `=', or else the in next ARGV-element.
335 When `pj_getopt' finds a long-named option, it returns 0 if that option's
336 `flag' field is nonzero, the value of the option's `val' field
337 if the `flag' field is zero.
338
339 The elements of ARGV aren't really const, because we permute them.
340 But we pretend they're const in the prototype to be compatible
341 with other systems.
342
343 LONGOPTS is a vector of `struct pj_getopt_option' terminated by an
344 element containing a name which is zero.
345
346 LONGIND returns the index in LONGOPT of the long-named option found.
347 It is only valid when a long-named option has been found by the most
348 recent call.
349
350 If LONG_ONLY is nonzero, '-' as well as '--' can introduce
351 long-named options. */
352
353static int
354_getopt_internal (int argc, char *const *argv, const char *optstring,
355 const struct pj_getopt_option *longopts, int *longind,
356 int long_only)
357{
358 pj_optarg = NULL;
359
360 if (pj_optind == 0 || !__getopt_initialized)
361 {
362 if (pj_optind == 0)
363 pj_optind = 1; /* Don't scan ARGV[0], the program name. */
364 optstring = _getopt_initialize (argc, argv, optstring);
365 __getopt_initialized = 1;
366 }
367
368 /* Test whether ARGV[pj_optind] points to a non-option argument.
369 Either it does not have option syntax, or there is an environment flag
370 from the shell indicating it is not an option. The later information
371 is only used when the used in the GNU libc. */
372#define NONOPTION_P (argv[pj_optind][0] != '-' || argv[pj_optind][1] == '\0')
373
374 if (nextchar == NULL || *nextchar == '\0')
375 {
376 /* Advance to the next ARGV-element. */
377
378 /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
379 moved back by the user (who may also have changed the arguments). */
380 if (last_nonopt > pj_optind)
381 last_nonopt = pj_optind;
382 if (first_nonopt > pj_optind)
383 first_nonopt = pj_optind;
384
385 if (ordering == PERMUTE)
386 {
387 /* If we have just processed some options following some non-options,
388 exchange them so that the options come first. */
389
390 if (first_nonopt != last_nonopt && last_nonopt != pj_optind)
391 exchange ((char **) argv);
392 else if (last_nonopt != pj_optind)
393 first_nonopt = pj_optind;
394
395 /* Skip any additional non-options
396 and extend the range of non-options previously skipped. */
397
398 while (pj_optind < argc && NONOPTION_P)
399 pj_optind++;
400 last_nonopt = pj_optind;
401 }
402
403 /* The special ARGV-element `--' means premature end of options.
404 Skip it like a null option,
405 then exchange with previous non-options as if it were an option,
406 then skip everything else like a non-option. */
407
408 if (pj_optind != argc && !pj_ansi_strcmp(argv[pj_optind], "--"))
409 {
410 pj_optind++;
411
412 if (first_nonopt != last_nonopt && last_nonopt != pj_optind)
413 exchange ((char **) argv);
414 else if (first_nonopt == last_nonopt)
415 first_nonopt = pj_optind;
416 last_nonopt = argc;
417
418 pj_optind = argc;
419 }
420
421 /* If we have done all the ARGV-elements, stop the scan
422 and back over any non-options that we skipped and permuted. */
423
424 if (pj_optind == argc)
425 {
426 /* Set the next-arg-index to point at the non-options
427 that we previously skipped, so the caller will digest them. */
428 if (first_nonopt != last_nonopt)
429 pj_optind = first_nonopt;
430 return -1;
431 }
432
433 /* If we have come to a non-option and did not permute it,
434 either stop the scan or describe it to the caller and pass it by. */
435
436 if (NONOPTION_P)
437 {
438 if (ordering == REQUIRE_ORDER)
439 return -1;
440 pj_optarg = argv[pj_optind++];
441 return 1;
442 }
443
444 /* We have found another option-ARGV-element.
445 Skip the initial punctuation. */
446
447 nextchar = (argv[pj_optind] + 1
448 + (longopts != NULL && argv[pj_optind][1] == '-'));
449 }
450
451 /* Decode the current option-ARGV-element. */
452
453 /* Check whether the ARGV-element is a long option.
454
455 If long_only and the ARGV-element has the form "-f", where f is
456 a valid short option, don't consider it an abbreviated form of
457 a long option that starts with f. Otherwise there would be no
458 way to give the -f short option.
459
460 On the other hand, if there's a long option "fubar" and
461 the ARGV-element is "-fu", do consider that an abbreviation of
462 the long option, just like "--fu", and not "-f" with arg "u".
463
464 This distinction seems to be the most useful approach. */
465
466 if (longopts != NULL
467 && (argv[pj_optind][1] == '-'
468 || (long_only && (argv[pj_optind][2] || !my_index (optstring, argv[pj_optind][1])))))
469 {
470 char *nameend;
471 const struct pj_getopt_option *p;
472 const struct pj_getopt_option *pfound = NULL;
473 int exact = 0;
474 int ambig = 0;
475 int indfound = -1;
476 int option_index;
477
478 for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
479 /* Do nothing. */ ;
480
481 /* Test all long options for either exact match
482 or abbreviated matches. */
483 for (p = longopts, option_index = 0; p->name; p++, option_index++)
484 if (!strncmp (p->name, nextchar, nameend - nextchar))
485 {
486 if ((unsigned int) (nameend - nextchar)
487 == (unsigned int) strlen (p->name))
488 {
489 /* Exact match found. */
490 pfound = p;
491 indfound = option_index;
492 exact = 1;
493 break;
494 }
495 else if (pfound == NULL)
496 {
497 /* First nonexact match found. */
498 pfound = p;
499 indfound = option_index;
500 }
501 else
502 /* Second or later nonexact match found. */
503 ambig = 1;
504 }
505
506 if (ambig && !exact)
507 {
508 nextchar += strlen (nextchar);
509 pj_optind++;
510 pj_optopt = 0;
511 return '?';
512 }
513
514 if (pfound != NULL)
515 {
516 option_index = indfound;
517 pj_optind++;
518 if (*nameend)
519 {
520 /* Don't test has_arg with >, because some C compilers don't
521 allow it to be used on enums. */
522 if (pfound->has_arg)
523 pj_optarg = nameend + 1;
524 else
525 {
526 nextchar += strlen (nextchar);
527
528 pj_optopt = pfound->val;
529 return '?';
530 }
531 }
532 else if (pfound->has_arg == 1)
533 {
534 if (pj_optind < argc)
535 pj_optarg = argv[pj_optind++];
536 else
537 {
538 nextchar += strlen (nextchar);
539 pj_optopt = pfound->val;
540 return optstring[0] == ':' ? ':' : '?';
541 }
542 }
543 nextchar += strlen (nextchar);
544 if (longind != NULL)
545 *longind = option_index;
546 if (pfound->flag)
547 {
548 *(pfound->flag) = pfound->val;
549 return 0;
550 }
551 return pfound->val;
552 }
553
554 /* Can't find it as a long option. If this is not pj_getopt_long_only,
555 or the option starts with '--' or is not a valid short
556 option, then it's an error.
557 Otherwise interpret it as a short option. */
558 if (!long_only || argv[pj_optind][1] == '-'
559 || my_index (optstring, *nextchar) == NULL)
560 {
561 nextchar = (char *) "";
562 pj_optind++;
563 pj_optopt = 0;
564 return '?';
565 }
566 }
567
568 /* Look at and handle the next short option-character. */
569
570 {
571 char c = *nextchar++;
572 char *temp = my_index (optstring, c);
573
574 /* Increment `pj_optind' when we start to process its last character. */
575 if (*nextchar == '\0')
576 ++pj_optind;
577
578 if (temp == NULL || c == ':')
579 {
580 pj_optopt = c;
581 return '?';
582 }
583 /* Convenience. Treat POSIX -W foo same as long option --foo */
584 if (temp[0] == 'W' && temp[1] == ';')
585 {
586 char *nameend;
587 const struct pj_getopt_option *p;
588 const struct pj_getopt_option *pfound = NULL;
589 int exact = 0;
590 int ambig = 0;
591 int indfound = 0;
592 int option_index;
593
594 /* This is an option that requires an argument. */
595 if (*nextchar != '\0')
596 {
597 pj_optarg = nextchar;
598 /* If we end this ARGV-element by taking the rest as an arg,
599 we must advance to the next element now. */
600 pj_optind++;
601 }
602 else if (pj_optind == argc)
603 {
604 pj_optopt = c;
605 if (optstring[0] == ':')
606 c = ':';
607 else
608 c = '?';
609 return c;
610 }
611 else
612 /* We already incremented `pj_optind' once;
613 increment it again when taking next ARGV-elt as argument. */
614 pj_optarg = argv[pj_optind++];
615
616 /* pj_optarg is now the argument, see if it's in the
617 table of longopts. */
618
619 for (nextchar = nameend = pj_optarg; *nameend && *nameend != '='; nameend++)
620 /* Do nothing. */ ;
621
622 /* Test all long options for either exact match
623 or abbreviated matches. */
624 for (p = longopts, option_index = 0; p->name; p++, option_index++)
625 if (!strncmp (p->name, nextchar, nameend - nextchar))
626 {
627 if ((unsigned int) (nameend - nextchar) == strlen (p->name))
628 {
629 /* Exact match found. */
630 pfound = p;
631 indfound = option_index;
632 exact = 1;
633 break;
634 }
635 else if (pfound == NULL)
636 {
637 /* First nonexact match found. */
638 pfound = p;
639 indfound = option_index;
640 }
641 else
642 /* Second or later nonexact match found. */
643 ambig = 1;
644 }
645 if (ambig && !exact)
646 {
647 nextchar += strlen (nextchar);
648 pj_optind++;
649 return '?';
650 }
651 if (pfound != NULL)
652 {
653 option_index = indfound;
654 if (*nameend)
655 {
656 /* Don't test has_arg with >, because some C compilers don't
657 allow it to be used on enums. */
658 if (pfound->has_arg)
659 pj_optarg = nameend + 1;
660 else
661 {
662 nextchar += strlen (nextchar);
663 return '?';
664 }
665 }
666 else if (pfound->has_arg == 1)
667 {
668 if (pj_optind < argc)
669 pj_optarg = argv[pj_optind++];
670 else
671 {
672 nextchar += strlen (nextchar);
673 return optstring[0] == ':' ? ':' : '?';
674 }
675 }
676 nextchar += strlen (nextchar);
677 if (longind != NULL)
678 *longind = option_index;
679 if (pfound->flag)
680 {
681 *(pfound->flag) = pfound->val;
682 return 0;
683 }
684 return pfound->val;
685 }
686 nextchar = NULL;
687 return 'W'; /* Let the application handle it. */
688 }
689 if (temp[1] == ':')
690 {
691 if (temp[2] == ':')
692 {
693 /* This is an option that accepts an argument optionally. */
694 if (*nextchar != '\0')
695 {
696 pj_optarg = nextchar;
697 pj_optind++;
698 }
699 else
700 pj_optarg = NULL;
701 nextchar = NULL;
702 }
703 else
704 {
705 /* This is an option that requires an argument. */
706 if (*nextchar != '\0')
707 {
708 pj_optarg = nextchar;
709 /* If we end this ARGV-element by taking the rest as an arg,
710 we must advance to the next element now. */
711 pj_optind++;
712 }
713 else if (pj_optind == argc)
714 {
715 pj_optopt = c;
716 if (optstring[0] == ':')
717 c = ':';
718 else
719 c = '?';
720 }
721 else
722 /* We already incremented `pj_optind' once;
723 increment it again when taking next ARGV-elt as argument. */
724 pj_optarg = argv[pj_optind++];
725 nextchar = NULL;
726 }
727 }
728 return c;
729 }
730}
731