mirror of
https://github.com/tmux/tmux.git
synced 2026-07-03 10:22:29 +00:00
Better version.
This commit is contained in:
85
cmd-parse.y
85
cmd-parse.y
@@ -756,65 +756,6 @@ cmd_parse_from_arguments_add(struct cmd_parse_node *seq,
|
|||||||
TAILQ_INSERT_TAIL(&(*cmd)->children, child, entry);
|
TAILQ_INSERT_TAIL(&(*cmd)->children, child, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Add one argv string, splitting unescaped ; as command separators:
|
|
||||||
*
|
|
||||||
* A single ; starts another command in the same sequence.
|
|
||||||
* A double ;; starts another sequence.
|
|
||||||
* A \; is kept as a literal semicolon in the argument.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
cmd_parse_from_argument_string(struct cmd_parse_node *root,
|
|
||||||
struct cmd_parse_node **seq, struct cmd_parse_node **cmd, const char *s)
|
|
||||||
{
|
|
||||||
char *buf;
|
|
||||||
size_t len = 0;
|
|
||||||
struct cmd_parse_node *child;
|
|
||||||
const char *cp;
|
|
||||||
|
|
||||||
buf = xmalloc(1);
|
|
||||||
*buf = '\0';
|
|
||||||
|
|
||||||
for (cp = s; *cp != '\0'; cp++) {
|
|
||||||
if (*cp == '\\' && cp[1] != '\0') {
|
|
||||||
cp++;
|
|
||||||
buf = xrealloc(buf, len + 2);
|
|
||||||
buf[len++] = *cp;
|
|
||||||
buf[len] = '\0';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*cp != ';') {
|
|
||||||
buf = xrealloc(buf, len + 2);
|
|
||||||
buf[len++] = *cp;
|
|
||||||
buf[len] = '\0';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len != 0) {
|
|
||||||
child = cmd_parse_new_string_node(buf, 0);
|
|
||||||
cmd_parse_from_arguments_add(*seq, cmd, child);
|
|
||||||
len = 0;
|
|
||||||
*buf = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cp[1] == ';') {
|
|
||||||
*cmd = NULL;
|
|
||||||
*seq = cmd_parse_new_node(CMD_PARSE_SEQUENCE, 0);
|
|
||||||
TAILQ_INSERT_TAIL(&root->children, *seq, entry);
|
|
||||||
cp++;
|
|
||||||
} else
|
|
||||||
*cmd = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len != 0) {
|
|
||||||
child = cmd_parse_new_string_node(buf, 0);
|
|
||||||
cmd_parse_from_arguments_add(*seq, cmd, child);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Build a parse tree directly from existing argument values. */
|
/* Build a parse tree directly from existing argument values. */
|
||||||
struct cmd_parse_tree *
|
struct cmd_parse_tree *
|
||||||
cmd_parse_from_arguments(struct args_value *values, u_int count)
|
cmd_parse_from_arguments(struct args_value *values, u_int count)
|
||||||
@@ -822,18 +763,37 @@ cmd_parse_from_arguments(struct args_value *values, u_int count)
|
|||||||
struct cmd_parse_tree *new;
|
struct cmd_parse_tree *new;
|
||||||
struct cmd_parse_node *root, *seq, *cmd = NULL, *child;
|
struct cmd_parse_node *root, *seq, *cmd = NULL, *child;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
char *copy;
|
||||||
|
size_t size;
|
||||||
|
int end;
|
||||||
|
|
||||||
root = cmd_parse_new_node(CMD_PARSE_ROOT, 0);
|
root = cmd_parse_new_node(CMD_PARSE_ROOT, 0);
|
||||||
seq = cmd_parse_new_node(CMD_PARSE_SEQUENCE, 0);
|
seq = cmd_parse_new_node(CMD_PARSE_SEQUENCE, 0);
|
||||||
TAILQ_INSERT_TAIL(&root->children, seq, entry);
|
TAILQ_INSERT_TAIL(&root->children, seq, entry);
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
|
end = 0;
|
||||||
|
|
||||||
switch (values[i].type) {
|
switch (values[i].type) {
|
||||||
case ARGS_NONE:
|
case ARGS_NONE:
|
||||||
continue;
|
continue;
|
||||||
case ARGS_STRING:
|
case ARGS_STRING:
|
||||||
cmd_parse_from_argument_string(root, &seq, &cmd,
|
copy = xstrdup(values[i].string);
|
||||||
values[i].string);
|
size = strlen(copy);
|
||||||
|
|
||||||
|
if (size != 0 && copy[size - 1] == ';') {
|
||||||
|
copy[--size] = '\0';
|
||||||
|
if (size > 0 && copy[size - 1] == '\\')
|
||||||
|
copy[size - 1] = ';';
|
||||||
|
else
|
||||||
|
end = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!end || size != 0) {
|
||||||
|
child = cmd_parse_new_string_node(copy, 0);
|
||||||
|
cmd_parse_from_arguments_add(seq, &cmd, child);
|
||||||
|
}
|
||||||
|
free(copy);
|
||||||
break;
|
break;
|
||||||
case ARGS_COMMANDS:
|
case ARGS_COMMANDS:
|
||||||
child = cmd_parse_new_commands_node(values[i].cmd, 0);
|
child = cmd_parse_new_commands_node(values[i].cmd, 0);
|
||||||
@@ -842,6 +802,9 @@ cmd_parse_from_arguments(struct args_value *values, u_int count)
|
|||||||
default:
|
default:
|
||||||
fatalx("unknown argument type");
|
fatalx("unknown argument type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (end)
|
||||||
|
cmd = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
new = xcalloc(1, sizeof *new);
|
new = xcalloc(1, sizeof *new);
|
||||||
|
|||||||
Reference in New Issue
Block a user