15 #include "panda_getopt_impl.h" 18 #if defined(HAVE_GETOPT) && defined(HAVE_GETOPT_LONG_ONLY) 42 PandaGetopt(
int argc,
char *
const argv[],
const char *optstring,
43 const struct option *longopts,
bool allow_one_hyphen_long);
45 void permute(
int argc,
char **mutable_argv);
46 int process(
int opterr,
int *longindex,
char *&optarg,
int &optind,
int &optopt);
49 size_t find_short_option(
char short_option);
50 size_t find_long_option(
const string &long_option);
52 void scan_options(
const char *optstring,
const struct option *longopts);
53 void scan_args(
int argc,
char *
const argv[]);
62 Option(
char short_option,
int has_arg);
63 Option(
const struct option *longopts,
int longopts_index);
68 const struct option *_option;
80 Param(
size_t opt_index,
size_t argv_index,
81 char short_option,
char *argument = NULL);
104 Arguments _output_argv;
110 Arguments _arguments;
114 bool _return_in_order;
119 bool _allow_one_hyphen_long;
128 size_t _next_argv_index;
141 PandaGetopt(
int argc,
char *
const argv[],
const char *optstring,
142 const struct option *longopts,
bool allow_one_hyphen_long) {
143 assert(optstring != NULL);
145 _return_in_order =
false;
146 _require_order =
false;
147 _allow_one_hyphen_long = allow_one_hyphen_long;
151 _options.push_back(Option(
'?', no_argument));
153 if (optstring[0] ==
'-') {
158 _return_in_order =
true;
161 _options.push_back(Option(
'\001', required_argument));
163 }
else if (optstring[0] ==
'+') {
168 _require_order =
true;
170 }
else if (getenv(
"POSIXLY_CORRECT") != NULL) {
172 _require_order =
true;
180 scan_options(optstring, longopts);
181 scan_args(argc, argv);
194 if (!_require_order && !_return_in_order) {
197 Arguments::const_iterator gi;
198 for (gi = _output_argv.begin(); gi != _output_argv.end(); ++gi) {
199 assert((
int)i < argc);
200 mutable_argv[i] = (*gi);
203 _next_argv_index = i;
204 for (gi = _arguments.begin(); gi != _arguments.end(); ++gi) {
205 assert((
int)i < argc);
206 mutable_argv[i] = (*gi);
209 assert((
int)i == argc);
222 process(
int opterr,
int *longindex,
char *&optarg,
int &optind,
int &optopt) {
223 if (_next_param >= _params.size()) {
224 optind = _next_argv_index;
228 const Param ¶m = _params[_next_param];
230 const Option &
option = _options[param._opt_index];
232 optarg = param._argument;
233 optind = (int)param._argv_index;
234 if (longindex != NULL) {
235 *longindex = option._longopts_index;
238 if (option._option != NULL) {
241 if (option._option->flag == NULL) {
242 return option._option->val;
244 *(option._option->flag) = option._option->val;
248 if (param._opt_index == 0 && opterr) {
250 optopt = param._short_option;
251 cerr <<
"Illegal option: -" << param._short_option <<
"\n";
256 return param._short_option;
267 find_short_option(
char short_option) {
268 size_t opt_index = 1;
269 while (opt_index < _options.size()) {
270 if (_options[opt_index]._short_option == short_option) {
289 find_long_option(
const string &long_option) {
290 string search = long_option;
291 size_t equals = search.find(
'=');
292 if (equals != string::npos) {
293 search = search.substr(0, equals);
296 size_t opt_index = 1;
297 while (opt_index < _options.size()) {
298 if (_options[opt_index]._long_option == search) {
315 scan_options(
const char *optstring,
const struct option *longopts) {
316 const char *p = optstring;
318 char short_option = *p;
319 int has_arg = no_argument;
322 has_arg = required_argument;
325 has_arg = optional_argument;
330 _options.push_back(Option(short_option, has_arg));
333 if (longopts != NULL) {
334 int longopts_index = 0;
335 while (longopts[longopts_index].name != NULL) {
336 _options.push_back(Option(longopts, longopts_index));
350 scan_args(
int argc,
char *
const argv[]) {
352 bool end_of_processing =
false;
354 while ((
int)ai < argc) {
355 assert(argv[ai] != NULL);
357 if (argv[ai][0] !=
'-' || end_of_processing) {
359 if (_require_order) {
362 if (_return_in_order) {
364 _params.push_back(Param(1, ai,
'\001', argv[ai]));
365 _output_argv.push_back(argv[ai]);
368 _arguments.push_back(argv[ai]);
371 }
else if (strcmp(argv[ai],
"--") == 0) {
374 _output_argv.push_back(argv[ai]);
375 end_of_processing =
true;
381 char *argument = NULL;
382 size_t opt_index = 0;
383 bool is_long_option =
false;
384 bool has_argument =
false;
386 if (argv[ai][1] ==
'-') {
388 option = argv[ai] + 2;
389 opt_index = find_long_option(option);
390 is_long_option =
true;
394 option = argv[ai] + 1;
395 if (_allow_one_hyphen_long) {
397 opt_index = find_long_option(option);
398 if (opt_index != 0) {
399 is_long_option =
true;
402 if (!is_long_option) {
403 opt_index = find_short_option(option[0]);
404 while (opt_index != 0 &&
405 _options[opt_index]._has_arg == no_argument &&
408 _params.push_back(Param(opt_index, ai, option[0]));
410 opt_index = find_short_option(option[0]);
413 if (opt_index != 0 && _options[opt_index]._has_arg != no_argument) {
414 if (option[1] !=
'\0') {
416 argument = option + 1;
423 if (is_long_option) {
424 char *equals = strchr(option,
'=');
425 if (equals != NULL) {
426 argument = equals + 1;
431 size_t argv_index = ai;
433 if (opt_index != 0 && _options[opt_index]._has_arg == required_argument &&
436 _output_argv.push_back(argv[ai]);
438 if ((
int)ai < argc) {
444 _params.push_back(Param(opt_index, argv_index, option[0], argument));
445 _output_argv.push_back(argv[ai]);
450 _next_argv_index = ai;
453 while ((
int)ai < argc) {
454 assert(argv[ai] != NULL);
455 _arguments.push_back(argv[ai]);
467 PandaGetopt::Option::
468 Option(
char short_option,
int has_arg) :
469 _short_option(short_option),
483 PandaGetopt::Option::
484 Option(
const struct option *longopts,
int longopts_index) :
486 _long_option(longopts[longopts_index].name),
487 _has_arg(longopts[longopts_index].has_arg),
488 _option(&longopts[longopts_index]),
489 _longopts_index(longopts_index)
499 Param(
size_t opt_index,
size_t argv_index,
char short_option,
char *argument) :
500 _opt_index(opt_index),
501 _argv_index(argv_index),
502 _short_option(short_option),
508 getopt(
int argc,
char *
const argv[],
const char *optstring) {
509 if (pgetopt == NULL) {
510 pgetopt =
new PandaGetopt(argc, argv, optstring, NULL,
false);
511 pgetopt->
permute(argc, (
char **)argv);
513 return pgetopt->
process(opterr, NULL, optarg, optind, optopt);
517 getopt_long(
int argc,
char *
const argv[],
const char *optstring,
518 const struct option *longopts,
int *longindex) {
519 if (pgetopt == NULL) {
520 pgetopt =
new PandaGetopt(argc, argv, optstring, longopts,
false);
521 pgetopt->
permute(argc, (
char **)argv);
523 return pgetopt->
process(opterr, longindex, optarg, optind, optopt);
527 getopt_long_only(
int argc,
char *
const argv[],
const char *optstring,
528 const struct option *longopts,
int *longindex) {
529 if (pgetopt == NULL) {
530 pgetopt =
new PandaGetopt(argc, argv, optstring, longopts,
true);
531 pgetopt->
permute(argc, (
char **)argv);
533 return pgetopt->
process(opterr, longindex, optarg, optind, optopt);
536 #endif // defined(HAVE_GETOPT) && defined(HAVE_GETOPT_LONG_ONLY) void permute(int argc, char **mutable_argv)
Permutes the argv array so that the non-option arguments are at the end of the list (if POSIXLY_CORRE...
int process(int panda_opterr, int *longindex, char *&panda_optarg, int &panda_optind, int &panda_optopt)
Can be called repeatedly to extract out the option arguments scanned from the argv list...
The implementation within this file of the various getopt() functions.