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 
94 char *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. */
109 int 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 
118 static char *nextchar;
119 
120 /* Callers store zero here to inhibit the error message
121  for unrecognized options. */
122 
123 int 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 
161 static 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)
180 extern char *getenv(const char *name);
181 extern int strcmp (const char *s1, const char *s2);
182 extern int strncmp(const char *s1, const char *s2, size_t n);
183 
184 static size_t my_strlen(const char *s);
185 static const char *my_index (const char *str, int chr);
186 #else
187 extern char *getenv ();
188 #endif
189 
190 static size_t my_strlen (const char *str)
191 {
192  size_t n = 0;
193  while (*str++)
194  n++;
195  return n;
196 }
197 
198 static 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 
217 static int first_nonopt;
218 static 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)
240 static void exchange (char **argv);
241 #endif
242 
243 static 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
363  ordering = PERMUTE;
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. */
417  if (first_nonopt != last_nonopt)
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 
689 int 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
int fe_opterr
Definition: fegetopt.c:123
static int first_nonopt
Definition: fegetopt.c:217
int fe_optind
Definition: fegetopt.c:109
static const char * my_index(const char *str, int chr)
Definition: fegetopt.c:198
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