00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
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
00097 long_opts[i].name = "help";
00098 }
00099 }
00100
00101
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
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
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 }