[alt.sources] GNU getopt hacked for MSDOS

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