X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=command-line-arguments.c;h=dc517b06ff6090c2290c5e85b6355e3c46f53978;hp=bf9aecabe86923e7dc3f560bd61f5e7119c5289b;hb=9836a8f42bf83d57950f670e69d72854ee5e063b;hpb=ab1487363edec7e0d89157b69634703beab622dc diff --git a/command-line-arguments.c b/command-line-arguments.c index bf9aecab..dc517b06 100644 --- a/command-line-arguments.c +++ b/command-line-arguments.c @@ -23,7 +23,10 @@ _process_keyword_arg (const notmuch_opt_desc_t *arg_desc, char next, const char while (keywords->name) { if (strcmp (arg_str, keywords->name) == 0) { if (arg_desc->output_var) { - *((int *)arg_desc->output_var) = keywords->value; + if (arg_desc->opt_type == NOTMUCH_OPT_KEYWORD_FLAGS) + *((int *)arg_desc->output_var) |= keywords->value; + else + *((int *)arg_desc->output_var) = keywords->value; } return TRUE; } @@ -118,55 +121,84 @@ parse_position_arg (const char *arg_str, int pos_arg_index, * parse a possible value, and assign to *output_var */ -notmuch_bool_t -parse_option (const char *arg, - const notmuch_opt_desc_t *options) { +int +parse_option (int argc, char **argv, const notmuch_opt_desc_t *options, int opt_index) +{ + assert(argv); - assert(arg); - assert(options); + const char *_arg = argv[opt_index]; - arg += 2; + assert(_arg); + assert(options); + const char *arg = _arg + 2; /* _arg starts with -- */ const notmuch_opt_desc_t *try; + + const char *next_arg = NULL; + if (opt_index < argc - 1 && strncmp (argv[opt_index + 1], "--", 2) != 0) + next_arg = argv[opt_index + 1]; + for (try = options; try->opt_type != NOTMUCH_OPT_END; try++) { - if (try->name && strncmp (arg, try->name, strlen (try->name)) == 0) { - char next = arg[strlen (try->name)]; - const char *value= arg+strlen(try->name)+1; - - /* If we have not reached the end of the argument - (i.e. the next character is not a space or delimiter) - then the argument could still match a longer option - name later in the option table. - */ - if (next != '=' && next != ':' && next != '\0') - continue; - - if (try->output_var == NULL) - INTERNAL_ERROR ("output pointer NULL for option %s", try->name); - - switch (try->opt_type) { - case NOTMUCH_OPT_KEYWORD: - return _process_keyword_arg (try, next, value); - break; - case NOTMUCH_OPT_BOOLEAN: - return _process_boolean_arg (try, next, value); - break; - case NOTMUCH_OPT_INT: - return _process_int_arg (try, next, value); - break; - case NOTMUCH_OPT_STRING: - return _process_string_arg (try, next, value); - break; - case NOTMUCH_OPT_POSITION: - case NOTMUCH_OPT_END: - default: - INTERNAL_ERROR ("unknown or unhandled option type %d", try->opt_type); - /*UNREACHED*/ - } + if (try->opt_type == NOTMUCH_OPT_INHERIT) { + int new_index = parse_option (argc, argv, try->output_var, opt_index); + if (new_index >= 0) + return new_index; } + + if (! try->name) + continue; + + if (strncmp (arg, try->name, strlen (try->name)) != 0) + continue; + + char next = arg[strlen (try->name)]; + const char *value = arg + strlen(try->name) + 1; + + /* + * If we have not reached the end of the argument (i.e. the + * next character is not a space or delimiter) then the + * argument could still match a longer option name later in + * the option table. + */ + if (next != '=' && next != ':' && next != '\0') + continue; + + if (next == '\0' && next_arg != NULL && try->opt_type != NOTMUCH_OPT_BOOLEAN) { + next = ' '; + value = next_arg; + opt_index ++; + } + + if (try->output_var == NULL) + INTERNAL_ERROR ("output pointer NULL for option %s", try->name); + + notmuch_bool_t opt_status = FALSE; + switch (try->opt_type) { + case NOTMUCH_OPT_KEYWORD: + case NOTMUCH_OPT_KEYWORD_FLAGS: + opt_status = _process_keyword_arg (try, next, value); + break; + case NOTMUCH_OPT_BOOLEAN: + opt_status = _process_boolean_arg (try, next, value); + break; + case NOTMUCH_OPT_INT: + opt_status = _process_int_arg (try, next, value); + break; + case NOTMUCH_OPT_STRING: + opt_status = _process_string_arg (try, next, value); + break; + case NOTMUCH_OPT_POSITION: + case NOTMUCH_OPT_END: + default: + INTERNAL_ERROR ("unknown or unhandled option type %d", try->opt_type); + /*UNREACHED*/ + } + if (opt_status) + return opt_index+1; + else + return -1; } - fprintf (stderr, "Unrecognized option: --%s\n", arg); - return FALSE; + return -1; } /* See command-line-arguments.h for description */ @@ -188,17 +220,16 @@ parse_arguments (int argc, char **argv, } } else { + int prev_opt_index = opt_index; if (strlen (argv[opt_index]) == 2) return opt_index+1; - more_args = parse_option (argv[opt_index], options); - if (more_args) { - opt_index++; - } else { - opt_index = -1; + opt_index = parse_option (argc, argv, options, opt_index); + if (opt_index < 0) { + fprintf (stderr, "Unrecognized option: %s\n", argv[prev_opt_index]); + more_args = FALSE; } - } }