Blame | Last modification | View Log | RSS feed
/* -*- c: tabs: 4 -*- ******************************************************* Module name : getopt* Module type : Core Services* Compiler(s) : ANSI C* Environment(s): n/a** Description:*Command line option parsing** Provides user functions*getoptgetoptl** Contants:*n/a** Version Who Date Description1.0 APY 02/06/97 Long argument version.1.1 APY 07/05/98 Core Services** $Name: $* $Source: /cvsroot/device/DEVL/UTILS/CMDFILE/getopt.c,v $* $Revision: 1.2 $ $Date: 2004/05/10 03:47:05 $ $State: Exp $* $Author: ayoung $ $Locker: $*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include "cmdfile.h"#include "getopt.h"#ifndef index#define index strchr#define rindex strrchr#endif/** get option letter from argument vector*/#ifndef sunint opterr = 1, /* if error message should be printed */optind = 1; /* index into parent argv vector */#elseextern int opterr;extern int optind;#endifint optopt, /* character checked for validity */optlidx = -1; /* long index */char *optarg; /* argument associated with option */#define BADCH (int)'?'#define EMSG ""/*----------------------------------------------------------------------------Synopsis:#include <getopt.h>int getopt(int nargc,char *const *nargv,const char *ostr)extern int optarg;extern int optind;extern int opterr;int CsGetoptl(int nargc,char *const *nargv,const char *ostr,const struct option *lopt,int long_only)extern int optlidx;MT-Level:UnsafePurpose:The CsGetopt function returns the next option letterin 'argv' that matches a letter in 'ostr'. It supportsall the rules of the command syntax standard (see below).This function is the functional replacement of thestandard UNIX getopt() function.The CsGetoptl functions extends the command syntaxincluding support for long options.'ostr' must contain the option letters the command usingCsGetopt()/CsGetoptl() will recognize; if a letter isfollowed by a colon, the option is expected to havean argument, or group of arguments, which may beseparated from it by white space. 'optarg' is set topoint to the start of the option argument on return.'optind' represents the 'argv' index of the nextargument to be processed. 'optind' is external andis initialised to 1 before the first call. When alloptions have been processed (that is, up to thefirst non-option argument), EOF is returned. Thespecial option "--" (two hyphens) may be used to delimitthe end of the options; when it is encountered, EOF isreturned and "--"' is skipped. This is useful indelimiting non-option arguments that begin with``-'' (hyphen).The additional parameters to CsGetoptl() enable longargument handling. 'lopt' defines the argument namesand 'long_only' is used to specify whether longoptions are only matched when preceded with "--" oror long and short arguments can be mixed.'optlidx' represents the 'lopt' index of the matchedlong argument, initialised to -1 upon each call.Parameters:nargc, Number of command line arguments.nargv, The NULL terinated argument list.ostr, Argument syntax specificationlopt, Specifies the pointer to the long argument liststruct option{char *name; Option nameint has_arg; 0=none, 1=required, 2=optionalint *flag; Value bufferint val; value return on detection};The 'name' fields contains the address of theNUL terminated string command label. 'has_arg'speicfies the whether an associated argumentisn't excepted (0), is required (1), or isoptional (2).The following manifest constants are defined foruse within the 'has_arg' field:no_argument No argument expectedrequired_argument An argument must be suppliedoptional_argument An optional argument'flag' is the optional address of the bufferassigned with the value of argument. 'val' statesthe value to be returned upon the given optionbeing encountered.long_only, When specified as non-zero, long arguments areonly matched when preceded with "--".Command Syntax Standard:The following command syntax should be obeyed. TheCsGetopt function supports Rules 3-10 below. Rules10b-10c are only active during long argument processing.The enforcement of the other rules must be done bythe command itself.1. Command names (name above) must be between two andnine characters long.2. Command names must include only lower-case lettersand digits.3. Option names (option above) must be one characterlong.4. All options must be preceded by "-".5. Options with no arguments may be grouped after asingle "-".6. The first option-argument (optarg above) followingan option must be preceded by a tab or space character.7. Option-arguments cannot be optional.8. Groups of option-arguments following an optionmust either be separated by commas or separated bytab or space character and quoted (-o xxx,z,yy or-o "xxx z yy").9. All options must precede operands (cmdarg above)on the command line.10. "--" may be used to indicate the end of the options.10b "--" may precede a long option.10c If a command element has the form "-f", where f is avalid short option, don't consider it an abbreviatedform of a long option that starts with f. Otherwisethere would be no way to give the -f short option.On the other hand, if there's a long option "fubar"and the command element is "-fu", do consider that anabbreviation of the long option, just like "--fu",and not "-f" with arg "u".11. The order of the options relative to one anothershould not matter.12. The relative order of the operands (cmdarg above)may affect their significance in ways determinedby the command with which they appear.13. "-" preceded and followed by a space charactershould only be used to mean standard input.Returns: int -The CsGetopt functions return the character matched, otherwiseEOF at the end of input stream, or '?' upon a parer error.The parser prints an error message on the standard errorand returns a "?" (question mark) when it encounters an optionletter not included in 'ostr' or 'lopt' or no argument is locatedafter an option that expects one. Error messages may bedisabled by setting 'opterr' to 0. The value of the characterthat caused the error is in 'optopt'.In addition CsGetoptl() generates messages when ambiguousarguments between the short and long selections are presented.Examples:The following code fragment shows how one might process thearguments for a command that can take the mutually exclusiveoptions a and b, and the option o, which requires anargument:#include <stdlib.h>#include <stdio.h>#include <csgetopt.h>int main(int argc, char **argv){int aflg=0, bflg=0, errflg=0, c;char *ofile = NULL;while ((c = CsGetopt(argc, argv, "abo:")) != EOF)switch (c) {case 'a':if (bflg)errflg++;else aflg++;break;case 'b':if (aflg)errflg++;else bflg++;break;case 'o':ofile = optarg;void)printf("ofile = %s\n", ofile);break;case '?':errflg++;}if (errflg) {(void)fprintf(stderr,"usage: cmd [-a|-b] [-o <filename>] files...\n");exit (2);}while(optind < argc)printf("%s\n", argv[optind++]);}The following code fragment shows how one might process thearguments for a command that can take the options 'a' and 'b',plus 'verbose' and 'debug' which requires an argument:#include <stdlib.h>#include <stdio.h>#include <csgetopt.h>static struct option longopts[] ={{"verbose", 0, NULL, 'v'},{"debug", 1, NULL, 'd'},};int main(int argc, char **argv){int aflg=0, bflg=0, debug=0, verbose=0, c;while ((c = CsGetoptl(argc, argv, "ab", longopts, 1)) != EOF)switch (c) {case 'a':aflg++;break;case 'b':bflg++;break;case 'd':debug = atoi(optarg);break;case 'v':verbose++;break;case '?':(void)fprintf(stderr,"usage: cmd [-ab] [-debug <lvl>] [-verbose] ...\n");exit (2);}:}----------------------------------------------------------------------------*/intgetopt(int nargc, char *const *nargv, const char *ostr){return getoptl(nargc, nargv, ostr, NULL, 0);}intgetopt_long(int nargc, char *const *nargv, const char *ostr,const struct option *lopts, int *longind){int ret = getoptl(nargc, nargv, ostr, lopts, 0);if (longind)*longind = optlidx;return (ret);}intgetopt_long_only(int nargc, char *const *nargv, const char *ostr,const struct option *lopts, int *longind){int ret = getoptl(nargc, nargv, ostr, lopts, 1);if (longind)*longind = optlidx;return (ret);}intgetoptl(int nargc, char *const *nargv, const char *ostr,const struct option *lopt, int long_only){static char *place = EMSG; /* option letter processing */register char *oli; /* option letter list index */char *pProg;if ((pProg = rindex(*nargv, '/')) == NULL)pProg = *nargv;else pProg++;optlidx = -1;if (!*place){/* Update scanning pointer */if (optind >= nargc || *(place = nargv[optind]) != '-'){place = EMSG;return (EOF);}if (place[1] && *++place == '-'){if (!*++place){/* Found "--" , meaning premature end of options */optind++;place = EMSG;return (EOF);}}/* Reference GCC 'getopt':* If ARGV-element has the form "-f", where f is a valid short* option, don't consider it an abbreviated form of a long* option that starts with f. Otherwise there would be no way* to give the -f short option.** On the other hand, if there's a long option "fubar" and* the ARGV-element is "-fu", do consider that an abbreviation* of the long option, just like "--fu", and not "-f" with* arg "u".** This distinction seems to be the most useful approach.*/if (lopt != NULL &&(nargv[optind][1] == '-' ||(!long_only && (nargv[optind][2] ||!index(ostr?ostr:"", nargv[optind][1]))))){const struct option *pOpt;#define EXTRACT 1#define NONEXTRACT 2#define AMBIGUOUS 4int flags = 0;char *pEnd;int i;/* Test all long options for either exact match* or abbreviated matches.*/for (pEnd = place; *pEnd && *pEnd != '='; pEnd++);for (pOpt=lopt, i=0; pOpt->name; pOpt++, i++)if (!strncmp(pOpt->name, place, pEnd-place)){if ((int)(pEnd - place) == (int)strlen(pOpt->name)){flags &= ~AMBIGUOUS;flags |= EXTRACT; /* Exact match */optlidx = i;break;}if (flags & NONEXTRACT)flags |= AMBIGUOUS; /* Multiple match(s) */else{flags |= NONEXTRACT; /* Part match */optlidx = i;}}if (flags & AMBIGUOUS){if (opterr)(void) fprintf(stderr,"%s: option `%s' is ambiguous\n",pProg, place);optind++;place = EMSG;return BADCH;}/* Long option match */if (flags & (EXTRACT|NONEXTRACT)){pOpt = lopt+optlidx;optind++;/* Parse argument request */if (*pEnd){if (pOpt->has_arg)optarg = pEnd+1;else{if (opterr){if (nargv[optind-1][1] == '-'){/* Long format */(void) fprintf(stderr,"%s: option `--%s' doesn't allow an argument\n",pProg, pOpt->name);} else {/* Short */(void) fprintf(stderr,"%s: option `%c%s' doesn't allow an argument\n",pProg, nargv[optind-1][0], pOpt->name);}}place = EMSG;return BADCH;}}else if (pOpt->has_arg){if (optind < nargc &&strcmp(nargv[optind], "--") != 0){/* Argument available (non-terminator) */optarg = nargv[optind++];}else if (pOpt->has_arg != optional_argument){/* No argument */if (opterr)(void) fprintf(stderr,"%s: option `%s' requires an argument\n",pProg, nargv[optind - 1]);place = EMSG;return (ostr && ostr[0] == ':' ? ':' : BADCH);}else{optarg = NULL; /* Optional argument */}}/* Return completion value */place = EMSG;if (pOpt->flag){*(pOpt->flag) = pOpt->val;return 0;}return pOpt->val;}/* Can't find it as a long option. If this is not* 'long_only', or the option starts with '--' or* is not a valid short option, then it's an error.** Otherwise interpret it as a short option.*/if (!long_only || nargv[optind][1] == '-' ||index(ostr ? ostr : "", *place) == NULL){if (opterr){if (nargv[optind][1] == '-') {/* Long format */(void) fprintf(stderr,"%s: unrecognized option `--%s'\n",pProg, place);} else {/* Short */(void) fprintf(stderr,"%s: unrecognized option `%c%s'\n",pProg, nargv[optind][0], place);}}optind++;place = EMSG;return BADCH;}}}/* Option letter okay? */if ((optopt = (int) *place++) == (int) ':' ||(oli = index(ostr, optopt)) == NULL){/* If the user didn't specify '-' as an option, assume it means EOF */if (optopt == (int) '-')return (EOF);if (!*place)++optind;if (opterr)(void) fprintf(stderr,"%s: illegal option -- %c\n",pProg, optopt);return (BADCH);}/*LINTED*/if (*++oli != ':'){/* Don't need argument */optarg = NULL;if (!*place)++optind;}else{/* Need an argument */if (*place){/* No white space */optarg = place;}else if (nargc <= ++optind || strcmp(nargv[optind], "--") == 0){/* No argument, or terminator encountered */if (opterr)(void) fprintf(stderr,"%s: option requires an argument -- %c\n",pProg, optopt);place = EMSG;return (BADCH);}else{/* White space -- return next argument */optarg = nargv[optind];}place = EMSG;++optind;}return (optopt); /* Dump back option letter */}