~emersion/mrsh

715e6efeb77b59b3be5a3fe567ce841fbf55a280 — Simon Ser 7 months ago 90610a2
shell: mrsh_state_init → mrsh_state_create
3 files changed, 48 insertions(+), 39 deletions(-)

M include/mrsh/shell.h
M main.c
M shell/shell.c
M include/mrsh/shell.h => include/mrsh/shell.h +2 -2
@@ 108,10 108,10 @@ struct mrsh_state {

struct mrsh_parser;

void mrsh_state_init(struct mrsh_state *state);
struct mrsh_state *mrsh_state_create(void);
void mrsh_state_destroy(struct mrsh_state *state);
void mrsh_state_set_parser_alias_func(
		struct mrsh_state *state, struct mrsh_parser *parser);
void mrsh_state_finish(struct mrsh_state *state);
void mrsh_env_set(struct mrsh_state *state,
	const char *key, const char *value, uint32_t attribs);
void mrsh_env_unset(struct mrsh_state *state, const char *key);

M main.c => main.c +32 -33
@@ 17,36 17,33 @@
extern char **environ;

int main(int argc, char *argv[]) {
	struct mrsh_state state = {0};
	mrsh_state_init(&state);
	struct mrsh_state *state = mrsh_state_create();

	struct mrsh_init_args init_args = {0};
	if (mrsh_process_args(&state, &init_args, argc, argv) != 0) {
		mrsh_state_finish(&state);
	if (mrsh_process_args(state, &init_args, argc, argv) != 0) {
		mrsh_state_destroy(state);
		return 1;
	}

	if (!mrsh_populate_env(&state, environ)) {
	if (!mrsh_populate_env(state, environ)) {
		return 1;
	}

	if (!(state.options & MRSH_OPT_NOEXEC)) {
	if (!(state->options & MRSH_OPT_NOEXEC)) {
		// If argv[0] begins with `-`, it's a login shell
		if (state.frame->argv[0][0] == '-') {
			mrsh_source_profile(&state);
		if (state->frame->argv[0][0] == '-') {
			mrsh_source_profile(state);
		}
		if (state.interactive) {
			mrsh_source_env(&state);
		if (state->interactive) {
			mrsh_source_env(state);
		}
	}

	state.term_fd = STDIN_FILENO;

	struct mrsh_buffer parser_buffer = {0};
	struct mrsh_parser *parser;
	int fd = -1;
	if (state.interactive) {
		interactive_init(&state);
	if (state->interactive) {
		interactive_init(state);
		parser = mrsh_parser_with_buffer(&parser_buffer);
	} else {
		if (init_args.command_str) {


@@ 67,29 64,29 @@ int main(int argc, char *argv[]) {
			parser = mrsh_parser_with_fd(fd);
		}
	}
	mrsh_state_set_parser_alias_func(&state, parser);
	mrsh_state_set_parser_alias_func(state, parser);

	if (state.interactive) {
		if (!mrsh_set_job_control(&state, true)) {
	if (state->interactive) {
		if (!mrsh_set_job_control(state, true)) {
			fprintf(stderr, "failed to enable job control\n");
		}
	}

	struct mrsh_buffer read_buffer = {0};
	while (state.exit == -1) {
		if (state.interactive) {
	while (state->exit == -1) {
		if (state->interactive) {
			char *prompt;
			if (read_buffer.len > 0) {
				prompt = mrsh_get_ps2(&state);
				prompt = mrsh_get_ps2(state);
			} else {
				// TODO: next_history_id
				prompt = mrsh_get_ps1(&state, 0);
				prompt = mrsh_get_ps1(state, 0);
			}
			char *line = NULL;
			size_t n = interactive_next(&state, &line, prompt);
			size_t n = interactive_next(state, &line, prompt);
			free(prompt);
			if (!line) {
				state.exit = state.last_status;
				state->exit = state->last_status;
				continue;
			}
			mrsh_buffer_append(&read_buffer, line, n);


@@ 111,43 108,45 @@ int main(int argc, char *argv[]) {
			if (err_msg != NULL) {
				mrsh_buffer_finish(&read_buffer);
				fprintf(stderr, "%s:%d:%d: syntax error: %s\n",
					state.frame->argv[0], err_pos.line, err_pos.column, err_msg);
				if (state.interactive) {
					state->frame->argv[0], err_pos.line, err_pos.column,
					err_msg);
				if (state->interactive) {
					continue;
				} else {
					state.exit = 1;
					state->exit = 1;
					break;
				}
			} else if (mrsh_parser_eof(parser)) {
				state.exit = state.last_status;
				state->exit = state->last_status;
				break;
			} else {
				fprintf(stderr, "unknown error\n");
				state.exit = 1;
				state->exit = 1;
				break;
			}
		} else {
			if ((state.options & MRSH_OPT_NOEXEC)) {
			if ((state->options & MRSH_OPT_NOEXEC)) {
				mrsh_program_print(prog);
			} else {
				mrsh_run_program(&state, prog);
				mrsh_run_program(state, prog);
			}
			mrsh_buffer_finish(&read_buffer);
		}
		mrsh_program_destroy(prog);
	}

	if (state.interactive) {
	if (state->interactive) {
		printf("\n");
	}

	int exit = state->exit;
	mrsh_buffer_finish(&read_buffer);
	mrsh_parser_destroy(parser);
	mrsh_buffer_finish(&parser_buffer);
	mrsh_state_finish(&state);
	mrsh_state_destroy(state);
	if (fd >= 0) {
		close(fd);
	}

	return state.exit;
	return exit;
}

M shell/shell.c => shell/shell.c +14 -4
@@ 18,12 18,21 @@ void function_destroy(struct mrsh_function *fn) {
	free(fn);
}

void mrsh_state_init(struct mrsh_state *state) {
struct mrsh_state *mrsh_state_create(void) {
	struct mrsh_state *state = calloc(1, sizeof(*state));
	if (state == NULL) {
		return NULL;
	}
	state->exit = -1;
	state->term_fd = -1;
	state->interactive = isatty(STDIN_FILENO);
	state->term_fd = STDIN_FILENO;
	state->interactive = isatty(state->term_fd);
	state->options = state->interactive ? MRSH_OPT_INTERACTIVE : 0;
	state->frame = calloc(1, sizeof(struct mrsh_call_frame));
	if (state->frame == NULL) {
		free(state);
		return NULL;
	}
	return state;
}

static const char *get_alias(const char *name, void *data) {


@@ 66,7 75,7 @@ static void call_frame_destroy(struct mrsh_call_frame *frame) {
	free(frame);
}

void mrsh_state_finish(struct mrsh_state *state) {
void mrsh_state_destroy(struct mrsh_state *state) {
	mrsh_hashtable_for_each(&state->variables, state_var_finish_iterator, NULL);
	mrsh_hashtable_finish(&state->variables);
	mrsh_hashtable_for_each(&state->functions, state_fn_finish_iterator, NULL);


@@ 88,6 97,7 @@ void mrsh_state_finish(struct mrsh_state *state) {
		call_frame_destroy(frame);
		frame = prev;
	}
	free(state);
}

void mrsh_env_set(struct mrsh_state *state,