[comp.sources.amiga] getopt part 1 of 1

ain@j.cc.purdue.edu (Patrick White) (12/30/87)

Program Name:	getopt
Submitted By:	adam%lamont.Columbia.edu@lamont (adam levin)
Summary:	This is an implementation of Unix's(tm) getopt function.
Poster Boy:  Pat White  (ain@j.cc.purdue.edu)
Tested.

NOTES:
   There is no .c file in the getopt code -- it is all in the .h file.
   Those of you who wish to add this to your own library may wish to
break this into a .h file and a .c file which will be included from
your library.


-- Pat White   (co-moderator comp.sources/binaries.amiga)
UUCP: j.cc.purdue.edu!ain  BITNET: PATWHITE@PURCCVM   PHONE: (317) 743-8421
U.S.  Mail:  320 Brown St. apt. 406,    West Lafayette, IN 47906

----------------------------------------


#!/bin/sh
# shar:    Shell Archiver
#	Run the following text with /bin/sh to create:
#	getopt.txt
#	getopt.doc
#	getopt.h
#	GOtest.c
cat << \SHAR_EOF > getopt.txt
Function note:
The function getopt() will allow you to easily handle any number of
options as input to your CLI-based programs.  It is NOT part of the ANSI
specifications for C, but I find that it makes including options for my
programs much less painful.

Compilation note:
If you have Manx's Aztec C (as I do), getopt can be compiled as either a 16-
or 32-bit integer function.  Use whichever mode your calling routine uses.

Just a note:
If you find this function useful (I hope you do; I hate remembering to type
"opt x" instead of "-x") I would appreciate receiving a picture postcard
from your locale bearing the most interesting tidbit of Amiga information
you are willing to share.  Thanks.

                  Adam Levin
                  133c Hudson Terrace
                  Piermont, NY  10968-1013

SHAR_EOF
cat << \SHAR_EOF > getopt.doc

GETOPT


NAME

	getopt - Get next option letter from argument vector.


USAGE


	int getopt(argc, argv, optstring);

	#include "getopt.h"

	int argc;
	char *argv[], *optstring;
	extern char *optarg;
	extern int optind, opterr, optopt;


DESCRIPTION

	The function getopt() returns the next option letter in argv that
matches a letter in optstring.  Optstring is a string of valid option
letters; if an option letter is followed by a colon (:), that option
is expected to have an argument that may or may not be separated from
it by white space.  Optarg is set to point to the start of the option's
argument on return from getopt();

	getopt() places in optind the argv index of the next argument to be
parsed.  Optind is external, and is initialized to 1 before the first
call to getopt().

	When all options have been parsed (that is, up to the first non-
option argument), getopt returns EOF.  The special option double dash
(--) may be used to delimit the end of the options.  EOF will be
returned and the double dash will be skipped.  The special option single
dash (-) may be used to indicate that stdin should be used as the next
input stream. EOF will be returned but the single dash will not be skipped.
The calling routine must then act on the presence of the single dash in the
argument vector.


DIAGNOSTICS

	If the external variable opterr is non-zero (the default) getopt()
prints an error message on stderr and returns a question mark (?) when
it encounters either an option character not in optstring or a valid
option without its required argument.

	In those cases where getopt() finds an option character not in
optstring, and returns a question mark, the external variable optopt
will contain the actual character found.

SHAR_EOF
cat << \SHAR_EOF > getopt.h
/*  getopt.h - Get next option letter from argument vector.
               v1.1  12-Dec-1987  aklevin
*/

#define GETOPT_H

#ifndef _STDIO_H
#include <stdio.h>
#endif

/*  optarg points to an option's argument (if any).
    optind holds the index of the next argument vector element to parse.
     Once all options have been parsed, points to the first non-option argument.
	 [If (optind > argc) then there are no more arguments].
    opterr, if set to 0 will suppress getopt's error messages (default is 1).
    optopt, while not usually documented, is used here to return the actual
     option character found, even when getopt itself returns '?'.
*/
char *optarg;
int optind=1, opterr=1, optopt;

