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