mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:26:05 +00:00 
			
		
		
		
	Merge branch 'obsd-master' into master
This commit is contained in:
		
							
								
								
									
										253
									
								
								cmd-parse.y
									
									
									
									
									
								
							
							
						
						
									
										253
									
								
								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,27 +584,23 @@ 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)) {
 | 
			
		||||
	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, line, s);
 | 
			
		||||
		cmdq_print(pi->item, "%s:%u: %s", pi->file, pi->line, s);
 | 
			
		||||
	else
 | 
			
		||||
			cmdq_print(pi->item, "%u: %s", line, s);
 | 
			
		||||
		cmdq_print(pi->item, "%u: %s", pi->line, s);
 | 
			
		||||
	free(s);
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
cmd_parse_free_arguments(struct cmd_parse_arguments *args)
 | 
			
		||||
cmd_parse_free_argument(struct cmd_parse_argument *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct cmd_parse_argument	*arg, *arg1;
 | 
			
		||||
 | 
			
		||||
	TAILQ_FOREACH_SAFE(arg, args, entry, arg1) {
 | 
			
		||||
	switch (arg->type) {
 | 
			
		||||
	case CMD_PARSE_STRING:
 | 
			
		||||
		free(arg->string);
 | 
			
		||||
@@ -616,15 +609,23 @@ cmd_parse_free_arguments(struct cmd_parse_arguments *args)
 | 
			
		||||
		cmd_parse_free_commands(arg->commands);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
		TAILQ_REMOVE(args, arg, entry);
 | 
			
		||||
	free(arg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
cmd_parse_free_arguments(struct cmd_parse_arguments *args)
 | 
			
		||||
{
 | 
			
		||||
	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_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);
 | 
			
		||||
	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);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		free(string);
 | 
			
		||||
		string = s;
 | 
			
		||||
	}
 | 
			
		||||
	if (string == NULL)
 | 
			
		||||
		string = xstrdup("");
 | 
			
		||||
	log_debug("%s: %s", __func__, string);
 | 
			
		||||
	return (string);
 | 
			
		||||
	last = TAILQ_LAST(cmds, cmd_parse_commands);
 | 
			
		||||
	if (last == NULL) {
 | 
			
		||||
		*cmdlist = cmd_list_new();
 | 
			
		||||
		return (1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
cmd_parse_flatten_command(struct cmd_parse_command *cmd)
 | 
			
		||||
	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;
 | 
			
		||||
	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);
 | 
			
		||||
		pr->status = CMD_PARSE_EMPTY;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* 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
 | 
			
		||||
@@ -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