You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
2.5 KiB
105 lines
2.5 KiB
/* getopt.c - Parse command-line options
|
|
*
|
|
* Copyright 2019 The Android Open Source Project
|
|
|
|
USE_GETOPT(NEWTOY(getopt, "^a(alternative)n:(name)o:(options)l*(long)(longoptions)Tu", TOYFLAG_USR|TOYFLAG_BIN))
|
|
|
|
config GETOPT
|
|
bool "getopt"
|
|
default n
|
|
help
|
|
usage: getopt [OPTIONS] [--] ARG...
|
|
|
|
Parse command-line options for use in shell scripts.
|
|
|
|
-a Allow long options starting with a single -.
|
|
-l OPTS Specify long options.
|
|
-n NAME Command name for error messages.
|
|
-o OPTS Specify short options.
|
|
-T Test whether this is a modern getopt.
|
|
-u Output options unquoted.
|
|
*/
|
|
|
|
#define FOR_getopt
|
|
#include "toys.h"
|
|
|
|
GLOBALS(
|
|
struct arg_list *l;
|
|
char *o, *n;
|
|
)
|
|
|
|
static void out(char *s)
|
|
{
|
|
if (FLAG(u)) printf(" %s", s);
|
|
else {
|
|
printf(" '");
|
|
for (; *s; s++) {
|
|
if (*s == '\'') printf("'\\''");
|
|
else putchar(*s);
|
|
}
|
|
printf("'");
|
|
}
|
|
}
|
|
|
|
static char *parse_long_opt(void *data, char *str, int len)
|
|
{
|
|
struct option **lopt_ptr = data, *lopt = *lopt_ptr;
|
|
|
|
// Trailing : or :: means this option takes a required or optional argument.
|
|
// no_argument = 0, required_argument = 1, optional_argument = 2.
|
|
for (lopt->has_arg = 0; len>0 && str[len-1] == ':'; lopt->has_arg++) len--;
|
|
if (!len || lopt->has_arg>2) return str;
|
|
|
|
lopt->name = xstrndup(str, len);
|
|
|
|
(*lopt_ptr)++;
|
|
return 0;
|
|
}
|
|
|
|
void getopt_main(void)
|
|
{
|
|
int argc = toys.optc+1;
|
|
char **argv = xzalloc(sizeof(char *)*(argc+1));
|
|
struct option *lopts = xzalloc(sizeof(struct option)*argc), *lopt = lopts;
|
|
int i = 0, j = 0, ch;
|
|
|
|
if (FLAG(T)) {
|
|
toys.exitval = 4;
|
|
return;
|
|
}
|
|
|
|
comma_args(TT.l, &lopt, "bad -l", parse_long_opt);
|
|
argv[j++] = TT.n ? TT.n : "getopt";
|
|
|
|
// Legacy mode: don't quote output and take the first argument as OPTSTR.
|
|
if (!FLAG(o)) {
|
|
toys.optflags |= FLAG_u;
|
|
TT.o = toys.optargs[i++];
|
|
if (!TT.o) error_exit("no OPTSTR");
|
|
--argc;
|
|
}
|
|
|
|
while (i<toys.optc) argv[j++] = toys.optargs[i++];
|
|
|
|
// BSD getopts don't honor argv[0] (for -n), so handle errors ourselves.
|
|
opterr = 0;
|
|
optind = 1;
|
|
while ((ch = (FLAG(a)?getopt_long_only:getopt_long)(argc, argv, TT.o,
|
|
lopts, &i)) != -1) {
|
|
if (ch == '?') {
|
|
fprintf(stderr, "%s: invalid option '%c'\n", argv[0], optopt);
|
|
toys.exitval = 1;
|
|
} else if (!ch) {
|
|
printf(" --%s", lopts[i].name);
|
|
if (lopts[i].has_arg) out(optarg ? optarg : "");
|
|
} else {
|
|
printf(" -%c", ch);
|
|
if (optarg) out(optarg);
|
|
}
|
|
}
|
|
|
|
printf(" --");
|
|
for (; optind<argc; optind++) out(argv[optind]);
|
|
printf("\n");
|
|
}
|