715e6efeb77b59b3be5a3fe567ce841fbf55a280 — Simon Ser 24 days ago 90610a2 master
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,