int
getopt(argc, argv, optstring)
int argc;
char *argv[], *optstring;
{

int any_more, i, result;
static int opthold, optsub=1;

/*  Reset optarg upon entry  */
*optarg = '\0';

/*  Reset optsub if caller has changed optind.  */
if (optind != opthold) optsub = 1;

/*  Look at each element of the argument vector still unparsed.  */
for ( ; optind < argc; optind++) {
	/*  Done if a non-option argument or single dash is reached.
		However, don't skip over said argument.  */
	if (argv[optind][0] != '-' || argv[optind][1] == '\0') break;

	/*  Got an option.  */

	/*  Done if "--" is reached.  Skip over it, too.  */
	if (argv[optind][1] == '-') {
		optind++;
		break;
	}

	/*  Look at each character in optstring.  */
	for (i=0; i < strlen(optstring); i++) {
		if ( (optopt = argv[optind][optsub]) != optstring[i]) continue;

		/*  Got a match.  */

		/*  Are there any more chars in this option?  e.g. `-abc'  */
		any_more = strlen(argv[optind])-optsub-1;

		/*  Does this option require an argument?  */
		if (optstring[i+1] == ':') {

			/*  Yes.  If this is the last argument, complain.  */
			if (optind == argc-1 && !any_more) {
				if (opterr) fprintf(stderr, "%s: `-%c' option requires an argument.\n", argv[0], optopt);
				optind++;
				result='?';
				goto leave;
			} /* end if (opt */

			/*  Qualifier is either rest of this argument (if any)
			    or next argument.  */
			else {
				if (!any_more) optarg = argv[++optind];
				else optarg = &argv[optind][optsub+1];
				optind++;
				optsub=1;
			} /* end else */
		} /* end if (opt */
		else {
			/*  No argument; just adjust indices.  */
			/*  Advance to next argument.  */
			if (!any_more) {
				optind++;
				optsub=1;
			} /* end if (! */
			/*  Advance to next character.  */
			else optsub++;
		} /* end else */
		result=optopt;
		goto leave;
	} /* end for (i=0 */
if (opterr) fprintf(stderr, "%s: Unrecognized option `-%c'.\n", argv[0], optopt);
if (strlen(argv[optind])-optsub-1) optsub++;
else {
	optind++;
	optsub=1;
}
result='?';
goto leave;
} /* end for ( ; */
result=EOF;
leave:
	opthold = optind;
	return(result);
} /* end getopt() */

SHAR_EOF
cat << \SHAR_EOF > GOtest.c
/*  GOtest.c - A test program to exercise getopt().

  usage: GOtest -a -b -c -d argument_d -e argument_e -f argument_f argsapoppin

*/

#include <stdio.h>
#include "getopt.h"

main(argc, argv)
int argc;
char *argv[];
{
int i, option;
char *optstring;
extern char *optarg;
extern int optind, opterr, optopt;

/*  optstring is a string of valid options for this program.
    a, b, & c are only flags, and hence have no arguments.
	The colons (:) following d, e, & f indicate that these
	three options require arguments.
*/
optstring = "abcd:e:f:";

printf("\noptstring: \"%s\", opterr: %d\n", optstring, opterr);

/*  Parse the options  (if any)  */
while ((option = getopt(argc, argv, optstring)) != EOF) {
  printf("getopt() returned '%c', optopt: '%c', optarg: \"%s\", optind: %d\n",
	option, optopt, optarg, optind);
}

/*  Display the remaining arguments  (if any)  */
for (i = optind; i < argc; i++)
	printf("argv[%d]: \"%s\"\n", i, argv[i]);

} /* end main */

SHAR_EOF
#	End of shell archive
exit 0
#
#	Dummy filler