Improve type safety by making arguments (whether from configuration or from the command line) have their own "struct arg_item" type, separate from the "struct trailer_item" type used to represent the trailers in the buffer being manipulated. This change also prepares "struct trailer_item" to be further differentiated from "struct arg_item" in future patches. --- trailer.c | 135 +++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 85 insertions(+), 50 deletions(-) diff --git a/trailer.c b/trailer.c index 54cc930..a9ed3f8 100644 --- a/trailer.c +++ b/trailer.c @@ -29,6 +29,12 @@ struct trailer_item { struct list_head list; char *token; char *value; +}; + +struct arg_item { + struct list_head list; + char *token; + char *value; struct conf_info conf; }; @@ -62,7 +68,7 @@ static size_t token_len_without_separator(const char *token, size_t len) return len; } -static int same_token(struct trailer_item *a, struct trailer_item *b) +static int same_token(struct trailer_item *a, struct arg_item *b) { size_t a_len = token_len_without_separator(a->token, strlen(a->token)); size_t b_len = token_len_without_separator(b->token, strlen(b->token)); @@ -71,12 +77,12 @@ static int same_token(struct trailer_item *a, struct trailer_item *b) return !strncasecmp(a->token, b->token, min_len); } -static int same_value(struct trailer_item *a, struct trailer_item *b) +static int same_value(struct trailer_item *a, struct arg_item *b) { return !strcasecmp(a->value, b->value); } -static int same_trailer(struct trailer_item *a, struct trailer_item *b) +static int same_trailer(struct trailer_item *a, struct arg_item *b) { return same_token(a, b) && same_value(a, b); } @@ -98,6 +104,13 @@ static inline void strbuf_replace(struct strbuf *sb, const char *a, const char * static void free_trailer_item(struct trailer_item *item) { + free(item->token); + free(item->value); + free(item); +} + +static void free_arg_item(struct arg_item *item) +{ free(item->conf.name); free(item->conf.key); free(item->conf.command); @@ -137,17 +150,29 @@ static void print_all(FILE *outfile, struct list_head *head, int trim_empty) } } +static struct trailer_item *trailer_from_arg(struct arg_item *arg_tok) +{ + struct trailer_item *new = xcalloc(sizeof(*new), 1); + new->token = arg_tok->token; + new->value = arg_tok->value; + arg_tok->token = arg_tok->value = NULL; + free_arg_item(arg_tok); + return new; +} + static void add_arg_to_input_list(struct trailer_item *on_tok, - struct trailer_item *arg_tok) + struct arg_item *arg_tok) { - if (after_or_end(arg_tok->conf.where)) - list_add(&arg_tok->list, &on_tok->list); + int aoe = after_or_end(arg_tok->conf.where); + struct trailer_item *to_add = trailer_from_arg(arg_tok); + if (aoe) + list_add(&to_add->list, &on_tok->list); else - list_add_tail(&arg_tok->list, &on_tok->list); + list_add_tail(&to_add->list, &on_tok->list); } static int check_if_different(struct trailer_item *in_tok, - struct trailer_item *arg_tok, + struct arg_item *arg_tok, int check_all, struct list_head *head) { @@ -200,7 +225,7 @@ static char *apply_command(const char *command, const char *arg) return result; } -static void apply_item_command(struct trailer_item *in_tok, struct trailer_item *arg_tok) +static void apply_item_command(struct trailer_item *in_tok, struct arg_item *arg_tok) { if (arg_tok->conf.command) { const char *arg; @@ -218,13 +243,13 @@ static void apply_item_command(struct trailer_item *in_tok, struct trailer_item } static void apply_arg_if_exists(struct trailer_item *in_tok, - struct trailer_item *arg_tok, + struct arg_item *arg_tok, struct trailer_item *on_tok, struct list_head *head) { switch (arg_tok->conf.if_exists) { case EXISTS_DO_NOTHING: - free_trailer_item(arg_tok); + free_arg_item(arg_tok); break; case EXISTS_REPLACE: apply_item_command(in_tok, arg_tok); @@ -241,39 +266,41 @@ static void apply_arg_if_exists(struct trailer_item *in_tok, if (check_if_different(in_tok, arg_tok, 1, head)) add_arg_to_input_list(on_tok, arg_tok); else - free_trailer_item(arg_tok); + free_arg_item(arg_tok); break; case EXISTS_ADD_IF_DIFFERENT_NEIGHBOR: apply_item_command(in_tok, arg_tok); if (check_if_different(on_tok, arg_tok, 0, head)) add_arg_to_input_list(on_tok, arg_tok); else - free_trailer_item(arg_tok); + free_arg_item(arg_tok); break; } } static void apply_arg_if_missing(struct list_head *head, - struct trailer_item *arg_tok) + struct arg_item *arg_tok) { enum action_where where; + struct trailer_item *to_add; switch (arg_tok->conf.if_missing) { case MISSING_DO_NOTHING: - free_trailer_item(arg_tok); + free_arg_item(arg_tok); break; case MISSING_ADD: where = arg_tok->conf.where; apply_item_command(NULL, arg_tok); + to_add = trailer_from_arg(arg_tok); if (after_or_end(where)) - list_add_tail(&arg_tok->list, head); + list_add_tail(&to_add->list, head); else - list_add(&arg_tok->list, head); + list_add(&to_add->list, head); } } static int find_same_and_apply_arg(struct list_head *head, - struct trailer_item *arg_tok) + struct arg_item *arg_tok) { struct list_head *pos; struct trailer_item *in_tok; @@ -306,11 +333,11 @@ static void process_trailers_lists(struct list_head *head, struct list_head *arg_head) { struct list_head *pos, *p; - struct trailer_item *arg_tok; + struct arg_item *arg_tok; list_for_each_safe(pos, p, arg_head) { int applied = 0; - arg_tok = list_entry(pos, struct trailer_item, list); + arg_tok = list_entry(pos, struct arg_item, list); list_del(pos); @@ -375,20 +402,20 @@ static void duplicate_conf(struct conf_info *dst, const struct conf_info *src) dst->command = xstrdup(src->command); } -static struct trailer_item *get_conf_item(const char *name) +static struct arg_item *get_conf_item(const char *name) { struct list_head *pos; - struct trailer_item *item; + struct arg_item *item; /* Look up item with same name */ list_for_each(pos, &conf_head) { - item = list_entry(pos, struct trailer_item, list); + item = list_entry(pos, struct arg_item, list); if (!strcasecmp(item->conf.name, name)) return item; } /* Item does not already exists, create it */ - item = xcalloc(sizeof(struct trailer_item), 1); + item = xcalloc(sizeof(*item), 1); duplicate_conf(&item->conf, &default_conf_info); item->conf.name = xstrdup(name); @@ -442,7 +469,7 @@ static int git_trailer_default_config(const char *conf_key, const char *value, v static int git_trailer_config(const char *conf_key, const char *value, void *cb) { const char *trailer_item, *variable_name; - struct trailer_item *item; + struct arg_item *item; struct conf_info *conf; char *name = NULL; enum trailer_info_type type; @@ -500,7 +527,7 @@ static int git_trailer_config(const char *conf_key, const char *value, void *cb) return 0; } -static const char *token_from_item(struct trailer_item *item, char *tok) +static const char *token_from_item(struct arg_item *item, char *tok) { if (item->conf.key) return item->conf.key; @@ -509,7 +536,7 @@ static const char *token_from_item(struct trailer_item *item, char *tok) return item->conf.name; } -static int token_matches_item(const char *tok, struct trailer_item *item, int tok_len) +static int token_matches_item(const char *tok, struct arg_item *item, int tok_len) { if (!strncasecmp(tok, item->conf.name, tok_len)) return 1; @@ -521,7 +548,7 @@ static int parse_trailer(struct strbuf *tok, struct strbuf *val, { size_t len; struct strbuf seps = STRBUF_INIT; - struct trailer_item *item; + struct arg_item *item; int tok_len; struct list_head *pos; @@ -547,12 +574,14 @@ static int parse_trailer(struct strbuf *tok, struct strbuf *val, /* Lookup if the token matches something in the config */ tok_len = token_len_without_separator(tok->buf, tok->len); - *conf = &default_conf_info; + if (conf) + *conf = &default_conf_info; list_for_each(pos, &conf_head) { - item = list_entry(pos, struct trailer_item, list); + item = list_entry(pos, struct arg_item, list); if (token_matches_item(tok->buf, item, tok_len)) { char *tok_buf = strbuf_detach(tok, NULL); - *conf = &item->conf; + if (conf) + *conf = &item->conf; strbuf_addstr(tok, token_from_item(item, tok_buf)); free(tok_buf); break; @@ -562,43 +591,51 @@ static int parse_trailer(struct strbuf *tok, struct strbuf *val, return 0; } -static void add_trailer_item(struct list_head *head, char *tok, char *val, - const struct conf_info *conf) +static void add_trailer_item(struct list_head *head, char *tok, char *val) { struct trailer_item *new = xcalloc(sizeof(*new), 1); new->token = tok; new->value = val; - duplicate_conf(&new->conf, conf); list_add_tail(&new->list, head); } +static void add_arg_item(struct list_head *arg_head, char *tok, char *val, + const struct conf_info *conf) +{ + struct arg_item *new = xcalloc(sizeof(*new), 1); + new->token = tok; + new->value = val; + duplicate_conf(&new->conf, conf); + list_add_tail(&new->list, arg_head); +} + static void process_command_line_args(struct list_head *arg_head, struct string_list *trailers) { struct string_list_item *tr; - struct trailer_item *item; + struct arg_item *item; struct strbuf tok = STRBUF_INIT; struct strbuf val = STRBUF_INIT; const struct conf_info *conf; struct list_head *pos; - /* Add a trailer item for each configured trailer with a command */ + /* Add an arg item for each configured trailer with a command */ list_for_each(pos, &conf_head) { - item = list_entry(pos, struct trailer_item, list); + item = list_entry(pos, struct arg_item, list); if (item->conf.command) - add_trailer_item(arg_head, - xstrdup(token_from_item(item, NULL)), - xstrdup(""), - &item->conf); + add_arg_item(arg_head, + xstrdup(token_from_item(item, NULL)), + xstrdup(""), + &item->conf); } - /* Add a trailer item for each trailer on the command line */ + /* Add an arg item for each trailer on the command line */ for_each_string_list_item(tr, trailers) { if (!parse_trailer(&tok, &val, &conf, tr->string)) - add_trailer_item(arg_head, - strbuf_detach(&tok, NULL), - strbuf_detach(&val, NULL), - conf); + add_arg_item(arg_head, + strbuf_detach(&tok, NULL), + strbuf_detach(&val, NULL), + conf); } } @@ -721,7 +758,6 @@ static int process_input_file(FILE *outfile, int patch_start, trailer_start, trailer_end, i; struct strbuf tok = STRBUF_INIT; struct strbuf val = STRBUF_INIT; - const struct conf_info *conf; /* Get the line count */ while (lines[count]) @@ -740,11 +776,10 @@ static int process_input_file(FILE *outfile, /* Parse trailer lines */ for (i = trailer_start; i < trailer_end; i++) { if (lines[i]->buf[0] != comment_line_char && - !parse_trailer(&tok, &val, &conf, lines[i]->buf)) + !parse_trailer(&tok, &val, NULL, lines[i]->buf)) add_trailer_item(head, strbuf_detach(&tok, NULL), - strbuf_detach(&val, NULL), - conf); + strbuf_detach(&val, NULL)); } return trailer_end; -- 2.8.0.rc3.226.g39d4020