home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / netds / sna / shared / getopt.c < prev    next >
Text File  |  1997-04-09  |  8KB  |  178 lines

  1. /*****************************************************************************
  2.  *
  3.  *  MODULE NAME : GETOPT.C
  4.  *
  5.  *  COPYRIGHTS:
  6.  *             This module contains code made available by IBM
  7.  *             Corporation on an AS IS basis.  Any one receiving the
  8.  *             module is considered to be licensed under IBM copyrights
  9.  *             to use the IBM-provided source code in any way he or she
  10.  *             deems fit, including copying it, compiling it, modifying
  11.  *             it, and redistributing it, with or without
  12.  *             modifications.  No license under any IBM patents or
  13.  *             patent applications is to be implied from this copyright
  14.  *             license.
  15.  *
  16.  *             A user of the module should understand that IBM cannot
  17.  *             provide technical support for the module and will not be
  18.  *             responsible for any consequences of use of the program.
  19.  *
  20.  *             Any notices, including this one, are not to be removed
  21.  *             from the module without the prior written consent of
  22.  *             IBM.
  23.  *
  24.  *  AUTHOR:   Original author:
  25.  *                 G. R. Blair (BOBBLAIR at AUSVM1)
  26.  *                 Internet: bobblair@bobblair.austin.ibm.com
  27.  *
  28.  *            Extensively revised by:
  29.  *                 John Q. Walker II, Ph.D. (JOHHQ at RALVM6)
  30.  *                 Internet: johnq@ralvm6.vnet.ibm.com
  31.  *
  32.  *****************************************************************************/
  33.  
  34. /******************************************************************************
  35.  * getopt()
  36.  *
  37.  * The getopt() function is a command line parser.  It returns the next
  38.  * option character in argv that matches an option character in opstring.
  39.  *
  40.  * The argv argument points to an array of argc+1 elements containing argc
  41.  * pointers to character strings followed by a null pointer.
  42.  *
  43.  * The opstring argument points to a string of option characters; if an
  44.  * option character is followed by a colon, the option is expected to have
  45.  * an argument that may or may not be separated from it by white space.
  46.  * The external variable optarg is set to point to the start of the option
  47.  * argument on return from getopt().
  48.  *
  49.  * The getopt() function places in optind the argv index of the next argument
  50.  * to be processed.  The system initializes the external variable optind to
  51.  * 1 before the first call to getopt().
  52.  *
  53.  * When all options have been processed (that is, up to the first nonoption
  54.  * argument), getopt() returns EOF.  The special option "--" may be used to
  55.  * delimit the end of the options; EOF will be returned, and "--" will be
  56.  * skipped.
  57.  *
  58.  * The getopt() function returns a question mark (?) when it encounters an
  59.  * option character not included in opstring.  This error message can be
  60.  * disabled by setting opterr to zero.  Otherwise, it returns the option
  61.  * character that was detected.
  62.  *
  63.  * If the special option "--" is detected, or all options have been
  64.  * processed, EOF is returned.
  65.  *
  66.  * Options are marked by either a minus sign (-) or a slash (/).
  67.  *
  68.  * No errors are defined.
  69.  *****************************************************************************/
  70.  
  71. #include <stdio.h>                  /* for EOF */
  72. #include <string.h>                 /* for strchr() */
  73.  
  74.  
  75. /* static (global) variables that are specified as exported by getopt() */
  76. char *optarg = NULL;    /* pointer to the start of the option argument  */
  77. int   optind = 1;       /* number of the next argv[] to be evaluated    */
  78. int   opterr = 1;       /* non-zero if a question mark should be returned
  79.                            when a non-valid option character is detected */
  80.  
  81. /* handle possible future character set concerns by putting this in a macro */
  82. #define _next_char(string)  (char)(*(string+1))
  83.  
  84. int getopt(int argc, char *argv[], char *opstring)
  85. {
  86.     static char *pIndexPosition = NULL; /* place inside current argv string */
  87.     char *pArgString = NULL;        /* where to start from next */
  88.     char *pOptString;               /* the string in our program */
  89.  
  90.  
  91.     if (pIndexPosition != NULL) {
  92.         /* we last left off inside an argv string */
  93.         if (*(++pIndexPosition)) {
  94.             /* there is more to come in the most recent argv */
  95.             pArgString = pIndexPosition;
  96.         }
  97.     }
  98.  
  99.     if (pArgString == NULL) {
  100.         /* we didn't leave off in the middle of an argv string */
  101.         if (optind >= argc) {
  102.             /* more command-line arguments than the argument count */
  103.             pIndexPosition = NULL;  /* not in the middle of anything */
  104.             return EOF;             /* used up all command-line arguments */
  105.         }
  106.  
  107.         /*---------------------------------------------------------------------
  108.          * If the next argv[] is not an option, there can be no more options.
  109.          *-------------------------------------------------------------------*/
  110.         pArgString = argv[optind++]; /* set this to the next argument ptr */
  111.  
  112.         if (('/' != *pArgString) && /* doesn't start with a slash or a dash? */
  113.             ('-' != *pArgString)) {
  114.             --optind;               /* point to current arg once we're done */
  115.             optarg = NULL;          /* no argument follows the option */
  116.             pIndexPosition = NULL;  /* not in the middle of anything */
  117.             return EOF;             /* used up all the command-line flags */
  118.         }
  119.  
  120.         /* check for special end-of-flags markers */
  121.         if ((strcmp(pArgString, "-") == 0) ||
  122.             (strcmp(pArgString, "--") == 0)) {
  123.             optarg = NULL;          /* no argument follows the option */
  124.             pIndexPosition = NULL;  /* not in the middle of anything */
  125.             return EOF;             /* encountered the special flag */
  126.         }
  127.  
  128.         pArgString++;               /* look past the / or - */
  129.     }
  130.  
  131.     if (':' == *pArgString) {       /* is it a colon? */
  132.         /*---------------------------------------------------------------------
  133.          * Rare case: if opterr is non-zero, return a question mark;
  134.          * otherwise, just return the colon we're on.
  135.          *-------------------------------------------------------------------*/
  136.         return (opterr ? (int)'?' : (int)':');
  137.     }
  138.     else if ((pOptString = strchr(opstring, *pArgString)) == 0) {
  139.         /*---------------------------------------------------------------------
  140.          * The letter on the command-line wasn't any good.
  141.          *-------------------------------------------------------------------*/
  142.         optarg = NULL;              /* no argument follows the option */
  143.         pIndexPosition = NULL;      /* not in the middle of anything */
  144.         return (opterr ? (int)'?' : (int)*pArgString);
  145.     }
  146.     else {
  147.         /*---------------------------------------------------------------------
  148.          * The letter on the command-line matches one we expect to see
  149.          *-------------------------------------------------------------------*/
  150.         if (':' == _next_char(pOptString)) { /* is the next letter a colon? */
  151.             /* It is a colon.  Look for an argument string. */
  152.             if ('\0' != _next_char(pArgString)) {  /* argument in this argv? */
  153.                 optarg = &pArgString[1];   /* Yes, it is */
  154.             }
  155.             else {
  156.                 /*-------------------------------------------------------------
  157.                  * The argument string must be in the next argv.
  158.                  * But, what if there is none (bad input from the user)?
  159.                  * In that case, return the letter, and optarg as NULL.
  160.                  *-----------------------------------------------------------*/
  161.                 if (optind < argc)
  162.                     optarg = argv[optind++];
  163.                 else {
  164.                     optarg = NULL;
  165.                     return (opterr ? (int)'?' : (int)*pArgString);
  166.                 }
  167.             }
  168.             pIndexPosition = NULL;  /* not in the middle of anything */
  169.         }
  170.         else {
  171.             /* it's not a colon, so just return the letter */
  172.             optarg = NULL;          /* no argument follows the option */
  173.             pIndexPosition = pArgString;    /* point to the letter we're on */
  174.         }
  175.         return (int)*pArgString;    /* return the letter that matched */
  176.     }
  177. }
  178.