diff --git a/arguments.c b/arguments.c index 9f080f52..16ad5110 100644 --- a/arguments.c +++ b/arguments.c @@ -127,77 +127,73 @@ args_free(struct args *args) free(args); } -/* Print a set of arguments. */ -size_t -args_print(struct args *args, char *buf, size_t len) +/* Add to string. */ +static void printflike(3, 4) +args_print_add(char **buf, size_t *len, const char *fmt, ...) { - size_t off, used; + va_list ap; + char *s; + size_t slen; + + va_start(ap, fmt); + slen = xvasprintf(&s, fmt, ap); + va_end(ap); + + *len += slen; + *buf = xrealloc(*buf, *len); + + strlcat(*buf, s, *len); + free(s); +} + +/* Print a set of arguments. */ +char * +args_print(struct args *args) +{ + size_t len; + char *buf; int i; - const char *quotes; struct args_entry *entry; - /* There must be at least one byte at the start. */ - if (len == 0) - return (0); - off = 0; + len = 1; + buf = xcalloc(1, len); /* Process the flags first. */ - buf[off++] = '-'; RB_FOREACH(entry, args_tree, &args->tree) { if (entry->value != NULL) continue; - if (off == len - 1) { - buf[off] = '\0'; - return (len); - } - buf[off++] = entry->flag; - buf[off] = '\0'; + if (*buf == '\0') + args_print_add(&buf, &len, "-"); + args_print_add(&buf, &len, "%c", entry->flag); } - if (off == 1) - buf[--off] = '\0'; /* Then the flags with arguments. */ RB_FOREACH(entry, args_tree, &args->tree) { if (entry->value == NULL) continue; - if (off >= len) { - /* snprintf will have zero terminated. */ - return (len); - } - - if (strchr(entry->value, ' ') != NULL) - quotes = "\""; + if (*buf != '\0') + args_print_add(&buf, &len, " -%c ", entry->flag); else - quotes = ""; - used = xsnprintf(buf + off, len - off, "%s-%c %s%s%s", - off != 0 ? " " : "", entry->flag, quotes, entry->value, - quotes); - if (used > len - off) - used = len - off; - off += used; + args_print_add(&buf, &len, "-%c ", entry->flag); + if (strchr(entry->value, ' ') != NULL) + args_print_add(&buf, &len, "\"%s\"", entry->value); + else + args_print_add(&buf, &len, "%s", entry->value); } /* And finally the argument vector. */ for (i = 0; i < args->argc; i++) { - if (off >= len) { - /* snprintf will have zero terminated. */ - return (len); - } - + if (*buf != '\0') + args_print_add(&buf, &len, " "); if (strchr(args->argv[i], ' ') != NULL) - quotes = "\""; + args_print_add(&buf, &len, "\"%s\"", args->argv[i]); else - quotes = ""; - used = xsnprintf(buf + off, len - off, "%s%s%s%s", - off != 0 ? " " : "", quotes, args->argv[i], quotes); - if (used > len - off) - used = len - off; - off += used; + args_print_add(&buf, &len, "%s", args->argv[i]); } - return (off); + return (buf); } /* Return if an argument is present. */ diff --git a/cmd-list-keys.c b/cmd-list-keys.c index 4355f24e..f0a59c0b 100644 --- a/cmd-list-keys.c +++ b/cmd-list-keys.c @@ -56,7 +56,6 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq) struct key_binding *bd; const char *key, *tablename, *r; char *cp, tmp[BUFSIZ]; - size_t used; int repeat, width, tablewidth, keywidth; if (self->entry == &cmd_list_commands_entry) @@ -115,11 +114,9 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq) strlcat(tmp, " ", sizeof tmp); free(cp); - used = strlen(tmp); - if (used < (sizeof tmp) - 1) { - cmd_list_print(bd->cmdlist, tmp + used, - (sizeof tmp) - used); - } + cp = cmd_list_print(bd->cmdlist); + strlcat(tmp, cp, sizeof tmp); + free(cp); cmdq_print(cmdq, "bind-key %s", tmp); } diff --git a/cmd-list.c b/cmd-list.c index 0c75ed49..59fc7796 100644 --- a/cmd-list.c +++ b/cmd-list.c @@ -99,25 +99,28 @@ cmd_list_free(struct cmd_list *cmdlist) free(cmdlist); } -size_t -cmd_list_print(struct cmd_list *cmdlist, char *buf, size_t len) +char * +cmd_list_print(struct cmd_list *cmdlist) { struct cmd *cmd; - size_t off, used; + char *buf, *this; + size_t len; + + len = 1; + buf = xcalloc(1, len); - off = 0; TAILQ_FOREACH(cmd, &cmdlist->list, qentry) { - if (off >= len) - break; - off += cmd_print(cmd, buf + off, len - off); - if (off >= len) - break; - if (TAILQ_NEXT(cmd, qentry) != NULL) { - used = xsnprintf(buf + off, len - off, " ; "); - if (used > len - off) - used = len - off; - off += used; - } + this = cmd_print(cmd); + + len += strlen(this) + 3; + buf = xrealloc(buf, len); + + strlcat(buf, this, len); + if (TAILQ_NEXT(cmd, qentry) != NULL) + strlcat(buf, " ; ", len); + + free(this); } - return (off); + + return (buf); } diff --git a/cmd-queue.c b/cmd-queue.c index 2d896212..c85fb048 100644 --- a/cmd-queue.c +++ b/cmd-queue.c @@ -184,11 +184,12 @@ cmdq_continue_one(struct cmd_q *cmdq) { struct cmd *cmd = cmdq->cmd; enum cmd_retval retval; - char tmp[1024]; + char *s; int flags = !!(cmd->flags & CMD_CONTROL); - cmd_print(cmd, tmp, sizeof tmp); - log_debug("cmdq %p: %s", cmdq, tmp); + s = cmd_print(cmd); + log_debug("cmdq %p: %s", cmdq, s); + free(s); cmdq->time = time(NULL); cmdq->number++; diff --git a/cmd.c b/cmd.c index badfcb4a..21e0f0c3 100644 --- a/cmd.c +++ b/cmd.c @@ -383,21 +383,19 @@ usage: return (NULL); } -size_t -cmd_print(struct cmd *cmd, char *buf, size_t len) +char * +cmd_print(struct cmd *cmd) { - size_t off, used; + char *out, *s; - off = xsnprintf(buf, len, "%s ", cmd->entry->name); - if (off + 1 < len) { - used = args_print(cmd->args, buf + off, len - off - 1); - if (used == 0) - off--; - else - off += used; - buf[off] = '\0'; - } - return (off); + s = args_print(cmd->args); + if (*s != '\0') + xasprintf(&out, "%s %s", cmd->entry->name, s); + else + out = xstrdup(cmd->entry->name); + free(s); + + return (out); } /* Adjust current mouse position for a pane. */ diff --git a/tmux.h b/tmux.h index 6a9f0cb4..0e746d3b 100644 --- a/tmux.h +++ b/tmux.h @@ -1667,7 +1667,7 @@ RB_PROTOTYPE(args_tree, args_entry, entry, args_cmp); struct args *args_create(int, ...); struct args *args_parse(const char *, int, char **); void args_free(struct args *); -size_t args_print(struct args *, char *, size_t); +char *args_print(struct args *); int args_has(struct args *, u_char); void args_set(struct args *, u_char, const char *); const char *args_get(struct args *, u_char); @@ -1696,7 +1696,7 @@ char **cmd_copy_argv(int, char **); void cmd_free_argv(int, char **); char *cmd_stringify_argv(int, char **); struct cmd *cmd_parse(int, char **, const char *, u_int, char **); -size_t cmd_print(struct cmd *, char *, size_t); +char *cmd_print(struct cmd *); int cmd_mouse_at(struct window_pane *, struct mouse_event *, u_int *, u_int *, int); struct winlink *cmd_mouse_window(struct mouse_event *, struct session **); @@ -1712,7 +1712,7 @@ enum cmd_retval cmd_attach_session(struct cmd_q *, const char *, int, int, /* cmd-list.c */ struct cmd_list *cmd_list_parse(int, char **, const char *, u_int, char **); void cmd_list_free(struct cmd_list *); -size_t cmd_list_print(struct cmd_list *, char *, size_t); +char *cmd_list_print(struct cmd_list *); /* cmd-queue.c */ struct cmd_q *cmdq_new(struct client *);