~emersion/mrsh

c89c540ef90438c432efd316ddf02fade297a38a — Simon Ser 5 days ago 53bb2d1
Check error even when mrsh_parse_program returns non-NULL

In the future, I'd like to make mrsh_parse_program return the
partially-parsed program on error to allow interactive shells to provide
syntax highlighting while typing.
5 files changed, 36 insertions(+), 41 deletions(-)

M builtin/dot.c
M builtin/eval.c
M builtin/trap.c
M example/highlight.c
M parser/word.c
M builtin/dot.c => builtin/dot.c +10 -12
@@ 31,7 31,7 @@ int builtin_dot(struct mrsh_state *state, int argc, char *argv[]) {
	int fd = open(path, O_RDONLY | O_CLOEXEC);
	if (fd < 0) {
		fprintf(stderr, "unable to open %s for reading: %s\n",
				argv[1], strerror(errno));
			argv[1], strerror(errno));
		goto error;
	}



@@ 39,18 39,16 @@ int builtin_dot(struct mrsh_state *state, int argc, char *argv[]) {
	struct mrsh_program *program = mrsh_parse_program(parser);

	int ret;
	if (!program) {
		struct mrsh_position err_pos;
		const char *err_msg = mrsh_parser_error(parser, &err_pos);
		if (err_msg != NULL) {
			fprintf(stderr, "%s %d:%d: %s\n",
				argv[1], err_pos.line, err_pos.column, err_msg);
			ret = 1;
		} else {
			ret = 0;
		}
	} else {
	struct mrsh_position err_pos;
	const char *err_msg = mrsh_parser_error(parser, &err_pos);
	if (err_msg != NULL) {
		fprintf(stderr, "%s %d:%d: %s\n",
			argv[1], err_pos.line, err_pos.column, err_msg);
		ret = 1;
	} else if (program != NULL) {
		ret = mrsh_run_program(state, program);
	} else {
		ret = 0;
	}

	mrsh_program_destroy(program);

M builtin/eval.c => builtin/eval.c +9 -11
@@ 32,18 32,16 @@ int builtin_eval(struct mrsh_state *state, int argc, char *argv[]) {
	struct mrsh_program *program = mrsh_parse_program(parser);

	int ret;
	if (!program) {
		struct mrsh_position err_pos;
		const char *err_msg = mrsh_parser_error(parser, &err_pos);
		if (err_msg != NULL) {
			fprintf(stderr, "%s %d:%d: %s\n",
				argv[1], err_pos.line, err_pos.column, err_msg);
			ret = 1;
		} else {
			ret = 0;
		}
	} else {
	struct mrsh_position err_pos;
	const char *err_msg = mrsh_parser_error(parser, &err_pos);
	if (err_msg != NULL) {
		fprintf(stderr, "%s %d:%d: %s\n",
			argv[1], err_pos.line, err_pos.column, err_msg);
		ret = 1;
	} else if (program != NULL) {
		ret = mrsh_run_program(state, program);
	} else {
		ret = 0;
	}

	mrsh_program_destroy(program);

M builtin/trap.c => builtin/trap.c +7 -9
@@ 163,16 163,14 @@ int builtin_trap(struct mrsh_state *state, int argc, char *argv[]) {
		struct mrsh_parser *parser =
			mrsh_parser_with_data(action_str, strlen(action_str));
		program = mrsh_parse_program(parser);
		if (program == NULL) {
			struct mrsh_position err_pos;
			const char *err_msg = mrsh_parser_error(parser, &err_pos);
			if (err_msg != NULL) {
				fprintf(stderr, "trap: %d:%d: %s\n",
					err_pos.line, err_pos.column, err_msg);
			} else {
				fprintf(stderr, "trap: unknown parse error\n");
			}

		struct mrsh_position err_pos;
		const char *err_msg = mrsh_parser_error(parser, &err_pos);
		if (err_msg != NULL) {
			fprintf(stderr, "trap: %d:%d: %s\n",
				err_pos.line, err_pos.column, err_msg);
			mrsh_parser_destroy(parser);
			mrsh_program_destroy(program);
			return 1;
		}
		mrsh_parser_destroy(parser);

M example/highlight.c => example/highlight.c +5 -5
@@ 309,12 309,12 @@ int main(int argc, char *argv[]) {

	struct mrsh_parser *parser = mrsh_parser_with_data(buf.data, buf.len);
	struct mrsh_program *prog = mrsh_parse_program(parser);
	const char *err_msg = mrsh_parser_error(parser, NULL);
	if (err_msg != NULL) {
		fprintf(stderr, "failed to parse script: %s\n", err_msg);
		return 1;
	}
	if (prog == NULL) {
		const char *err_msg = mrsh_parser_error(parser, NULL);
		if (err_msg != NULL) {
			fprintf(stderr, "failed to parse script: %s\n", err_msg);
			return 1;
		}
		return 0;
	}
	mrsh_parser_destroy(parser);

M parser/word.c => parser/word.c +5 -4
@@ 342,10 342,11 @@ static struct mrsh_word_command *expect_word_command(

	struct mrsh_program *prog = mrsh_parse_program(parser);
	parser->alias = alias;
	if (prog == NULL) {
		if (!mrsh_parser_error(parser, NULL)) {
			parser_set_error(parser, "expected a program");
		}
	if (mrsh_parser_error(parser, NULL) != NULL) {
		mrsh_program_destroy(prog);
		return NULL;
	} else if (prog == NULL) {
		parser_set_error(parser, "expected a program");
		return NULL;
	}