~emersion/mrsh

0264e7fb6ea4decac0b05970ac7eaf4fcd012577 — Simon Ser 1 year, 8 months ago e902a4f
Only split fields on expansion/substitution results

Closes: https://github.com/emersion/mrsh/issues/144
3 files changed, 27 insertions(+), 1 deletions(-)

M include/mrsh/ast.h
M shell/task/word.c
M shell/word.c
M include/mrsh/ast.h => include/mrsh/ast.h +4 -0
@@ 63,6 63,10 @@ struct mrsh_word_string {
	char *str;
	bool single_quoted;

	// true if candidate for field splitting (ie. result of parameter
	// expansion, command substitution or arithmetic expansion)
	bool split_fields;

	struct mrsh_range range;
};


M shell/task/word.c => shell/task/word.c +22 -0
@@ 146,6 146,7 @@ static int run_word_command(struct mrsh_context *ctx, struct mrsh_word **word_pt

	struct mrsh_word_string *ws =
		mrsh_word_string_create(mrsh_buffer_steal(&buf), false);
	ws->split_fields = true;
	swap_words(word_ptr, &ws->word);
	return job_wait_process(process);
}


@@ 212,10 213,12 @@ static struct mrsh_word *expand_positional_params(struct mrsh_state *state,
		if (i > 1 && sep[0] != '\0') {
			struct mrsh_word_string *ws =
				mrsh_word_string_create(strdup(sep), false);
			ws->split_fields = true;
			mrsh_array_add(&words, &ws->word);
		}
		struct mrsh_word_string *ws =
			mrsh_word_string_create(strdup(arg), quote_args);
		ws->split_fields = true;
		mrsh_array_add(&words, &ws->word);
	}



@@ 223,6 226,23 @@ static struct mrsh_word *expand_positional_params(struct mrsh_state *state,
	return &wl->word;
}

static void mark_word_split_fields(struct mrsh_word *word) {
	switch (word->type) {
	case MRSH_WORD_STRING:;
		struct mrsh_word_string *ws = mrsh_word_get_string(word);
		ws->split_fields = true;
		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++) {
			mark_word_split_fields(wl->children.data[i]);
		}
		break;
	default:
		break;
	}
}

static struct mrsh_word *create_word_string(const char *str) {
	struct mrsh_word_string *ws = mrsh_word_string_create(strdup(str), false);
	return &ws->word;


@@ 517,6 537,7 @@ static int _run_word(struct mrsh_context *ctx, struct mrsh_word **word_ptr,
			}
			result = create_word_string("");
		}
		mark_word_split_fields(result);
		if (result->type != MRSH_WORD_STRING) {
			ret = run_word(ctx, &result);
			if (ret < 0) {


@@ 563,6 584,7 @@ static int _run_word(struct mrsh_context *ctx, struct mrsh_word **word_ptr,

				struct mrsh_word_string *ws =
					mrsh_word_string_create(strdup(buf), false);
				ws->split_fields = true;
				swap_words(word_ptr, &ws->word);
				ret = 0;
			}

M shell/word.c => shell/word.c +1 -1
@@ 157,7 157,7 @@ static void _split_fields(struct split_fields_data *data,
	case MRSH_WORD_STRING:;
		const struct mrsh_word_string *ws = mrsh_word_get_string(word);

		if (ws->single_quoted) {
		if (ws->single_quoted || !ws->split_fields) {
			add_to_cur_field(data, mrsh_word_copy(word));
			data->in_ifs = data->in_ifs_non_space = false;
			return;