version 1.2, 2009/07/11 19:14:56 |
version 1.3, 2009/07/13 23:11:35 |
|
|
|
|
#include "tmux.h" |
#include "tmux.h" |
|
|
#define CMD_FLAGS "adDgkruU" |
int cmd_getopt(int, char **, const char *, uint64_t); |
#define CMD_FLAGMASK (CMD_AFLAG|CMD_DFLAG|CMD_BIGDFLAG|CMD_GFLAG|CMD_KFLAG| \ |
int cmd_flags(int, uint64_t, uint64_t *); |
CMD_RFLAG|CMD_UFLAG|CMD_BIGUFLAG) |
size_t cmd_print_flags(char *, size_t, size_t, uint64_t); |
|
|
int cmd_do_flags(int, int, int *); |
|
size_t cmd_print_flags(char *, size_t, size_t, int); |
|
int cmd_fill_argument(int, char **, int, char **); |
int cmd_fill_argument(int, char **, int, char **); |
|
|
size_t |
size_t |
|
|
return (xsnprintf(buf, len, "%s%s", prefix, arg)); |
return (xsnprintf(buf, len, "%s%s", prefix, arg)); |
} |
} |
|
|
|
/* Prepend flags from chflags onto flagstr and call getopt. */ |
int |
int |
cmd_do_flags(int opt, int iflags, int *oflags) |
cmd_getopt(int argc, char **argv, const char *flagstr, uint64_t chflags) |
{ |
{ |
switch (opt) { |
u_char ch; |
case 'a': |
char buf[128]; |
if (iflags & CMD_AFLAG) { |
size_t len, off; |
(*oflags) |= CMD_AFLAG; |
|
|
*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 (0); |
} |
} |
return (-1); |
if (opt == 'A' + ch && ichflags & CMD_CHFLAG(opt)) { |
case 'd': |
(*ochflags) |= CMD_CHFLAG(opt); |
if (iflags & CMD_DFLAG) { |
|
(*oflags) |= CMD_DFLAG; |
|
return (0); |
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; |
|
return (0); |
|
} |
|
return (-1); |
|
case 'U': |
|
if (iflags & CMD_BIGUFLAG) { |
|
(*oflags) |= CMD_BIGUFLAG; |
|
return (0); |
|
} |
|
return (-1); |
|
} |
} |
return (1); |
return (-1); |
} |
} |
|
|
|
/* Print the flags supported in chflags. */ |
size_t |
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; |
size_t boff = off; |
|
|
if ((flags & CMD_FLAGMASK) == 0) |
if (chflags == 0) |
return (0); |
return (0); |
off += xsnprintf(buf + off, len - off, " -"); |
off += xsnprintf(buf + off, len - off, " -"); |
if (off < len && flags & CMD_AFLAG) |
|
off += xsnprintf(buf + off, len - off, "a"); |
for (ch = 0; ch < 26; ch++) { |
if (off < len && flags & CMD_BIGDFLAG) |
if (chflags & CMD_CHFLAG('a' + ch)) |
off += xsnprintf(buf + off, len - off, "D"); |
off += xsnprintf(buf + off, len - off, "%c", 'a' + ch); |
if (off < len && flags & CMD_DFLAG) |
if (chflags & CMD_CHFLAG('A' + ch)) |
off += xsnprintf(buf + off, len - off, "d"); |
off += xsnprintf(buf + off, len - off, "%c", 'A' + ch); |
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"); |
|
return (off - boff); |
return (off - boff); |
} |
} |
|
|
|
|
struct cmd_target_data *data; |
struct cmd_target_data *data; |
|
|
self->data = data = xmalloc(sizeof *data); |
self->data = data = xmalloc(sizeof *data); |
data->flags = 0; |
data->chflags = 0; |
data->target = NULL; |
data->target = NULL; |
data->arg = NULL; |
data->arg = NULL; |
} |
} |
|
|
cmd_target_parse(struct cmd *self, int argc, char **argv, char **cause) |
cmd_target_parse(struct cmd *self, int argc, char **argv, char **cause) |
{ |
{ |
struct cmd_target_data *data; |
struct cmd_target_data *data; |
|
const struct cmd_entry *entry = self->entry; |
int opt; |
int opt; |
|
|
/* Don't use the entry version since it may be dependent on key. */ |
/* Don't use the entry version since it may be dependent on key. */ |
cmd_target_init(self, 0); |
cmd_target_init(self, 0); |
data = self->data; |
data = self->data; |
|
|
while ((opt = getopt(argc, argv, CMD_FLAGS "t:")) != -1) { |
while ((opt = cmd_getopt(argc, argv, "t:", entry->chflags)) != -1) { |
switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) { |
if (cmd_flags(opt, entry->chflags, &data->chflags) == 0) |
case -1: |
|
goto usage; |
|
case 0: |
|
continue; |
continue; |
} |
|
switch (opt) { |
switch (opt) { |
case 't': |
case 't': |
if (data->target == NULL) |
if (data->target == NULL) |
|
|
off += xsnprintf(buf, len, "%s", self->entry->name); |
off += xsnprintf(buf, len, "%s", self->entry->name); |
if (data == NULL) |
if (data == NULL) |
return (off); |
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) |
if (off < len && data->target != NULL) |
off += cmd_prarg(buf + off, len - off, " -t ", data->target); |
off += cmd_prarg(buf + off, len - off, " -t ", data->target); |
if (off < len && data->arg != NULL) |
if (off < len && data->arg != NULL) |
|
|
struct cmd_srcdst_data *data; |
struct cmd_srcdst_data *data; |
|
|
self->data = data = xmalloc(sizeof *data); |
self->data = data = xmalloc(sizeof *data); |
data->flags = 0; |
data->chflags = 0; |
data->src = NULL; |
data->src = NULL; |
data->dst = NULL; |
data->dst = NULL; |
data->arg = NULL; |
data->arg = NULL; |
|
|
cmd_srcdst_parse(struct cmd *self, int argc, char **argv, char **cause) |
cmd_srcdst_parse(struct cmd *self, int argc, char **argv, char **cause) |
{ |
{ |
struct cmd_srcdst_data *data; |
struct cmd_srcdst_data *data; |
|
const struct cmd_entry *entry = self->entry; |
int opt; |
int opt; |
|
|
cmd_srcdst_init(self, 0); |
cmd_srcdst_init(self, 0); |
data = self->data; |
data = self->data; |
|
|
while ((opt = getopt(argc, argv, CMD_FLAGS "s:t:")) != -1) { |
while ((opt = cmd_getopt(argc, argv, "s:t:", entry->chflags)) != -1) { |
switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) { |
if (cmd_flags(opt, entry->chflags, &data->chflags) == 0) |
case -1: |
|
goto usage; |
|
case 0: |
|
continue; |
continue; |
} |
|
switch (opt) { |
switch (opt) { |
case 's': |
case 's': |
if (data->src == NULL) |
if (data->src == NULL) |
|
|
off += xsnprintf(buf, len, "%s", self->entry->name); |
off += xsnprintf(buf, len, "%s", self->entry->name); |
if (data == NULL) |
if (data == NULL) |
return (off); |
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) |
if (off < len && data->src != NULL) |
off += xsnprintf(buf + off, len - off, " -s %s", data->src); |
off += xsnprintf(buf + off, len - off, " -s %s", data->src); |
if (off < len && data->dst != NULL) |
if (off < len && data->dst != NULL) |
|
|
struct cmd_buffer_data *data; |
struct cmd_buffer_data *data; |
|
|
self->data = data = xmalloc(sizeof *data); |
self->data = data = xmalloc(sizeof *data); |
data->flags = 0; |
data->chflags = 0; |
data->target = NULL; |
data->target = NULL; |
data->buffer = -1; |
data->buffer = -1; |
data->arg = NULL; |
data->arg = NULL; |
|
|
cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause) |
cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause) |
{ |
{ |
struct cmd_buffer_data *data; |
struct cmd_buffer_data *data; |
|
const struct cmd_entry *entry = self->entry; |
int opt, n; |
int opt, n; |
const char *errstr; |
const char *errstr; |
|
|
cmd_buffer_init(self, 0); |
cmd_buffer_init(self, 0); |
data = self->data; |
data = self->data; |
|
|
while ((opt = getopt(argc, argv, CMD_FLAGS "b:t:")) != -1) { |
while ((opt = cmd_getopt(argc, argv, "b:t:", entry->chflags)) != -1) { |
switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) { |
if (cmd_flags(opt, entry->chflags, &data->chflags) == 0) |
case -1: |
|
goto usage; |
|
case 0: |
|
continue; |
continue; |
} |
|
switch (opt) { |
switch (opt) { |
case 'b': |
case 'b': |
if (data->buffer == -1) { |
if (data->buffer == -1) { |
|
|
off += xsnprintf(buf, len, "%s", self->entry->name); |
off += xsnprintf(buf, len, "%s", self->entry->name); |
if (data == NULL) |
if (data == NULL) |
return (off); |
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) |
if (off < len && data->buffer != -1) |
off += xsnprintf(buf + off, len - off, " -b %d", data->buffer); |
off += xsnprintf(buf + off, len - off, " -b %d", data->buffer); |
if (off < len && data->target != NULL) |
if (off < len && data->target != NULL) |
|
|
struct cmd_option_data *data; |
struct cmd_option_data *data; |
|
|
self->data = data = xmalloc(sizeof *data); |
self->data = data = xmalloc(sizeof *data); |
data->flags = 0; |
data->chflags = 0; |
data->target = NULL; |
data->target = NULL; |
data->option = NULL; |
data->option = NULL; |
data->value = NULL; |
data->value = NULL; |
|
|
cmd_option_parse(struct cmd *self, int argc, char **argv, char **cause) |
cmd_option_parse(struct cmd *self, int argc, char **argv, char **cause) |
{ |
{ |
struct cmd_option_data *data; |
struct cmd_option_data *data; |
|
const struct cmd_entry *entry = self->entry; |
int opt; |
int opt; |
|
|
/* Don't use the entry version since it may be dependent on key. */ |
/* Don't use the entry version since it may be dependent on key. */ |
cmd_option_init(self, 0); |
cmd_option_init(self, 0); |
data = self->data; |
data = self->data; |
|
|
while ((opt = getopt(argc, argv, CMD_FLAGS "t:")) != -1) { |
while ((opt = cmd_getopt(argc, argv, "t:", entry->chflags)) != -1) { |
switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) { |
if (cmd_flags(opt, entry->chflags, &data->chflags) == 0) |
case -1: |
|
goto usage; |
|
case 0: |
|
continue; |
continue; |
} |
|
switch (opt) { |
switch (opt) { |
case 't': |
case 't': |
if (data->target == NULL) |
if (data->target == NULL) |
|
|
off += xsnprintf(buf, len, "%s", self->entry->name); |
off += xsnprintf(buf, len, "%s", self->entry->name); |
if (data == NULL) |
if (data == NULL) |
return (off); |
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) |
if (off < len && data->target != NULL) |
off += cmd_prarg(buf + off, len - off, " -t ", data->target); |
off += cmd_prarg(buf + off, len - off, " -t ", data->target); |
if (off < len && data->option != NULL) |
if (off < len && data->option != NULL) |
|
|
struct cmd_pane_data *data; |
struct cmd_pane_data *data; |
|
|
self->data = data = xmalloc(sizeof *data); |
self->data = data = xmalloc(sizeof *data); |
data->flags = 0; |
data->chflags = 0; |
data->target = NULL; |
data->target = NULL; |
data->arg = NULL; |
data->arg = NULL; |
data->pane = -1; |
data->pane = -1; |
|
|
cmd_pane_parse(struct cmd *self, int argc, char **argv, char **cause) |
cmd_pane_parse(struct cmd *self, int argc, char **argv, char **cause) |
{ |
{ |
struct cmd_pane_data *data; |
struct cmd_pane_data *data; |
|
const struct cmd_entry *entry = self->entry; |
int opt, n; |
int opt, n; |
const char *errstr; |
const char *errstr; |
|
|
|
|
cmd_pane_init(self, 0); |
cmd_pane_init(self, 0); |
data = self->data; |
data = self->data; |
|
|
while ((opt = getopt(argc, argv, CMD_FLAGS "p:t:")) != -1) { |
while ((opt = cmd_getopt(argc, argv, "p:t:", entry->chflags)) != -1) { |
switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) { |
if (cmd_flags(opt, entry->chflags, &data->chflags) == 0) |
case -1: |
|
goto usage; |
|
case 0: |
|
continue; |
continue; |
} |
|
switch (opt) { |
switch (opt) { |
case 'p': |
case 'p': |
if (data->pane == -1) { |
if (data->pane == -1) { |
|
|
off += xsnprintf(buf, len, "%s", self->entry->name); |
off += xsnprintf(buf, len, "%s", self->entry->name); |
if (data == NULL) |
if (data == NULL) |
return (off); |
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) |
if (off < len && data->target != NULL) |
off += cmd_prarg(buf + off, len - off, " -t ", data->target); |
off += cmd_prarg(buf + off, len - off, " -t ", data->target); |
if (off < len && data->arg != NULL) |
if (off < len && data->arg != NULL) |