diff options
Diffstat (limited to 'src/libmowgli/ext/getopt_long.c')
-rw-r--r-- | src/libmowgli/ext/getopt_long.c | 288 |
1 files changed, 194 insertions, 94 deletions
diff --git a/src/libmowgli/ext/getopt_long.c b/src/libmowgli/ext/getopt_long.c index adf64e5..dd70325 100644 --- a/src/libmowgli/ext/getopt_long.c +++ b/src/libmowgli/ext/getopt_long.c @@ -33,37 +33,40 @@ #include "getopt_long.h" -int mowgli_opterr = 1; /* if error message should be printed */ -int mowgli_optind = 1; /* index into parent argv vector */ -int mowgli_optopt = '?'; /* character checked for validity */ -int mowgli_optreset = 0; /* reset getopt */ -char *mowgli_optarg = NULL; /* argument associated with option */ +int mowgli_opterr = 1; /* if error message should be printed */ +int mowgli_optind = 1; /* index into parent argv vector */ +int mowgli_optopt = '?';/* character checked for validity */ +int mowgli_optreset = 0;/* reset getopt */ +char *mowgli_optarg = NULL; /* argument associated with option */ /* XXX: suppress const warnings */ -#define __UNCONST(a) ((void *)(unsigned long)(const void *)(a)) +#define __UNCONST(a) ((void *) (unsigned long) (const void *) (a)) -#define IGNORE_FIRST (*options == '-' || *options == '+') -#define PRINT_ERROR ((mowgli_opterr) && ((*options != ':') \ - || (IGNORE_FIRST && options[1] != ':'))) +#define IGNORE_FIRST (*options == '-' || *options == '+') +#define PRINT_ERROR ((mowgli_opterr) && ((*options != ':') \ + || (IGNORE_FIRST && options[1] != ':'))) #define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL) -#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST) +#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST) + /* XXX: GNU ignores PC if *options == '-' */ -#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-') +#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-') /* return values */ -#define BADCH (int)'?' -#define BADARG ((IGNORE_FIRST && options[1] == ':') \ - || (*options == ':') ? (int)':' : (int)'?') -#define INORDER (int)1 +#define BADCH (int) '?' +#define BADARG ((IGNORE_FIRST && options[1] == ':') \ + || (*options == ':') ? (int) ':' : (int) '?') +#define INORDER (int) 1 -#define EMSG "" +#define EMSG "" static inline void warnx(const char *fmt, ...) { va_list ap; + va_start(ap, fmt); vfprintf(stderr, fmt, ap); + fputc('\n', stderr); va_end(ap); } @@ -71,11 +74,11 @@ static int getopt_internal(int, char **, const char *); static int gcd(int, int); static void permute_args(int, int, int, char **); -static const char *place = EMSG; /* option letter processing */ +static const char *place = EMSG;/* option letter processing */ /* XXX: set mowgli_optreset to 1 rather than these two */ -static int nonopt_start = -1; /* first non option argument (for permute) */ -static int nonopt_end = -1; /* first option after non options (for permute) */ +static int nonopt_start = -1; /* first non option argument (for permute) */ +static int nonopt_end = -1; /* first option after non options (for permute) */ /* Error messages */ static const char recargchar[] = "option requires an argument -- %c"; @@ -85,7 +88,6 @@ static const char noarg[] = "option doesn't take an argument -- %.*s"; static const char illoptchar[] = "unknown option -- %c"; static const char illoptstring[] = "unknown option -- %s"; - /* * Compute the greatest common divisor of a and b. */ @@ -95,12 +97,14 @@ gcd(int a, int b) int c; c = a % b; - while (c != 0) { + + while (c != 0) + { a = b; b = c; c = a % b; } - + return b; } @@ -125,14 +129,18 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end, char **nargv) ncycle = gcd(nnonopts, nopts); cyclelen = (opt_end - panonopt_start) / ncycle; - for (i = 0; i < ncycle; i++) { - cstart = panonopt_end+i; + for (i = 0; i < ncycle; i++) + { + cstart = panonopt_end + i; pos = cstart; - for (j = 0; j < cyclelen; j++) { + + for (j = 0; j < cyclelen; j++) + { if (pos >= panonopt_end) pos -= nnonopts; else pos += nopts; + swap = nargv[pos]; nargv[pos] = nargv[cstart]; nargv[cstart] = swap; @@ -148,7 +156,7 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end, char **nargv) static int getopt_internal(int nargc, char **nargv, const char *options) { - char *oli; /* option letter list index */ + char *oli; /* option letter list index */ int optchar; return_val_if_fail(nargv != NULL, -1); @@ -166,116 +174,167 @@ getopt_internal(int nargc, char **nargv, const char *options) if (mowgli_optreset) nonopt_start = nonopt_end = -1; + start: - if (mowgli_optreset || !*place) { /* update scanning pointer */ + + if (mowgli_optreset || !*place) /* update scanning pointer */ + { mowgli_optreset = 0; - if (mowgli_optind >= nargc) { /* end of argument vector */ + + if (mowgli_optind >= nargc) /* end of argument vector */ + { place = EMSG; - if (nonopt_end != -1) { + + if (nonopt_end != -1) + { /* do permutation, if we have to */ permute_args(nonopt_start, nonopt_end, - mowgli_optind, nargv); + mowgli_optind, nargv); mowgli_optind -= nonopt_end - nonopt_start; } - else if (nonopt_start != -1) { + else if (nonopt_start != -1) + { /* * If we skipped non-options, set mowgli_optind * to the first of them. */ mowgli_optind = nonopt_start; } + nonopt_start = nonopt_end = -1; return -1; } + if ((*(place = nargv[mowgli_optind]) != '-') - || (place[1] == '\0')) { /* found non-option */ + || (place[1] == '\0')) /* found non-option */ + { place = EMSG; - if (IN_ORDER) { + + if (IN_ORDER) + { /* - * GNU extension: + * GNU extension: * return non-option as argument to option 1 */ mowgli_optarg = nargv[mowgli_optind++]; return INORDER; } - if (!PERMUTE) { + + if (!PERMUTE) /* * if no permutation wanted, stop parsing * at first non-option */ return -1; - } + /* do permutation */ if (nonopt_start == -1) + { nonopt_start = mowgli_optind; - else if (nonopt_end != -1) { + } + else if (nonopt_end != -1) + { permute_args(nonopt_start, nonopt_end, - mowgli_optind, nargv); + mowgli_optind, nargv); nonopt_start = mowgli_optind - - (nonopt_end - nonopt_start); + (nonopt_end - nonopt_start); nonopt_end = -1; } + mowgli_optind++; + /* process next argument */ goto start; } - if (nonopt_start != -1 && nonopt_end == -1) + + if ((nonopt_start != -1) && (nonopt_end == -1)) nonopt_end = mowgli_optind; - if (place[1] && *++place == '-') { /* found "--" */ + + if (place[1] && (*++place == '-')) /* found "--" */ + { place++; return -2; } } - if ((optchar = (int)*place++) == (int)':' || - (oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) { + + if (((optchar = (int) *place++) == (int) ':') || + ((oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL)) + { /* option letter unknown or ':' */ if (!*place) ++mowgli_optind; + if (PRINT_ERROR) warnx(illoptchar, optchar); + mowgli_optopt = optchar; return BADCH; } - if (optchar == 'W' && oli[1] == ';') { /* -W long-option */ - /* XXX: what if no long options provided (called by getopt)? */ - if (*place) + + if ((optchar == 'W') && (oli[1] == ';'))/* -W long-option */ + { /* XXX: what if no long options provided (called by getopt)? */ + if (*place) return -2; - if (++mowgli_optind >= nargc) { /* no arg */ + if (++mowgli_optind >= nargc) /* no arg */ + { place = EMSG; + if (PRINT_ERROR) warnx(recargchar, optchar); + mowgli_optopt = optchar; return BADARG; - } else /* white space */ + } + else /* white space */ + { place = nargv[mowgli_optind]; + } + /* * Handle -W arg the same as --arg (which causes getopt to * stop parsing). */ return -2; } - if (*++oli != ':') { /* doesn't take argument */ + + if (*++oli != ':') /* doesn't take argument */ + { if (!*place) ++mowgli_optind; - } else { /* takes (optional) argument */ + } + else /* takes (optional) argument */ + { mowgli_optarg = NULL; - if (*place) /* no white space */ + + if (*place) /* no white space */ + { mowgli_optarg = __UNCONST(place); + } + /* XXX: disable test for :: if PC? (GNU doesn't) */ - else if (oli[1] != ':') { /* arg not optional */ - if (++mowgli_optind >= nargc) { /* no arg */ + else if (oli[1] != ':') /* arg not optional */ + { + if (++mowgli_optind >= nargc) /* no arg */ + { place = EMSG; + if (PRINT_ERROR) warnx(recargchar, optchar); + mowgli_optopt = optchar; return BADARG; - } else + } + else + { mowgli_optarg = nargv[mowgli_optind]; + } } + place = EMSG; ++mowgli_optind; } + /* dump back option letter */ return optchar; } @@ -286,11 +345,11 @@ start: * * [eventually this will replace the real getopt] */ -int -mowgli_getopt(nargc, nargv, options) - int nargc; - char * const *nargv; - const char *options; +int mowgli_getopt(nargc, nargv, options) +int nargc; + +char *const *nargv; +const char *options; { int retval; @@ -298,20 +357,26 @@ mowgli_getopt(nargc, nargv, options) return_val_if_fail(options != NULL, -1); retval = getopt_internal(nargc, __UNCONST(nargv), options); - if (retval == -2) { + + if (retval == -2) + { ++mowgli_optind; + /* * We found an option (--), so if we skipped non-options, * we have to permute. */ - if (nonopt_end != -1) { + if (nonopt_end != -1) + { permute_args(nonopt_start, nonopt_end, mowgli_optind, - __UNCONST(nargv)); + __UNCONST(nargv)); mowgli_optind -= nonopt_end - nonopt_start; } + nonopt_start = nonopt_end = -1; retval = -1; } + return retval; } @@ -320,23 +385,25 @@ mowgli_getopt(nargc, nargv, options) * Parse argc/argv argument vector. */ int -mowgli_getopt_long(int nargc, char * const *nargv, const char *options, - const mowgli_getopt_option_t *long_options, int *idx) +mowgli_getopt_long(int nargc, char *const *nargv, const char *options, const mowgli_getopt_option_t *long_options, int *idx) { int retval; -#define IDENTICAL_INTERPRETATION(_x, _y) \ - (long_options[(_x)].has_arg == long_options[(_y)].has_arg && \ - long_options[(_x)].flag == long_options[(_y)].flag && \ +#define IDENTICAL_INTERPRETATION(_x, _y) \ + (long_options[(_x)].has_arg == long_options[(_y)].has_arg && \ + long_options[(_x)].flag == long_options[(_y)].flag && \ long_options[(_x)].val == long_options[(_y)].val) return_val_if_fail(nargv != NULL, -1); return_val_if_fail(options != NULL, -1); return_val_if_fail(long_options != NULL, -1); + /* idx may be NULL */ retval = getopt_internal(nargc, __UNCONST(nargv), options); - if (retval == -2) { + + if (retval == -2) + { char *current_argv, *has_equal; size_t current_argv_len; int i, ambiguous, match; @@ -348,58 +415,75 @@ mowgli_getopt_long(int nargc, char * const *nargv, const char *options, mowgli_optind++; place = EMSG; - if (*current_argv == '\0') { /* found "--" */ - /* + if (*current_argv == '\0') /* found "--" */ + { /* * We found an option (--), so if we skipped * non-options, we have to permute. */ - if (nonopt_end != -1) { + if (nonopt_end != -1) + { permute_args(nonopt_start, nonopt_end, - mowgli_optind, __UNCONST(nargv)); + mowgli_optind, __UNCONST(nargv)); mowgli_optind -= nonopt_end - nonopt_start; } + nonopt_start = nonopt_end = -1; return -1; } - if ((has_equal = strchr(current_argv, '=')) != NULL) { + + if ((has_equal = strchr(current_argv, '=')) != NULL) + { /* argument found (--option=arg) */ current_argv_len = has_equal - current_argv; has_equal++; - } else + } + else + { current_argv_len = strlen(current_argv); + } - for (i = 0; long_options[i].name; i++) { + for (i = 0; long_options[i].name; i++) + { /* find matching long option */ if (strncmp(current_argv, long_options[i].name, - current_argv_len)) + current_argv_len)) continue; if (strlen(long_options[i].name) == - (unsigned)current_argv_len) { + (unsigned) current_argv_len) + { /* exact match */ match = i; ambiguous = 0; break; } - if (match == -1) /* partial match */ + + if (match == -1)/* partial match */ match = i; else if (!IDENTICAL_INTERPRETATION(i, match)) ambiguous = 1; } - if (ambiguous) { + + if (ambiguous) + { /* ambiguous abbreviation */ if (PRINT_ERROR) - warnx(ambig, (int)current_argv_len, - current_argv); + warnx(ambig, (int) current_argv_len, + current_argv); + mowgli_optopt = 0; return BADCH; } - if (match != -1) { /* option found */ - if (long_options[match].has_arg == no_argument - && has_equal) { + + if (match != -1)/* option found */ + { + if ((long_options[match].has_arg == no_argument) + && has_equal) + { if (PRINT_ERROR) - warnx(noarg, (int)current_argv_len, - current_argv); + warnx(noarg, (int) current_argv_len, + current_argv); + /* * XXX: GNU sets mowgli_optopt to val regardless of * flag @@ -408,29 +492,34 @@ mowgli_getopt_long(int nargc, char * const *nargv, const char *options, mowgli_optopt = long_options[match].val; else mowgli_optopt = 0; + return BADARG; } - if (long_options[match].has_arg == required_argument || - long_options[match].has_arg == optional_argument) { + + if ((long_options[match].has_arg == required_argument) || + (long_options[match].has_arg == optional_argument)) + { if (has_equal) mowgli_optarg = has_equal; else if (long_options[match].has_arg == - required_argument) { + required_argument) /* * optional argument doesn't use * next nargv */ mowgli_optarg = nargv[mowgli_optind++]; - } } + if ((long_options[match].has_arg == required_argument) - && (mowgli_optarg == NULL)) { + && (mowgli_optarg == NULL)) + { /* * Missing argument; leading ':' * indicates no error should be generated */ if (PRINT_ERROR) warnx(recargstring, current_argv); + /* * XXX: GNU sets mowgli_optopt to val regardless * of flag @@ -439,23 +528,34 @@ mowgli_getopt_long(int nargc, char * const *nargv, const char *options, mowgli_optopt = long_options[match].val; else mowgli_optopt = 0; + --mowgli_optind; return BADARG; } - } else { /* unknown option */ + } + else /* unknown option */ + { if (PRINT_ERROR) warnx(illoptstring, current_argv); + mowgli_optopt = 0; return BADCH; } - if (long_options[match].flag) { + + if (long_options[match].flag) + { *long_options[match].flag = long_options[match].val; retval = 0; - } else + } + else + { retval = long_options[match].val; + } + if (idx) *idx = match; } + return retval; #undef IDENTICAL_INTERPRETATION } |