~emersion/annotatesh

002787d69543708c469a6fc39339efdc44a9d1ec — Simon Ser 1 year, 3 months ago 59ec78b master
Add support for function definitions
2 files changed, 76 insertions(+), 20 deletions(-)

M main.c
M meson.build
M main.c => main.c +74 -20
@@ 7,6 7,18 @@

#include "posix.h"

struct function_def {
	char *name;
	struct mrsh_position pos;
};

struct context {
	struct function_def fn_defs[512];
	size_t fn_defs_len;

	struct json_object *annotations_arr;
};

static int str_in_array_cmp(const void *e1, const void *e2) {
	const char *s1 = *(const char **)e1;
	const char *s2 = *(const char **)e2;


@@ 17,7 29,17 @@ static bool str_in_array(const char *str, const char **arr, size_t arr_len) {
	return bsearch(&str, arr, arr_len, sizeof(char *), str_in_array_cmp) != NULL;
}

static const char *posix_cmd_link(const char *name) {
static const struct function_def *find_function_def(struct context *ctx,
		const char *name) {
	for (size_t i = 0; i < ctx->fn_defs_len; i++) {
		if (strcmp(ctx->fn_defs[i].name, name) == 0) {
			return &ctx->fn_defs[i];
		}
	}
	return NULL;
}

static const char *cmd_link(struct context *ctx, const char *name) {
	static char link[512];

	if (strcmp(name, ":") == 0) {


@@ 28,8 50,11 @@ static const char *posix_cmd_link(const char *name) {
		name = "test";
	}

	const struct function_def *fn_def = find_function_def(ctx, name);
	if (str_in_array(name, special_builtins, special_builtins_len)) {
		snprintf(link, sizeof(link), "%s%s", POSIX_URL_SPECIAL_BUILTIN, name);
	} else if (fn_def != NULL) {
		snprintf(link, sizeof(link), "#L%d", fn_def->pos.line);
	} else if (str_in_array(name, utilities, utilities_len)) {
		snprintf(link, sizeof(link), "%s/%s.html", POSIX_URL_UTILITY, name);
	} else {


@@ 39,25 64,14 @@ static const char *posix_cmd_link(const char *name) {
	return link;
}

static void node_iterator(struct mrsh_node *node, void *data) {
	struct json_object *arr = data;

	if (node->type != MRSH_NODE_COMMAND) {
		return;
	}

	struct mrsh_command *cmd = mrsh_node_get_command(node);
	if (cmd->type != MRSH_SIMPLE_COMMAND) {
		return;
	}

	struct mrsh_simple_command *sc = mrsh_command_get_simple_command(cmd);
static void handle_simple_command(struct context *ctx,
		struct mrsh_simple_command *sc) {
	if (sc->name == NULL) {
		return;
	}

	char *str = mrsh_word_str(sc->name);
	const char *link = posix_cmd_link(str);
	const char *link = cmd_link(ctx, str);
	free(str);

	if (link == NULL) {


@@ 74,7 88,41 @@ static void node_iterator(struct mrsh_node *node, void *data) {
	json_object_object_add(obj, "len",
		json_object_new_int(end.offset - begin.offset));
	json_object_object_add(obj, "to", json_object_new_string(link));
	json_object_array_add(arr, obj);
	json_object_array_add(ctx->annotations_arr, obj);
}

static void handle_function_definition(struct context *ctx,
		struct mrsh_function_definition *fn_def) {
	if (ctx->fn_defs_len >= sizeof(ctx->fn_defs) / sizeof(ctx->fn_defs[0])) {
		abort();
	}
	struct function_def *f = &ctx->fn_defs[ctx->fn_defs_len];
	f->name = strdup(fn_def->name);
	f->pos = fn_def->name_range.begin;
	ctx->fn_defs_len++;
}

static void node_iterator(struct mrsh_node *node, void *data) {
	struct context *ctx = data;

	if (node->type != MRSH_NODE_COMMAND) {
		return;
	}

	struct mrsh_command *cmd = mrsh_node_get_command(node);
	switch (cmd->type) {
	case MRSH_SIMPLE_COMMAND:;
		struct mrsh_simple_command *sc = mrsh_command_get_simple_command(cmd);
		handle_simple_command(ctx, sc);
		break;
	case MRSH_FUNCTION_DEFINITION:;
		struct mrsh_function_definition *fn =
			mrsh_command_get_function_definition(cmd);
		handle_function_definition(ctx, fn);
		break;
	default:
		break; // Nothing to do
	}
}

int main(int argc, char *argv[]) {


@@ 95,12 143,18 @@ int main(int argc, char *argv[]) {
	}
	mrsh_parser_destroy(parser);

	struct json_object *arr = json_object_new_array();
	mrsh_node_for_each(&prog->node, node_iterator, arr);
	struct context ctx = {
		.annotations_arr = json_object_new_array(),
	};
	mrsh_node_for_each(&prog->node, node_iterator, &ctx);
	mrsh_program_destroy(prog);

	json_object_to_fd(STDOUT_FILENO, arr,
	json_object_to_fd(STDOUT_FILENO, ctx.annotations_arr,
		JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED);
	json_object_put(arr);

	for (size_t i = 0; i < ctx.fn_defs_len; i++) {
		free(ctx.fn_defs[i].name);
	}
	json_object_put(ctx.annotations_arr);
	return 0;
}

M meson.build => meson.build +2 -0
@@ 22,6 22,8 @@ add_project_arguments(cc.get_supported_arguments([
	'-Wno-unused-parameter',
]), language: 'c')

add_project_arguments('-D_POSIX_C_SOURCE=200809L', language: 'c')

jsonc = dependency('json-c', version: '>=0.13')

# Try first to find mrsh as a subproject, then as a system dependency