~emersion/mrsh

231caa7786beaba1be7a118bc88887049fd15030 — Simon Ser 2 years ago 8fd05a3
shell/task/word: don't perform tilde expansion in run_word
M builtin/export.c => builtin/export.c +5 -2
@@ 53,8 53,11 @@ int builtin_export(struct mrsh_state *state, int argc, char *argv[]) {
			free(key);
			return 1;
		}
		char *new_val = strdup(val);
		expand_tilde(state, &new_val);
		struct mrsh_word_string *ws =
			mrsh_word_string_create(strdup(val), false);
		expand_tilde(state, &ws->word, true);
		char *new_val = mrsh_word_str(&ws->word);
		mrsh_word_destroy(&ws->word);
		mrsh_env_set(state, key, new_val, attrib | prev_attribs);
		free(key);
		free(new_val);

M include/shell/task.h => include/shell/task.h +2 -2
@@ 23,8 23,8 @@

struct context;

int run_word(struct context *ctx, struct mrsh_word **word_ptr,
	enum tilde_expansion tilde_expansion);
/* Perform parameter expansion, command substitution and arithmetic expansion. */
int run_word(struct context *ctx, struct mrsh_word **word_ptr);
int run_simple_command(struct context *ctx, struct mrsh_simple_command *sc);
int run_command(struct context *ctx, struct mrsh_command *cmd);
int run_and_or_list(struct context *ctx, struct mrsh_and_or_list *and_or_list);

M include/shell/word.h => include/shell/word.h +3 -11
@@ 3,19 3,11 @@

#include <mrsh/shell.h>

enum tilde_expansion {
	// Don't perform tilde expansion at all
	TILDE_EXPANSION_NONE,
	// Only expand at the begining of words
	TILDE_EXPANSION_NAME,
	// Expand at the begining of words and after semicolons
	TILDE_EXPANSION_ASSIGNMENT,
};

/**
 * Performs tilde expansion. It leaves the string as-is in case of error.
 * Performs tilde expansion. It leaves the word as-is in case of error.
 */
void expand_tilde(struct mrsh_state *state, char **str_ptr);
void expand_tilde(struct mrsh_state *state, struct mrsh_word *word,
	bool assignment);
