Header And Logo

PostgreSQL
| The world's most advanced open source database.

getopt_long.c

Go to the documentation of this file.
00001 /*
00002  * getopt_long() -- long options parser
00003  *
00004  * Portions Copyright (c) 1987, 1993, 1994
00005  * The Regents of the University of California.  All rights reserved.
00006  *
00007  * Portions Copyright (c) 2003
00008  * PostgreSQL Global Development Group
00009  *
00010  * Redistribution and use in source and binary forms, with or without
00011  * modification, are permitted provided that the following conditions
00012  * are met:
00013  * 1. Redistributions of source code must retain the above copyright
00014  *    notice, this list of conditions and the following disclaimer.
00015  * 2. Redistributions in binary form must reproduce the above copyright
00016  *    notice, this list of conditions and the following disclaimer in the
00017  *    documentation and/or other materials provided with the distribution.
00018  * 3. Neither the name of the University nor the names of its contributors
00019  *    may be used to endorse or promote products derived from this software
00020  *    without specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  *
00034  * src/port/getopt_long.c
00035  */
00036 
00037 #include "c.h"
00038 
00039 #include "getopt_long.h"
00040 
00041 #define BADCH   '?'
00042 #define BADARG  ':'
00043 #define EMSG    ""
00044 
00045 
00046 /*
00047  * getopt_long
00048  *  Parse argc/argv argument vector, with long options.
00049  *
00050  * This implementation does not use optreset.  Instead, we guarantee that
00051  * it can be restarted on a new argv array after a previous call returned -1,
00052  * if the caller resets optind to 1 before the first call of the new series.
00053  * (Internally, this means we must be sure to reset "place" to EMSG before
00054  * returning -1.)
00055  */
00056 int
00057 getopt_long(int argc, char *const argv[],
00058             const char *optstring,
00059             const struct option * longopts, int *longindex)
00060 {
00061     static char *place = EMSG;  /* option letter processing */
00062     char       *oli;            /* option letter list index */
00063 
00064     if (!*place)
00065     {                           /* update scanning pointer */
00066         if (optind >= argc)
00067         {
00068             place = EMSG;
00069             return -1;
00070         }
00071 
00072         place = argv[optind];
00073 
00074         if (place[0] != '-')
00075         {
00076             place = EMSG;
00077             return -1;
00078         }
00079 
00080         place++;
00081 
00082         if (place[0] && place[0] == '-' && place[1] == '\0')
00083         {                       /* found "--" */
00084             ++optind;
00085             place = EMSG;
00086             return -1;
00087         }
00088 
00089         if (place[0] && place[0] == '-' && place[1])
00090         {
00091             /* long option */
00092             size_t      namelen;
00093             int         i;
00094 
00095             place++;
00096 
00097             namelen = strcspn(place, "=");
00098             for (i = 0; longopts[i].name != NULL; i++)
00099             {
00100                 if (strlen(longopts[i].name) == namelen
00101                     && strncmp(place, longopts[i].name, namelen) == 0)
00102                 {
00103                     if (longopts[i].has_arg)
00104                     {
00105                         if (place[namelen] == '=')
00106                             optarg = place + namelen + 1;
00107                         else if (optind < argc - 1)
00108                         {
00109                             optind++;
00110                             optarg = argv[optind];
00111                         }
00112                         else
00113                         {
00114                             if (optstring[0] == ':')
00115                                 return BADARG;
00116                             if (opterr)
00117                                 fprintf(stderr,
00118                                    "%s: option requires an argument -- %s\n",
00119                                         argv[0], place);
00120                             place = EMSG;
00121                             optind++;
00122                             return BADCH;
00123                         }
00124                     }
00125                     else
00126                     {
00127                         optarg = NULL;
00128                         if (place[namelen] != 0)
00129                         {
00130                             /* XXX error? */
00131                         }
00132                     }
00133 
00134                     optind++;
00135 
00136                     if (longindex)
00137                         *longindex = i;
00138 
00139                     place = EMSG;
00140 
00141                     if (longopts[i].flag == NULL)
00142                         return longopts[i].val;
00143                     else
00144                     {
00145                         *longopts[i].flag = longopts[i].val;
00146                         return 0;
00147                     }
00148                 }
00149             }
00150 
00151             if (opterr && optstring[0] != ':')
00152                 fprintf(stderr,
00153                         "%s: illegal option -- %s\n", argv[0], place);
00154             place = EMSG;
00155             optind++;
00156             return BADCH;
00157         }
00158     }
00159 
00160     /* short option */
00161     optopt = (int) *place++;
00162 
00163     oli = strchr(optstring, optopt);
00164     if (!oli)
00165     {
00166         if (!*place)
00167             ++optind;
00168         if (opterr && *optstring != ':')
00169             fprintf(stderr,
00170                     "%s: illegal option -- %c\n", argv[0], optopt);
00171         return BADCH;
00172     }
00173 
00174     if (oli[1] != ':')
00175     {                           /* don't need argument */
00176         optarg = NULL;
00177         if (!*place)
00178             ++optind;
00179     }
00180     else
00181     {                           /* need an argument */
00182         if (*place)             /* no white space */
00183             optarg = place;
00184         else if (argc <= ++optind)
00185         {                       /* no arg */
00186             place = EMSG;
00187             if (*optstring == ':')
00188                 return BADARG;
00189             if (opterr)
00190                 fprintf(stderr,
00191                         "%s: option requires an argument -- %c\n",
00192                         argv[0], optopt);
00193             return BADCH;
00194         }
00195         else
00196             /* white space */
00197             optarg = argv[optind];
00198         place = EMSG;
00199         ++optind;
00200     }
00201     return optopt;
00202 }