coan 4.2.4
get_options.c
Go to the documentation of this file.
00001 
00002 /***************************************************************************
00003  *   Copyright (C) 2004 - 2006 Symbian Software Ltd.                       *
00004  *   All rights reserved.                                                  *
00005  *   Copyright (C) 2007-2011 Mike Kinghan, imk@strudl.org                  *
00006  *   All rights reserved.                                                  *
00007  *                                                                         *
00008  *   Contributed originally by Mike Kinghan, imk@strudl.org                *
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  *                                                                         *
00014  *   Redistributions of source code must retain the above copyright        *
00015  *   notice, this list of conditions and the following disclaimer.         *
00016  *                                                                         *
00017  *   Redistributions in binary form must reproduce the above copyright     *
00018  *   notice, this list of conditions and the following disclaimer in the   *
00019  *   documentation and/or other materials provided with the distribution.  *
00020  *                                                                         *
00021  *   Neither the name of Symbian Software Ltd. nor the names of its        *
00022  *   contributors may be used to endorse or promote products derived from  *
00023  *   this software without specific prior written permission.              *
00024  *                                                                         *
00025  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   *
00026  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     *
00027  *   LIMITED TO, THE IMPLIED WARRANTIES OF  MERCHANTABILITY AND FITNESS    *
00028  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE        *
00029  *   COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,   *
00030  *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,  *
00031  *   BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS *
00032  *   OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    *
00033  *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,*
00034  *   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF *
00035  *   THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH  *
00036  *   DAMAGE.                                                               *
00037  *                                                                         *
00038  **************************************************************************/
00039 
00040 #include "get_options.h"
00041 #include <assert.h>
00042 #include <string.h>
00043 
00049 /* API */
00050 
00051 int optind;
00052 int optopt;
00053 char *optarg;
00054 
00055 cmd_option_t const *
00056 get_command_option(int argc, char *argv[], cmd_option_t const * commands)
00057 {
00058     if (argc > 1) {
00059         cmd_option_t const * command = commands;
00060         assert(commands);
00061         for (   ; command->name; ++command) {
00062             if (!strcmp(argv[1],command->name)) {
00063                 return command;
00064             }
00065         }
00066     }
00067     return NULL;
00068 }
00069 
00070 bool
00071 opts_are_compatible(    int opt_excluder, int opt_excluded,
00072                         struct exclusion_list const *exclusions, bool indexed)
00073 {
00074     struct exclusion_list const * which;
00075     bool verdict = true;
00076     assert(exclusions);
00077     if (indexed) {
00078         which = exclusions + opt_excluder;
00079     } else {
00080         which = exclusions;
00081         for (   ; which->excluder; ++which) {
00082             if (which->excluder == opt_excluder) {
00083                 break;
00084             }
00085         }
00086     }
00087     if (which->excluder) {
00088         int const *excluded = which->excluded;
00089         if (excluded) {
00090             for (       ; *excluded; ++excluded ) {
00091                 if (opt_excluded == *excluded) {
00092                     verdict = false;
00093                 }
00094             }
00095         }
00096     }
00097     return verdict;
00098 }
00099 
00100 int
00101 getopt_long(int argc, char * argv[], const char *optstr,
00102             const struct option *longopts, int *longind)
00103 {
00104     char *opt;
00105     optarg = NULL;
00106     if (longind) {
00107         *longind = -1;
00108     }
00109     if (optind < 0) {
00110         return -1;
00111     }
00112     if (optind == 0) {  /* Initial or re-initialising call*/
00113         ++optind; /* Skip argv[0]*/
00114     }
00115     if (optind >= argc) {
00116         return -1;
00117     }
00118     opt = argv[optind];
00119     if (*opt == '-') {  /* argv[optind] is an option*/
00120         ++optind;
00121         if (*++opt == ':') {
00122             optopt = ':';
00123             return '?';
00124         }
00125         if (*opt != '-') { /* Short option*/
00126             char *where = strchr(optstr,*opt);
00127             if (!where) {
00128                 optopt = *opt;
00129                 return '?';
00130             }
00131             if (where[1] != ':') {      /* No argument*/
00132                 if (opt[1]) {
00133                     optopt = *opt;
00134                     return '?';
00135                 }
00136                 optarg = NULL;
00137                 return *opt;
00138             } else if (where[2] != ':') { /* Optional argument*/
00139                 if (opt[1] != 0) {      /* arg abuts opt*/
00140                     optarg = opt + 1;
00141                     return *opt;
00142                 } else if (optind >= argc || *argv[optind] == '-') {
00143                     /* No arg*/
00144                     optarg = NULL;
00145                     return *opt;
00146                 } else {        /* Arg is next argv*/
00147                     optarg = argv[optind++];
00148                     return *opt;
00149                 }
00150             } else {    /* Required argument*/
00151                 if (opt[1] != 0) {      /* arg abuts opt*/
00152                     optarg = opt + 1;
00153                     return *opt;
00154                 } else if (optind >= argc || *argv[optind] == '-') {
00155                     /* Required arg missing*/
00156                     optopt = *opt;
00157                     return '?';
00158                 } else {        /* arg is next argv*/
00159                     optarg = argv[optind++];
00160                     return *opt;
00161                 }
00162             }
00163         } else { /* Long option*/
00164             int i, match = -1;
00165             size_t optlen;
00166             /* Test for `opt=arg' and get length of opt*/
00167             char *eq = strchr(++opt,'=');
00168             if (eq) {
00169                 optarg = eq + 1;
00170                 optlen = eq - opt;
00171             } else {
00172                 optlen = strlen(opt);
00173             }
00174             /* Test for exactly one match of the option*/
00175             for (i = 0; longopts[i].name != NULL; ++i) {
00176                 if (!strncmp(opt,longopts[i].name,optlen)) {
00177                     if (match != -1) {
00178                         match = -1;
00179                         break;
00180                     }
00181                     match = i;
00182                 }
00183             }
00184             if (longind != NULL) {
00185                 *longind = match;
00186             }
00187             if (match == -1) { /* Not found*/
00188                 return '?';
00189             }
00190             switch(longopts[match].has_arg) {
00191             case no_argument:
00192                 if (optarg) {   /* Illegal arg*/
00193                     return '?';
00194                 }
00195                 break;
00196             case required_argument:
00197                 if (optarg) {   /* Arg after `='*/
00198                     break;
00199                 }
00200                 if (optind >= argc || *argv[optind] == '-') {
00201                     /* Required arg missing*/
00202                     return '?';
00203                 }
00204                 /* Arg is next argv*/
00205                 optarg = argv[optind++];
00206                 break;
00207             case optional_argument:
00208                 if (optarg) {   /* Arg after `='*/
00209                     break;
00210                 }
00211                 if (optarg || optind >= argc || *argv[optind] == '-') {
00212                     /* No argument*/
00213                     break;
00214                 }
00215                 optarg = argv[optind++];
00216                 break;
00217             default:
00218                 assert(false);
00219             }
00220             /* Store or return value as required*/
00221             if (longopts[match].flag != NULL) {
00222                 *(longopts[match].flag) = longopts[i].val;
00223                 return 0;
00224             } else {
00225                 return longopts[match].val;
00226             }
00227         }
00228     } else {
00229         /* argv[optind] is a non-option.
00230                         We want to shuffle it to the end*/
00231         bool done = true;       /* Posit no more options to the right*/
00232         int i;
00233         for (i = optind; done && i < argc; ++i) {
00234             /* Now see if this is true*/
00235             done = *argv[i] != '-';
00236         }
00237         if (done) { /* There are no more options to the right*/
00238             optarg = argv[optind]; /* optind at start of non-options*/
00239             return -1; /* All done*/
00240         } else { /* There are more options to the right*/
00241             /* Swap the current non-opt to the end of argv*/
00242             char *temp = argv[optind];
00243             memmove(argv + optind,argv + optind + 1,
00244                     (argc - optind - 1) * sizeof(char *));
00245             argv[argc - 1] = temp;
00246             /* Try for another option*/
00247             return getopt_long(argc,argv,optstr,longopts,longind);
00248         }
00249     }
00250 }
00251 
00252 const char *
00253 get_long_opt_name(struct option const * longopts, int opt)
00254 {
00255     struct option const * longopt = longopts;
00256     for (       ;       longopt->name; ++longopt) {
00257         if (longopt->val == opt) {
00258             return longopt->name;
00259         }
00260     }
00261     return NULL;
00262 }
00263 
00264 
00265 /* EOF*/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines