My Project
fegetopt.c
Go to the documentation of this file.
1/****************************************
2* Computer Algebra System SINGULAR *
3****************************************/
4
5/* Getopt for GNU.
6 NOTE: getopt is now part of the C library, so if you don't know what
7 "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
8 before changing it!
9
10 Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94
11 Free Software Foundation, Inc.
12
13 This program is free software; you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by the
15 Free Software Foundation; either version 2, or (at your option) any
16 later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
26
27/*
28 obachman 9/99: adapted to Singular by
29 * adding prefix fe_ to global variables
30 * extended fe_option structure
31*/
32
33
34
35
36
37#ifndef __STDC__
38# ifndef const
39# define const
40# endif
41#endif
42
43/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. */
44#ifndef _NO_PROTO
45#define _NO_PROTO
46#endif
47
48#include <stdio.h>
49/* #include "tailor.h" */
50
51/* Comment out all this code if we are using the GNU C Library, and are not
52 actually compiling the library itself. This code is part of the GNU C
53 Library, but also included in many other GNU distributions. Compiling
54 and linking in this code is a waste when using the GNU C library
55 (especially if it is a shared library). Rather than having every GNU
56 program understand `configure --with-gnu-libc' and omit the object files,
57 it is simpler to just do this in the source for each such file. */
58
59/* This needs to come after some library #include
60 to get __GNU_LIBRARY__ defined. */
61#ifdef __GNU_LIBRARY__
62/* Don't include stdlib.h for non-GNU C libraries because some of them
63 contain conflicting prototypes for getopt. */
64#include <stdlib.h>
65#endif /* GNU C library. */
66
67/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
68 long-named option. Because this is not POSIX.2 compliant, it is
69 being phased out. */
70/* #define GETOPT_COMPAT */
71
72/* This version of `getopt' appears to the caller like standard Unix `getopt'
73 but it behaves differently for the user, since it allows the user
74 to intersperse the options with the other arguments.
75
76 As `getopt' works, it permutes the elements of ARGV so that,
77 when it is done, all the options precede everything else. Thus
78 all application programs are extended to handle flexible argument order.
79
80 Setting the environment variable POSIXLY_CORRECT disables permutation.
81 Then the behavior is completely standard.
82
83 GNU application programs can use a third alternative mode in which
84 they can distinguish the relative order of options and other arguments. */
85
86#include "fegetopt.h"
87
88/* For communication from `getopt' to the caller.
89 When `getopt' finds an option that takes an argument,
90 the argument value is returned here.
91 Also, when `ordering' is RETURN_IN_ORDER,
92 each non-option ARGV-element is returned here. */
93
94char *fe_optarg = 0;
95
96/* Index in ARGV of the next element to be scanned.
97 This is used for communication to and from the caller
98 and for communication between successive calls to `getopt'.
99
100 On entry to `getopt', zero means this is the first call; initialize.
101
102 When `getopt' returns EOF, this is the index of the first of the
103 non-option elements that the caller should itself scan.
104
105 Otherwise, `fe_optind' communicates from one call to the next
106 how much of ARGV has been scanned so far. */
107
108/* XXX 1003.2 says this must be 1 before any call. */
109int fe_optind = 0;
110
111/* The next char to be scanned in the option-element
112 in which the last option character we returned was found.
113 This allows us to pick up the scan where we left off.
114
115 If this is zero, or a null string, it means resume the scan
116 by advancing to the next ARGV-element. */
117
118static char *nextchar;
119
120/* Callers store zero here to inhibit the error message
121 for unrecognized options. */
122
123int fe_opterr = 1;
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 getopt implementation. */
128
129#define BAD_OPTION '\0'
131
132/* Describe how to deal with options that follow non-option ARGV-elements.
133
134 If the caller did not specify anything,
135 the default is REQUIRE_ORDER if the environment variable
136 POSIXLY_CORRECT is defined, PERMUTE otherwise.
137
138 REQUIRE_ORDER means don't recognize them as options;
139 stop option processing when the first non-option is seen.
140 This is what Unix does.
141 This mode of operation is selected by either setting the environment
142 variable POSIXLY_CORRECT, or using `+' as the first character
143 of the list of option characters.
144
145 PERMUTE is the default. We permute the contents of ARGV as we scan,
146 so that eventually all the non-options are at the end. This allows options
147 to be given in any order, even with programs that were not written to
148 expect this.
149
150 RETURN_IN_ORDER is an option available to programs that were written
151 to expect options and other ARGV-elements in any order and that care about
152 the ordering of the two. We describe each non-option ARGV-element
153 as if it were the argument of an option with character code 1.
154 Using `-' as the first character of the list of option characters
155 selects this mode of operation.
156
157 The special argument `--' forces an end of option-scanning regardless
158 of the value of `ordering'. In the case of RETURN_IN_ORDER, only
159 `--' can cause `getopt' to return EOF with `fe_optind' != ARGC. */
160
161static enum
162{
165
166#ifdef __GNU_LIBRARY__
167/* We want to avoid inclusion of string.h with non-GNU libraries
168 because there are many ways it can cause trouble.
169 On some systems, it contains special magic macros that don't work
170 in GCC. */
171#include <string.h>
172#define my_index strchr
173#define my_strlen strlen
174#else
175
176/* Avoid depending on library functions or files
177 whose names are inconsistent. */
178
179#if __STDC__ || defined(PROTO)
180extern char *getenv(const char *name);
181extern int strcmp (const char *s1, const char *s2);
182extern int strncmp(const char *s1, const char *s2, size_t n);
183
184static size_t my_strlen(const char *s);
185static const char *my_index (const char *str, int chr);
186#else
187extern char *getenv ();
188#endif
189
190static size_t my_strlen (const char *str)
191{
192 size_t n = 0;
193 while (*str++)
194 n++;
195 return n;
196}
197
198static const char * my_index (const char *str, int chr)
199{
200 while (*str)
201 {
202 if (*str == chr)
203 return (const char *) str;
204 str++;
205 }
206 return 0;
207}
208
209#endif /* GNU C library. */
210
211/* Handle permutation of arguments. */
212
213/* Describe the part of ARGV that contains non-options that have
214 been skipped. `first_nonopt' is the index in ARGV of the first of them;
215 `last_nonopt' is the index after the last of them. */
216
217static int first_nonopt;
218static int last_nonopt;
219
220/* Exchange two adjacent subsequences of ARGV.
221 One subsequence is elements [first_nonopt,last_nonopt)
222 which contains all the non-options that have been skipped so far.
223 The other is elements [last_nonopt,fe_optind), which contains all
224 the options processed since those non-options were skipped.
225
226 `first_nonopt' and `last_nonopt' are relocated so that they describe
227 the new indices of the non-options in ARGV after they are moved.
228
229 To perform the swap, we first reverse the order of all elements. So
230 all options now come before all non options, but they are in the
231 wrong order. So we put back the options and non options in original
232 order by reversing them again. For example:
233 original input: a b c -x -y
234 reverse all: -y -x c b a
235 reverse options: -x -y c b a
236 reverse non options: -x -y a b c
237*/
238
239#if __STDC__ || defined(PROTO)
240static void exchange (char **argv);
241#endif
242
243static void exchange (char **argv)
244{
245 char *temp, **first, **last;
246
247 /* Reverse all the elements [first_nonopt, fe_optind) */
248 first = &argv[first_nonopt];
249 last = &argv[fe_optind-1];
250 while (first < last) {
251 temp = *first; *first = *last; *last = temp; first++; last--;
252 }
253 /* Put back the options in order */
254 first = &argv[first_nonopt];
256 last = &argv[first_nonopt - 1];
257 while (first < last) {
258 temp = *first; *first = *last; *last = temp; first++; last--;
259 }
260
261 /* Put back the non options in order */
262 first = &argv[first_nonopt];
264 last = &argv[last_nonopt-1];
265 while (first < last) {
266 temp = *first; *first = *last; *last = temp; first++; last--;
267 }
268}
269
270/* Scan elements of ARGV (whose length is ARGC) for option characters
271 given in OPTSTRING.
272
273 If an element of ARGV starts with '-', and is not exactly "-" or "--",
274 then it is an option element. The characters of this element
275 (aside from the initial '-') are option characters. If `getopt'
276 is called repeatedly, it returns successively each of the option characters
277 from each of the option elements.
278
279 If `getopt' finds another option character, it returns that character,
280 updating `fe_optind' and `nextchar' so that the next call to `getopt' can
281 resume the scan with the following option character or ARGV-element.
282
283 If there are no more option characters, `getopt' returns `EOF'.
284 Then `fe_optind' is the index in ARGV of the first ARGV-element
285 that is not an option. (The ARGV-elements have been permuted
286 so that those that are not options now come last.)
287
288 OPTSTRING is a string containing the legitimate option characters.
289 If an option character is seen that is not listed in OPTSTRING,
290 return BAD_OPTION after printing an error message. If you set `fe_opterr' to
291 zero, the error message is suppressed but we still return BAD_OPTION.
292
293 If a char in OPTSTRING is followed by a colon, that means it wants an arg,
294 so the following text in the same ARGV-element, or the text of the following
295 ARGV-element, is returned in `fe_optarg'. Two colons mean an option that
296 wants an optional arg; if there is text in the current ARGV-element,
297 it is returned in `fe_optarg', otherwise `fe_optarg' is set to zero.
298
299 If OPTSTRING starts with `-' or `+', it requests different methods of
300 handling the non-option ARGV-elements.
301 See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
302
303 Long-named options begin with `--' instead of `-'.
304 Their names may be abbreviated as long as the abbreviation is unique
305 or is an exact match for some defined option. If they have an
306 argument, it follows the option name in the same ARGV-element, separated
307 from the option name by a `=', or else the in next ARGV-element.
308 When `getopt' finds a long-named option, it returns
309 the value of the option's `val' field.
310
311 The elements of ARGV aren't really const, because we permute them.
312 But we pretend they're const in the prototype to be compatible
313 with other systems.
314
315 LONGOPTS is a vector of `struct fe_option' terminated by an
316 element containing a name which is zero.
317
318 LONGIND returns the index in LONGOPT of the long-named option found.
319 It is only valid when a long-named option has been found by the most
320 recent call.
321
322 If LONG_ONLY is nonzero, '-' as well as '--' can introduce
323 long-named options. */
324
326 int argc,
327 char *const *argv,
328 const char *optstring,
329 const struct fe_option *longopts,
330 int *longind,
331 int long_only)
332{
333 int option_index;
334
335 fe_optarg = 0;
336
337 /* Initialize the internal data when the first call is made.
338 Start processing options with ARGV-element 1 (since ARGV-element 0
339 is the program name); the sequence of previously skipped
340 non-option ARGV-elements is empty. */
341
342 if (fe_optind == 0)
343 {
345
346 nextchar = NULL;
347
348 /* Determine how to handle the ordering of options and nonoptions. */
349
350 if (optstring[0] == '-')
351 {
353 ++optstring;
354 }
355 else if (optstring[0] == '+')
356 {
358 ++optstring;
359 }
360 else if (getenv ("POSIXLY_CORRECT") != NULL)
362 else
364 }
365
366 if (nextchar == NULL || *nextchar == '\0')
367 {
368 if (ordering == PERMUTE)
369 {
370 /* If we have just processed some options following some non-options,
371 exchange them so that the options come first. */
372
374 exchange ((char **) argv);
375 else if (last_nonopt != fe_optind)
377
378 /* Now skip any additional non-options
379 and extend the range of non-options previously skipped. */
380
381 while (fe_optind < argc
382 && (argv[fe_optind][0] != '-' || argv[fe_optind][1] == '\0')
383#ifdef GETOPT_COMPAT
384 && (longopts == NULL
385 || argv[fe_optind][0] != '+' || argv[fe_optind][1] == '\0')
386#endif /* GETOPT_COMPAT */
387 )
388 fe_optind++;
390 }
391
392 /* Special ARGV-element `--' means premature end of options.
393 Skip it like a null option,
394 then exchange with previous non-options as if it were an option,
395 then skip everything else like a non-option. */
396
397 if (fe_optind != argc && !strcmp (argv[fe_optind], "--"))
398 {
399 fe_optind++;
400
402 exchange ((char **) argv);
403 else if (first_nonopt == last_nonopt)
405 last_nonopt = argc;
406
407 fe_optind = argc;
408 }
409
410 /* If we have done all the ARGV-elements, stop the scan
411 and back over any non-options that we skipped and permuted. */
412
413 if (fe_optind == argc)
414 {
415 /* Set the next-arg-index to point at the non-options
416 that we previously skipped, so the caller will digest them. */
419 return EOF;
420 }
421
422 /* If we have come to a non-option and did not permute it,
423 either stop the scan or describe it to the caller and pass it by. */
424
425 if ((argv[fe_optind][0] != '-' || argv[fe_optind][1] == '\0')
426#ifdef GETOPT_COMPAT
427 && (longopts == NULL
428 || argv[fe_optind][0] != '+' || argv[fe_optind][1] == '\0')
429#endif /* GETOPT_COMPAT */
430 )
431 {
432 if (ordering == REQUIRE_ORDER)
433 return EOF;
434 fe_optarg = argv[fe_optind++];
435 return 1;
436 }
437
438 /* We have found another option-ARGV-element.
439 Start decoding its characters. */
440
441 nextchar = (argv[fe_optind] + 1
442 + (longopts != NULL && argv[fe_optind][1] == '-'));
443 }
444
445 if (longopts != NULL
446 && ((argv[fe_optind][0] == '-'
447 && (argv[fe_optind][1] == '-' || long_only))
448#ifdef GETOPT_COMPAT
449 || argv[fe_optind][0] == '+'
450#endif /* GETOPT_COMPAT */
451 ))
452 {
453 const struct fe_option *p;
454 char *s = nextchar;
455 int exact = 0;
456 int ambig = 0;
457 const struct fe_option *pfound = NULL;
458 int indfound = 0;
459
460 while (*s && *s != '=')
461 s++;
462
463 /* Test all options for either exact match or abbreviated matches. */
464 for (p = longopts, option_index = 0; p->name;
465 p++, option_index++)
466 if (!strncmp (p->name, nextchar, s - nextchar))
467 {
468 if (s - nextchar == (long)my_strlen (p->name))
469 {
470 /* Exact match found. */
471 pfound = p;
472 indfound = option_index;
473 exact = 1;
474 break;
475 }
476 else if (pfound == NULL)
477 {
478 /* First nonexact match found. */
479 pfound = p;
480 indfound = option_index;
481 }
482 else
483 /* Second nonexact match found. */
484 ambig = 1;
485 }
486
487 if (ambig && !exact)
488 {
489 if (fe_opterr)
490 fprintf (stderr, "%s: option `%s' is ambiguous\n",
491 argv[0], argv[fe_optind]);
493 fe_optind++;
494 return BAD_OPTION;
495 }
496
497 if (pfound != NULL)
498 {
499 option_index = indfound;
500 fe_optind++;
501 if (*s)
502 {
503 /* Don't test has_arg with >, because some C compilers don't
504 allow it to be used on enums. */
505 if (pfound->has_arg)
506 fe_optarg = s + 1;
507 else
508 {
509 if (fe_opterr)
510 {
511 if (argv[fe_optind - 1][1] == '-')
512 /* --option */
513 fprintf (stderr,
514 "%s: option `--%s' doesn't allow an argument\n",
515 argv[0], pfound->name);
516 else
517 /* +option or -option */
518 fprintf (stderr,
519 "%s: option `%c%s' doesn't allow an argument\n",
520 argv[0], argv[fe_optind - 1][0], pfound->name);
521 }
523 return BAD_OPTION;
524 }
525 }
526 else if (pfound->has_arg == 1)
527 {
528 if (fe_optind < argc)
529 fe_optarg = argv[fe_optind++];
530 else
531 {
532 if (fe_opterr)
533 fprintf (stderr, "%s: option `%s' requires an argument\n",
534 argv[0], argv[fe_optind - 1]);
536 return optstring[0] == ':' ? ':' : BAD_OPTION;
537 }
538 }
540 if (longind != NULL)
541 *longind = option_index;
542 return pfound->val;
543 }
544 /* Can't find it as a long option. If this is not getopt_long_only,
545 or the option starts with '--' or is not a valid short
546 option, then it's an error.
547 Otherwise interpret it as a short option. */
548 if (!long_only || argv[fe_optind][1] == '-'
549#ifdef GETOPT_COMPAT
550 || argv[fe_optind][0] == '+'
551#endif /* GETOPT_COMPAT */
552 || my_index (optstring, *nextchar) == NULL)
553 {
554 if (fe_opterr)
555 {
556 if (argv[fe_optind][1] == '-')
557 /* --option */
558 fprintf (stderr, "%s: unrecognized option `--%s'\n",
559 argv[0], nextchar);
560 else
561 /* +option or -option */
562 fprintf (stderr, "%s: unrecognized option `%c%s'\n",
563 argv[0], argv[fe_optind][0], nextchar);
564 }
565 nextchar = (char *) "";
566 fe_optind++;
567 return BAD_OPTION;
568 }
569 }
570
571 /* Look at and handle the next option-character. */
572
573 {
574 char c = *nextchar++;
575 const char *temp = my_index (optstring, c);
576
577 /* Increment `fe_optind' when we start to process its last character. */
578 if (*nextchar == '\0')
579 ++fe_optind;
580
581 if (temp == NULL || c == ':')
582 {
583 if (fe_opterr)
584 {
585#if 0
586 if (c < 040 || c >= 0177)
587 fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
588 argv[0], c);
589 else
590 fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
591#else
592 /* 1003.2 specifies the format of this message. */
593 fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
594#endif
595 }
596 fe_optopt = c;
597 return BAD_OPTION;
598 }
599 if (temp[1] == ':')
600 {
601 if (temp[2] == ':')
602 {
603 /* This is an option that accepts an argument optionally. */
604 if (*nextchar != '\0')
605 {
607 fe_optind++;
608 }
609 else
610 fe_optarg = 0;
611 nextchar = NULL;
612 }
613 else
614 {
615 /* This is an option that requires an argument. */
616 if (*nextchar != '\0')
617 {
619 /* If we end this ARGV-element by taking the rest as an arg,
620 we must advance to the next element now. */
621 fe_optind++;
622 }
623 else if (fe_optind == argc)
624 {
625 if (fe_opterr)
626 {
627#if 0
628 fprintf (stderr, "%s: option `-%c' requires an argument\n",
629 argv[0], c);
630#else
631 /* 1003.2 specifies the format of this message. */
632 fprintf (stderr, "%s: option requires an argument -- %c\n",
633 argv[0], c);
634#endif
635 }
636 fe_optopt = c;
637 if (optstring[0] == ':')
638 c = ':';
639 else
640 c = BAD_OPTION;
641 }
642 else
643 /* We already incremented `fe_optind' once;
644 increment it again when taking next ARGV-elt as argument. */
645 fe_optarg = argv[fe_optind++];
646 nextchar = NULL;
647 }
648 }
649 return c;
650 }
651}
652
654 int argc,
655 char *const *argv,
656 const char *optstring)
657{
658 return _fe_getopt_internal (argc, argv, optstring,
659 (const struct fe_option *) 0,
660 (int *) 0,
661 0);
662}
663
665 int argc,
666 char *const *argv,
667 const char *options,
668 const struct fe_option *long_options,
669 int *opt_index)
670{
671 return _fe_getopt_internal (argc, argv, options, long_options, opt_index, 0);
672}
673
675 int argc,
676 char *const *argv,
677 const char *options,
678 const struct fe_option *long_options,
679 int *opt_index)
680{
681 return _fe_getopt_internal (argc, argv, options, long_options, opt_index, 1);
682}
683
684#ifdef TEST_GETOPT
685
686/* Compile with -DTEST_GETOPT to make an executable for use in testing
687 the above definition of `getopt'. */
688
689int main (int argc, char **argv)
690{
691 int c;
692 int digit_optind = 0;
693
694 while (1)
695 {
696 int this_option_optind = optind ? optind : 1;
697
698 c = fe_getopt (argc, argv, "abc:d:0123456789");
699 if (c == EOF)
700 break;
701
702 switch (c)
703 {
704 case '0':
705 case '1':
706 case '2':
707 case '3':
708 case '4':
709 case '5':
710 case '6':
711 case '7':
712 case '8':
713 case '9':
714 if (digit_optind != 0 && digit_optind != this_option_optind)
715 printf ("digits occur in two different argv-elements.\n");
716 digit_optind = this_option_optind;
717 printf ("option %c\n", c);
718 break;
719
720 case 'a':
721 printf ("option a\n");
722 break;
723
724 case 'b':
725 printf ("option b\n");
726 break;
727
728 case 'c':
729 printf ("option c with value `%s'\n", fe_optarg);
730 break;
731
732 case BAD_OPTION:
733 break;
734
735 default:
736 printf ("?? fe_getopt returned character code 0%o ??\n", c);
737 }
738 }
739
740 if (fe_optind < argc)
741 {
742 printf ("non-option ARGV-elements: ");
743 while (fe_optind < argc)
744 printf ("%s ", argv[fe_optind++]);
745 printf ("\n");
746 }
747
748 exit (0);
749}
750
751#endif /* TEST_GETOPT */
int p
Definition: cfModGcd.cc:4078
const CanonicalForm int s
Definition: facAbsFact.cc:51
char name(const Variable &v)
Definition: factory.h:189
@ REQUIRE_ORDER
Definition: fegetopt.c:163
@ RETURN_IN_ORDER
Definition: fegetopt.c:163
@ PERMUTE
Definition: fegetopt.c:163
int fe_getopt(int argc, char *const *argv, const char *optstring)
Definition: fegetopt.c:653
#define BAD_OPTION
Definition: fegetopt.c:129
int fe_getopt_long_only(int argc, char *const *argv, const char *options, const struct fe_option *long_options, int *opt_index)
Definition: fegetopt.c:674
static enum @0 ordering
int fe_getopt_long(int argc, char *const *argv, const char *options, const struct fe_option *long_options, int *opt_index)
Definition: fegetopt.c:664
static void exchange(char **argv)
Definition: fegetopt.c:243
static size_t my_strlen(const char *str)
Definition: fegetopt.c:190
static char * nextchar
Definition: fegetopt.c:118
char * fe_optarg
Definition: fegetopt.c:94
int _fe_getopt_internal(int argc, char *const *argv, const char *optstring, const struct fe_option *longopts, int *longind, int long_only)
Definition: fegetopt.c:325
static int last_nonopt
Definition: fegetopt.c:218
static const char * my_index(const char *str, int chr)
Definition: fegetopt.c:198
int fe_opterr
Definition: fegetopt.c:123
static int first_nonopt
Definition: fegetopt.c:217
int fe_optind
Definition: fegetopt.c:109
int fe_optopt
Definition: fegetopt.c:130
char * getenv()
int val
Definition: fegetopt.h:88
char * name
Definition: fegetopt.h:83
int has_arg
Definition: fegetopt.h:87
STATIC_VAR poly last
Definition: hdegree.cc:1173
char * str(leftv arg)
Definition: shared.cc:704
#define NULL
Definition: omList.c:12
int main(int argc, char *argv[])
Definition: omTables.c:165