diff --git a/ell.c b/ell.c index b4f5f2b..870b19c 100755 --- a/ell.c +++ b/ell.c @@ -622,44 +622,9 @@ parser_run (struct parser *self, const char **e) { // --- Runtime ----------------------------------------------------------------- -struct context; -typedef bool (*handler_fn) (struct context *, struct item *, struct item **); - -struct native_fn { - struct native_fn *next; ///< The next link in the chain - handler_fn handler; ///< Internal C handler, or NULL - char name[]; ///< The name of the function -}; - -struct native_fn *g_native; ///< Maps words to functions - -static struct native_fn * -native_find (const char *name) { - for (struct native_fn *fn = g_native; fn; fn = fn->next) - if (!strcmp (fn->name, name)) - return fn; - return NULL; -} - -static bool -native_register (const char *name, handler_fn handler) { - struct native_fn *fn = native_find (name); - if (!fn) { - if (!(fn = calloc (1, sizeof *fn + strlen (name) + 1))) - return false; - strcpy (fn->name, name); - fn->next = g_native; - g_native = fn; - } - - fn->handler = handler; - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - struct context { struct item *variables; ///< List of variables + struct native_fn *native; ///< Maps strings to C functions char *error; ///< Error information bool error_is_fatal; ///< Whether the error can be catched @@ -668,6 +633,14 @@ struct context { void *user_data; ///< User data }; +typedef bool (*handler_fn) (struct context *, struct item *, struct item **); + +struct native_fn { + struct native_fn *next; ///< The next link in the chain + handler_fn handler; ///< Internal C handler, or NULL + char name[]; ///< The name of the function +}; + static void context_init (struct context *ctx) { memset (ctx, 0, sizeof *ctx); @@ -675,6 +648,11 @@ context_init (struct context *ctx) { static void context_free (struct context *ctx) { + struct native_fn *next, *iter; + for (iter = ctx->native; iter; iter = next) { + next = iter->next; + free (iter); + } item_free_list (ctx->variables); free (ctx->error); } @@ -719,6 +697,30 @@ set (struct context *ctx, const char *name, struct item *value) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +static struct native_fn * +native_find (struct context *ctx, const char *name) { + for (struct native_fn *fn = ctx->native; fn; fn = fn->next) + if (!strcmp (fn->name, name)) + return fn; + return NULL; +} + +static bool +native_register (struct context *ctx, const char *name, handler_fn handler) { + struct native_fn *fn = native_find (ctx, name); + if (!fn) { + if (!(fn = calloc (1, sizeof *fn + strlen (name) + 1))) + return false; + strcpy (fn->name, name); + fn->next = ctx->native; + ctx->native = fn; + } + fn->handler = handler; + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + static bool set_error (struct context *ctx, const char *format, ...) { va_list ap; @@ -795,10 +797,10 @@ execute_and_set_args (struct context *ctx, struct item *following) { static bool execute_native (struct context *ctx, - struct native_fn *fn, struct item *next, struct item **res) { + struct native_fn *fn, struct item *following, struct item **result) { struct item *args = NULL; - bool ok = execute_args (ctx, next, &args) - && fn->handler (ctx, args, res); + bool ok = execute_args (ctx, following, &args) + && fn->handler (ctx, args, result); item_free_list (args); return ok; } @@ -839,7 +841,7 @@ execute_statement // Maybe something like (choose [@f1 @f2 @f3]) arg1 arg2 arg3 if (!body) { - struct native_fn *fn = native_find (name); + struct native_fn *fn = native_find (ctx, name); if (!fn) return set_error (ctx, "unknown function: %s", name); if (execute_native (ctx, fn, following, result)) @@ -1067,35 +1069,8 @@ defn (fn_concatenate) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static bool -init_native_library (void) -{ - return native_register ("set", fn_set) - && native_register ("list", fn_list) - && native_register ("if", fn_if) - && native_register ("for", fn_for) - && native_register ("break", fn_break) - && native_register ("map", fn_map) - && native_register ("filter", fn_filter) - && native_register ("print", fn_print) - && native_register ("..", fn_concatenate); -} - -static void -free_native_library (void) { - struct native_fn *next, *iter; - for (iter = g_native; iter; iter = next) { - next = iter->next; - free (iter); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - static bool init_runtime_library (struct context *ctx) { - bool ok = true; - struct { const char *name; ///< Name of the function const char *definition; ///< The defining script @@ -1105,6 +1080,7 @@ init_runtime_library (struct context *ctx) { { "unless", "arg cond body; if (not (eval @cond)) @body" }, }; + bool ok = true; for (size_t i = 0; i < N_ELEMENTS (functions); i++) { struct parser parser; parser_init (&parser, @@ -1123,7 +1099,17 @@ init_runtime_library (struct context *ctx) { item_free_list (body); parser_free (&parser); } - return ok; + + return ok + && native_register (ctx, "set", fn_set) + && native_register (ctx, "list", fn_list) + && native_register (ctx, "if", fn_if) + && native_register (ctx, "for", fn_for) + && native_register (ctx, "break", fn_break) + && native_register (ctx, "map", fn_map) + && native_register (ctx, "filter", fn_filter) + && native_register (ctx, "print", fn_print) + && native_register (ctx, "..", fn_concatenate); } // --- Main -------------------------------------------------------------------- @@ -1161,8 +1147,7 @@ main (int argc, char *argv[]) { struct context ctx; context_init (&ctx); - if (!init_native_library () - || !init_runtime_library (&ctx)) + if (!init_runtime_library (&ctx)) printf ("%s\n", "runtime library initialization failed"); struct item *result = NULL; @@ -1176,8 +1161,6 @@ main (int argc, char *argv[]) { if (failure) printf ("%s: %s\n", "runtime error", failure); context_free (&ctx); - - free_native_library (); return 0; }