summaryrefslogtreecommitdiffstats
path: root/cmd-generic.c
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@openbsd.org>2009-07-13 23:11:35 +0000
committerNicholas Marriott <nicm@openbsd.org>2009-07-13 23:11:35 +0000
commit5f108d9df6bada119def52518152a487f8695702 (patch)
tree2ae6420cfdea4f68ce031e9a1ed62c2756c2c588 /cmd-generic.c
parent5d91555c7c8d88577892e0a2e2bde2cde60a2882 (diff)
Having fixed flags for single-character getopt options is a bit hard to
maintain and is only going to get worse as more are used. So instead, add a new uint64_t member to cmd_entry which is a bitmask of upper and lowercase options accepted by the command. This means new single character options can be used without the need to add it explicitly to the list.
Diffstat (limited to 'cmd-generic.c')
-rw-r--r--cmd-generic.c188
1 files changed, 77 insertions, 111 deletions
diff --git a/cmd-generic.c b/cmd-generic.c
index 1b2e17a9..ea0d4d16 100644
--- a/cmd-generic.c
+++ b/cmd-generic.c
@@ -23,12 +23,9 @@
#include "tmux.h"
-#define CMD_FLAGS "adDgkruU"
-#define CMD_FLAGMASK (CMD_AFLAG|CMD_DFLAG|CMD_BIGDFLAG|CMD_GFLAG|CMD_KFLAG| \
- CMD_RFLAG|CMD_UFLAG|CMD_BIGUFLAG)
-
-int cmd_do_flags(int, int, int *);
-size_t cmd_print_flags(char *, size_t, size_t, int);
+int cmd_getopt(int, char **, const char *, uint64_t);
+int cmd_flags(int, uint64_t, uint64_t *);
+size_t cmd_print_flags(char *, size_t, size_t, uint64_t);
int cmd_fill_argument(int, char **, int, char **);
size_t
@@ -39,86 +36,70 @@ cmd_prarg(char *buf, size_t len, const char *prefix, char *arg)
return (xsnprintf(buf, len, "%s%s", prefix, arg));
}
+/* Prepend flags from chflags onto flagstr and call getopt. */
int
-cmd_do_flags(int opt, int iflags, int *oflags)
+cmd_getopt(int argc, char **argv, const char *flagstr, uint64_t chflags)
{
- switch (opt) {
- case 'a':
- if (iflags & CMD_AFLAG) {
- (*oflags) |= CMD_AFLAG;
- return (0);
- }
- return (-1);
- case 'd':
- if (iflags & CMD_DFLAG) {
- (*oflags) |= CMD_DFLAG;
- return (0);
- }
- return (-1);
- case 'D':
- if (iflags & CMD_BIGDFLAG) {
- (*oflags) |= CMD_BIGDFLAG;
- return (0);
- }
- return (-1);
- case 'g':
- if (iflags & CMD_GFLAG) {
- (*oflags) |= CMD_GFLAG;
- return (0);
- }
- return (-1);
- case 'k':
- if (iflags & CMD_KFLAG) {
- (*oflags) |= CMD_KFLAG;
- return (0);
- }
- return (-1);
- case 'r':
- if (iflags & CMD_RFLAG) {
- (*oflags) |= CMD_RFLAG;
- return (0);
- }
- return (-1);
- case 'u':
- if (iflags & CMD_UFLAG) {
- (*oflags) |= CMD_UFLAG;
+ u_char ch;
+ char buf[128];
+ size_t len, off;
+
+ *buf = '\0';
+
+ len = sizeof buf;
+ off = 0;
+
+ for (ch = 0; ch < 26; ch++) {
+ if (chflags & CMD_CHFLAG('a' + ch))
+ off += xsnprintf(buf + off, len - off, "%c", 'a' + ch);
+ if (chflags & CMD_CHFLAG('A' + ch))
+ off += xsnprintf(buf + off, len - off, "%c", 'A' + ch);
+ }
+
+ strlcat(buf, flagstr, sizeof buf);
+
+ return (getopt(argc, argv, buf));
+}
+
+/*
+ * If this option is expected (in ichflags), set it in ochflags, otherwise
+ * return -1.
+ */
+int
+cmd_flags(int opt, uint64_t ichflags, uint64_t *ochflags)
+{
+ u_char ch;
+
+ for (ch = 0; ch < 26; ch++) {
+ if (opt == 'a' + ch && ichflags & CMD_CHFLAG(opt)) {
+ (*ochflags) |= CMD_CHFLAG(opt);
return (0);
}
- return (-1);
- case 'U':
- if (iflags & CMD_BIGUFLAG) {
- (*oflags) |= CMD_BIGUFLAG;
+ if (opt == 'A' + ch && ichflags & CMD_CHFLAG(opt)) {
+ (*ochflags) |= CMD_CHFLAG(opt);
return (0);
}
- return (-1);
}
- return (1);
+ return (-1);
}
+/* Print the flags supported in chflags. */
size_t
-cmd_print_flags(char *buf, size_t len, size_t off, int flags)
+cmd_print_flags(char *buf, size_t len, size_t off, uint64_t chflags)
{
+ u_char ch;
size_t boff = off;
- if ((flags & CMD_FLAGMASK) == 0)
+ if (chflags == 0)
return (0);
off += xsnprintf(buf + off, len - off, " -");
- if (off < len && flags & CMD_AFLAG)
- off += xsnprintf(buf + off, len - off, "a");
- if (off < len && flags & CMD_BIGDFLAG)
- off += xsnprintf(buf + off, len - off, "D");
- if (off < len && flags & CMD_DFLAG)
- off += xsnprintf(buf + off, len - off, "d");
- if (off < len && flags & CMD_GFLAG)
- off += xsnprintf(buf + off, len - off, "g");
- if (off < len && flags & CMD_KFLAG)
- off += xsnprintf(buf + off, len - off, "k");
- if (off < len && flags & CMD_RFLAG)
- off += xsnprintf(buf + off, len - off, "r");
- if (off < len && flags & CMD_UFLAG)
- off += xsnprintf(buf + off, len - off, "u");
- if (off < len && flags & CMD_BIGUFLAG)
- off += xsnprintf(buf + off, len - off, "U");
+
+ for (ch = 0; ch < 26; ch++) {
+ if (chflags & CMD_CHFLAG('a' + ch))
+ off += xsnprintf(buf + off, len - off, "%c", 'a' + ch);
+ if (chflags & CMD_CHFLAG('A' + ch))
+ off += xsnprintf(buf + off, len - off, "%c", 'A' + ch);
+ }
return (off - boff);
}
@@ -153,7 +134,7 @@ cmd_target_init(struct cmd *self, unused int key)
struct cmd_target_data *data;
self->data = data = xmalloc(sizeof *data);
- data->flags = 0;
+ data->chflags = 0;
data->target = NULL;
data->arg = NULL;
}
@@ -162,19 +143,16 @@ int
cmd_target_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_target_data *data;
+ const struct cmd_entry *entry = self->entry;
int opt;
/* Don't use the entry version since it may be dependent on key. */
cmd_target_init(self, 0);
data = self->data;
- while ((opt = getopt(argc, argv, CMD_FLAGS "t:")) != -1) {
- switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) {
- case -1:
- goto usage;
- case 0:
+ while ((opt = cmd_getopt(argc, argv, "t:", entry->chflags)) != -1) {
+ if (cmd_flags(opt, entry->chflags, &data->chflags) == 0)
continue;
- }
switch (opt) {
case 't':
if (data->target == NULL)
@@ -240,7 +218,7 @@ cmd_target_print(struct cmd *self, char *buf, size_t len)
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
- off += cmd_print_flags(buf, len, off, data->flags);
+ off += cmd_print_flags(buf, len, off, data->chflags);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->arg != NULL)
@@ -254,7 +232,7 @@ cmd_srcdst_init(struct cmd *self, unused int key)
struct cmd_srcdst_data *data;
self->data = data = xmalloc(sizeof *data);
- data->flags = 0;
+ data->chflags = 0;
data->src = NULL;
data->dst = NULL;
data->arg = NULL;
@@ -264,18 +242,15 @@ int
cmd_srcdst_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_srcdst_data *data;
+ const struct cmd_entry *entry = self->entry;
int opt;
cmd_srcdst_init(self, 0);
data = self->data;
- while ((opt = getopt(argc, argv, CMD_FLAGS "s:t:")) != -1) {
- switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) {
- case -1:
- goto usage;
- case 0:
+ while ((opt = cmd_getopt(argc, argv, "s:t:", entry->chflags)) != -1) {
+ if (cmd_flags(opt, entry->chflags, &data->chflags) == 0)
continue;
- }
switch (opt) {
case 's':
if (data->src == NULL)
@@ -349,7 +324,7 @@ cmd_srcdst_print(struct cmd *self, char *buf, size_t len)
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
- off += cmd_print_flags(buf, len, off, data->flags);
+ off += cmd_print_flags(buf, len, off, data->chflags);
if (off < len && data->src != NULL)
off += xsnprintf(buf + off, len - off, " -s %s", data->src);
if (off < len && data->dst != NULL)
@@ -365,7 +340,7 @@ cmd_buffer_init(struct cmd *self, unused int key)
struct cmd_buffer_data *data;
self->data = data = xmalloc(sizeof *data);
- data->flags = 0;
+ data->chflags = 0;
data->target = NULL;
data->buffer = -1;
data->arg = NULL;
@@ -375,19 +350,16 @@ int
cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_buffer_data *data;
+ const struct cmd_entry *entry = self->entry;
int opt, n;
const char *errstr;
cmd_buffer_init(self, 0);
data = self->data;
- while ((opt = getopt(argc, argv, CMD_FLAGS "b:t:")) != -1) {
- switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) {
- case -1:
- goto usage;
- case 0:
+ while ((opt = cmd_getopt(argc, argv, "b:t:", entry->chflags)) != -1) {
+ if (cmd_flags(opt, entry->chflags, &data->chflags) == 0)
continue;
- }
switch (opt) {
case 'b':
if (data->buffer == -1) {
@@ -464,7 +436,7 @@ cmd_buffer_print(struct cmd *self, char *buf, size_t len)
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
- off += cmd_print_flags(buf, len, off, data->flags);
+ off += cmd_print_flags(buf, len, off, data->chflags);
if (off < len && data->buffer != -1)
off += xsnprintf(buf + off, len - off, " -b %d", data->buffer);
if (off < len && data->target != NULL)
@@ -480,7 +452,7 @@ cmd_option_init(struct cmd *self, unused int key)
struct cmd_option_data *data;
self->data = data = xmalloc(sizeof *data);
- data->flags = 0;
+ data->chflags = 0;
data->target = NULL;
data->option = NULL;
data->value = NULL;
@@ -490,19 +462,16 @@ int
cmd_option_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_option_data *data;
+ const struct cmd_entry *entry = self->entry;
int opt;
/* Don't use the entry version since it may be dependent on key. */
cmd_option_init(self, 0);
data = self->data;
- while ((opt = getopt(argc, argv, CMD_FLAGS "t:")) != -1) {
- switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) {
- case -1:
- goto usage;
- case 0:
+ while ((opt = cmd_getopt(argc, argv, "t:", entry->chflags)) != -1) {
+ if (cmd_flags(opt, entry->chflags, &data->chflags) == 0)
continue;
- }
switch (opt) {
case 't':
if (data->target == NULL)
@@ -577,7 +546,7 @@ cmd_option_print(struct cmd *self, char *buf, size_t len)
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
- off += cmd_print_flags(buf, len, off, data->flags);
+ off += cmd_print_flags(buf, len, off, data->chflags);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->option != NULL)
@@ -593,7 +562,7 @@ cmd_pane_init(struct cmd *self, unused int key)
struct cmd_pane_data *data;
self->data = data = xmalloc(sizeof *data);
- data->flags = 0;
+ data->chflags = 0;
data->target = NULL;
data->arg = NULL;
data->pane = -1;
@@ -603,6 +572,7 @@ int
cmd_pane_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_pane_data *data;
+ const struct cmd_entry *entry = self->entry;
int opt, n;
const char *errstr;
@@ -610,13 +580,9 @@ cmd_pane_parse(struct cmd *self, int argc, char **argv, char **cause)
cmd_pane_init(self, 0);
data = self->data;
- while ((opt = getopt(argc, argv, CMD_FLAGS "p:t:")) != -1) {
- switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) {
- case -1:
- goto usage;
- case 0:
+ while ((opt = cmd_getopt(argc, argv, "p:t:", entry->chflags)) != -1) {
+ if (cmd_flags(opt, entry->chflags, &data->chflags) == 0)
continue;
- }
switch (opt) {
case 'p':
if (data->pane == -1) {
@@ -693,7 +659,7 @@ cmd_pane_print(struct cmd *self, char *buf, size_t len)
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
- off += cmd_print_flags(buf, len, off, data->flags);
+ off += cmd_print_flags(buf, len, off, data->chflags);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->arg != NULL)