- char *optstring = make_optstring();
- struct option *options = make_options();
- int ret, longidx = 0;
- struct opt_table *e;
-
- /* We will do our own error reporting. */
- opterr = 0;
- opt_argv0 = argv[0];
-
- /* Reset in case we're called more than once. */
- optopt = 0;
- optind = 0;
- while ((ret = getopt_long(*argc, argv, optstring, options, &longidx))
- != -1) {
- char *problem;
- const char *name;
-
- /* optopt is 0 if it's an unknown long option, *or* if
- * -? is a valid short option. */
- if (ret == '?') {
- if (optopt || strncmp(argv[optind-1], "--", 2) == 0) {
- parse_fail(errlog, optopt, argv[optind-1]+2,
- "unrecognized option");
- break;
- }
- } else if (ret == ':') {
- /* Missing argument: longidx not updated :( */
- parse_fail(errlog, optopt, argv[optind-1]+2,
- "option requires an argument");
- break;
- }
-
- if (ret != 0)
- e = find_short(ret);
- else
- e = find_long(longidx, &name);
-
- if (e->flags == OPT_HASARG)
- problem = e->cb_arg(optarg, e->arg);
- else
- problem = e->cb(e->arg);
-
- if (problem) {
- parse_fail(errlog, ret, name, problem);
- free(problem);
- break;
- }
- }
- free(optstring);
- free(options);
- if (ret != -1)
- return false;
-
- /* We hide everything but remaining arguments. */
- memmove(&argv[1], &argv[optind], sizeof(argv[1]) * (*argc-optind+1));
- *argc -= optind - 1;