static int parse_sup_line (void *ctx, char *line, char **query_str, tag_op_list_t *tag_ops) { regmatch_t match[3]; char *file_tags; int rerr; tag_op_list_reset (tag_ops); chomp_newline (line); /* Silently ignore blank lines */ if (line[0] == '\0') { return 1; } rerr = xregexec (®ex, line, 3, match, 0); if (rerr == REG_NOMATCH) { fprintf (stderr, "Warning: Ignoring invalid sup format line: %s\n", line); return 1; } *query_str = talloc_strndup_debug (ctx, line + match[1].rm_so, match[1].rm_eo - match[1].rm_so); file_tags = talloc_strndup_debug (ctx, line + match[2].rm_so, match[2].rm_eo - match[2].rm_so); char *tok = file_tags; size_t tok_len = 0; tag_op_list_reset (tag_ops); while ((tok = strtok_len (tok + tok_len, " ", &tok_len)) != NULL) { if (*(tok + tok_len) != '\0') { *(tok + tok_len) = '\0'; tok_len++; } if (tag_op_list_append (tag_ops, tok, FALSE)) return -1; } return 0; }
tag_parse_status_t parse_tag_command_line (void *ctx, int argc, char **argv, char **query_str, tag_op_list_t *tag_ops) { int i; tag_op_list_reset (tag_ops); for (i = 0; i < argc; i++) { if (strcmp (argv[i], "--") == 0) { i++; break; } if (argv[i][0] != '+' && argv[i][0] != '-') break; notmuch_bool_t is_remove = argv[i][0] == '-'; const char *msg; msg = illegal_tag (argv[i] + 1, is_remove); if (msg) { fprintf (stderr, "Error: %s", msg); return TAG_PARSE_INVALID; } tag_op_list_append (tag_ops, argv[i] + 1, is_remove); } *query_str = query_string_from_args (ctx, argc - i, &argv[i]); if (*query_str == NULL || **query_str == '\0') { fprintf (stderr, "Error: notmuch tag requires at least one search term.\n"); return TAG_PARSE_INVALID; } return TAG_PARSE_SUCCESS; }
tag_parse_status_t parse_tag_line (void *ctx, char *line, tag_op_flag_t flags, char **query_string, tag_op_list_t *tag_ops) { char *tok = line; size_t tok_len = 0; char *line_for_error; tag_parse_status_t ret = TAG_PARSE_SUCCESS; chomp_newline (line); line_for_error = talloc_strdup (ctx, line); if (line_for_error == NULL) { fprintf (stderr, "Error: out of memory\n"); return TAG_PARSE_OUT_OF_MEMORY; } /* remove leading space */ while (*tok == ' ' || *tok == '\t') tok++; /* Skip empty and comment lines. */ if (*tok == '\0' || *tok == '#') { ret = TAG_PARSE_SKIPPED; goto DONE; } tag_op_list_reset (tag_ops); /* Parse tags. */ while ((tok = strtok_len (tok + tok_len, " ", &tok_len)) != NULL) { notmuch_bool_t remove; char *tag; /* Optional explicit end of tags marker. */ if (tok_len == 2 && strncmp (tok, "--", tok_len) == 0) { tok = strtok_len (tok + tok_len, " ", &tok_len); if (tok == NULL) { ret = line_error (TAG_PARSE_INVALID, line_for_error, "no query string after --"); goto DONE; } break; } /* Implicit end of tags. */ if (*tok != '-' && *tok != '+') break; /* If tag is terminated by NUL, there's no query string. */ if (*(tok + tok_len) == '\0') { ret = line_error (TAG_PARSE_INVALID, line_for_error, "no query string"); goto DONE; } /* Terminate, and start next token after terminator. */ *(tok + tok_len++) = '\0'; remove = (*tok == '-'); tag = tok + 1; /* Maybe refuse illegal tags. */ if (! (flags & TAG_FLAG_BE_GENEROUS)) { const char *msg = illegal_tag (tag, remove); if (msg) { ret = line_error (TAG_PARSE_INVALID, line_for_error, msg); goto DONE; } } /* Decode tag. */ if (hex_decode_inplace (tag) != HEX_SUCCESS) { ret = line_error (TAG_PARSE_INVALID, line_for_error, "hex decoding of tag %s failed", tag); goto DONE; } if (tag_op_list_append (tag_ops, tag, remove)) { ret = line_error (TAG_PARSE_OUT_OF_MEMORY, line_for_error, "aborting"); goto DONE; } } if (tok == NULL) { /* use a different error message for testing */ ret = line_error (TAG_PARSE_INVALID, line_for_error, "missing query string"); goto DONE; } /* tok now points to the query string */ *query_string = tok; DONE: talloc_free (line_for_error); return ret; }