=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/cmd-parse.y,v retrieving revision 1.35 retrieving revision 1.36 diff -c -r1.35 -r1.36 *** src/usr.bin/tmux/cmd-parse.y 2021/08/20 06:30:57 1.35 --- src/usr.bin/tmux/cmd-parse.y 2021/08/20 09:06:26 1.36 *************** *** 1,4 **** ! /* $OpenBSD: cmd-parse.y,v 1.35 2021/08/20 06:30:57 nicm Exp $ */ /* * Copyright (c) 2019 Nicholas Marriott --- 1,4 ---- ! /* $OpenBSD: cmd-parse.y,v 1.36 2021/08/20 09:06:26 nicm Exp $ */ /* * Copyright (c) 2019 Nicholas Marriott *************** *** 60,68 **** u_int line; struct cmd_parse_arguments arguments; - int argc; - char **argv; - TAILQ_ENTRY(cmd_parse_command) entry; }; TAILQ_HEAD(cmd_parse_commands, cmd_parse_command); --- 60,65 ---- *************** *** 92,101 **** static void cmd_parse_free_command(struct cmd_parse_command *); static struct cmd_parse_commands *cmd_parse_new_commands(void); static void cmd_parse_free_commands(struct cmd_parse_commands *); ! static char *cmd_parse_commands_to_string(struct cmd_parse_commands *); ! static void cmd_parse_print_commands(struct cmd_parse_input *, u_int, struct cmd_list *); - static void cmd_parse_flatten_command(struct cmd_parse_command *); %} --- 89,98 ---- static void cmd_parse_free_command(struct cmd_parse_command *); static struct cmd_parse_commands *cmd_parse_new_commands(void); static void cmd_parse_free_commands(struct cmd_parse_commands *); ! static void cmd_parse_build_commands(struct cmd_parse_commands *, ! struct cmd_parse_input *, struct cmd_parse_result *); ! static void cmd_parse_print_commands(struct cmd_parse_input *, struct cmd_list *); %} *************** *** 587,605 **** } static void ! cmd_parse_print_commands(struct cmd_parse_input *pi, u_int line, ! struct cmd_list *cmdlist) { char *s; ! if (pi->item != NULL && (pi->flags & CMD_PARSE_VERBOSE)) { ! s = cmd_list_print(cmdlist, 0); ! if (pi->file != NULL) ! cmdq_print(pi->item, "%s:%u: %s", pi->file, line, s); ! else ! cmdq_print(pi->item, "%u: %s", line, s); ! free(s); } } static void --- 584,615 ---- } static void ! cmd_parse_print_commands(struct cmd_parse_input *pi, struct cmd_list *cmdlist) { char *s; ! if (pi->item == NULL || (~pi->flags & CMD_PARSE_VERBOSE)) ! return; ! s = cmd_list_print(cmdlist, 0); ! if (pi->file != NULL) ! cmdq_print(pi->item, "%s:%u: %s", pi->file, pi->line, s); ! else ! cmdq_print(pi->item, "%u: %s", pi->line, s); ! free(s); ! } ! ! static void ! cmd_parse_free_argument(struct cmd_parse_argument *arg) ! { ! switch (arg->type) { ! case CMD_PARSE_STRING: ! free(arg->string); ! break; ! case CMD_PARSE_COMMANDS: ! cmd_parse_free_commands(arg->commands); ! break; } + free(arg); } static void *************** *** 608,630 **** struct cmd_parse_argument *arg, *arg1; TAILQ_FOREACH_SAFE(arg, args, entry, arg1) { - switch (arg->type) { - case CMD_PARSE_STRING: - free(arg->string); - break; - case CMD_PARSE_COMMANDS: - cmd_parse_free_commands(arg->commands); - break; - } TAILQ_REMOVE(args, arg, entry); ! free(arg); } } static void cmd_parse_free_command(struct cmd_parse_command *cmd) { - cmd_free_argv(cmd->argc, cmd->argv); cmd_parse_free_arguments(&cmd->arguments); free(cmd); } --- 618,631 ---- struct cmd_parse_argument *arg, *arg1; TAILQ_FOREACH_SAFE(arg, args, entry, arg1) { TAILQ_REMOVE(args, arg, entry); ! cmd_parse_free_argument(arg); } } static void cmd_parse_free_command(struct cmd_parse_command *cmd) { cmd_parse_free_arguments(&cmd->arguments); free(cmd); } *************** *** 729,874 **** } } ! static char * ! cmd_parse_commands_to_string(struct cmd_parse_commands *cmds) { ! struct cmd_parse_command *cmd; ! char *string = NULL, *s, *line; ! TAILQ_FOREACH(cmd, cmds, entry) { ! cmd_parse_flatten_command(cmd); ! line = cmd_stringify_argv(cmd->argc, cmd->argv); ! if (string == NULL) ! s = line; ! else { ! xasprintf(&s, "%s ; %s", s, line); ! free(line); ! } ! free(string); ! string = s; } ! if (string == NULL) ! string = xstrdup(""); ! log_debug("%s: %s", __func__, string); ! return (string); } ! static void ! cmd_parse_flatten_command(struct cmd_parse_command *cmd) { struct cmd_parse_argument *arg; ! char *s; ! cmd->argc = 0; ! cmd->argv = NULL; TAILQ_FOREACH(arg, &cmd->arguments, entry) { switch (arg->type) { case CMD_PARSE_STRING: ! cmd_append_argv(&cmd->argc, &cmd->argv, arg->string); break; case CMD_PARSE_COMMANDS: ! s = cmd_parse_commands_to_string(arg->commands); ! cmd_append_argv(&cmd->argc, &cmd->argv, s); free(s); break; } } - } ! static struct cmd * ! cmd_parse_build_command(struct cmd_parse_command *cmd, ! struct cmd_parse_input *pi, u_int line, struct cmd_parse_result *pr) ! { ! struct cmd *add; ! char *cause; ! ! add = cmd_parse(cmd->argc, cmd->argv, pi->file, line, &cause); if (add == NULL) { pr->status = CMD_PARSE_ERROR; ! pr->error = cmd_parse_get_error(pi->file, line, cause); free(cause); return (NULL); } ! return (add); } ! static struct cmd_parse_result * cmd_parse_build_commands(struct cmd_parse_commands *cmds, ! struct cmd_parse_input *pi) { ! static struct cmd_parse_result pr; ! struct cmd_parse_commands *cmds2; ! struct cmd_parse_command *cmd, *cmd2, *next, *next2, *after; u_int line = UINT_MAX; ! int i; ! struct cmd_list *current = NULL, *result; ! struct cmd *add; ! char *name, *alias, *cause, *s; /* Check for an empty list. */ if (TAILQ_EMPTY(cmds)) { ! cmd_parse_free_commands(cmds); ! pr.status = CMD_PARSE_EMPTY; ! return (&pr); } - /* Flatten command arguments. */ - cmd_parse_log_commands(cmds, __func__); - TAILQ_FOREACH(cmd, cmds, entry) - cmd_parse_flatten_command(cmd); - /* - * Walk the commands and expand any aliases. Each alias is parsed - * individually to a new command list, any trailing arguments appended - * to the last command, and all commands inserted into the original - * command list. - */ - TAILQ_FOREACH_SAFE(cmd, cmds, entry, next) { - name = cmd->argv[0]; - - alias = cmd_get_alias(name); - if (alias == NULL) - continue; - - line = cmd->line; - log_debug("%s: %u %s = %s", __func__, line, name, alias); - - pi->line = line; - cmds2 = cmd_parse_do_buffer(alias, strlen(alias), pi, &cause); - free(alias); - if (cmds2 == NULL) { - pr.status = CMD_PARSE_ERROR; - pr.error = cause; - goto out; - } - - cmd2 = TAILQ_LAST(cmds2, cmd_parse_commands); - if (cmd2 == NULL) { - TAILQ_REMOVE(cmds, cmd, entry); - cmd_parse_free_command(cmd); - continue; - } - cmd_parse_flatten_command(cmd2); - for (i = 1; i < cmd->argc; i++) - cmd_append_argv(&cmd2->argc, &cmd2->argv, cmd->argv[i]); - - after = cmd; - TAILQ_FOREACH_SAFE(cmd2, cmds2, entry, next2) { - cmd2->line = line; - TAILQ_REMOVE(cmds2, cmd2, entry); - TAILQ_INSERT_AFTER(cmds, after, cmd2, entry); - after = cmd2; - } - cmd_parse_free_commands(cmds2); - - TAILQ_REMOVE(cmds, cmd, entry); - cmd_parse_free_command(cmd); - } - - /* * Parse each command into a command list. Create a new command list * for each line (unless the flag is set) so they get a new group (so * the queue knows which ones to remove if a command fails when --- 730,851 ---- } } ! static int ! cmd_parse_expand_alias(struct cmd_parse_command *cmd, ! struct cmd_parse_input *pi, struct cmd_parse_result *pr, ! struct cmd_list **cmdlist) { ! struct cmd_parse_argument *arg, *arg1, *first, *after; ! struct cmd_parse_commands *cmds; ! struct cmd_parse_command *last; ! char *alias, *name, *cause; ! *cmdlist = NULL; ! first = TAILQ_FIRST(&cmd->arguments); ! if (first == NULL || first->type != CMD_PARSE_STRING) { ! pr->status = CMD_PARSE_EMPTY; ! return (1); ! } ! name = first->string; ! alias = cmd_get_alias(name); ! if (alias == NULL) ! return (0); ! log_debug("%s: %u alias %s = %s", __func__, pi->line, name, alias); ! ! cmds = cmd_parse_do_buffer(alias, strlen(alias), pi, &cause); ! free(alias); ! if (cmds == NULL) { ! pr->status = CMD_PARSE_ERROR; ! pr->error = cause; ! return (1); } ! ! last = TAILQ_LAST(cmds, cmd_parse_commands); ! if (last == NULL) { ! *cmdlist = cmd_list_new(); ! return (1); ! } ! ! TAILQ_REMOVE(&cmd->arguments, first, entry); ! cmd_parse_free_argument(first); ! ! after = TAILQ_NEXT(TAILQ_FIRST(&last->arguments), entry); ! TAILQ_FOREACH_SAFE(arg, &cmd->arguments, entry, arg1) { ! TAILQ_REMOVE(&cmd->arguments, arg, entry); ! if (after == NULL) ! TAILQ_INSERT_TAIL(&last->arguments, arg, entry); ! else ! TAILQ_INSERT_AFTER(&last->arguments, after, arg, entry); ! after = arg; ! } ! cmd_parse_log_commands(cmds, __func__); ! ! cmd_parse_build_commands(cmds, pi, pr); ! if (pr->status != CMD_PARSE_SUCCESS) ! *cmdlist = pr->cmdlist; ! return (1); } ! static struct cmd_list * ! cmd_parse_build_command(struct cmd_parse_command *cmd, ! struct cmd_parse_input *pi, struct cmd_parse_result *pr) { struct cmd_parse_argument *arg; ! struct cmd_list *cmdlist; ! struct cmd *add; ! char *s, **argv = NULL, *cause; ! int argc = 0; ! if (cmd_parse_expand_alias(cmd, pi, pr, &cmdlist)) ! return (cmdlist); TAILQ_FOREACH(arg, &cmd->arguments, entry) { switch (arg->type) { case CMD_PARSE_STRING: ! cmd_append_argv(&argc, &argv, arg->string); break; case CMD_PARSE_COMMANDS: ! cmd_parse_build_commands(arg->commands, pi, pr); ! if (pr->status != CMD_PARSE_SUCCESS) ! return (NULL); ! s = cmd_list_print(pr->cmdlist, 0); ! cmd_append_argv(&argc, &argv, s); free(s); break; } } ! add = cmd_parse(argc, argv, pi->file, pi->line, &cause); if (add == NULL) { pr->status = CMD_PARSE_ERROR; ! pr->error = cmd_parse_get_error(pi->file, pi->line, cause); free(cause); return (NULL); } ! cmdlist = cmd_list_new(); ! cmd_list_append(cmdlist, add); ! return (cmdlist); } ! static void cmd_parse_build_commands(struct cmd_parse_commands *cmds, ! struct cmd_parse_input *pi, struct cmd_parse_result *pr) { ! struct cmd_parse_command *cmd; u_int line = UINT_MAX; ! struct cmd_list *current = NULL, *result, *add; ! char *s; /* Check for an empty list. */ if (TAILQ_EMPTY(cmds)) { ! pr->status = CMD_PARSE_EMPTY; ! return; } + cmd_parse_log_commands(cmds, __func__); /* * Parse each command into a command list. Create a new command list * for each line (unless the flag is set) so they get a new group (so * the queue knows which ones to remove if a command fails when *************** *** 878,884 **** TAILQ_FOREACH(cmd, cmds, entry) { if (((~pi->flags & CMD_PARSE_ONEGROUP) && cmd->line != line)) { if (current != NULL) { ! cmd_parse_print_commands(pi, line, current); cmd_list_move(result, current); cmd_list_free(current); } --- 855,861 ---- TAILQ_FOREACH(cmd, cmds, entry) { if (((~pi->flags & CMD_PARSE_ONEGROUP) && cmd->line != line)) { if (current != NULL) { ! cmd_parse_print_commands(pi, current); cmd_list_move(result, current); cmd_list_free(current); } *************** *** 886,903 **** } if (current == NULL) current = cmd_list_new(); ! line = cmd->line; ! add = cmd_parse_build_command(cmd, pi, line, &pr); if (add == NULL) { cmd_list_free(result); cmd_list_free(current); ! goto out; } ! cmd_list_append(current, add); } if (current != NULL) { ! cmd_parse_print_commands(pi, line, current); cmd_list_move(result, current); cmd_list_free(current); } --- 863,881 ---- } if (current == NULL) current = cmd_list_new(); ! line = pi->line = cmd->line; ! add = cmd_parse_build_command(cmd, pi, pr); if (add == NULL) { cmd_list_free(result); cmd_list_free(current); ! return; } ! cmd_list_move(current, add); ! cmd_list_free(add); } if (current != NULL) { ! cmd_parse_print_commands(pi, current); cmd_list_move(result, current); cmd_list_free(current); } *************** *** 906,918 **** log_debug("%s: %s", __func__, s); free(s); ! pr.status = CMD_PARSE_SUCCESS; ! pr.cmdlist = result; ! ! out: ! cmd_parse_free_commands(cmds); ! ! return (&pr); } struct cmd_parse_result * --- 884,891 ---- log_debug("%s: %s", __func__, s); free(s); ! pr->status = CMD_PARSE_SUCCESS; ! pr->cmdlist = result; } struct cmd_parse_result * *************** *** 935,941 **** pr.error = cause; return (&pr); } ! return (cmd_parse_build_commands(cmds, pi)); } struct cmd_parse_result * --- 908,917 ---- pr.error = cause; return (&pr); } ! cmd_parse_build_commands(cmds, pi, &pr); ! cmd_parse_free_commands(cmds); ! return (&pr); ! } struct cmd_parse_result * *************** *** 1036,1042 **** pr.error = cause; return (&pr); } ! return (cmd_parse_build_commands(cmds, pi)); } static void --- 1012,1020 ---- pr.error = cause; return (&pr); } ! cmd_parse_build_commands(cmds, pi, &pr); ! cmd_parse_free_commands(cmds); ! return (&pr); } static void *************** *** 1066,1071 **** --- 1044,1050 ---- struct cmd_parse_result * cmd_parse_from_arguments(int argc, char **argv, struct cmd_parse_input *pi) { + static struct cmd_parse_result pr; struct cmd_parse_input input; struct cmd_parse_commands *cmds; char **copy, **new_argv; *************** *** 1115,1121 **** } cmd_free_argv(argc, copy); ! return (cmd_parse_build_commands(cmds, pi)); } static int printflike(1, 2) --- 1094,1102 ---- } cmd_free_argv(argc, copy); ! cmd_parse_build_commands(cmds, pi, &pr); ! cmd_parse_free_commands(cmds); ! return (&pr); } static int printflike(1, 2)