home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / c / xv221src / jpeg / egetopt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-23  |  7.5 KB  |  291 lines

  1. /*
  2.  * egetopt.c -- Extended 'getopt'.
  3.  *
  4.  * A while back, a public-domain version of getopt() was posted to the
  5.  * net.  A bit later, a gentleman by the name of Keith Bostic made some
  6.  * enhancements and reposted it.
  7.  *
  8.  * In recent weeks (i.e., early-to-mid 1988) there's been some
  9.  * heated discussion in comp.lang.c about the merits and drawbacks
  10.  * of getopt(), especially with regard to its handling of '?'.
  11.  *
  12.  * In light of this, I have taken Mr. Bostic's public-domain getopt()
  13.  * and have made some changes that I hope will be considered to be
  14.  * improvements.  I call this routine 'egetopt' ("Extended getopt").
  15.  * The default behavior of this routine is the same as that of getopt(),
  16.  * but it has some optional features that make it more useful.  These
  17.  * options are controlled by the settings of some global variables.
  18.  * By not setting any of these extra global variables, you will have
  19.  * the same functionality as getopt(), which should satisfy those
  20.  * purists who believe getopt() is perfect and can never be improved.
  21.  * If, on the other hand, you are someone who isn't satisfied with the
  22.  * status quo, egetopt() may very well give you the added capabilities
  23.  * you want.
  24.  *
  25.  * Look at the enclosed README file for a description of egetopt()'s
  26.  * new features.
  27.  *
  28.  * The code was originally posted to the net as getopt.c by ...
  29.  *
  30.  *    Keith Bostic
  31.  *    ARPA: keith@seismo 
  32.  *    UUCP: seismo!keith
  33.  *
  34.  * Current version: added enhancements and comments, reformatted code.
  35.  *
  36.  *    Lloyd Zusman
  37.  *    Master Byte Software
  38.  *    Los Gatos, California
  39.  *    Internet:    ljz@fx.com
  40.  *    UUCP:        ...!ames!fxgrp!ljz
  41.  *
  42.  *        May, 1988
  43.  *
  44.  * Modified for use in free JPEG code:
  45.  *
  46.  *    Ed Hanway
  47.  *    UUCP:    uunet!sisd!jeh
  48.  *
  49.  *    October, 1991
  50.  */
  51.  
  52. /* The original egetopt.c was written not to need stdio.h.
  53.  * For the JPEG code this is an unnecessary and unportable assumption.
  54.  * Also, we make all the variables and routines "static" to avoid
  55.  * possible conflicts with a system-library version of getopt.
  56.  *
  57.  * In the JPEG code, this file is compiled by #including it in jcmain.c
  58.  * or jdmain.c.  Since ANSI2KNR does not process include files, we can't
  59.  * rely on it to convert function definitions to K&R style.  Hence we
  60.  * provide both styles of function header with an explicit #ifdef PROTO (ick).
  61.  */
  62.  
  63. #define GVAR static        /* make empty to export these variables */
  64.  
  65. /*
  66.  * None of these constants are referenced in the executable portion of
  67.  * the code ... their sole purpose is to initialize global variables.
  68.  */
  69. #define BADCH        (int)'?'
  70. #define NEEDSEP        (int)':'
  71. #define MAYBESEP    (int)'\0'
  72. #define EMSG        ""
  73. #define START        "-"
  74.  
  75. /*
  76.  * Here are all the pertinent global variables.
  77.  */
  78. GVAR int opterr = 1;        /* if true, output error message */
  79. GVAR int optind = 1;        /* index into parent argv vector */
  80. GVAR int optopt;        /* character checked for validity */
  81. GVAR int optbad = BADCH;    /* character returned on error */
  82. GVAR int optchar = 0;        /* character that begins returned option */
  83. GVAR int optneed = NEEDSEP;    /* flag for mandatory argument */
  84. GVAR int optmaybe = MAYBESEP;    /* flag for optional argument */
  85. #if defined(__GNUC__) && defined(MSDOS)
  86. GVAR char *optarg;        /* argument associated with option */
  87. #else /* defined(__GNUC__) && defined(MSDOS) */
  88. GVAR const char *optarg;    /* argument associated with option */
  89. #endif /* defined(__GNUC__) && defined(MSDOS) */
  90. GVAR const char *optstart = START; /* list of characters that start options */
  91.  
  92.  
  93. /*
  94.  * Macros.
  95.  */
  96.  
  97. /*
  98.  * Conditionally print out an error message and return (depends on the
  99.  * setting of 'opterr').
  100.  */
  101. #define TELL(S)    { \
  102.     if (opterr) \
  103.         fprintf(stderr, "%s%s%c\n", *nargv, (S), optopt); \
  104.     return (optbad); \
  105. }
  106.  
  107. /*
  108.  * This works similarly to index() and strchr().  I include it so that you
  109.  * don't need to be concerned as to which one your system has.
  110.  */
  111.  
  112. #ifdef PROTO
  113. LOCAL const char *
  114. _sindex (const char *string, int ch)
  115. #else
  116. LOCAL const char *
  117. _sindex (string, ch)
  118.      const char *string;
  119.      int ch;
  120. #endif
  121. {
  122.     if (string != NULL) {
  123.         for (; *string != '\0'; ++string) {
  124.             if (*string == (char)ch) {
  125.                 return (string);
  126.             }
  127.         }
  128.     }
  129.  
  130.     return (NULL);
  131. }
  132.  
  133. /*
  134.  * Here it is:
  135.  */
  136.  
  137. #ifdef PROTO
  138. LOCAL int
  139. egetopt (int nargc, char **nargv, const char *ostr)
  140. #else
  141. LOCAL int
  142. egetopt (nargc, nargv, ostr)
  143.      int nargc;
  144.      char **nargv;
  145.      const char *ostr;
  146. #endif
  147. {
  148.     static const char *place = EMSG; /* option letter processing */
  149.     register const char *oli;     /* option letter list index */
  150.     register const char *osi = NULL; /* option start list index */
  151.  
  152.     if (nargv == (char **)NULL) {
  153.         return (EOF);
  154.     }
  155.  
  156.     if (nargc <= optind || nargv[optind] == NULL) {
  157.         return (EOF);
  158.     }
  159.  
  160.     if (place == NULL) {
  161.         place = EMSG;
  162.     }
  163.  
  164.     /*
  165.      * Update scanning pointer.
  166.      */
  167.     if (*place == '\0') {
  168.         place = nargv[optind];
  169.         if (place == NULL) {
  170.             return (EOF);
  171.         }
  172.         osi = _sindex(optstart, *place);
  173.         if (osi != NULL) {
  174.             optchar = (int)*osi;
  175.         }
  176.         if (optind >= nargc || osi == NULL || *++place == '\0') {
  177.                 return (EOF);
  178.         }
  179.  
  180.         /*
  181.          * Two adjacent, identical flag characters were found.
  182.          * This takes care of "--", for example.
  183.          */
  184.         if (*place == place[-1]) {
  185.             ++optind;
  186.             return (EOF);
  187.         }
  188.     }
  189.  
  190.     /*
  191.      * If the option is a separator or the option isn't in the list,
  192.      * we've got an error.
  193.      */
  194.     optopt = (int)*place++;
  195.     oli = _sindex(ostr, optopt);
  196.     if (optopt == optneed || optopt == optmaybe || oli == NULL) {
  197.         /*
  198.          * If we're at the end of the current argument, bump the
  199.          * argument index.
  200.          */
  201.         if (*place == '\0') {
  202.             ++optind;
  203.         }
  204.         TELL(": illegal option -- ");    /* byebye */
  205.     }
  206.  
  207.     /*
  208.      * If there is no argument indicator, then we don't even try to
  209.      * return an argument.
  210.      */
  211.     ++oli;
  212.     if (*oli == '\0' || (*oli != optneed && *oli != optmaybe)) {
  213.         /*
  214.          * If we're at the end of the current argument, bump the
  215.          * argument index.
  216.          */
  217.         if (*place == '\0') {
  218.             ++optind;
  219.         }
  220.         optarg = NULL;
  221.     }
  222.     /*
  223.      * If we're here, there's an argument indicator.  It's handled
  224.      * differently depending on whether it's a mandatory or an
  225.      * optional argument.
  226.      */
  227.     else {
  228.         /*
  229.          * If there's no white space, use the rest of the
  230.          * string as the argument.  In this case, it doesn't
  231.          * matter if the argument is mandatory or optional.
  232.          */
  233.         if (*place != '\0') {
  234.             optarg = place;
  235.         }
  236.         /*
  237.          * If we're here, there's whitespace after the option.
  238.          *
  239.          * Is it a mandatory argument?  If so, return the
  240.          * next command-line argument if there is one.
  241.          */
  242.         else if (*oli == optneed) {
  243.             /*
  244.              * If we're at the end of the argument list, there
  245.              * isn't an argument and hence we have an error.
  246.              * Otherwise, make 'optarg' point to the argument.
  247.              */
  248.             if (nargc <= ++optind) {
  249.                 place = EMSG;
  250.                 TELL(": option requires an argument -- ");
  251.             }
  252.             else {
  253.                 optarg = nargv[optind];
  254.             }
  255.         }
  256.         /*
  257.          * If we're here it must have been an optional argument.
  258.          */
  259.         else {
  260.             if (nargc <= ++optind) {
  261.                 place = EMSG;
  262.                 optarg = NULL;
  263.             }
  264.             else {
  265.                 optarg = nargv[optind];
  266.                 if (optarg == NULL) {
  267.                     place = EMSG;
  268.                 }
  269.                 /*
  270.                  * If the next item begins with a flag
  271.                  * character, we treat it like a new
  272.                  * argument.  This is accomplished by
  273.                  * decrementing 'optind' and returning
  274.                  * a null argument.
  275.                  */
  276.                 else if (_sindex(optstart, *optarg) != NULL) {
  277.                     --optind;
  278.                     optarg = NULL;
  279.                 }
  280.             }
  281.         }
  282.         place = EMSG;
  283.         ++optind;
  284.     }
  285.  
  286.     /*
  287.      * Return option letter.
  288.      */
  289.     return (optopt);
  290. }
  291.