mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	Actually parse contents of {} as a command and then convert to a string
instead of just copying arguments around as strings.
This commit is contained in:
		
							
								
								
									
										271
									
								
								cmd-parse.y
									
									
									
									
									
								
							
							
						
						
									
										271
									
								
								cmd-parse.y
									
									
									
									
									
								
							| @@ -60,9 +60,6 @@ struct cmd_parse_command { | ||||
| 	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); | ||||
| @@ -92,10 +89,10 @@ static char	*cmd_parse_get_error(const char *, u_int, const char *); | ||||
| 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, | ||||
| 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 *); | ||||
| static void	 cmd_parse_flatten_command(struct cmd_parse_command *); | ||||
|  | ||||
| %} | ||||
|  | ||||
| @@ -587,19 +584,32 @@ cmd_parse_get_error(const char *file, u_int line, const char *error) | ||||
| } | ||||
|  | ||||
| static void | ||||
| cmd_parse_print_commands(struct cmd_parse_input *pi, u_int line, | ||||
|     struct cmd_list *cmdlist) | ||||
| cmd_parse_print_commands(struct cmd_parse_input *pi, 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); | ||||
| 	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,23 +618,14 @@ cmd_parse_free_arguments(struct cmd_parse_arguments *args) | ||||
| 	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); | ||||
| 		cmd_parse_free_argument(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); | ||||
| } | ||||
| @@ -729,144 +730,120 @@ cmd_parse_log_commands(struct cmd_parse_commands *cmds, const char *prefix) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static char * | ||||
| cmd_parse_commands_to_string(struct cmd_parse_commands *cmds) | ||||
| 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_command	 *cmd; | ||||
| 	char				 *string = NULL, *s, *line; | ||||
| 	struct cmd_parse_argument	*arg, *arg1, *first, *after; | ||||
| 	struct cmd_parse_commands	*cmds; | ||||
| 	struct cmd_parse_command	*last; | ||||
| 	char				*alias, *name, *cause; | ||||
|  | ||||
| 	TAILQ_FOREACH(cmd, cmds, entry) { | ||||
| 		cmd_parse_flatten_command(cmd); | ||||
| 	*cmdlist = NULL; | ||||
|  | ||||
| 		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; | ||||
| 	first = TAILQ_FIRST(&cmd->arguments); | ||||
| 	if (first == NULL || first->type != CMD_PARSE_STRING) { | ||||
| 		pr->status = CMD_PARSE_EMPTY; | ||||
| 		return (1); | ||||
| 	} | ||||
| 	if (string == NULL) | ||||
| 		string = xstrdup(""); | ||||
| 	log_debug("%s: %s", __func__, string); | ||||
| 	return (string); | ||||
| 	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 void | ||||
| cmd_parse_flatten_command(struct cmd_parse_command *cmd) | ||||
| 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; | ||||
| 	char				*s; | ||||
| 	struct cmd_list			*cmdlist; | ||||
| 	struct cmd			*add; | ||||
| 	char				*s, **argv = NULL, *cause; | ||||
| 	int				 argc = 0; | ||||
|  | ||||
| 	cmd->argc = 0; | ||||
| 	cmd->argv = NULL; | ||||
| 	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(&cmd->argc, &cmd->argv, arg->string); | ||||
| 			cmd_append_argv(&argc, &argv, arg->string); | ||||
| 			break; | ||||
| 		case CMD_PARSE_COMMANDS: | ||||
| 			s = cmd_parse_commands_to_string(arg->commands); | ||||
| 			cmd_append_argv(&cmd->argc, &cmd->argv, s); | ||||
| 			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; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| 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); | ||||
| 	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, line, cause); | ||||
| 		pr->error = cmd_parse_get_error(pi->file, pi->line, cause); | ||||
| 		free(cause); | ||||
| 		return (NULL); | ||||
| 	} | ||||
| 	return (add); | ||||
| 	cmdlist = cmd_list_new(); | ||||
| 	cmd_list_append(cmdlist, add); | ||||
| 	return (cmdlist); | ||||
| } | ||||
|  | ||||
| static struct cmd_parse_result * | ||||
| static void | ||||
| cmd_parse_build_commands(struct cmd_parse_commands *cmds, | ||||
|     struct cmd_parse_input *pi) | ||||
|     struct cmd_parse_input *pi, struct cmd_parse_result *pr) | ||||
| { | ||||
| 	static struct cmd_parse_result	 pr; | ||||
| 	struct cmd_parse_commands	*cmds2; | ||||
| 	struct cmd_parse_command	*cmd, *cmd2, *next, *next2, *after; | ||||
| 	struct cmd_parse_command	*cmd; | ||||
| 	u_int				 line = UINT_MAX; | ||||
| 	int				 i; | ||||
| 	struct cmd_list			*current = NULL, *result; | ||||
| 	struct cmd			*add; | ||||
| 	char				*name, *alias, *cause, *s; | ||||
| 	struct cmd_list			*current = NULL, *result, *add; | ||||
| 	char				*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); | ||||
| 		pr->status = CMD_PARSE_EMPTY; | ||||
| 		return; | ||||
| 	} | ||||
|  	cmd_parse_log_commands(cmds, __func__); | ||||
|  | ||||
| 	/* | ||||
| 	 * Parse each command into a command list. Create a new command list | ||||
| @@ -878,7 +855,7 @@ cmd_parse_build_commands(struct cmd_parse_commands *cmds, | ||||
| 	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_parse_print_commands(pi, current); | ||||
| 				cmd_list_move(result, current); | ||||
| 				cmd_list_free(current); | ||||
| 			} | ||||
| @@ -886,18 +863,19 @@ cmd_parse_build_commands(struct cmd_parse_commands *cmds, | ||||
| 		} | ||||
| 		if (current == NULL) | ||||
| 			current = cmd_list_new(); | ||||
| 		line = cmd->line; | ||||
| 		line = pi->line = cmd->line; | ||||
|  | ||||
| 		add = cmd_parse_build_command(cmd, pi, line, &pr); | ||||
| 		add = cmd_parse_build_command(cmd, pi, pr); | ||||
| 		if (add == NULL) { | ||||
| 			cmd_list_free(result); | ||||
| 			cmd_list_free(current); | ||||
| 			goto out; | ||||
| 			return; | ||||
| 		} | ||||
| 		cmd_list_append(current, add); | ||||
| 		cmd_list_move(current, add); | ||||
| 		cmd_list_free(add); | ||||
| 	} | ||||
| 	if (current != NULL) { | ||||
| 		cmd_parse_print_commands(pi, line, current); | ||||
| 		cmd_parse_print_commands(pi, current); | ||||
| 		cmd_list_move(result, current); | ||||
| 		cmd_list_free(current); | ||||
| 	} | ||||
| @@ -906,13 +884,8 @@ cmd_parse_build_commands(struct cmd_parse_commands *cmds, | ||||
| 	log_debug("%s: %s", __func__, s); | ||||
| 	free(s); | ||||
|  | ||||
| 	pr.status = CMD_PARSE_SUCCESS; | ||||
| 	pr.cmdlist = result; | ||||
|  | ||||
| out: | ||||
| 	cmd_parse_free_commands(cmds); | ||||
|  | ||||
| 	return (&pr); | ||||
| 	pr->status = CMD_PARSE_SUCCESS; | ||||
| 	pr->cmdlist = result; | ||||
| } | ||||
|  | ||||
| struct cmd_parse_result * | ||||
| @@ -935,7 +908,10 @@ cmd_parse_from_file(FILE *f, struct cmd_parse_input *pi) | ||||
| 		pr.error = cause; | ||||
| 		return (&pr); | ||||
| 	} | ||||
| 	return (cmd_parse_build_commands(cmds, pi)); | ||||
| 	cmd_parse_build_commands(cmds, pi, &pr); | ||||
| 	cmd_parse_free_commands(cmds); | ||||
| 	return (&pr); | ||||
|  | ||||
| } | ||||
|  | ||||
| struct cmd_parse_result * | ||||
| @@ -1036,7 +1012,9 @@ cmd_parse_from_buffer(const void *buf, size_t len, struct cmd_parse_input *pi) | ||||
| 		pr.error = cause; | ||||
| 		return (&pr); | ||||
| 	} | ||||
| 	return (cmd_parse_build_commands(cmds, pi)); | ||||
| 	cmd_parse_build_commands(cmds, pi, &pr); | ||||
| 	cmd_parse_free_commands(cmds); | ||||
| 	return (&pr); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -1066,6 +1044,7 @@ cmd_parse_add_command(struct cmd_parse_commands *cmds, | ||||
| 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,7 +1094,9 @@ cmd_parse_from_arguments(int argc, char **argv, struct cmd_parse_input *pi) | ||||
| 	} | ||||
|  | ||||
| 	cmd_free_argv(argc, copy); | ||||
| 	return (cmd_parse_build_commands(cmds, pi)); | ||||
| 	cmd_parse_build_commands(cmds, pi, &pr); | ||||
| 	cmd_parse_free_commands(cmds); | ||||
| 	return (&pr); | ||||
| } | ||||
|  | ||||
| static int printflike(1, 2) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 nicm
					nicm