8 #include "wvscatterhash.h"
12 #undef __error_t_defined
33 : short_option(_short_option), long_option(_long_option), desc(_desc)
43 return WvString::null;
63 void remove(
char short_option,
WvStringParm long_option);
66 void add_required_arg();
67 void subtract_required_arg();
80 bool argp_add(
const char *name,
int key,
const char *arg,
int flags,
81 const char *doc,
int group);
83 void argp_init(
size_t size = 0);
96 WvArgsOptionList options_list;
97 WvArgsOptionDict options_dict;
100 size_t required_args;
107 void WvArgsOption::add_to_argp(
WvArgsData &data)
109 data.argp_add(long_option, short_option, 0, 0, desc, 0);
148 return WvString::null;
174 return WvString::null;
200 return WvString::null;
223 return WvString::null;
251 return WvString::null;
253 return WvString(
"invalid option `%s'", arg);
277 data.argp_add(long_option, short_option, arg_desc, 0, desc, 0);
302 char *tailptr = NULL;
304 long int tmp = strtol(arg, &tailptr, 10);
305 if (errno == ERANGE || tmp > INT_MAX || tmp < INT_MIN )
308 return WvString(
"`%s': invalid number.", arg);
313 return WvString(
"`%s': invalid number.", arg);
318 return WvString::null;
344 char *tailptr = NULL;
346 long int tmp = strtol(arg, &tailptr, 10);
350 return WvString(
"`%s': invalid number.", arg);
355 return WvString(
"`%s': invalid number.", arg);
360 return WvString::null;
386 char *tailptr = NULL;
388 float tmp = strtof(arg, &tailptr);
392 return WvString(
"`%s': invalid number.", arg);
397 return WvString(
"`%s': invalid number.", arg);
402 return WvString::null;
428 char *tailptr = NULL;
430 double tmp = strtod(arg, &tailptr);
434 return WvString(
"`%s': invalid number.", arg);
439 return WvString(
"`%s': invalid number.", arg);
444 return WvString::null;
471 return WvString::null;
497 return WvString::null;
525 return WvString::null;
527 return WvString(
"invalid option: `%s'", arg);
532 WvArgsData::WvArgsData()
533 : flags(0), argp_(NULL), argp_index(0), argp_size(0),
534 required_args(0), maximum_args(0), last_no_key(-1)
539 WvArgsData::~WvArgsData()
552 void *WvArgsData::self()
const
563 if (!option->short_option)
564 option->short_option = last_no_key--;
566 options_list.append(option,
true);
567 options_dict.add(option,
false);
573 void WvArgsData::remove(
char short_option,
WvStringParm long_option)
577 WvArgsOptionList::Iter i(options_list);
578 for (i.rewind(); i.next(); )
580 bool matches_short =
false;
581 bool matches_long =
false;
583 if (short_option !=
'\0' && i->short_option == short_option)
584 matches_short =
true;
585 if (!long_option.
isnull() && i->long_option == long_option)
588 if ((matches_short && matches_long)
589 || (matches_short && i->long_option.isnull())
590 || (matches_long && i->short_option ==
'\0'))
593 options_dict.remove(i.ptr());
601 else if (matches_short)
605 i->short_option =
'\0';
606 options_dict.remove(i.ptr());
607 options_dict.add(i.ptr(),
false);
609 else if (matches_long)
612 i->long_option = WvString::null;
618 void WvArgsData::zap()
631 void WvArgsData::argp_init(
size_t size)
644 void WvArgsData::argp_build()
647 argp_init(options_list.count() + 2);
649 WvArgsOptionList::Iter i(options_list);
650 for (i.rewind(); i.next(); )
651 i->add_to_argp(*
this);
655 bool WvArgsData::argp_add(
const argp_option &option)
657 if (argp_index >= (argp_size - 1))
664 memcpy(argp_ + argp_index, &option,
sizeof(
argp_option));
667 memset(argp_ + argp_index, 0,
sizeof(
argp_option));
672 bool WvArgsData::argp_add(
const char *name,
int key,
const char *arg,
673 int flags,
const char *doc,
int group)
675 if (argp_index >= (argp_size - 1))
686 option->flags = flags;
688 option->group =
group;
691 memset(argp_ + argp_index, 0,
sizeof(
argp_option));
696 bool WvArgsData::argp_double()
699 void *tmp = realloc(argp_, 2 * argp_size *
sizeof(
argp_option));
709 void WvArgsData::add_required_arg()
715 void WvArgsData::subtract_required_arg()
727 error_t WvArgsData::parser(
int key,
char *arg,
struct argp_state *state)
734 if (state->arg_num >= data->maximum_args)
739 data->args_.append(arg);
742 case ARGP_KEY_NO_ARGS:
744 if (state->arg_num < data->required_args)
755 WvString error = option->process(arg);
758 argp_failure(state, argp_err_exit_status, 0,
764 return ARGP_ERR_UNKNOWN;
791 if (header && footer)
792 prog_doc =
WvString(
"%s\v%s", header, footer);
796 prog_doc =
WvString(
" \v%s", footer);
799 argp_program_version = version;
800 argp_program_bug_address = email;
802 struct argp argp = { data->argp(), &WvArgsData::parser, args_doc, prog_doc,
805 bool error = argp_parse(&
argp, argc, argv, data->flags, 0, data->self());
809 remaining_args->zap();
810 WvStringList::Iter i(data->args());
811 for (i.rewind(); i.next(); )
812 remaining_args->add(
new WvString(*i),
true);
821 this->version = version;
833 this->header = header;
839 this->footer = footer;
845 struct argp argp = { data->argp(), 0, 0, 0, 0, 0, 0 };
846 argp_help(&
argp, stdout, ARGP_HELP_STD_USAGE, argv[0]);
852 struct argp argp = { data->argp(), 0, 0, 0, 0, 0, 0 };
853 argp_help(&
argp, stdout, ARGP_HELP_STD_HELP, argv[0]);
859 data->remove(short_option, long_option);
867 data->remove(short_option, long_option);
875 data->remove(short_option, long_option);
883 data->remove(short_option, long_option);
891 data->remove(short_option, long_option);
892 data->add(
new WvArgsIntOption(short_option, long_option, desc, arg_desc,
899 data->remove(short_option, long_option);
907 data->remove(short_option, long_option);
915 data->remove(short_option, long_option);
924 data->remove(short_option, long_option);
933 data->remove(short_option, long_option);
935 desc, arg_desc, val));
942 data->remove(short_option, long_option);
950 data->remove(short_option, WvString::null);
956 data->remove(0, long_option);
968 data->add_required_arg();
970 args_doc.append(
" ");
971 args_doc.append(desc);
974 args_doc.append(
"...");
975 data->maximum_args = LONG_MAX;
977 else if (data->maximum_args < LONG_MAX)
978 ++(data->maximum_args);
986 data->subtract_required_arg();
994 case NO_EXIT_ON_ERRORS:
995 return data->flags & ARGP_NO_EXIT;
1002 void WvArgs::set_flag(
const flags_t flag,
const bool value)
1004 printf(
"set_flag(%d, %d)\n", flag, value);
1008 case NO_EXIT_ON_ERRORS:
1009 mask = ARGP_NO_EXIT;
1016 data->flags |= mask;
1018 data->flags &= ~mask;
1020 printf(
"set_flag(%d, %d) = %d\n", flag, value, data->flags);