diff options
| author | David Moc <personal@cdatgoose.org> | 2026-05-30 21:53:05 +0200 |
|---|---|---|
| committer | David Moc <personal@cdatgoose.org> | 2026-05-30 21:53:05 +0200 |
| commit | e930cc6bdc7f62befac063d7d9d016ffb0a64f1a (patch) | |
| tree | 52118a1e990ae88f5f0410c8caea129609e22e19 /src/config.c | |
Added the old repo, refactored it, added the C jit.
Diffstat (limited to 'src/config.c')
| -rw-r--r-- | src/config.c | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..b416d7a --- /dev/null +++ b/src/config.c @@ -0,0 +1,293 @@ +#include "config.h" + +#include "buffers.h" +#include "ccdjit.h" +#include "common.h" +#include "ecex.h" +#include "eval.h" +#include "util.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +typedef int (*ecex_config_init_fn)(ecex_t *ed); + +typedef struct host_symbol { + const char *name; + void *addr; +} host_symbol_t; + +void ecex_print_ccdjit_error(ccdjit_context *ctx) { + const ccdjit_diagnostic *diag = ccdjit_context_last_error(ctx); + + if (!diag) { + fprintf(stderr, "ccdjit: unknown error\n"); + return; + } + + fprintf(stderr, + "ccdjit error [%s] %s:%d:%d: %s\n", + diag->phase ? diag->phase : "?", + diag->filename ? diag->filename : "<input>", + diag->line, + diag->column, + diag->message ? diag->message : "(no message)"); + + if (diag->source_line) fprintf(stderr, "%s\n", diag->source_line); + if (diag->caret_line) fprintf(stderr, "%s\n", diag->caret_line); +} + +#define HOST_SYMBOL(fn) { #fn, (void *)(fn) } + +static const host_symbol_t host_symbols[] = { + HOST_SYMBOL(ecex_current_buffer), + HOST_SYMBOL(ecex_create_buffer), + HOST_SYMBOL(ecex_find_buffer), + HOST_SYMBOL(ecex_switch_buffer), + HOST_SYMBOL(ecex_next_buffer), + HOST_SYMBOL(ecex_previous_buffer), + HOST_SYMBOL(ecex_current_window), + HOST_SYMBOL(ecex_window_count), + HOST_SYMBOL(ecex_split_window_vertically), + HOST_SYMBOL(ecex_split_window_horizontally), + HOST_SYMBOL(ecex_other_window), + HOST_SYMBOL(ecex_previous_window), + HOST_SYMBOL(ecex_delete_window), + HOST_SYMBOL(ecex_delete_other_windows), + HOST_SYMBOL(ecex_kill_buffer), + + HOST_SYMBOL(ecex_register_command), + HOST_SYMBOL(ecex_execute_command), + HOST_SYMBOL(ecex_bind_key), + HOST_SYMBOL(ecex_lookup_key), + HOST_SYMBOL(ecex_define_major_mode), + HOST_SYMBOL(ecex_major_mode_by_name), + HOST_SYMBOL(ecex_major_mode_name), + HOST_SYMBOL(ecex_buffer_set_major_mode), + HOST_SYMBOL(ecex_buffer_set_major_mode_by_name), + HOST_SYMBOL(ecex_buffer_major_mode_name), + HOST_SYMBOL(ecex_bind_mode_key), + HOST_SYMBOL(ecex_lookup_key_for_buffer), + HOST_SYMBOL(ecex_key_sequence_has_prefix_for_buffer), + HOST_SYMBOL(ecex_auto_set_major_mode), + HOST_SYMBOL(ecex_list_commands), + HOST_SYMBOL(ecex_list_buffers), + HOST_SYMBOL(ecex_create_interactive_buffer), + HOST_SYMBOL(ecex_interactive_append_line), + HOST_SYMBOL(ecex_interactive_activate_current_line), + HOST_SYMBOL(ecex_find_file), + HOST_SYMBOL(ecex_save_current_buffer), + HOST_SYMBOL(ecex_write_current_buffer), + HOST_SYMBOL(ecex_request_prompt), + HOST_SYMBOL(ecex_clear_prompt_request), + HOST_SYMBOL(ecex_complete_command), + HOST_SYMBOL(ecex_eval_source), + HOST_SYMBOL(ecex_eval_current_buffer), + HOST_SYMBOL(ecex_eval_current_line), + HOST_SYMBOL(ecex_eval_current_region), + HOST_SYMBOL(ecex_eval_file), + HOST_SYMBOL(ecex_eval_rerun_last), + + HOST_SYMBOL(ecex_set_font), + HOST_SYMBOL(ecex_get_font_size), + HOST_SYMBOL(ecex_set_font_size), + HOST_SYMBOL(ecex_adjust_font_size), + HOST_SYMBOL(ecex_set_bg_color), + HOST_SYMBOL(ecex_set_fg_color), + HOST_SYMBOL(ecex_set_status_bg_color), + HOST_SYMBOL(ecex_set_status_fg_color), + HOST_SYMBOL(ecex_set_status_border_color), + HOST_SYMBOL(ecex_set_cursor_color), + HOST_SYMBOL(ecex_set_region_bg_color), + HOST_SYMBOL(ecex_set_minibuffer_bg_color), + HOST_SYMBOL(ecex_set_minibuffer_fg_color), + HOST_SYMBOL(ecex_set_completion_fg_color), + HOST_SYMBOL(ecex_set_completion_enabled), + HOST_SYMBOL(ecex_set_interactive_highlight_bg_color), + HOST_SYMBOL(ecex_set_interactive_highlight_fg_color), + + HOST_SYMBOL(buffer_clear), + HOST_SYMBOL(buffer_set_text), + HOST_SYMBOL(buffer_insert), + HOST_SYMBOL(buffer_insert_at), + HOST_SYMBOL(buffer_append), + HOST_SYMBOL(buffer_prepend), + HOST_SYMBOL(buffer_insert_char), + HOST_SYMBOL(buffer_insert_char_at), + HOST_SYMBOL(buffer_delete_range), + HOST_SYMBOL(buffer_delete_selection), + HOST_SYMBOL(buffer_replace_selection), + HOST_SYMBOL(buffer_backspace), + HOST_SYMBOL(buffer_delete_forward), + HOST_SYMBOL(buffer_kill_line), + + HOST_SYMBOL(buffer_set_point), + HOST_SYMBOL(buffer_move_left), + HOST_SYMBOL(buffer_move_right), + HOST_SYMBOL(buffer_move_up), + HOST_SYMBOL(buffer_move_down), + HOST_SYMBOL(buffer_move_word_left), + HOST_SYMBOL(buffer_move_word_right), + HOST_SYMBOL(buffer_move_beginning_of_line), + HOST_SYMBOL(buffer_move_end_of_line), + HOST_SYMBOL(buffer_move_beginning_of_buffer), + HOST_SYMBOL(buffer_move_end_of_buffer), + + HOST_SYMBOL(buffer_set_mark), + HOST_SYMBOL(buffer_clear_mark), + HOST_SYMBOL(buffer_has_selection), + HOST_SYMBOL(buffer_selection_range), + + HOST_SYMBOL(buffer_line_start_at), + HOST_SYMBOL(buffer_line_end_at), + HOST_SYMBOL(buffer_current_line_start), + HOST_SYMBOL(buffer_current_line_end), + HOST_SYMBOL(buffer_current_column), + HOST_SYMBOL(buffer_current_line_number), + HOST_SYMBOL(buffer_line_count), + HOST_SYMBOL(buffer_substring), + HOST_SYMBOL(buffer_current_line_copy), + + HOST_SYMBOL(buffer_load_file), + HOST_SYMBOL(buffer_save), + HOST_SYMBOL(buffer_save_as), + HOST_SYMBOL(buffer_set_interactive), + HOST_SYMBOL(buffer_is_interactive), + HOST_SYMBOL(buffer_clear_interactive_actions), + HOST_SYMBOL(buffer_add_interactive_action), + HOST_SYMBOL(buffer_interactive_action_at_line), +}; + +#undef HOST_SYMBOL + +int ecex_register_host_symbols(ccdjit_context *ctx) { + for (size_t i = 0; i < ECEX_ARRAY_LEN(host_symbols); i++) { + if (ccdjit_context_register_symbol(ctx, + host_symbols[i].name, + host_symbols[i].addr) != 0) { + fprintf(stderr, "ecex: failed to register symbol: %s\n", host_symbols[i].name); + ecex_print_ccdjit_error(ctx); + return ECEX_ERR; + } + } + + return ECEX_OK; +} + +static int add_include_path(ccdjit_context *ctx, const char *path) { + if (ccdjit_context_add_include_path(ctx, path) == 0) return ECEX_OK; + + fprintf(stderr, "ecex: failed to add include path: %s\n", path); + ecex_print_ccdjit_error(ctx); + return ECEX_ERR; +} + +int ecex_add_ccdjit_include_paths(ccdjit_context *ctx) { + if (add_include_path(ctx, "include") != ECEX_OK) return ECEX_ERR; + if (add_include_path(ctx, "../include") != ECEX_OK) return ECEX_ERR; + + const char *env_include = getenv("ECEX_INCLUDE"); + if (env_include && env_include[0]) { + if (add_include_path(ctx, env_include) != ECEX_OK) return ECEX_ERR; + } + + return ECEX_OK; +} + +static char *make_config_source_with_forced_main(const char *path) { + size_t source_size = 0; + char *source = ecex_read_entire_file(path, &source_size); + if (!source) return NULL; + + const char *forced_main = + "\n" + "\n" + "int main(int argc, char **argv) {\n" + " (void)argc;\n" + " (void)argv;\n" + " return ecex_config_init((ecex_t *)0);\n" + "}\n"; + + size_t forced_main_len = strlen(forced_main); + char *combined = malloc(source_size + forced_main_len + 1); + if (!combined) { + free(source); + return NULL; + } + + memcpy(combined, source, source_size); + memcpy(combined + source_size, forced_main, forced_main_len + 1); + + free(source); + return combined; +} + +int ecex_load_c_config(ecex_t *ed, const char *path) { + if (!ed || !path) return ECEX_ERR; + + ccdjit_context *ctx = ccdjit_context_new(NULL); + if (!ctx) { + fprintf(stderr, "ecex: failed to create ccdjit context\n"); + return ECEX_ERR; + } + + if (ecex_add_ccdjit_include_paths(ctx) != ECEX_OK || ecex_register_host_symbols(ctx) != ECEX_OK) { + ccdjit_context_free(ctx); + return ECEX_ERR; + } + + char *source = make_config_source_with_forced_main(path); + if (!source) { + fprintf(stderr, "ecex: failed to read or prepare config: %s\n", path); + ccdjit_context_free(ctx); + return ECEX_ERR; + } + + ccdjit_module *module = NULL; + if (ccdjit_compile_string(ctx, source, path, &module) != 0) { + fprintf(stderr, "ecex: failed to compile config: %s\n", path); + ecex_print_ccdjit_error(ctx); + free(source); + ccdjit_context_free(ctx); + return ECEX_ERR; + } + + free(source); + + ecex_config_init_fn init = + (ecex_config_init_fn)ccdjit_module_symbol(module, "ecex_config_init"); + + if (!init) { + fprintf(stderr, "ecex: config missing function: ecex_config_init\n"); + ecex_print_ccdjit_error(ctx); + ccdjit_module_free(module); + ccdjit_context_free(ctx); + return ECEX_ERR; + } + + int result = init(ed); + if (result != 0) { + fprintf(stderr, "ecex: config init failed with code: %d\n", result); + ccdjit_module_free(module); + ccdjit_context_free(ctx); + return ECEX_ERR; + } + + if (ecex_keep_jit_module(ed, module) != ECEX_OK) { + fprintf(stderr, "ecex: failed to retain config module\n"); + ccdjit_module_free(module); + ccdjit_context_free(ctx); + return ECEX_ERR; + } + + if (ecex_set_config_path(ed, path) != ECEX_OK) { + fprintf(stderr, "ecex: failed to remember config path: %s\n", path); + ccdjit_context_free(ctx); + return ECEX_ERR; + } + + ccdjit_context_free(ctx); + fprintf(stderr, "ecex: loaded config: %s\n", path); + return ECEX_OK; +} |
