bschwart@elbereth.rutgers.edu (some great stormfowl, whenever he has walked his while) (12/05/89)
#! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: readme getopt.c makefile # Wrapped by trashman@crud on Mon Dec 04 23:38:47 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f readme -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"readme\" else echo shar: Extracting \"readme\" \(594 characters\) sed "s/^X//" >readme <<'END_OF_readme' XGNU getopt for MSDOS and Microsoft C. X XEnclosed: X X * README This file (the appetizer). X * GETOPT.C The main course. X * MAKEFILE The dessert, an ndmake-file X that makes libraries and a test X program. X XThe MSDOS-specific capabilities are invoked Xby defining MSDOS_FLAGS at compile time. XIn particular, "/" is allowed as a synonym Xfor "-" and "/-" as a synonym for "--". X XI chose to hack the GNU getopt after hacking Xthe AT&T getopt and realising that it wouldn't Xallow for "/" style flags after non-option arguments-- Xnot very MSDOS-like behaviour. X X -- Barry Schwartz, Dec. 1989 END_OF_readme if test 594 -ne `wc -c <readme`; then echo shar: \"readme\" unpacked with wrong size! fi # end of overwriting check fi if test -f getopt.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"getopt.c\" else echo shar: Extracting \"getopt.c\" \(18046 characters\) sed "s/^X//" >getopt.c <<'END_OF_getopt.c' X/*- X * GNU getopt, hacked for MSDOS and Microsoft C 5.1 and QuickC. X * X * Barry Schwartz, Dec. 1989 X * X * New compile-time defs: X * MSDOS Defined by Microsoft compilers X * MSDOS_FLAGS Allow "/" as a synonym for "-" X * and "/-" as a synonym for "--" X * PROTO ANSI-style parameters X */ X X/* X * Getopt for GNU. Copyright (C) 1987 Free Software Foundation, Inc. X * X * NO WARRANTY X * X * BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY NO X * WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT WHEN X * OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, RICHARD M. X * STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS" WITHOUT X * WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT X * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A X * PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE X * OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU X * ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. X * X * IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. STALLMAN, X * THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY WHO MAY X * MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE LIABLE TO X * YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER X * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR X * INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA X * BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A X * FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS X * PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH X * DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. X * X * GENERAL PUBLIC LICENSE TO COPY X * X * 1. You may copy and distribute verbatim copies of this source file as you X * receive it, in any medium, provided that you conspicuously and X * appropriately publish on each copy a valid copyright notice "Copyright X * (C) 1987 Free Software Foundation, Inc."; and include following the X * copyright notice a verbatim copy of the above disclaimer of warranty X * and of this License. You may charge a distribution fee for the X * physical act of transferring a copy. X * X * 2. You may modify your copy or copies of this source file or any portion X * of it, and copy and distribute such modifications under the terms of X * Paragraph 1 above, provided that you also do the following: X * X * a) cause the modified files to carry prominent notices stating that you X * changed the files and the date of any change; and X * X * b) cause the whole of any work that you distribute or publish, that in X * whole or in part contains or is a derivative of this program or any X * part thereof, to be licensed at no charge to all third parties on terms X * identical to those contained in this License Agreement (except that you X * may choose to grant more extensive warranty protection to third X * parties, at your option). X * X * c) You may charge a distribution fee for the physical act of transferring X * a copy, and you may at your option offer warranty protection in X * exchange for a fee. X * X * 3. You may copy and distribute this program or any portion of it in X * compiled, executable or object code form under the terms of Paragraphs X * 1 and 2 above provided that you do the following: X * X * a) cause each such copy to be accompanied by the corresponding X * machine-readable source code, which must be distributed under the terms X * of Paragraphs 1 and 2 above; or, X * X * b) cause each such copy to be accompanied by a written offer, with no time X * limit, to give any third party free (except for a nominal shipping X * charge) a machine readable copy of the corresponding source code, to be X * distributed under the terms of Paragraphs 1 and 2 above; or, X * X * c) in the case of a recipient of this program in compiled, executable or X * object code form (without the corresponding source code) you shall X * cause copies you distribute to be accompanied by a copy of the written X * offer of source code which you received along with the copy you X * received. X * X * 4. You may not copy, sublicense, distribute or transfer this program X * except as expressly provided under this License Agreement. Any attempt X * otherwise to copy, sublicense, distribute or transfer this program is X * void and your rights to use the program under this License agreement X * shall be automatically terminated. However, parties who have received X * computer software programs from you with this License Agreement will X * not have their licenses terminated so long as such parties remain in X * full compliance. X * X * 5. If you wish to incorporate parts of this program into other free X * programs whose distribution conditions are different, write to the Free X * Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not X * yet worked out a simple rule that can be stated here, but we will often X * permit this. We will be guided by the two goals of preserving the free X * status of all derivatives of our free software and of promoting the X * sharing and reuse of software. X * X * X * In other words, you are welcome to use, share and improve this program. X * You are forbidden to forbid anyone else to use, share and improve what X * you give them. Help stamp out software-hoarding! X */ X X X/* X * This version of `getopt' appears to the caller like standard Unix X * `getopt' but it behaves differently for the user, since it allows the X * user to intersperse the options with the other arguments. X * X * As `getopt' works, it permutes the elements of `argv' so that, when it is X * done, all the options precede everything else. Thus all application X * programs are extended to handle flexible argument order. X * X * Setting the environment variable _POSIX_OPTION_ORDER disables permutation. X * Then the behavior is completely standard. X * X * GNU application programs can use a third alternative mode in which they X * can distinguish the relative order of options and other arguments. X */ X X#include <stdio.h> X#if defined(MSDOS) X#include <malloc.h> X#include <string.h> X#endif X X#if defined(sparc) X#include <alloca.h> X#endif X#if defined(USG) || defined(MSDOS) X#define bcopy(s, d, l) memcpy((d), (s), (l)) X#define index strchr X#endif X X/* X * For communication from `getopt' to the caller. When `getopt' finds an X * option that takes an argument, the argument value is returned here. X * Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element X * is returned here. X */ X Xchar *optarg = 0; X X/* X * Index in ARGV of the next element to be scanned. This is used for X * communication to and from the caller and for communication between X * successive calls to `getopt'. X * X * On entry to `getopt', zero means this is the first call; initialize. X * X * When `getopt' returns EOF, this is the index of the first of the X * non-option elements that the caller should itself scan. X * X * Otherwise, `optind' communicates from one call to the next how much of X * ARGV has been scanned so far. X */ X Xint optind = 0; X X/* X * The next char to be scanned in the option-element in which the last X * option character we returned was found. This allows us to pick up the X * scan where we left off. X * X * If this is zero, or a null string, it means resume the scan by advancing X * to the next ARGV-element. X */ X Xstatic char *nextchar; X X/* X * Callers store zero here to inhibit the error message for unrecognized X * options. X */ X Xint opterr = 1; X X/* X * Describe how to deal with options that follow non-option ARGV-elements. X * X * UNSPECIFIED means the caller did not specify anything; the default is then X * REQUIRE_ORDER if the environment variable _OPTIONS_FIRST is defined, X * PERMUTE otherwise. X * X * REQUIRE_ORDER means don't recognize them as options. Stop option X * processing when the first non-option is seen. This is what Unix does. X * X * PERMUTE is the default. We permute the contents of `argv' as we scan, so X * that eventually all the options are at the end. This allows options to X * be given in any order, even with programs that were not written to X * expect this. X * X * RETURN_IN_ORDER is an option available to programs that were written to X * expect options and other ARGV-elements in any order and that care about X * the ordering of the two. We describe each non-option ARGV-element as X * if it were the argument of an option with character code zero. Using X * `-' as the first character of the list of option characters requests X * this mode of operation. X * X * The special argument `--' forces an end of option-scanning regardless of X * the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can X * cause `getopt' to return EOF with `optind' != ARGC. X */ X Xstatic enum X{ X REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER X} ordering; X X X/* Handle permutation of arguments. */ X X/* X * Describe the part of ARGV that contains non-options that have been X * skipped. `first_nonopt' is the index in ARGV of the first of them; X * `last_nonopt' is the index after the last of them. X */ X Xstatic int first_nonopt; Xstatic int last_nonopt; X X/* X * Exchange two adjacent subsequences of ARGV. One subsequence is elements X * [first_nonopt,last_nonopt) which contains all the non-options that have X * been skipped so far. The other is elements [last_nonopt,optind), which X * contains all the options processed since those non-options were X * skipped. X * X * `first_nonopt' and `last_nonopt' are relocated so that they describe the X * new indices of the non-options in ARGV after they are moved. X */ X X#if defined(PROTO) X Xstatic void Xexchange(char **argv) X X#else X Xstatic void Xexchange(argv) Xchar **argv; X X#endif X{ X int nonopts_size X = (last_nonopt - first_nonopt) * sizeof(char *); X char **temp = (char **) alloca(nonopts_size); X X /* Interchange the two blocks of data in argv. */ X X bcopy(&argv[first_nonopt], temp, nonopts_size); X bcopy(&argv[last_nonopt], &argv[first_nonopt], X (optind - last_nonopt) * sizeof(char *)); X bcopy(temp, &argv[first_nonopt + optind - last_nonopt], X nonopts_size); X X /* Update records for the slots the non-options now occupy. */ X X first_nonopt += (optind - last_nonopt); X last_nonopt = optind; X} X X X/* X * Scan elements of ARGV (whose length is ARGC) for option characters X * given in OPTSTRING. X * X * If an element of ARGV starts with '-', and is not exactly "-" or "--", X * then it is an option element. The characters of this element (aside X * from the initial '-') are option characters. If `getopt' is called X * repeatedly, it returns successively each of theoption characters from X * each of the option elements. X * X * If `getopt' finds another option character, it returns that character, X * updating `optind' and `nextchar' so that the next call to `getopt' can X * resume the scan with the following option character or ARGV-element. X * X * If there are no more option characters, `getopt' returns `EOF'. Then X * `optind' is the index in ARGV of the first ARGV-element that is not an X * option. (The ARGV-elements have been permuted so that those that are X * not options now come last.) X * X * OPTSTRING is a string containing the legitimate option characters. A colon X * in OPTSTRING means that the previous character is an option that wants X * an argument. The argument is taken from the rest of the current X * ARGV-element, or from the following ARGV-element, and returned in X * `optarg'. X * X * If an option character is seen that is not listed in OPTSTRING, return '?' X * after printing an error message. If you set `opterr' to zero, the X * error message is suppressed but we still return '?'. X * X * If a char in OPTSTRING is followed by a colon, that means it wants an arg, X * so the following text in the same ARGV-element, or the text of the X * following ARGV-element, is returned in `optarg. Two colons mean an X * option that wants an optional arg; if there is text in the current X * ARGV-element, it is returned in `optarg'. X * X * If OPTSTRING starts with `-', it requests a different method of handling X * the non-option ARGV-elements. See the comments about RETURN_IN_ORDER, X * above. X */ X X#if defined(PROTO) X Xint Xgetopt(int argc, char **argv, char *optstring) X X#else X Xint Xgetopt(argc, argv, optstring) Xint argc; Xchar **argv; Xchar *optstring; X X#endif X{ X /* X * Initialize the internal data when the first call is made. Start X * processing options with ARGV-element 1 (since ARGV-element 0 is the X * program name); the sequence of previously skipped non-option X * ARGV-elements is empty. X */ X X if (optind == 0) X { X first_nonopt = last_nonopt = optind = 1; X X nextchar = 0; X X /* X * Determine how to handle the ordering of options and nonoptions. X */ X X if (optstring[0] == '-') X ordering = RETURN_IN_ORDER; X else X if (getenv("_POSIX_OPTION_ORDER") != 0) X ordering = REQUIRE_ORDER; X else X ordering = PERMUTE; X } X X if (nextchar == 0 || *nextchar == 0) X { X if (ordering == PERMUTE) X { X /* X * If we have just processed some options following some X * non-options, exchange them so that the options come first. X */ X X if (first_nonopt != last_nonopt && last_nonopt != optind) X exchange(argv); X else X if (last_nonopt != optind) X first_nonopt = optind; X X /* X * Now skip any additional non-options and extend the range of X * non-options previously skipped. X */ X X while (optind < argc X#if !defined(MSDOS_FLAGS) X && (argv[optind][0] != '-' X#else X && ((argv[optind][0] != '-' && argv[optind][0] != '/') X#endif X || argv[optind][1] == 0)) X optind++; X last_nonopt = optind; X } X X /* X * Special ARGV-element `--' means premature end of options. Skip X * it like a null option, then exchange with previous non-options X * as if it were an option, then skip everything else like a X * non-option. X */ X X#if !defined(MSDOS_FLAGS) X if (optind != argc && !strcmp(argv[optind], "--")) X#else X if (optind != argc && X !(strcmp(argv[optind], "--") && strcmp(argv[optind], "/-"))) X#endif X { X optind++; X X if (first_nonopt != last_nonopt && last_nonopt != optind) X exchange(argv); X else X if (first_nonopt == last_nonopt) X first_nonopt = optind; X last_nonopt = argc; X X optind = argc; X } X X /* X * If we have done all the ARGV-elements, stop the scan and back X * over any non-options that we skipped and permuted. X */ X X if (optind == argc) X { X /* X * Set the next-arg-index to point at the non-options that we X * previously skipped, so the caller will digest them. X */ X if (first_nonopt != last_nonopt) X optind = first_nonopt; X return EOF; X } X X /* X * If we have come to a non-option and did not permute it, either X * stop the scan or describe it to the caller and pass it by. X */ X X#if !defined(MSDOS_FLAGS) X if (argv[optind][0] != '-' || argv[optind][1] == 0) X#else X if ((argv[optind][0] != '-' && argv[optind][0] != '/') X || argv[optind][1] == 0) X#endif X { X if (ordering == REQUIRE_ORDER) X return EOF; X optarg = argv[optind++]; X return 0; X } X X /* X * We have found another option-ARGV-element. Start decoding its X * characters. X */ X X nextchar = argv[optind] + 1; X } X X /* Look at and handle the next option-character. */ X X { X char c = *nextchar++; X char *temp = (char *) index(optstring, c); X X /* X * Increment `optind' when we start to process its last character. X */ X if (*nextchar == 0) X optind++; X X if (temp == 0 || c == ':') X { X if (opterr != 0) X { X if (c < 040 || c >= 0177) X fprintf(stderr, "%s: unrecognized option, character code 0%o\n", X argv[0], c); X else X fprintf(stderr, "%s: unrecognized option `-%c'\n", X argv[0], c); X } X return '?'; X } X if (temp[1] == ':') X { X if (temp[2] == ':') X { X /* X * This is an option that accepts an argument optionally. X */ X if (*nextchar != 0) X { X optarg = nextchar; X optind++; X } X else X optarg = 0; X nextchar = 0; X } X else X { X /* X * This is an option that requires an argument. X */ X if (*nextchar != 0) X { X optarg = nextchar; X /* X * If we end this ARGV-element by taking the rest as X * an arg, we must advance to the next element now. X */ X optind++; X } X else X if (optind == argc) X { X if (opterr != 0) X fprintf(stderr, "%s: no argument for `-%c' option\n", X argv[0], c); X c = '?'; X } X else X /* X * We already incremented `optind' once; increment it X * again when taking next ARGV-elt as argument. X */ X optarg = argv[optind++]; X nextchar = 0; X } X } X return c; X } X} X X X#if defined(TEST) X X/* X * Compile with -DTEST to make an executable for use in testing the above X * definition of `getopt'. X */ X Xint Xmain(argc, argv) Xint argc; Xchar **argv; X{ X char c; X int digit_optind = 0; X X while (1) X { X int this_option_optind = optind; X if ((c = getopt(argc, argv, "abc:d:0123456789")) == EOF) X break; X X switch (c) X { X case '0': X case '1': X case '2': X case '3': X case '4': X case '5': X case '6': X case '7': X case '8': X case '9': X if (digit_optind != 0 && digit_optind != this_option_optind) X printf("digits occur in two different argv-elements.\n"); X digit_optind = this_option_optind; X printf("option %c\n", c); X break; X X case 'a': X printf("option a\n"); X break; X X case 'b': X printf("option b\n"); X break; X X case 'c': X printf("option c with value `%s'\n", optarg); X break; X X case '?': X break; X X default: X printf("?? getopt returned character code 0%o ??\n", c); X } X } X X if (optind < argc) X { X printf("non-option ARGV-elements: "); X while (optind < argc) X printf("%s ", argv[optind++]); X printf("\n"); X } X X return 0; X} X X#endif END_OF_getopt.c if test 18046 -ne `wc -c <getopt.c`; then echo shar: \"getopt.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f makefile -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"makefile\" else echo shar: Extracting \"makefile\" \(653 characters\) sed "s/^X//" >makefile <<'END_OF_makefile' X# Ndmake makefile for GNU getopt libraries X XCC = cl X# Microsoft C 5.1 and QuickC define MSDOS automatically XDEFS = -DMSDOS_FLAGS -DPROTO XCFLAGS = -A$(MODEL) $(DEFS) X Xall: done.S done.M done.C done.L X Xdone.S: getopt.c X make Sgnuget.lib MODEL=S Xdone.M: getopt.c X make Mgnuget.lib MODEL=M Xdone.C: getopt.c X make Cgnuget.lib MODEL=C Xdone.L: getopt.c X make Lgnuget.lib MODEL=L X X$(MODEL)gnuget.lib: getopt.obj X -del $(MODEL)gnuget.lib X lib $(MODEL)gnuget +getopt.obj; X del getopt.obj X echo done >done.$(MODEL) X Xtest.exe: getopt.c X cl -Fetest $(DEFS) -DTEST getopt.c X Xclean: X -del test.exe X -del getopt.obj X -del done.? X Xclobber: clean X -del ?gnuget.lib END_OF_makefile if test 653 -ne `wc -c <makefile`; then echo shar: \"makefile\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of shell archive. exit 0 -- Barry Schwartz, Chief SAPsucker bbs@cdspr.rutgers.edu Grad Student, Dept. of Elec. and Comp. Engg. bschwart@elbereth.rutgers.edu Rutgers University College of Engg. bbs@hankel.rutgers.edu Piscataway, NJ 08854 U.S.A. rutgers!cdspr!bbs