From cc9c507f24e9d52f1857cba56b3b00f80dc50628 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Fri, 23 Mar 2012 15:33:53 +0100 Subject: [PATCH] bee/beegetopt: fix major option handling bug we need to preserve the location of '--' option ending when pre parsing commandline arguments in bee. so beegetopt was changed to be able to do so if the new option --keep-option-end is used. there was an API-breaking change in bee_getopt() since flags are now set in optctl and not via the third argument of (bee_getopt()). since we also need the new flag in lower option parsing this was the cleanest way to do so at the moment. since this is new nobody should get hurt after we release this 8) i'm really sorry for changing the API 8) --- src/bee.sh.in | 2 ++ src/bee_getopt.c | 13 ++++++++----- src/bee_getopt.h | 5 ++++- src/beegetopt.c | 12 +++++++++--- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/bee.sh.in b/src/bee.sh.in index 3bd66f3..26c1fca 100644 --- a/src/bee.sh.in +++ b/src/bee.sh.in @@ -85,6 +85,7 @@ function search_tool_cmd { } options=$(${BEE_BINDIR}/beegetopt --name=bee \ + --keep-option-end \ --option=destdir/d= \ -- "${@}") @@ -105,6 +106,7 @@ done options=$(${BEE_BINDIR}/beegetopt --name=bee \ --stop-on-no-option \ --no-skip-unknown-option \ + --keep-option-end \ --option=print-config \ --option=help/h \ --option=version/V \ diff --git a/src/bee_getopt.c b/src/bee_getopt.c index 57f30e3..e05a55a 100644 --- a/src/bee_getopt.c +++ b/src/bee_getopt.c @@ -73,6 +73,8 @@ int bee_getopt_init(struct bee_getopt_ctl *ctl, int argc, char **argv, struct be ctl->_argc = argc; ctl->_unhandled_shortopts = NULL; + ctl->flags = 0; + return err?0:1; } @@ -353,7 +355,8 @@ static int _bee_getopt_long(struct bee_getopt_ctl *optctl, int *optindex) /* match & skip '--' and pop all remaining arguments */ if(maybe_long && (optctl->argv[this][2] == '\0')) { - optctl->optind++; + if(!(optctl->flags & BEE_FLAG_KEEPOPTIONEND)) + optctl->optind++; bee_getopt_pop_all_arguments(optctl); return BEE_GETOPT_END; } @@ -394,7 +397,7 @@ int bee_getopt_long(struct bee_getopt_ctl *optctl, int *optindex) return _bee_getopt_long(optctl, optindex); } -int bee_getopt(struct bee_getopt_ctl *optctl, int *optindex, int flags) +int bee_getopt(struct bee_getopt_ctl *optctl, int *optindex) { int opt; @@ -404,7 +407,7 @@ int bee_getopt(struct bee_getopt_ctl *optctl, int *optindex, int flags) return BEE_GETOPT_NOVALUE; case BEE_GETOPT_NOOPT: - if (flags & BEE_FLAG_STOPONNOOPT) { + if (optctl->flags & BEE_FLAG_STOPONNOOPT) { bee_getopt_pop_all_arguments(optctl); return BEE_GETOPT_END; } @@ -417,11 +420,11 @@ int bee_getopt(struct bee_getopt_ctl *optctl, int *optindex, int flags) return BEE_GETOPT_ERROR; case BEE_GETOPT_OPTUNKNOWN: - if (flags & BEE_FLAG_STOPONUNKNOWN) { + if (optctl->flags & BEE_FLAG_STOPONUNKNOWN) { bee_getopt_pop_all_arguments(optctl); return BEE_GETOPT_END; } - if (!(flags & BEE_FLAG_SKIPUNKNOWN)) { + if (!(optctl->flags & BEE_FLAG_SKIPUNKNOWN)) { if (optctl->program) fprintf(stderr, "%s: ", optctl->program); fprintf(stderr, "unrecognized option '%s'.\n", optctl->argv[optctl->optind]); diff --git a/src/bee_getopt.h b/src/bee_getopt.h index 1b07077..9f5b193 100644 --- a/src/bee_getopt.h +++ b/src/bee_getopt.h @@ -37,6 +37,7 @@ #define BEE_FLAG_SKIPUNKNOWN (1<<0) #define BEE_FLAG_STOPONNOOPT (1<<1) #define BEE_FLAG_STOPONUNKNOWN (1<<2) +#define BEE_FLAG_KEEPOPTIONEND (1<<3) #define BEE_OPT_LONG(name) .long_opt = (name) #define BEE_OPT_SHORT(short) .short_opt = (short) @@ -165,13 +166,15 @@ struct bee_getopt_ctl { int _argc; int _optcnt; char *_unhandled_shortopts; + + int flags; }; void bee_getopt_pop_current_argument(struct bee_getopt_ctl *optctl); int bee_getopt_init(struct bee_getopt_ctl *ctl, int argc, char **argv, struct bee_option *optv); int bee_getopt_long(struct bee_getopt_ctl *optctl, int *optindex); -int bee_getopt(struct bee_getopt_ctl *optctl, int *optindex, int flags); +int bee_getopt(struct bee_getopt_ctl *optctl, int *optindex); void bee_getopt_print_quoted(char *s); diff --git a/src/beegetopt.c b/src/beegetopt.c index 3b42b6d..ccf622a 100644 --- a/src/beegetopt.c +++ b/src/beegetopt.c @@ -49,6 +49,7 @@ void usage(void) " by default unknown options are skipped\n" " and handled as non-option argument.\n" " -S is ignored if -U is given.\n" + " -k | --keep-option-end respect but keep '--' at it's position\n" "\n" " -h | --help print this little help\n" " -V | --version print version\n" @@ -81,6 +82,7 @@ int main(int argc, char *argv[]) BEE_OPTION_REQUIRED_ARG("name", 'n'), BEE_OPTION_NO_ARG("stop-on-unknown-option", 'U'), BEE_OPTION_NO_ARG("stop-on-no-option", 'N'), + BEE_OPTION_NO_ARG("keep-option-end", 'k'), BEE_OPTION_NO_ARG("no-skip-unknown-option", 'S'), BEE_OPTION_END }; @@ -105,7 +107,7 @@ int main(int argc, char *argv[]) optctl.program = "beegetopt"; - while((opt=bee_getopt(&optctl, &i, 0)) != BEE_GETOPT_END) { + while((opt=bee_getopt(&optctl, &i)) != BEE_GETOPT_END) { if (opt == BEE_GETOPT_ERROR) { exit(1); @@ -131,6 +133,10 @@ int main(int argc, char *argv[]) flags |= BEE_FLAG_STOPONUNKNOWN; break; + case 'k': + flags |= BEE_FLAG_KEEPOPTIONEND; + break; + case 'S': flags &= ~BEE_FLAG_SKIPUNKNOWN; break; @@ -236,9 +242,9 @@ int main(int argc, char *argv[]) bee_getopt_init(&optctl, optctl.argc-optctl.optind, &argv[optctl.optind+1], beeopts); optctl.program = name?name:"program"; + optctl.flags = flags; - while((opt=bee_getopt(&optctl, &i, flags)) != BEE_GETOPT_END) { - + while((opt=bee_getopt(&optctl, &i)) != BEE_GETOPT_END) { if (opt == BEE_GETOPT_ERROR) { exit(1); }