~emersion/mrsh

99d61e0c183a1eb8f611488a90a3765086e6daef — Drew DeVault 11 months ago e1e599b
mrsh_state: move loop control into call frame
5 files changed, 23 insertions(+), 22 deletions(-)

M builtin/break.c
M builtin/exit.c
M include/mrsh/shell.h
M shell/shell.c
M shell/task/task.c
M builtin/break.c => builtin/break.c +4 -4
@@ 25,12 25,12 @@ int builtin_break(struct mrsh_state *state, int argc, char *argv[]) {
		}
	}

	if (n > state->nloops) {
		n = state->nloops;
	if (n > state->frame->nloops) {
		n = state->frame->nloops;
	}

	state->nloops -= n - 1;
	state->branch_control =
	state->frame->nloops -= n - 1;
	state->frame->branch_control =
		strcmp(argv[0], "break") == 0 ? MRSH_BRANCH_BREAK : MRSH_BRANCH_CONTINUE;
	return TASK_STATUS_INTERRUPTED;
}

M builtin/exit.c => builtin/exit.c +1 -1
@@ 27,6 27,6 @@ int builtin_exit(struct mrsh_state *state, int argc, char *argv[]) {
	}

	state->exit = status;
	state->branch_control = MRSH_BRANCH_EXIT;
	state->frame->branch_control = MRSH_BRANCH_EXIT;
	return TASK_STATUS_INTERRUPTED;
}

M include/mrsh/shell.h => include/mrsh/shell.h +9 -8
@@ 75,12 75,6 @@ struct mrsh_function {
	struct mrsh_command *body;
};

struct mrsh_call_frame {
	char **argv;
	int argc;
	struct mrsh_call_frame *prev;
};

struct mrsh_job;

enum mrsh_branch_control {


@@ 90,6 84,15 @@ enum mrsh_branch_control {
	MRSH_BRANCH_EXIT,
};

struct mrsh_call_frame {
	char **argv;
	int argc;
	struct mrsh_call_frame *prev;

	enum mrsh_branch_control branch_control;
	int nloops;
};

struct mrsh_state {
	int exit;
	int fd;


@@ 109,8 112,6 @@ struct mrsh_state {
	struct mrsh_job *foreground_job;

	// TODO: move this to context
	enum mrsh_branch_control branch_control;
	int nloops;
	bool child; // true if we're not the main shell process
};


M shell/shell.c => shell/shell.c +1 -1
@@ 21,7 21,6 @@ void mrsh_function_destroy(struct mrsh_function *fn) {
void mrsh_state_init(struct mrsh_state *state) {
	state->exit = -1;
	state->fd = -1;
	state->nloops = 0;
	state->interactive = isatty(STDIN_FILENO);
	state->options = state->interactive ? MRSH_OPT_INTERACTIVE : 0;
	state->frame = calloc(1, sizeof(struct mrsh_call_frame));


@@ 124,6 123,7 @@ void mrsh_push_frame(struct mrsh_state *state, int argc, const char *argv[]) {
	for (int i = 0; i < argc; ++i) {
		next->argv[i] = strdup(argv[i]);
	}
	next->nloops = 0;
	next->prev = state->frame;
	state->frame = next;
}

M shell/task/task.c => shell/task/task.c +8 -8
@@ 63,7 63,7 @@ static int run_if_clause(struct context *ctx, struct mrsh_if_clause *ic) {
}

static int run_loop_clause(struct context *ctx, struct mrsh_loop_clause *lc) {
	int loop_num = ++ctx->state->nloops;
	int loop_num = ++ctx->state->frame->nloops;

	int loop_ret = 0;
	while (ctx->state->exit == -1) {


@@ 97,11 97,11 @@ static int run_loop_clause(struct context *ctx, struct mrsh_loop_clause *lc) {
		continue;

interrupt:
		if (ctx->state->nloops < loop_num) {
		if (ctx->state->frame->nloops < loop_num) {
			loop_ret = TASK_STATUS_INTERRUPTED; // break to parent loop
			break;
		}
		switch (ctx->state->branch_control) {
		switch (ctx->state->frame->branch_control) {
		case MRSH_BRANCH_BREAK:
		case MRSH_BRANCH_RETURN:
		case MRSH_BRANCH_EXIT:


@@ 116,12 116,12 @@ interrupt:
		}
	}

	--ctx->state->nloops;
	--ctx->state->frame->nloops;
	return loop_ret;
}

static int run_for_clause(struct context *ctx, struct mrsh_for_clause *fc) {
	int loop_num = ++ctx->state->nloops;
	int loop_num = ++ctx->state->frame->nloops;

	struct mrsh_array word_fields = {0};
	for (size_t i = 0; i < fc->word_list.len; i++) {


@@ 167,12 167,12 @@ static int run_for_clause(struct context *ctx, struct mrsh_for_clause *fc) {
		continue;

interrupt:
		if (ctx->state->nloops < loop_num) {
		if (ctx->state->frame->nloops < loop_num) {
			loop_ret = TASK_STATUS_INTERRUPTED; // break to parent loop
			break;
		}
		bool break_loop = false;
		switch (ctx->state->branch_control) {
		switch (ctx->state->frame->branch_control) {
		case MRSH_BRANCH_BREAK:
		case MRSH_BRANCH_RETURN:
		case MRSH_BRANCH_EXIT:


@@ 192,7 192,7 @@ interrupt:
	}
	mrsh_array_finish(&expanded_fields);

	--ctx->state->nloops;
	--ctx->state->frame->nloops;
	return loop_ret;
}