diff options
85 files changed, 1688 insertions, 3046 deletions
diff --git a/arguments.c b/arguments.c new file mode 100644 index 00000000..dce6333b --- /dev/null +++ b/arguments.c @@ -0,0 +1,222 @@ +/* $Id: arguments.c,v 1.1 2011-01-07 14:45:33 tcunha Exp $ */ + +/* + * Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> + +#include <bitstring.h> +#include <stdlib.h> +#include <string.h> + +#include "tmux.h" + +/* Create an arguments set with no flags. */ +struct args * +args_create(int argc, ...) +{ + struct args *args; + va_list ap; + int i; + + args = xcalloc(1, sizeof *args); + if ((args->flags = bit_alloc(SCHAR_MAX)) == NULL) + fatal("bit_alloc failed"); + + args->argc = argc; + if (argc == 0) + args->argv = NULL; + else + args->argv = xcalloc(argc, sizeof **args->argv); + + va_start(ap, argc); + for (i = 0; i < argc; i++) + args->argv[i] = xstrdup(va_arg(ap, char *)); + va_end(ap); + + return (args); +} + +/* Parse an argv and argc into a new argument set. */ +struct args * +args_parse(const char *template, int argc, char **argv) +{ + struct args *args; + char *ptr; + int opt; + + args = xcalloc(1, sizeof *args); + if ((args->flags = bit_alloc(SCHAR_MAX)) == NULL) + fatal("bit_alloc failed"); + + optreset = 1; + optind = 1; + + while ((opt = getopt(argc, argv, template)) != -1) { + if (opt < 0 || opt >= SCHAR_MAX) + continue; + if (opt == '?' || (ptr = strchr(template, opt)) == NULL) { + xfree(args->flags); + xfree(args); + return (NULL); + } + + bit_set(args->flags, opt); + if (ptr[1] == ':') { + if (args->values[opt] != NULL) + xfree(args->values[opt]); + args->values[opt] = xstrdup(optarg); + } + } + argc -= optind; + argv += optind; + + args->argc = argc; + args->argv = cmd_copy_argv(argc, argv); + + return (args); +} + +/* Free an arguments set. */ +void +args_free(struct args *args) +{ + u_int i; + + cmd_free_argv(args->argc, args->argv); + + for (i = 0; i < SCHAR_MAX; i++) { + if (args->values[i] != NULL) + xfree(args->values[i]); + } + + xfree(args->flags); + xfree(args); +} + +/* Print a set of arguments. */ +size_t +args_print(struct args *args, char *buf, size_t len) +{ + size_t off; + int i; + const char *quotes; + + /* There must be at least one byte at the start. */ + if (len == 0) + return (0); + off = 0; + + /* Process the flags first. */ + buf[off++] = '-'; + for (i = 0; i < SCHAR_MAX; i++) { + if (!bit_test(args->flags, i) || args->values[i] != NULL) + continue; + + if (off == len - 1) { + buf[off] = '\0'; + return (len); + } + buf[off++] = i; + buf[off] = '\0'; + } + if (off == 1) + buf[--off] = '\0'; + + /* Then the flags with arguments. */ + for (i = 0; i < SCHAR_MAX; i++) { + if (!bit_test(args->flags, i) || args->values[i] == NULL) + continue; + + if (off >= len) { + /* snprintf will have zero terminated. */ + return (len); + } + + if (strchr(args->values[i], ' ') != NULL) + quotes = "\""; + else + quotes = ""; + off += xsnprintf(buf + off, len - off, "%s-%c %s%s%s", + off != 0 ? " " : "", i, quotes, args->values[i], quotes); + } + + /* And finally the argument vector. */ + for (i = 0; i < args->argc; i++) { + if (off >= len) { + /* snprintf will have zero terminated. */ + return (len); + } + + if (strchr(args->argv[i], ' ') != NULL) + quotes = "\""; + else + quotes = ""; + off += xsnprintf(buf + off, len - off, "%s%s%s%s", + off != 0 ? " " : "", quotes, args->argv[i], quotes); + } + + return (off); +} + +/* Return if an argument is present. */ +int +args_has(struct args *args, u_char ch) +{ + return (bit_test(args->flags, ch)); +} + +/* Set argument value. */ +void +args_set(struct args *args, u_char ch, const char *value) +{ + if (value != NULL) { + if (args->values[ch] != NULL) + xfree(args->values[ch]); + args->values[ch] = xstrdup(value); + } + bit_set(args->flags, ch); +} + +/* Get argument value. Will be NULL if it isn't present. */ +const char * +args_get(struct args *args, u_char ch) +{ + return (args->values[ch]); +} + +/* Convert an argument value to a number. */ +long long +args_strtonum(struct args *args, + u_char ch, long long minval, long long maxval, char **cause) +{ + const char *errstr; + long long ll; + + if (!args_has(args, ch)) { + *cause = xstrdup("missing"); + return (0); + } + + ll = strtonum(args->values[ch], minval, maxval, &errstr); + if (errstr != NULL) { + *cause = xstrdup(errstr); + return (0); + } + + *cause = NULL; + return (ll); +} diff --git a/cmd-attach-session.c b/cmd-attach-session.c index 32ac58a9..3272c78e 100644 --- a/cmd-attach-session.c +++ b/cmd-attach-session.c @@ -1,4 +1,4 @@ -/* $Id: cmd-attach-session.c,v 1.38 2011-01-03 23:27:54 tcunha Exp $ */ +/* $Id: cmd-attach-session.c,v 1.39 2011-01-07 14:45:33 tcunha Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -28,37 +28,37 @@ int cmd_attach_session_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_attach_session_entry = { "attach-session", "attach", + "drt:", 0, 0, "[-dr] " CMD_TARGET_SESSION_USAGE, - CMD_CANTNEST|CMD_STARTSERVER|CMD_SENDENVIRON, "dr", - cmd_target_init, - cmd_target_parse, - cmd_attach_session_exec, - cmd_target_free, - cmd_target_print + CMD_CANTNEST|CMD_STARTSERVER|CMD_SENDENVIRON, + NULL, + NULL, + cmd_attach_session_exec }; int cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct session *s; - struct client *c; - const char *update; - char *overrides, *cause; - u_int i; + struct args *args = self->args; + struct session *s; + struct client *c; + const char *update; + char *overrides, *cause; + u_int i; if (RB_EMPTY(&sessions)) { ctx->error(ctx, "no sessions"); return (-1); } - if ((s = cmd_find_session(ctx, data->target)) == NULL) + + if ((s = cmd_find_session(ctx, args_get(args, 't'))) == NULL) return (-1); if (ctx->cmdclient == NULL && ctx->curclient == NULL) return (0); if (ctx->cmdclient == NULL) { - if (cmd_check_flag(data->chflags, 'd')) { + if (args_has(self->args, 'd')) { /* * Can't use server_write_session in case attaching to * the same session as currently attached to. @@ -90,10 +90,10 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx) return (-1); } - if (cmd_check_flag(data->chflags, 'r')) + if (args_has(self->args, 'r')) ctx->cmdclient->flags |= CLIENT_READONLY; - if (cmd_check_flag(data->chflags, 'd')) + if (args_has(self->args, 'd')) server_write_session(s, MSG_DETACH, NULL, 0); ctx->cmdclient->session = s; diff --git a/cmd-bind-key.c b/cmd-bind-key.c index c5440b48..db92f6fd 100644 --- a/cmd-bind-key.c +++ b/cmd-bind-key.c @@ -1,4 +1,4 @@ -/* $Id: cmd-bind-key.c,v 1.29 2010-07-02 02:43:01 tcunha Exp $ */ +/* $Id: cmd-bind-key.c,v 1.30 2011-01-07 14:45:33 tcunha Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -26,136 +26,87 @@ * Bind a key to a command, this recurses through cmd_*. */ -int cmd_bind_key_parse(struct cmd *, int, char **, char **); +int cmd_bind_key_check(struct args *); int cmd_bind_key_exec(struct cmd *, struct cmd_ctx *); -void cmd_bind_key_free(struct cmd *); -size_t cmd_bind_key_print(struct cmd *, char *, size_t); -int cmd_bind_key_table(struct cmd *, struct cmd_ctx *); - -struct cmd_bind_key_data { - int key; - int can_repeat; - struct cmd_list *cmdlist; - - int command_key; - char *tablename; - char *modecmd; -}; +int cmd_bind_key_table(struct cmd *, struct cmd_ctx *, int); const struct cmd_entry cmd_bind_key_entry = { "bind-key", "bind", + "cnrt:", 1, -1, "[-cnr] [-t key-table] key command [arguments]", - 0, "", + 0, NULL, - cmd_bind_key_parse, - cmd_bind_key_exec, - cmd_bind_key_free, - cmd_bind_key_print + cmd_bind_key_check, + cmd_bind_key_exec }; int -cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause) +cmd_bind_key_check(struct args *args) { - struct cmd_bind_key_data *data; - int opt, no_prefix = 0; - - self->data = data = xmalloc(sizeof *data); - data->can_repeat = 0; - data->cmdlist = NULL; - data->command_key = 0; - data->tablename = NULL; - data->modecmd = NULL; - - while ((opt = getopt(argc, argv, "cnrt:")) != -1) { - switch (opt) { - case 'c': - data->command_key = 1; - break; - case 'n': - no_prefix = 1; - break; - case 'r': - data->can_repeat = 1; - break; - case 't': - if (data->tablename == NULL) - data->tablename = xstrdup(optarg); - break; - default: - goto usage; - } - } - argc -= optind; - argv += optind; - if (argc < 1) - goto usage; - - if ((data->key = key_string_lookup_string(argv[0])) == KEYC_NONE) { - xasprintf(cause, "unknown key: %s", argv[0]); - goto error; - } - if (!no_prefix) - data->key |= KEYC_PREFIX; - - argc--; - argv++; - if (data->tablename != NULL) { - if (argc != 1) - goto usage; - data->modecmd = xstrdup(argv[0]); + if (args_has(args, 't')) { + if (args->argc != 1) + return (-1); } else { - if ((data->cmdlist = cmd_list_parse(argc, argv, cause)) == NULL) - goto error; + if (args->argc < 2) + return (-1); } - return (0); - -usage: - xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); - -error: - self->entry->free(self); - return (-1); } int -cmd_bind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx) +cmd_bind_key_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_bind_key_data *data = self->data; + struct args *args = self->args; + char *cause; + struct cmd_list *cmdlist; + int key; - if (data == NULL) - return (0); - if (data->tablename != NULL) - return (cmd_bind_key_table(self, ctx)); + key = key_string_lookup_string(args->argv[0]); + if (key == KEYC_NONE) { + ctx->error(ctx, "unknown key: %s", args->argv[0]); + return (-1); + } + + if (args_has(args, 't')) + return (cmd_bind_key_table(self, ctx, key)); - key_bindings_add(data->key, data->can_repeat, data->cmdlist); - data->cmdlist->references++; + cmdlist = cmd_list_parse(args->argc - 1, args->argv + 1, &cause); + if (cmdlist == NULL) { + ctx->error(ctx, "%s", cause); + xfree(cause); + return (-1); + } + if (!args_has(args, 'n')) + key |= KEYC_PREFIX; + key_bindings_add(key, args_has(args, 'r'), cmdlist); return (0); } int -cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx) +cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx, int key) { - struct cmd_bind_key_data *data = self->data; + struct args *args = self->args; + const char *tablename; const struct mode_key_table *mtab; struct mode_key_binding *mbind, mtmp; enum mode_key_cmd cmd; - if ((mtab = mode_key_findtable(data->tablename)) == NULL) { - ctx->error(ctx, "unknown key table: %s", data->tablename); + tablename = args_get(args, 't'); + if ((mtab = mode_key_findtable(tablename)) == NULL) { + ctx->error(ctx, "unknown key table: %s", tablename); return (-1); } - cmd = mode_key_fromstring(mtab->cmdstr, data->modecmd); + cmd = mode_key_fromstring(mtab->cmdstr, args->argv[0]); if (cmd == MODEKEY_NONE) { - ctx->error(ctx, "unknown command: %s", data->modecmd); + ctx->error(ctx, "unknown command: %s", args->argv[0]); return (-1); } - mtmp.key = data->key & ~KEYC_PREFIX; - mtmp.mode = data->command_key ? 1 : 0; + mtmp.key = key; + mtmp.mode = !!args_has(args, 'c'); if ((mbind = SPLAY_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) { mbind->cmd = cmd; return (0); @@ -167,45 +118,3 @@ cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx) SPLAY_INSERT(mode_key_tree, mtab->tree, mbind); return (0); } - -void -cmd_bind_key_free(struct cmd *self) -{ - struct cmd_bind_key_data *data = self->data; - - if (data->cmdlist != NULL) - cmd_list_free(data->cmdlist); - if (data->tablename != NULL) - xfree(data->tablename); - if (data->modecmd != NULL) - xfree(data->modecmd); - xfree(data); -} - -size_t -cmd_bind_key_print(struct cmd *self, char *buf, size_t len) -{ - struct cmd_bind_key_data *data = self->data; - size_t off = 0; - const char *skey; - - off += xsnprintf(buf, len, "%s", self->entry->name); - if (data == NULL) - return (off); - - if (off < len && data->command_key) - off += xsnprintf(buf + off, len - off, " -c"); - if (off < len && !(data->key & KEYC_PREFIX)) - off += xsnprintf(buf + off, len - off, " -n"); - if (off < len && data->can_repeat) - off += xsnprintf(buf + off, len - off, " -r"); - if (off < len && data->tablename != NULL) - off += cmd_prarg(buf + off, len - off, " -t ", data->tablename); - if (off < len) { - skey = key_string_lookup_key(data->key & ~KEYC_PREFIX); - off += xsnprintf(buf + off, len - off, " %s ", skey); - } - if (off < len) - off += cmd_list_print(data->cmdlist, buf + off, len - off); - return (off); -} diff --git a/cmd-break-pane.c b/cmd-break-pane.c index dd9bdaf9..41c723a5 100644 --- a/cmd-break-pane.c +++ b/cmd-break-pane.c @@ -1,4 +1,4 @@ -/* $Id: cmd-break-pane.c,v 1.11 2009-12-04 22:14:47 tcunha Exp $ */ +/* $Id: cmd-break-pane.c,v 1.12 2011-01-07 14:45:33 tcunha Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourcef |