lmtlibrary.c /size: 2892 b    last modification: 2025-02-21 11:03
1/*
2    See license.txt in the root of this project.
3*/
4
5/*tex
6
7    There is not much here. We only implement a mechanism for storing optional libraries. The
8    engine is self contained and doesn't depend on large and complex libraries. One can (try to)
9    load libraries at runtime. The optional ones that come with the engine end up in the
10    |optional| namespace.
11
12*/
13# include "luametatex.h"
14
15void lmt_library_initialize(lua_State *L)
16{
17    lua_getglobal(L,"optional");
18    if (! lua_istable(L, -1)) {
19        lua_pop(L, 1);
20        lua_newtable(L);
21        lua_setglobal(L, "optional");
22    } else {
23        lua_pop(L, 1);
24    }
25}
26
27void lmt_library_register(lua_State *L, const char *name, luaL_Reg functions[])
28{
29    lmt_library_initialize(L);
30    lua_getglobal(L, "optional");
31    lua_pushstring(L, name);
32    lua_newtable(L);
33    luaL_setfuncs(L, functions, 0);
34    lua_rawset(L, -3);
35    lua_pop(L, 1);
36}
37
38lmt_library lmt_library_load(const char *filename)
39{
40    lmt_library lib = { .lib = NULL };
41    if (filename && strlen(filename)) {
42        lib.lib = lmt_library_open_indeed(filename);
43        lib.okay = lib.lib != NULL;
44        if (! lib.okay) {
45            tex_formatted_error("lmt library", "unable to load '%s', error %i, quitting\n", filename, lmt_library_last_error());
46        }
47    }
48    return lib;
49}
50
51lmt_library_function lmt_library_find(lmt_library lib, const char *source)
52{
53    if (lib.lib && lib.okay) {
54        lmt_library_function target = lmt_library_find_indeed(lib.lib, source);
55        if (target) {
56            return target;
57        } else {
58            lib.okay = 0;
59            tex_formatted_error("lmt library", "unable to locate '%s', quitting\n", source);
60        }
61    }
62    return NULL;
63}
64
65int lmt_library_okay(lmt_library lib)
66{
67    return lib.lib && lib.okay;
68};
69
70/* experiment */
71
72static int librarylib_load(lua_State *L)
73{
74    /* So we permit it in mtxrun (for now, when we test). */
75    if (lmt_engine_state.lua_only || lmt_engine_state.permit_loadlib) {
76        const char *filename = lua_tostring(L, 1);
77        const char *openname = lua_tostring(L, 2);
78        if (filename && openname) {
79            lmt_library lib = lmt_library_load(filename);
80            if (lmt_library_okay(lib)) {
81                lua_CFunction target = lmt_library_find_indeed(lib.lib, openname);
82                if (target) {
83                    lua_pushcfunction(L, target);
84                    lua_pushstring(L, filename);
85                    return 2;
86                }
87            }
88        }
89    } else {
90        tex_formatted_error("lmt library", "loading is not permitted, quitting\n");
91    }
92    return 0;
93};
94
95static struct luaL_Reg librarylib_function_list[] = {
96    { "load", librarylib_load },
97    { NULL,   NULL            },
98};
99
100int luaopen_library(lua_State * L)
101{
102    lmt_library_register(L, "library", librarylib_function_list);
103    return 0;
104}
105