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