=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/arguments.c,v retrieving revision 1.20 retrieving revision 1.21 diff -c -r1.20 -r1.21 *** src/usr.bin/tmux/arguments.c 2017/08/23 09:14:21 1.20 --- src/usr.bin/tmux/arguments.c 2019/04/28 20:05:50 1.21 *************** *** 1,4 **** ! /* $OpenBSD: arguments.c,v 1.20 2017/08/23 09:14:21 nicm Exp $ */ /* * Copyright (c) 2010 Nicholas Marriott --- 1,4 ---- ! /* $OpenBSD: arguments.c,v 1.21 2019/04/28 20:05:50 nicm Exp $ */ /* * Copyright (c) 2010 Nicholas Marriott *************** *** 29,37 **** * Manipulate command arguments. */ struct args_entry { u_char flag; ! char *value; RB_ENTRY(args_entry) entry; }; --- 29,43 ---- * Manipulate command arguments. */ + struct args_value { + char *value; + TAILQ_ENTRY(args_value) entry; + }; + TAILQ_HEAD(args_values, args_value); + struct args_entry { u_char flag; ! struct args_values values; RB_ENTRY(args_entry) entry; }; *************** *** 93,104 **** { struct args_entry *entry; struct args_entry *entry1; cmd_free_argv(args->argc, args->argv); RB_FOREACH_SAFE(entry, args_tree, &args->tree, entry1) { RB_REMOVE(args_tree, &args->tree, entry); ! free(entry->value); free(entry); } --- 99,116 ---- { struct args_entry *entry; struct args_entry *entry1; + struct args_value *value; + struct args_value *value1; cmd_free_argv(args->argc, args->argv); RB_FOREACH_SAFE(entry, args_tree, &args->tree, entry1) { RB_REMOVE(args_tree, &args->tree, entry); ! TAILQ_FOREACH_SAFE(value, &entry->values, entry, value1) { ! TAILQ_REMOVE(&entry->values, value, entry); ! free(value->value); ! free(value); ! } free(entry); } *************** *** 124,145 **** free(s); } /* Print a set of arguments. */ char * args_print(struct args *args) { size_t len; ! char *buf, *escaped; ! int i, flags; struct args_entry *entry; ! static const char quoted[] = " #\"';$"; len = 1; buf = xcalloc(1, len); /* Process the flags first. */ RB_FOREACH(entry, args_tree, &args->tree) { ! if (entry->value != NULL) continue; if (*buf == '\0') --- 136,204 ---- free(s); } + /* Add value to string. */ + static void + args_print_add_value(char **buf, size_t *len, struct args_entry *entry, + struct args_value *value) + { + static const char quoted[] = " #\"';$"; + char *escaped; + int flags; + + if (**buf != '\0') + args_print_add(buf, len, " -%c ", entry->flag); + else + args_print_add(buf, len, "-%c ", entry->flag); + + flags = VIS_OCTAL|VIS_TAB|VIS_NL; + if (value->value[strcspn(value->value, quoted)] != '\0') + flags |= VIS_DQ; + utf8_stravis(&escaped, value->value, flags); + if (flags & VIS_DQ) + args_print_add(buf, len, "\"%s\"", escaped); + else + args_print_add(buf, len, "%s", escaped); + free(escaped); + } + + /* Add argument to string. */ + static void + args_print_add_argument(char **buf, size_t *len, const char *argument) + { + static const char quoted[] = " #\"';$"; + char *escaped; + int flags; + + if (**buf != '\0') + args_print_add(buf, len, " "); + + flags = VIS_OCTAL|VIS_TAB|VIS_NL; + if (argument[strcspn(argument, quoted)] != '\0') + flags |= VIS_DQ; + utf8_stravis(&escaped, argument, flags); + if (flags & VIS_DQ) + args_print_add(buf, len, "\"%s\"", escaped); + else + args_print_add(buf, len, "%s", escaped); + free(escaped); + } + /* Print a set of arguments. */ char * args_print(struct args *args) { size_t len; ! char *buf; ! int i; struct args_entry *entry; ! struct args_value *value; len = 1; buf = xcalloc(1, len); /* Process the flags first. */ RB_FOREACH(entry, args_tree, &args->tree) { ! if (!TAILQ_EMPTY(&entry->values)) continue; if (*buf == '\0') *************** *** 149,189 **** /* Then the flags with arguments. */ RB_FOREACH(entry, args_tree, &args->tree) { ! if (entry->value == NULL) ! continue; ! ! if (*buf != '\0') ! args_print_add(&buf, &len, " -%c ", entry->flag); ! else ! args_print_add(&buf, &len, "-%c ", entry->flag); ! ! flags = VIS_OCTAL|VIS_TAB|VIS_NL; ! if (entry->value[strcspn(entry->value, quoted)] != '\0') ! flags |= VIS_DQ; ! utf8_stravis(&escaped, entry->value, flags); ! if (flags & VIS_DQ) ! args_print_add(&buf, &len, "\"%s\"", escaped); ! else ! args_print_add(&buf, &len, "%s", escaped); ! free(escaped); } /* And finally the argument vector. */ ! for (i = 0; i < args->argc; i++) { ! if (*buf != '\0') ! args_print_add(&buf, &len, " "); - flags = VIS_OCTAL|VIS_TAB|VIS_NL; - if (args->argv[i][strcspn(args->argv[i], quoted)] != '\0') - flags |= VIS_DQ; - utf8_stravis(&escaped, args->argv[i], flags); - if (flags & VIS_DQ) - args_print_add(&buf, &len, "\"%s\"", escaped); - else - args_print_add(&buf, &len, "%s", escaped); - free(escaped); - } - return (buf); } --- 208,221 ---- /* Then the flags with arguments. */ RB_FOREACH(entry, args_tree, &args->tree) { ! TAILQ_FOREACH(value, &entry->values, entry) ! args_print_add_value(&buf, &len, entry, value); } /* And finally the argument vector. */ ! for (i = 0; i < args->argc; i++) ! args_print_add_argument(&buf, &len, args->argv[i]); return (buf); } *************** *** 196,217 **** /* Set argument value in the arguments tree. */ void ! args_set(struct args *args, u_char ch, const char *value) { struct args_entry *entry; ! /* Replace existing argument. */ ! if ((entry = args_find(args, ch)) != NULL) { ! free(entry->value); ! entry->value = NULL; ! } else { entry = xcalloc(1, sizeof *entry); entry->flag = ch; RB_INSERT(args_tree, &args->tree, entry); } ! if (value != NULL) ! entry->value = xstrdup(value); } /* Get argument value. Will be NULL if it isn't present. */ --- 228,251 ---- /* Set argument value in the arguments tree. */ void ! args_set(struct args *args, u_char ch, const char *s) { struct args_entry *entry; + struct args_value *value; ! entry = args_find(args, ch); ! if (entry == NULL) { entry = xcalloc(1, sizeof *entry); entry->flag = ch; + TAILQ_INIT(&entry->values); RB_INSERT(args_tree, &args->tree, entry); } ! if (s != NULL) { ! value = xcalloc(1, sizeof *value); ! value->value = xstrdup(s); ! TAILQ_INSERT_TAIL(&entry->values, value, entry); ! } } /* Get argument value. Will be NULL if it isn't present. */ *************** *** 222,230 **** if ((entry = args_find(args, ch)) == NULL) return (NULL); ! return (entry->value); } /* Convert an argument value to a number. */ long long args_strtonum(struct args *args, u_char ch, long long minval, long long maxval, --- 256,291 ---- if ((entry = args_find(args, ch)) == NULL) return (NULL); ! return (TAILQ_LAST(&entry->values, args_values)->value); } + /* Get first value in argument. */ + const char * + args_first_value(struct args *args, u_char ch, struct args_value **value) + { + struct args_entry *entry; + + if ((entry = args_find(args, ch)) == NULL) + return (NULL); + + *value = TAILQ_FIRST(&entry->values); + if (*value == NULL) + return (NULL); + return ((*value)->value); + } + + /* Get next value in argument. */ + const char * + args_next_value(struct args_value **value) + { + if (*value == NULL) + return (NULL); + *value = TAILQ_NEXT(*value, entry); + if (*value == NULL) + return (NULL); + return ((*value)->value); + } + /* Convert an argument value to a number. */ long long args_strtonum(struct args *args, u_char ch, long long minval, long long maxval, *************** *** 233,245 **** const char *errstr; long long ll; struct args_entry *entry; if ((entry = args_find(args, ch)) == NULL) { *cause = xstrdup("missing"); return (0); } ! ll = strtonum(entry->value, minval, maxval, &errstr); if (errstr != NULL) { *cause = xstrdup(errstr); return (0); --- 294,308 ---- const char *errstr; long long ll; struct args_entry *entry; + struct args_value *value; if ((entry = args_find(args, ch)) == NULL) { *cause = xstrdup("missing"); return (0); } + value = TAILQ_LAST(&entry->values, args_values); ! ll = strtonum(value->value, minval, maxval, &errstr); if (errstr != NULL) { *cause = xstrdup(errstr); return (0);