Basic Image AlgorithmS Library 2.8.0

getopt_long_W32.cpp

00001 // must be first: 
00002 //#include "precompiled.h"
00003 
00004 /*  $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $  */
00005 /*  $FreeBSD: src/lib/libc/stdlib/getopt_long.c,v 1.2 2002/10/16 22:18:42 alfred Exp $ */
00006 
00007 /*-
00008  * Copyright (c) 2000 The NetBSD Foundation, Inc.
00009  * All rights reserved.
00010  *
00011  * This code is derived from software contributed to The NetBSD Foundation
00012  * by Dieter Baron and Thomas Klausner.
00013  *
00014  * Redistribution and use in source and binary forms, with or without
00015  * modification, are permitted provided that the following conditions
00016  * are met:
00017  * 1. Redistributions of source code must retain the above copyright
00018  *    notice, this list of conditions and the following disclaimer.
00019  * 2. Redistributions in binary form must reproduce the above copyright
00020  *    notice, this list of conditions and the following disclaimer in the
00021  *    documentation and/or other materials provided with the distribution.
00022  * 3. All advertising materials mentioning features or use of this software
00023  *    must display the following acknowledgement:
00024  *        This product includes software developed by the NetBSD
00025  *        Foundation, Inc. and its contributors.
00026  * 4. Neither the name of The NetBSD Foundation nor the names of its
00027  *    contributors may be used to endorse or promote products derived
00028  *    from this software without specific prior written permission.
00029  *
00030  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
00031  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00032  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00033  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
00034  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00035  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00036  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00037  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00038  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00039  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00040  * POSSIBILITY OF SUCH DAMAGE.
00041  */
00042 
00043 #define _CRT_SECURE_NO_DEPRECATE 
00044 #include <stdio.h>
00045 
00046 #include "getopt_W32.h"
00047 #include <stdlib.h>
00048 #include <string.h>
00049 
00050 #ifdef _WIN32
00051 
00052 /* Windows needs warnx().  We change the definition though:
00053  *  1. (another) global is defined, opterrmsg, which holds the error message
00054  *  2. errors are always printed out on stderr w/o the program name
00055  * Note that opterrmsg always gets set no matter what opterr is set to.  The
00056  * error message will not be printed if opterr is 0 as usual.
00057  */
00058 
00059 #include <stdio.h>
00060 #include <stdarg.h>
00061 
00062 extern char opterrmsg[128];
00063 char opterrmsg[128]; /* last error message is stored here */
00064 
00065 static void warnx(int print_error, const char *fmt, ...)
00066 {
00067     va_list ap;
00068     va_start(ap, fmt);
00069     if (fmt != NULL)
00070         _vsnprintf(opterrmsg, 128, fmt, ap);
00071     else
00072         opterrmsg[0]='\0';
00073     va_end(ap);
00074     if (print_error) {
00075         fprintf(stderr, opterrmsg);
00076         fprintf(stderr, "\n");
00077     }
00078 }
00079 
00080 #endif /*_WIN32*/
00081 
00082 /* not part of the original file */
00083 #ifndef _DIAGASSERT
00084 #  define _DIAGASSERT(X)
00085 #endif
00086 
00087 #if HAVE_CONFIG_H && !HAVE_GETOPT_LONG && !HAVE_DECL_OPTIND
00088 #  define REPLACE_GETOPT
00089 #endif
00090 
00091 #ifdef REPLACE_GETOPT
00092 #  ifdef __weak_alias
00093      __weak_alias(getopt,_getopt)
00094 #  endif
00095 
00096   int   opterr = 1;     /* if error message should be printed */
00097   int   optind = 1;     /* index into parent argv vector */
00098   int   optopt = '?';       /* character checked for validity */
00099   int   optreset;       /* reset getopt */
00100   char    *optarg;      /* argument associated with option */
00101 #elif HAVE_CONFIG_H && !HAVE_DECL_OPTRESET
00102   static int optreset;
00103 #endif
00104 
00105 #ifdef __weak_alias
00106 __weak_alias(getopt_long,_getopt_long)
00107 #endif
00108 
00109 #if !HAVE_GETOPT_LONG
00110 #define IGNORE_FIRST    (*options == '-' || *options == '+')
00111 #define PRINT_ERROR ((opterr) && ((*options != ':') \
00112                       || (IGNORE_FIRST && options[1] != ':')))
00113 #define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL)
00114 #define PERMUTE         (!IS_POSIXLY_CORRECT && !IGNORE_FIRST)
00115 /* XXX: GNU ignores PC if *options == '-' */
00116 #define IN_ORDER        (!IS_POSIXLY_CORRECT && *options == '-')
00117 
00118 /* return values */
00119 #define BADCH   (int)'?'
00120 #define BADARG      ((IGNORE_FIRST && options[1] == ':') \
00121              || (*options == ':') ? (int)':' : (int)'?')
00122 #define INORDER (int)1
00123 
00124 #define EMSG    ""
00125 
00126 static int getopt_internal(int, char * const *, const char *);
00127 static int gcd(int, int);
00128 static void permute_args(int, int, int, char * const *);
00129 
00130 static char *place = EMSG; /* option letter processing */
00131 
00132 /* XXX: set optreset to 1 rather than these two */
00133 static int nonopt_start = -1; /* first non option argument (for permute) */
00134 static int nonopt_end = -1;   /* first option after non options (for permute) */
00135 
00136 /* Error messages */
00137 static const char recargchar[] = "option requires an argument -- %c";
00138 static const char recargstring[] = "option requires an argument -- %s";
00139 static const char ambig[] = "ambiguous option -- %.*s";
00140 static const char noarg[] = "option doesn't take an argument -- %.*s";
00141 static const char illoptchar[] = "unknown option -- %c";
00142 static const char illoptstring[] = "unknown option -- %s";
00143 
00144 
00145 /*
00146  * Compute the greatest common divisor of a and b.
00147  */
00148 static int
00149 gcd(int a, int b)
00150 {
00151     int c;
00152 
00153     c = a % b;
00154     while (c != 0) {
00155         a = b;
00156         b = c;
00157         c = a % b;
00158     }
00159        
00160     return b;
00161 }
00162 
00163 /*
00164  * Exchange the block from nonopt_start to nonopt_end with the block
00165  * from nonopt_end to opt_end (keeping the same order of arguments
00166  * in each block).
00167  */
00168 static void
00169 permute_args(int panonopt_start, int panonopt_end,int opt_end, char * const * nargv)
00170 {
00171     int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
00172     char *swap;
00173 
00174     _DIAGASSERT(nargv != NULL);
00175 
00176     /*
00177      * compute lengths of blocks and number and size of cycles
00178      */
00179     nnonopts = panonopt_end - panonopt_start;
00180     nopts = opt_end - panonopt_end;
00181     ncycle = gcd(nnonopts, nopts);
00182     cyclelen = (opt_end - panonopt_start) / ncycle;
00183 
00184     for (i = 0; i < ncycle; i++) {
00185         cstart = panonopt_end+i;
00186         pos = cstart;
00187         for (j = 0; j < cyclelen; j++) {
00188             if (pos >= panonopt_end)
00189                 pos -= nnonopts;
00190             else
00191                 pos += nopts;
00192             swap = nargv[pos];
00193             /* LINTED const cast */
00194             ((char **) nargv)[pos] = nargv[cstart];
00195             /* LINTED const cast */
00196             ((char **)nargv)[cstart] = swap;
00197         }
00198     }
00199 }
00200 
00201 /*
00202  * getopt_internal --
00203  *  Parse argc/argv argument vector.  Called by user level routines.
00204  *  Returns -2 if -- is found (can be long option or end of options marker).
00205  */
00206 static 
00207 int getopt_internal (int nargc, char * const *nargv, const char *options)
00208 {
00209     char *oli;              /* option letter list index */
00210     int optchar;
00211 
00212     _DIAGASSERT(nargv != NULL);
00213     _DIAGASSERT(options != NULL);
00214 
00215     optarg = NULL;
00216 
00217     /*
00218      * XXX Some programs (like rsyncd) expect to be able to
00219      * XXX re-initialize optind to 0 and have getopt_long(3)
00220      * XXX properly function again.  Work around this braindamage.
00221      */
00222     if (optind == 0)
00223         optind = 1;
00224 
00225     if (optreset)
00226         nonopt_start = nonopt_end = -1;
00227 start:
00228     if (optreset || !*place) {      /* update scanning pointer */
00229         optreset = 0;
00230         if (optind >= nargc) {          /* end of argument vector */
00231             place = EMSG;
00232             if (nonopt_end != -1) {
00233                 /* do permutation, if we have to */
00234                 permute_args(nonopt_start, nonopt_end,
00235                     optind, nargv);
00236                 optind -= nonopt_end - nonopt_start;
00237             }
00238             else if (nonopt_start != -1) {
00239                 /*
00240                  * If we skipped non-options, set optind
00241                  * to the first of them.
00242                  */
00243                 optind = nonopt_start;
00244             }
00245             nonopt_start = nonopt_end = -1;
00246             return -1;
00247         }
00248         if ((*(place = nargv[optind]) != '-')
00249             || (place[1] == '\0')) {    /* found non-option */
00250             place = EMSG;
00251             if (IN_ORDER) {
00252                 /*
00253                  * GNU extension: 
00254                  * return non-option as argument to option 1
00255                  */
00256                 optarg = nargv[optind++];
00257                 return INORDER;
00258             }
00259             if (!PERMUTE) {
00260                 /*
00261                  * if no permutation wanted, stop parsing
00262                  * at first non-option
00263                  */
00264                 return -1;
00265             }
00266             /* do permutation */
00267             if (nonopt_start == -1)
00268                 nonopt_start = optind;
00269             else if (nonopt_end != -1) {
00270                 permute_args(nonopt_start, nonopt_end,
00271                     optind, nargv);
00272                 nonopt_start = optind -
00273                     (nonopt_end - nonopt_start);
00274                 nonopt_end = -1;
00275             }
00276             optind++;
00277             /* process next argument */
00278             goto start;
00279         }
00280         if (nonopt_start != -1 && nonopt_end == -1)
00281             nonopt_end = optind;
00282         if (place[1] && *++place == '-') {  /* found "--" */
00283             place++;
00284             return -2;
00285         }
00286     }
00287     if ((optchar = (int)*place++) == (int)':' ||
00288         (oli = (char*)strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) {
00289         /* option letter unknown or ':' */
00290         if (!*place)
00291             ++optind;
00292 #ifndef _WIN32
00293         if (PRINT_ERROR)
00294             warnx(illoptchar, optchar);
00295 #else
00296             warnx(PRINT_ERROR, illoptchar, optchar);
00297 #endif
00298         optopt = optchar;
00299         return BADCH;
00300     }
00301     if (optchar == 'W' && oli[1] == ';') {      /* -W long-option */
00302         /* XXX: what if no long options provided (called by getopt)? */
00303         if (*place) 
00304             return -2;
00305 
00306         if (++optind >= nargc) {    /* no arg */
00307             place = EMSG;
00308 #ifndef _WIN32
00309             if (PRINT_ERROR)
00310                 warnx(recargchar, optchar);
00311 #else
00312                 warnx(PRINT_ERROR, recargchar, optchar);
00313 #endif
00314             optopt = optchar;
00315             return BADARG;
00316         } else              /* white space */
00317             place = nargv[optind];
00318         /*
00319          * Handle -W arg the same as --arg (which causes getopt to
00320          * stop parsing).
00321          */
00322         return -2;
00323     }
00324     if (*++oli != ':') {            /* doesn't take argument */
00325         if (!*place)
00326             ++optind;
00327     } else {                /* takes (optional) argument */
00328         optarg = NULL;
00329         if (*place)         /* no white space */
00330             optarg = place;
00331         /* XXX: disable test for :: if PC? (GNU doesn't) */
00332         else if (oli[1] != ':') {   /* arg not optional */
00333             if (++optind >= nargc) {    /* no arg */
00334                 place = EMSG;
00335 #ifndef _WIN32
00336                 if (PRINT_ERROR)
00337                     warnx(recargchar, optchar);
00338 #else
00339                     warnx(PRINT_ERROR, recargchar, optchar);
00340 #endif
00341                 optopt = optchar;
00342                 return BADARG;
00343             } else
00344                 optarg = nargv[optind];
00345         }
00346         place = EMSG;
00347         ++optind;
00348     }
00349     /* dump back option letter */
00350     return optchar;
00351 }
00352 
00353 #ifdef REPLACE_GETOPT
00354 /*
00355  * getopt --
00356  *  Parse argc/argv argument vector.
00357  *
00358  * [eventually this will replace the real getopt]
00359  */
00360 int
00361 BIASCommon_EXPORT getopt(nargc, nargv, options)
00362     int nargc;
00363     char * const *nargv;
00364     const char *options;
00365 {
00366     int retval;
00367 
00368     _DIAGASSERT(nargv != NULL);
00369     _DIAGASSERT(options != NULL);
00370 
00371     if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
00372         ++optind;
00373         /*
00374          * We found an option (--), so if we skipped non-options,
00375          * we have to permute.
00376          */
00377         if (nonopt_end != -1) {
00378             permute_args(nonopt_start, nonopt_end, optind,
00379                        nargv);
00380             optind -= nonopt_end - nonopt_start;
00381         }
00382         nonopt_start = nonopt_end = -1;
00383         retval = -1;
00384     }
00385     return retval;
00386 }
00387 #endif
00388 
00389 /*
00390  * getopt_long --
00391  *  Parse argc/argv argument vector.
00392  */
00393 int
00394 getopt_long(int nargc, char * const * nargv, const char *options, 
00395             const struct option *long_options, int *idx)
00396 {
00397     int retval;
00398 
00399     _DIAGASSERT(nargv != NULL);
00400     _DIAGASSERT(options != NULL);
00401     _DIAGASSERT(long_options != NULL);
00402     /* idx may be NULL */
00403 
00404     if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
00405         char *current_argv, *has_equal;
00406         size_t current_argv_len;
00407         int i, match;
00408 
00409         current_argv = place;
00410         match = -1;
00411 
00412         optind++;
00413         place = EMSG;
00414 
00415         if (*current_argv == '\0') {        /* found "--" */
00416             /*
00417              * We found an option (--), so if we skipped
00418              * non-options, we have to permute.
00419              */
00420             if (nonopt_end != -1) {
00421                 permute_args(nonopt_start, nonopt_end,
00422                     optind, nargv);
00423                 optind -= nonopt_end - nonopt_start;
00424             }
00425             nonopt_start = nonopt_end = -1;
00426             return -1;
00427         }
00428         if ((has_equal = strchr(current_argv, '=')) != NULL) {
00429             /* argument found (--option=arg) */
00430             current_argv_len = has_equal - current_argv;
00431             has_equal++;
00432         } else
00433             current_argv_len = strlen(current_argv);
00434         
00435         for (i = 0; long_options[i].name; i++) {
00436             /* find matching long option */
00437             if (strncmp(current_argv, long_options[i].name,
00438                 current_argv_len))
00439                 continue;
00440 
00441             if (strlen(long_options[i].name) ==
00442                 (unsigned)current_argv_len) {
00443                 /* exact match */
00444                 match = i;
00445                 break;
00446             }
00447             if (match == -1)        /* partial match */
00448                 match = i;
00449             else {
00450                 /* ambiguous abbreviation */
00451 #ifndef _WIN32
00452                 if (PRINT_ERROR)
00453                     warnx(ambig, (int)current_argv_len,
00454                          current_argv);
00455 #else
00456                     warnx(PRINT_ERROR, ambig, (int)current_argv_len,
00457                          current_argv);
00458 #endif
00459                 optopt = 0;
00460                 return BADCH;
00461             }
00462         }
00463         if (match != -1) {          /* option found */
00464                 if (long_options[match].has_arg == no_argument
00465                 && has_equal) {
00466 #ifndef _WIN32
00467                 if (PRINT_ERROR)
00468                     warnx(noarg, (int)current_argv_len,
00469                          current_argv);
00470 #else
00471                     warnx(PRINT_ERROR, noarg, (int)current_argv_len,
00472                          current_argv);
00473 #endif
00474                 /*
00475                  * XXX: GNU sets optopt to val regardless of
00476                  * flag
00477                  */
00478                 if (long_options[match].flag == NULL)
00479                     optopt = long_options[match].val;
00480                 else
00481                     optopt = 0;
00482                 return BADARG;
00483             }
00484             if (long_options[match].has_arg == required_argument ||
00485                 long_options[match].has_arg == optional_argument) {
00486                 if (has_equal)
00487                     optarg = has_equal;
00488                 else if (long_options[match].has_arg ==
00489                     required_argument) {
00490                     /*
00491                      * optional argument doesn't use
00492                      * next nargv
00493                      */
00494                     optarg = nargv[optind++];
00495                 }
00496             }
00497             if ((long_options[match].has_arg == required_argument)
00498                 && (optarg == NULL)) {
00499                 /*
00500                  * Missing argument; leading ':'
00501                  * indicates no error should be generated
00502                  */
00503 #ifndef _WIN32
00504                 if (PRINT_ERROR)
00505                     warnx(recargstring, current_argv);
00506 #else
00507                     warnx(PRINT_ERROR, recargstring, current_argv);
00508 #endif
00509                 /*
00510                  * XXX: GNU sets optopt to val regardless
00511                  * of flag
00512                  */
00513                 if (long_options[match].flag == NULL)
00514                     optopt = long_options[match].val;
00515                 else
00516                     optopt = 0;
00517                 --optind;
00518                 return BADARG;
00519             }
00520         } else {            /* unknown option */
00521 #ifndef _WIN32
00522             if (PRINT_ERROR)
00523                 warnx(illoptstring, current_argv);
00524 #else
00525                 warnx(PRINT_ERROR, illoptstring, current_argv);
00526 #endif
00527             optopt = 0;
00528             return BADCH;
00529         }
00530         if (long_options[match].flag) {
00531             *long_options[match].flag = long_options[match].val;
00532             retval = 0;
00533         } else 
00534             retval = long_options[match].val;
00535         if (idx)
00536             *idx = match;
00537     }
00538     return retval;
00539 }
00540 #endif /* !GETOPT_LONG */
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends