dlvhex  2.5.0
vs10/getopt.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1987, 1993, 1994, 1996
00003  *  The Regents of the University of California.  All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. All advertising materials mentioning features or use of this software
00014  *    must display the following acknowledgement:
00015  *  This product includes software developed by the University of
00016  *  California, Berkeley and its contributors.
00017  * 4. Neither the name of the University nor the names of its contributors
00018  *    may be used to endorse or promote products derived from this software
00019  *    without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00022  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00025  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00026  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00027  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00028  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00030  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031  * SUCH DAMAGE.
00032  */
00033 #include <assert.h>
00034 #include <errno.h>
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include "getopt.h"
00039 
00040 int   opterr = 0;   /* if error message should be printed */
00041 int   optind = 1;   /* index into parent argv vector */
00042 int   optopt = 0;   /* character checked for validity */
00043 int   optreset = 0; /* reset getopt */
00044 char *optarg;   /* argument associated with option */
00045 
00046 #define __P(x) x
00047 #define _DIAGASSERT(x) assert(x)
00048 
00049 static char * __progname __P((char *));
00050 int getopt_internal __P((int, char * const *, const char *));
00051 
00052 static char *
00053 __progname(nargv0)
00054     char * nargv0;
00055 {
00056     char * tmp;
00057 
00058     _DIAGASSERT(nargv0 != NULL);
00059 
00060     tmp = strrchr(nargv0, '/');
00061     if (tmp)
00062         tmp++;
00063     else
00064         tmp = nargv0;
00065     return(tmp);
00066 }
00067 
00068 #define BADCH   (int)'?'
00069 #define BADARG  (int)':'
00070 #define EMSG    ""
00071 
00072 /*
00073  * getopt --
00074  *  Parse argc/argv argument vector.
00075  */
00076 int
00077 getopt_internal(nargc, nargv, ostr)
00078     int nargc;
00079     char * const *nargv;
00080     const char *ostr;
00081 {
00082     static char *place = EMSG;      /* option letter processing */
00083     char *oli;              /* option letter list index */
00084 
00085     _DIAGASSERT(nargv != NULL);
00086     _DIAGASSERT(ostr != NULL);
00087 
00088     if (optreset || !*place) {      /* update scanning pointer */
00089         optreset = 0;
00090         if (optind >= nargc || *(place = nargv[optind]) != '-') {
00091             place = EMSG;
00092             return (-1);
00093         }
00094         if (place[1] && *++place == '-') {  /* found "--" */
00095             /* ++optind; */
00096             place = EMSG;
00097             return (-2);
00098         }
00099     }                   /* option letter okay? */
00100     if ((optopt = (int)*place++) == (int)':' ||
00101         !(oli = strchr(ostr, optopt))) {
00102         /*
00103          * if the user didn't specify '-' as an option,
00104          * assume it means -1.
00105          */
00106         if (optopt == (int)'-')
00107             return (-1);
00108         if (!*place)
00109             ++optind;
00110         if (opterr && *ostr != ':')
00111             (void)fprintf(stderr,
00112                 "%s: illegal option -- %c\n", __progname(nargv[0]), optopt);
00113         return (BADCH);
00114     }
00115     if (*++oli != ':') {            /* don't need argument */
00116         optarg = NULL;
00117         if (!*place)
00118             ++optind;
00119     } else {                /* need an argument */
00120         if (*place)         /* no white space */
00121             optarg = place;
00122         else if (nargc <= ++optind) {   /* no arg */
00123             place = EMSG;
00124             if ((opterr) && (*ostr != ':'))
00125                 (void)fprintf(stderr,
00126                     "%s: option requires an argument -- %c\n",
00127                     __progname(nargv[0]), optopt);
00128             return (BADARG);
00129         } else              /* white space */
00130             optarg = nargv[optind];
00131         place = EMSG;
00132         ++optind;
00133     }
00134     return (optopt);            /* dump back option letter */
00135 }
00136 
00137 #if 0
00138 /*
00139  * getopt --
00140  *  Parse argc/argv argument vector.
00141  */
00142 int
00143 getopt2(nargc, nargv, ostr)
00144     int nargc;
00145     char * const *nargv;
00146     const char *ostr;
00147 {
00148     int retval;
00149 
00150     if ((retval = getopt_internal(nargc, nargv, ostr)) == -2) {
00151         retval = -1;
00152         ++optind; 
00153     }
00154     return(retval);
00155 }
00156 #endif
00157 
00158 /*
00159  * getopt_long --
00160  *  Parse argc/argv argument vector.
00161  */
00162 int
00163 getopt_long(nargc, nargv, options, long_options, index)
00164     int nargc;
00165     char ** nargv;
00166     char * options;
00167     struct option * long_options;
00168     int * index;
00169 {
00170     int retval;
00171 
00172     _DIAGASSERT(nargv != NULL);
00173     _DIAGASSERT(options != NULL);
00174     _DIAGASSERT(long_options != NULL);
00175     /* index may be NULL */
00176 
00177     if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
00178         char *current_argv = nargv[optind++] + 2, *has_equal;
00179         int i, current_argv_len, match = -1;
00180 
00181         if (*current_argv == '\0') {
00182             return(-1);
00183         }
00184         if ((has_equal = strchr(current_argv, '=')) != NULL) {
00185             current_argv_len = has_equal - current_argv;
00186             has_equal++;
00187         } else
00188             current_argv_len = strlen(current_argv);
00189 
00190         for (i = 0; long_options[i].name; i++) { 
00191             if (strncmp(current_argv, long_options[i].name, current_argv_len))
00192                 continue;
00193 
00194             if (strlen(long_options[i].name) == (unsigned)current_argv_len) { 
00195                 match = i;
00196                 break;
00197             }
00198             if (match == -1)
00199                 match = i;
00200         }
00201         if (match != -1) {
00202             if (long_options[match].has_arg == required_argument ||
00203                 long_options[match].has_arg == optional_argument) {
00204                 if (has_equal)
00205                     optarg = has_equal;
00206                 else
00207                     optarg = nargv[optind++];
00208             }
00209             if ((long_options[match].has_arg == required_argument)
00210                 && (optarg == NULL)) {
00211                 /*
00212                  * Missing argument, leading :
00213                  * indicates no error should be generated
00214                  */
00215                 if ((opterr) && (*options != ':'))
00216                     (void)fprintf(stderr,
00217                       "%s: option requires an argument -- %s\n",
00218                       __progname(nargv[0]), current_argv);
00219                 return (BADARG);
00220             }
00221         } else { /* No matching argument */
00222             if ((opterr) && (*options != ':'))
00223                 (void)fprintf(stderr,
00224                     "%s: illegal option -- %s\n", __progname(nargv[0]), current_argv);
00225             return (BADCH);
00226         }
00227         if (long_options[match].flag) {
00228             *long_options[match].flag = long_options[match].val;
00229             retval = 0;
00230         } else 
00231             retval = long_options[match].val;
00232         if (index)
00233             *index = match;
00234     }
00235     return(retval);
00236 }