Getopt.cc

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2005-2006 Intel Corporation
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
00015  */
00016 
00017 #include <stdio.h>
00018 #include <unistd.h>
00019 
00020 #include "config.h"
00021 
00022 #ifdef HAVE_GETOPT_LONG
00023 #include <getopt.h>
00024 #else
00025 #include "compat/getopt.h"
00026 #endif
00027 
00028 #include "Getopt.h"
00029 
00030 namespace oasys {
00031 
00032 //----------------------------------------------------------------------
00033 Getopt::Getopt()
00034 {
00035     memset(&opts_, 0, sizeof(opts_));
00036 }
00037 
00038 //----------------------------------------------------------------------
00039 Getopt::~Getopt()
00040 {
00041     while (!allopts_.empty()) {
00042         delete allopts_.back();
00043         allopts_.pop_back();
00044     }
00045 }
00046 
00047 //----------------------------------------------------------------------
00048 void
00049 Getopt::addopt(Opt* opt)
00050 {
00051     if (opt->shortopt_ != 0) {
00052         int c = opt->shortopt_;
00053         if (opts_[c]) {
00054             fprintf(stderr,
00055                     "FATAL ERROR: multiple addopt calls for char '%c'\n", c);
00056             abort();
00057         }
00058         
00059         opts_[c] = opt;
00060     }
00061     allopts_.push_back(opt);
00062 }
00063 
00064 //----------------------------------------------------------------------
00065 int
00066 Getopt::getopt(const char* progname, int argc, char* const argv[],
00067                const char* extra_usage)
00068 {
00069     Opt* opt;
00070     char short_opts[256];
00071     char* optstring = short_opts;
00072     int c, i;
00073     struct option* long_opts;
00074 
00075     int nopts = allopts_.size(); 
00076 
00077     // alloc two extra getopt -- one for help, one for all zeros
00078     long_opts = (struct option*) malloc(sizeof(struct option) * (nopts + 2));
00079     memset(long_opts, 0, sizeof(struct option) * (nopts + 2));
00080     
00081     for (i = 0; i < nopts; ++i)
00082     {
00083         opt = allopts_[i];
00084         
00085         if (opt->shortopt_) {
00086             *optstring++ = opt->shortopt_;
00087             if (opt->needval_) {
00088                 *optstring++ = ':';
00089             }
00090         }
00091 
00092         if (opt->longopt_) {
00093             long_opts[i].name = opt->longopt_;
00094             long_opts[i].has_arg = opt->needval_;
00095         } else {
00096             // ignore this slot
00097             long_opts[i].name = "help";
00098         }
00099     }
00100                                         
00101     // tack on the help option
00102     *optstring++ = 'h';
00103     *optstring++ = 'H';
00104     long_opts[nopts].name = "help";
00105     
00106     while (1) {
00107         c = ::getopt_long(argc, argv, short_opts, long_opts, &i);
00108         switch(c) {
00109         case 0:
00110             if (!strcmp(long_opts[i].name, "help"))
00111             {
00112                 usage(progname, extra_usage);
00113                 exit(0);
00114             }
00115 
00116             opt = allopts_[i];
00117 
00118             if (opt->set(optarg, optarg ? strlen(optarg) : 0) != 0) {
00119                 fprintf(stderr, "invalid value '%s' for option '--%s'\n",
00120                         optarg, opt->longopt_);
00121                 exit(1);
00122             }
00123 
00124             break;
00125         case ':':
00126             // missing value to option
00127             fprintf(stderr, "option %s requires a value\n", long_opts[i].name);
00128             usage(progname, extra_usage);
00129             exit(0);
00130             
00131         case '?':
00132         case 'h':
00133         case 'H':
00134             usage(progname, extra_usage);
00135             exit(0);
00136             
00137         case -1:
00138             // end of list
00139             goto done;
00140             
00141         default:
00142             if (c < 0 || c > 256) {
00143                 fprintf(stderr, "FATAL ERROR: %d returned from getopt\n", c);
00144                 abort();
00145             }
00146             opt = opts_[c];
00147 
00148             if (!opt) {
00149                 fprintf(stderr, "unknown char '%c' returned from getopt\n", c);
00150                 exit(1);
00151             }
00152                 
00153             if (opt->set(optarg, optarg ? strlen(optarg) : 0) != 0) {
00154                 fprintf(stderr, "invalid value '%s' for option '-%c'\n",
00155                         optarg, c);
00156                 exit(1);
00157             }
00158             
00159             if (opt->setp_)
00160                 *opt->setp_ = true;
00161             
00162         }
00163     }
00164 
00165  done:
00166     free(long_opts);
00167     return optind;
00168 }
00169 
00170 //----------------------------------------------------------------------
00171 void
00172 Getopt::usage(const char* progname, const char* extra_usage)
00173 {
00174     OptList::iterator iter;
00175     char opts[128];
00176 
00177     const char* s = strrchr(progname, '/');
00178     if (s != NULL) {
00179         progname = s + 1;
00180     }
00181     fprintf(stderr, "usage: %s [opts] %s\n\nopts:\n",
00182             progname, extra_usage);
00183 
00184     snprintf(opts, sizeof(opts), "-h, --help");
00185     fprintf(stderr, "  %-24s%s\n", opts, "show usage");
00186 
00187     for (iter = allopts_.begin(); iter != allopts_.end(); ++iter)
00188     {
00189         Opt* opt = *iter;
00190         
00191         if (opt->shortopt_ && opt->longopt_)
00192         {
00193             snprintf(opts, sizeof(opts), "-%c, --%s %s",
00194                      opt->shortopt_, opt->longopt_, opt->valdesc_);
00195         }
00196         else if (opt->shortopt_)
00197         {
00198             snprintf(opts, sizeof(opts), "-%c %s",
00199                      opt->shortopt_, opt->valdesc_);
00200         } else {
00201             snprintf(opts, sizeof(opts), "--%s %s    ",
00202                      opt->longopt_, opt->valdesc_);
00203         }
00204 
00205         if (strlen(opts) <= 24) {
00206             fprintf(stderr, "  %-24s%s\n", opts, opt->desc_);
00207         } else {
00208             fprintf(stderr, "  %s\n", opts);
00209             fprintf(stderr, "                          %s\n", opt->desc_);
00210         }
00211     }
00212 }
00213 
00214 } // namespace oasys

Generated on Sat Sep 8 08:36:17 2007 for DTN Reference Implementation by  doxygen 1.5.3