/**
 * Performs field splitting on `word`, writing fields to `fields`. This should
 * be done after expansions/substitutions.

M shell/task/simple_command.c => shell/task/simple_command.c +10 -5
@@ 215,7 215,8 @@ static void expand_assignments(struct context *ctx,
		struct mrsh_array *assignments) {
	for (size_t i = 0; i < assignments->len; ++i) {
		struct mrsh_assignment *assign = assignments->data[i];
		run_word(ctx, &assign->value, TILDE_EXPANSION_ASSIGNMENT);
		expand_tilde(ctx->state, assign->value, true);
		run_word(ctx, &assign->value);
		// TODO: report errors
	}
}


@@ 278,7 279,8 @@ int run_simple_command(struct context *ctx, struct mrsh_simple_command *sc) {
	// we'll mutate the tree
	sc = copy_simple_command(sc);

	int ret = run_word(ctx, &sc->name, TILDE_EXPANSION_NAME);
	expand_tilde(ctx->state, sc->name, false);
	int ret = run_word(ctx, &sc->name);
	if (ret < 0) {
		return ret;
	}


@@ 287,7 289,8 @@ int run_simple_command(struct context *ctx, struct mrsh_simple_command *sc) {
	for (size_t i = 0; i < sc->arguments.len; ++i) {
		struct mrsh_word **arg_ptr =
			(struct mrsh_word **)&sc->arguments.data[i];
		ret = run_word(ctx, arg_ptr, TILDE_EXPANSION_NAME);
		expand_tilde(ctx->state, *arg_ptr, false);
		ret = run_word(ctx, arg_ptr);
		if (ret < 0) {
			return ret;
		}


@@ 295,14 298,16 @@ int run_simple_command(struct context *ctx, struct mrsh_simple_command *sc) {

	for (size_t i = 0; i < sc->io_redirects.len; ++i) {
		struct mrsh_io_redirect *redir = sc->io_redirects.data[i];
		ret = run_word(ctx, &redir->name, TILDE_EXPANSION_NAME);
		expand_tilde(ctx->state, redir->name, false);
		ret = run_word(ctx, &redir->name);
		if (ret < 0) {
			return ret;
		}
		for (size_t j = 0; j < redir->here_document.len; ++j) {
			struct mrsh_word **line_word_ptr =
				(struct mrsh_word **)&redir->here_document.data[j];
			ret = run_word(ctx, line_word_ptr, TILDE_EXPANSION_NAME);
			expand_tilde(ctx->state, *line_word_ptr, false);
			ret = run_word(ctx, line_word_ptr);
			if (ret < 0) {
				return ret;
			}

M shell/task/task.c => shell/task/task.c +9 -4
@@ 128,7 128,8 @@ static int run_for_clause(struct context *ctx, struct mrsh_for_clause *fc) {
		// TODO: this mutates the AST
		struct mrsh_word **word_ptr =
			(struct mrsh_word **)&fc->word_list.data[i];
		int ret = run_word(ctx, word_ptr, TILDE_EXPANSION_NAME);
		expand_tilde(ctx->state, *word_ptr, false);
		int ret = run_word(ctx, word_ptr);
		if (ret < 0) {
			return ret;
		}


@@ 193,7 194,8 @@ interrupt:

static int run_case_clause(struct context *ctx, struct mrsh_case_clause *cc) {
	struct mrsh_word *word = mrsh_word_copy(cc->word);
	int ret = run_word(ctx, &word, TILDE_EXPANSION_NAME);
	expand_tilde(ctx->state, word, false);
	int ret = run_word(ctx, &word);
	if (ret < 0) {
		mrsh_word_destroy(word);
		return ret;


@@ 210,7 212,8 @@ static int run_case_clause(struct context *ctx, struct mrsh_case_clause *cc) {
			// TODO: this mutates the AST
			struct mrsh_word **word_ptr =
				(struct mrsh_word **)&ci->patterns.data[j];
			int ret = run_word(ctx, word_ptr, TILDE_EXPANSION_NAME);
			expand_tilde(ctx->state, *word_ptr, false);
			int ret = run_word(ctx, word_ptr);
			if (ret < 0) {
				return ret;
			}


@@ 392,9 395,11 @@ int mrsh_run_program(struct mrsh_state *state, struct mrsh_program *prog) {
}

int mrsh_run_word(struct mrsh_state *state, struct mrsh_word **word) {
	expand_tilde(state, *word, false);

	struct context ctx = { .state = state };
	int last_status = state->last_status;
	int ret = run_word(&ctx, word, TILDE_EXPANSION_NAME);
	int ret = run_word(&ctx, word);
	state->last_status = last_status;
	return ret;
}

M shell/task/word.c => shell/task/word.c +4 -13
@@ 202,18 202,12 @@ static int apply_parameter_op(struct context *ctx,
	assert(false);
}

int run_word(struct context *ctx, struct mrsh_word **word_ptr,
		enum tilde_expansion tilde_expansion) {
int run_word(struct context *ctx, struct mrsh_word **word_ptr) {
	struct mrsh_word *word = *word_ptr;

	int ret;
	switch (word->type) {
	case MRSH_WORD_STRING:;
		struct mrsh_word_string *ws = mrsh_word_get_string(word);
		if (!ws->single_quoted && tilde_expansion != TILDE_EXPANSION_NONE) {
			// TODO: TILDE_EXPANSION_ASSIGNMENT
			expand_tilde(ctx->state, &ws->str);
		}
		return 0;
	case MRSH_WORD_PARAMETER:;
		struct mrsh_word_parameter *wp = mrsh_word_get_parameter(word);


@@ 244,7 238,7 @@ int run_word(struct context *ctx, struct mrsh_word **word_ptr,
		}
		if (result_word != NULL) {
			result_word = mrsh_word_copy(result_word);
			ret = run_word(ctx, &result_word, tilde_expansion);
			ret = run_word(ctx, &result_word);
			if (ret < 0) {
				return ret;
			}


@@ 261,7 255,7 @@ int run_word(struct context *ctx, struct mrsh_word **word_ptr,
		// For arithmetic words, we need to expand the arithmetic expression
		// before parsing and evaluating it
		struct mrsh_word_arithmetic *wa = mrsh_word_get_arithmetic(word);
		ret = run_word(ctx, &wa->body, TILDE_EXPANSION_NONE);
		ret = run_word(ctx, &wa->body);
		if (ret < 0) {
			return ret;
		}


@@ 306,10 300,7 @@ int run_word(struct context *ctx, struct mrsh_word **word_ptr,
		for (size_t i = 0; i < wl->children.len; ++i) {
			struct mrsh_word **child_ptr =
				(struct mrsh_word **)&wl->children.data[i];
			if (i > 0 || wl->double_quoted) {
				tilde_expansion = TILDE_EXPANSION_NONE;
			}
			ret = run_word(ctx, child_ptr, tilde_expansion);
			ret = run_word(ctx, child_ptr);
			if (ret < 0) {
				return ret;
			}

M shell/word.c => shell/word.c +26 -1
@@ 10,7 10,7 @@
#include "shell/shell.h"
#include "shell/word.h"

void expand_tilde(struct mrsh_state *state, char **str_ptr) {
static void expand_tilde_str(struct mrsh_state *state, char **str_ptr) {
	char *str = *str_ptr;
	if (str[0] != '~') {
		return;


@@ 56,6 56,31 @@ void expand_tilde(struct mrsh_state *state, char **str_ptr) {
	*str_ptr = expanded;
}

void expand_tilde(struct mrsh_state *state, struct mrsh_word *word,
		bool assignment) {
	switch (word->type) {
	case MRSH_WORD_STRING:;
		struct mrsh_word_string *ws = mrsh_word_get_string(word);
		if (!ws->single_quoted) {
			// TODO: assignment
			expand_tilde_str(state, &ws->str);
		}
		break;
	case MRSH_WORD_LIST:;
		struct mrsh_word_list *wl = mrsh_word_get_list(word);
		for (size_t i = 0; i < wl->children.len; ++i) {
			struct mrsh_word *child = wl->children.data[i];
			if (i > 0 || wl->double_quoted) {
				continue;
			}
			expand_tilde(state, child, assignment);
		}
		break;
	default:
		break;
	}
}

struct split_fields_data {
	struct mrsh_array *fields;
	struct mrsh_word_list *cur_field;