lmtlualib.c /size: 21 Kb    last modification: 2025-02-21 11:03
1/*
2    See license.txt in the root of this project.
3*/
4
5# include "luametatex.h"
6
7/*tex
8
9    Some code here originates from the beginning of \LUATEX\ development, like the bytecode
10    registers. They provide a way to store (compiled) \LUA\ code in the format file. In the
11    meantime there are plenty of ways to use \LUA\ code in the frontend so an interface at the
12    \TEX\ end makes no longer much sense.
13
14    This module also provides some statistics and control options. Keep in mind that the engine
15    also can act as a \LUA\ engine, so some of that property is reflected in the code.
16
17*/
18
19# define LOAD_BUF_SIZE 64*1024
20# define UINT_MAX32    0xFFFFFFFF
21
22# define LUA_FUNCTIONS          "lua.functions"
23# define LUA_BYTECODES          "lua.bytecodes"
24# define LUA_BYTECODES_INDIRECT "lua.bytecodes.indirect"
25
26typedef struct bytecode {
27    unsigned char *buf;
28    int            size;
29    int            alloc;
30} bytecode;
31
32static bytecode *lmt_bytecode_registers = NULL;
33
34void lmt_dump_registers(dumpstream f)
35{
36    dump_int(f, lmt_lua_state.version_number);
37    dump_int(f, lmt_lua_state.release_number);
38    dump_int(f, lmt_lua_state.integer_size);
39    dump_int(f, lmt_lua_state.bytecode_max);
40    if (lmt_bytecode_registers) {
41        int n = 0;
42        for (int k = 0; k <= lmt_lua_state.bytecode_max; k++) {
43            if (lmt_bytecode_registers[k].size != 0) {
44                n++;
45            }
46        }
47        dump_int(f, n);
48        for (int k = 0; k <= lmt_lua_state.bytecode_max; k++) {
49            bytecode b = lmt_bytecode_registers[k];
50            if (b.size != 0) {
51                dump_int(f, k);
52                dump_int(f, b.size);
53                dump_items(f, (char *) b.buf, 1, b.size);
54            }
55        }
56    }
57}
58
59void lmt_undump_registers(dumpstream f)
60{
61    int version_number = 0;
62    int release_number = 0;
63    int integer_size = 0;
64    undump_int(f, version_number);
65    if (version_number != lmt_lua_state.version_number) {
66        tex_fatal_undump_error("mismatching Lua version number");
67    }
68    undump_int(f, release_number);
69    if (release_number != lmt_lua_state.release_number) {
70        tex_fatal_undump_error("mismatching Lua release number");
71    }
72    undump_int(f, integer_size);
73    if (integer_size != lmt_lua_state.integer_size) {
74        tex_fatal_undump_error("different integer size");
75    }
76    undump_int(f, lmt_lua_state.bytecode_max);
77    if (lmt_lua_state.bytecode_max < 0) {
78        tex_fatal_undump_error("not enough memory for undumping bytecodes"); /* old */
79    } else {
80        size_t s = (lmt_lua_state.bytecode_max + 1) * sizeof(bytecode);
81        int n = (int) s;
82        lmt_bytecode_registers = (bytecode *) lmt_memory_malloc(s);
83        if (lmt_bytecode_registers) {
84            lmt_lua_state.bytecode_bytes = n;
85            for (int j = 0; j <= lmt_lua_state.bytecode_max; j++) {
86                lmt_bytecode_registers[j].buf = NULL;
87                lmt_bytecode_registers[j].size = 0;
88                lmt_bytecode_registers[j].alloc = 0;
89            }
90            undump_int(f, n);
91            for (int j = 0; j < n; j++) {
92                unsigned char *buffer;
93                int slot, size;
94                undump_int(f, slot);
95                undump_int(f, size);
96                buffer = (unsigned char *) lmt_memory_malloc((unsigned) size);
97                if (buffer) {
98                    memset(buffer, 0, (size_t) size);
99                    undump_items(f, buffer, 1, size);
100                    lmt_bytecode_registers[slot].buf = buffer;
101                    lmt_bytecode_registers[slot].size = size;
102                    lmt_bytecode_registers[slot].alloc = size;
103                    lmt_lua_state.bytecode_bytes += size;
104                } else {
105                    tex_fatal_undump_error("not enough memory for undumping bytecodes");
106                }
107            }
108        }
109    }
110}
111
112static void lualib_aux_bytecode_register_shadow_set(lua_State *L, int k)
113{
114    /*tex the stack holds the value to be set */
115    luaL_getmetatable(L, LUA_BYTECODES_INDIRECT);
116    if (lua_istable(L, -1)) {
117        lua_pushvalue(L, -2);
118        lua_rawseti(L, -2, k);
119    }
120    lua_pop(L, 2); /*tex pop table or nil and value */
121}
122
123static int lualib_aux_bytecode_register_shadow_get(lua_State *L, int k)
124{
125    /*tex the stack holds the value to be set */
126    int ret = 0;
127    luaL_getmetatable(L, LUA_BYTECODES_INDIRECT);
128    if (lua_istable(L, -1)) {
129        if (lua_rawgeti(L, -1, k) != LUA_TNIL) {
130            ret = 1;
131        }
132        /*tex store the value or nil, deeper down  */
133        lua_insert(L, -3);
134        /*tex pop the value or nil at top */
135        lua_pop(L, 1);
136    }
137    /*tex pop table or nil */
138    lua_pop(L, 1);
139    return ret;
140}
141
142static int lualib_aux_writer(lua_State *L, const void *b, size_t size, void *B)
143{
144    bytecode *buf = (bytecode *) B;
145    (void) L;
146    if ((int) (buf->size + (int) size) > buf->alloc) {
147        unsigned newalloc = (unsigned) (buf->alloc + (int) size + LOAD_BUF_SIZE);
148        unsigned char *bb = lmt_memory_realloc(buf->buf, newalloc);
149        if (bb) {
150            buf->buf = bb;
151            buf->alloc = newalloc;
152        } else {
153            return luaL_error(L, "something went wrong with handling bytecodes");
154        }
155    }
156    memcpy(buf->buf + buf->size, b, size);
157    buf->size += (int) size;
158    lmt_lua_state.bytecode_bytes += (unsigned) size;
159    return 0;
160}
161
162static const char *lualib_aux_reader(lua_State *L, void *ud, size_t *size)
163{
164    bytecode *buf = (bytecode *) ud;
165    (void) L;
166    *size = (size_t) buf->size;
167    return (const char *) buf->buf;
168}
169
170static int lualib_valid_bytecode(lua_State *L, int slot)
171{
172    if (slot < 0 || slot > lmt_lua_state.bytecode_max) {
173        return luaL_error(L, "bytecode register out of range");
174    } else if (lualib_aux_bytecode_register_shadow_get(L, slot) || ! lmt_bytecode_registers[slot].buf) {
175        return luaL_error(L, "undefined bytecode register");
176    } else if (lua_load(L, lualib_aux_reader, (void *) (lmt_bytecode_registers + slot), "bytecode", NULL)) {
177        return luaL_error(L, "bytecode register doesn't load well");
178    } else {
179        return 1;
180    }
181}
182
183static int lualib_get_bytecode(lua_State *L)
184{
185    int slot = lmt_checkinteger(L, 1);
186    if (lualib_valid_bytecode(L, slot)) {
187        lua_pushvalue(L, -1);
188        lualib_aux_bytecode_register_shadow_set(L, slot);
189        return 1;
190    } else {
191        return 0;
192    }
193}
194
195static int lmt_handle_bytecode_call(lua_State *L, int slot)
196{
197    int stacktop = lua_gettop(L);
198    int error = 1;
199    if (lualib_valid_bytecode(L, slot)) {
200        /*tex function index */
201        lua_pushinteger(L, slot);
202        /*tex push traceback function */
203        lua_pushcfunction(L, lmt_traceback);
204        /*tex put it under chunk  */
205        lua_insert(L, stacktop);
206        ++lmt_lua_state.bytecode_callback_count;
207        error = lua_pcall(L, 1, 0, stacktop);
208        /*tex remove traceback function */
209        lua_remove(L, stacktop);
210        if (error) {
211            lua_gc(L, LUA_GCCOLLECT, 0);
212            lmt_error(L, "bytecode call", slot, (error == LUA_ERRRUN ? 0 : 1));
213        }
214    }
215    lua_settop(L, stacktop);
216    return ! error;
217}
218
219void lmt_bytecode_call(int slot)
220{
221    lmt_handle_bytecode_call(lmt_lua_state.lua_instance, slot);
222}
223
224/*tex
225    We don't report an error so this this permits a loop over the bytecode array.
226*/
227
228static int lualib_call_bytecode(lua_State *L)
229{
230    int k = lmt_checkinteger(L, -1);
231    if (k >= 0 && ! lualib_aux_bytecode_register_shadow_get(L, k)) {
232        if (k <= lmt_lua_state.bytecode_max && lmt_bytecode_registers[k].buf) {
233            lmt_handle_bytecode_call(L, k);
234            /* We can have a function pushed! */
235        } else {
236            k = -1;
237        }
238    } else {
239        k = -1;
240    }
241    lua_pushboolean(L, k != -1);
242    /*tex At most 1. */
243    return 1;
244}
245
246static int lualib_set_bytecode(lua_State *L)
247{
248    int k = lmt_checkinteger(L, 1);
249    int i = k + 1;
250    if ((k < 0) || (k > max_bytecode_index)) {
251        return luaL_error(L, "bytecode register out of range");
252    } else {
253        int ltype = lua_type(L, 2);
254        int strip = lua_toboolean(L, 3);
255        if (ltype != LUA_TFUNCTION && ltype != LUA_TNIL) {
256            return luaL_error(L, "bytecode register should be a function or nil");
257        } else {
258            /*tex Later calls expect the function at the top of the stack. */
259            lua_settop(L, 2);
260            if (k > lmt_lua_state.bytecode_max) {
261                bytecode *r = lmt_memory_realloc(lmt_bytecode_registers, (size_t) i * sizeof(bytecode));
262                if (r) {
263                    lmt_bytecode_registers = r;
264                    lmt_lua_state.bytecode_bytes += ((int) sizeof(bytecode) * (k + 1 - (lmt_lua_state.bytecode_max > 0 ? lmt_lua_state.bytecode_max : 0)));
265                    for (unsigned j = (unsigned) (lmt_lua_state.bytecode_max + 1); j <= (unsigned) k; j++) {
266                        lmt_bytecode_registers[j].buf = NULL;
267                        lmt_bytecode_registers[j].size = 0;
268                        lmt_bytecode_registers[j].alloc = 0;
269                    }
270                    lmt_lua_state.bytecode_max = k;
271                } else {
272                    return luaL_error(L, "bytecode register exceeded memory");
273                }
274            }
275            if (lmt_bytecode_registers[k].buf) {
276                lmt_memory_free(lmt_bytecode_registers[k].buf);
277                lmt_lua_state.bytecode_bytes -= lmt_bytecode_registers[k].size;
278                lmt_bytecode_registers[k].size = 0;
279                lmt_bytecode_registers[k].buf = NULL;
280                lua_pushnil(L);
281                lualib_aux_bytecode_register_shadow_set(L, k);
282            }
283            if (ltype == LUA_TFUNCTION) {
284                lmt_bytecode_registers[k].buf = lmt_memory_calloc(1, LOAD_BUF_SIZE);
285                if (lmt_bytecode_registers[k].buf) {
286                    lmt_bytecode_registers[k].alloc = LOAD_BUF_SIZE;
287                 // memset(lua_bytecode_registers[k].buf, 0, LOAD_BUF_SIZE);
288                    lua_dump(L, lualib_aux_writer, (void *) (lmt_bytecode_registers + k), strip);
289                } else {
290                    return luaL_error(L, "bytecode register exceeded memory");
291                }
292            }
293            lua_pop(L, 1);
294        }
295    }
296    return 0;
297}
298
299void lmt_initialize_functions(int set_size)
300{
301    lua_State *L = lmt_lua_state.lua_instance;
302    if (set_size) {
303        tex_engine_get_config_number("functionsize", &lmt_lua_state.function_table_size);
304        if (lmt_lua_state.function_table_size < 0) {
305            lmt_lua_state.function_table_size = 0;
306        }
307        lua_createtable(L, lmt_lua_state.function_table_size, 0);
308    } else {
309        lua_newtable(L);
310    }
311    lmt_lua_state.function_table_id = luaL_ref(L, LUA_REGISTRYINDEX);
312    /* not needed, so unofficial */
313    lua_pushstring(L, LUA_FUNCTIONS);
314    lua_rawgeti(L, LUA_REGISTRYINDEX, lmt_lua_state.function_table_id);
315    lua_settable(L, LUA_REGISTRYINDEX);
316}
317
318static int lualib_get_functions_table(lua_State *L)
319{
320    if (lua_toboolean(L, lua_gettop(L))) {
321        /*tex Beware: this can have side effects when used without care. */
322        lmt_initialize_functions(1);
323    }
324    lua_rawgeti(L, LUA_REGISTRYINDEX, lmt_lua_state.function_table_id);
325    return 1;
326}
327
328static int lualib_new_table(lua_State *L)
329{
330    int i = lmt_checkinteger(L, 1);
331    int h = lmt_checkinteger(L, 2);
332    lua_createtable(L, i < 0 ? 0 : i, h < 0 ? 0 : h);
333    return 1;
334}
335
336static int lualib_new_index(lua_State *L)
337{
338    int n = lmt_checkinteger(L, 1);
339    int t = lua_gettop(L);
340    lua_createtable(L, n < 0 ? 0 : n, 0);
341    if (t == 2) {
342        for (lua_Integer i = 1; i <= n; i++) {
343            lua_pushvalue(L, 2);
344            lua_rawseti(L, -2, i);
345        }
346    }
347    return 1;
348}
349
350static int lualib_get_stack_top(lua_State *L)
351{
352    lua_pushinteger(L, lua_gettop(L));
353    return 1;
354}
355
356static int lualib_get_runtime(lua_State *L)
357{
358    lua_pushnumber(L, aux_get_run_time());
359    return 1;
360}
361
362static int lualib_get_currenttime(lua_State *L)
363{
364    lua_pushnumber(L, aux_get_current_time());
365    return 1;
366}
367
368static int lualib_set_exitcode(lua_State *L)
369{
370    lmt_error_state.default_exit_code = lmt_checkinteger(L, 1);
371    return 0;
372}
373
374static int lualib_get_exitcode(lua_State *L)
375{
376    lua_pushinteger(L, lmt_error_state.default_exit_code);
377    return 1;
378}
379
380/*tex
381
382    The |getpreciseticks()| call returns a number. This number has no meaning in itself but
383    successive calls can be used to calculate a delta with a previous call. When the number is fed
384    into |getpreciseseconds(n)| a number is returned representing seconds.
385
386*/
387
388# ifdef _WIN32
389
390#   define clock_inittime()
391
392    static int lualib_get_preciseticks(lua_State *L)
393    {
394        LARGE_INTEGER t;
395        QueryPerformanceCounter(&t);
396        lua_pushnumber(L, (double) t.QuadPart);
397        return 1;
398    }
399
400    static int lualib_get_preciseseconds(lua_State *L)
401    {
402        LARGE_INTEGER t;
403        QueryPerformanceFrequency(&t);
404        lua_pushnumber(L, luaL_optnumber(L, 1, 0) / (double) t.QuadPart);
405        return 1;
406    }
407
408# else
409
410#   if (defined(__MACH__) && ! defined(CLOCK_PROCESS_CPUTIME_ID))
411
412        /* https://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x */
413
414#       include <mach/mach_time.h>
415#       define CLOCK_PROCESS_CPUTIME_ID 1
416
417        static double conversion_factor;
418
419        static void clock_inittime()
420        {
421            mach_timebase_info_data_t timebase;
422            mach_timebase_info(&timebase);
423            conversion_factor = (double) timebase.numer / (double) timebase.denom;
424        }
425
426        static int clock_gettime(int clk_id, struct timespec *t)
427        {
428            uint64_t time;
429            double nseconds, seconds;
430            (void) clk_id; /* please the compiler */
431            time = mach_absolute_time();
432            nseconds = ((double) time * conversion_factor);
433            seconds  = ((double) time * conversion_factor / 1e9);
434            t->tv_sec = seconds;
435            t->tv_nsec = nseconds;
436            return 0;
437        }
438
439#   else
440
441#       define clock_inittime()
442
443#   endif
444
445    static int lualib_get_preciseticks(lua_State *L)
446    {
447        struct timespec t;
448        clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&t);
449        lua_pushnumber(L, t.tv_sec*1000000000.0 + t.tv_nsec);
450        return 1;
451    }
452
453    static int lualib_get_preciseseconds(lua_State *L)
454    {
455        lua_pushnumber(L, ((double) luaL_optnumber(L, 1, 0)) / 1000000000.0);
456        return 1;
457    }
458
459# endif
460
461static int lualib_get_startupfile(lua_State *L)
462{
463    lua_pushstring(L, lmt_engine_state.startup_filename);
464    return 1;
465}
466
467static int lualib_get_version(lua_State *L)
468{
469    lua_pushstring(L, LUA_VERSION);
470    return 1;
471}
472
473/* obsolete:
474static int lualib_get_hashchars(lua_State *L)
475{
476    lua_pushinteger(L, 1 << LUAI_HASHLIMIT);
477    return 1;
478}
479*/
480
481/*
482static int lualib_get_doing_the(lua_State *L)
483{
484    lua_pushboolean(L, lua_state.doing_the);
485    return 1;
486}
487*/
488
489/* This makes the (already old and rusty) profiler 2.5 times faster. */
490
491/*
492static lua_State *getthread (lua_State *L, int *arg) 
493{
494    if (lua_isthread(L, 1)) {
495        *arg = 1;
496        return lua_tothread(L, 1);
497    } else {
498       *arg = 0;
499       return L;
500    }
501}
502
503static int lualib_get_debug_info(lua_State *L) 
504{
505    lua_Debug ar;
506    int arg;
507    lua_State *L1 = getthread(L, &arg);
508    if (lua_getstack(L1, 2, &ar) && lua_getinfo(L1, "nS", &ar)) {
509        ....
510    }
511    return 0;
512}
513*/
514
515/*
516static int lualib_get_debug_info(lua_State *L) 
517{
518    if (! lua_isthread(L, 1)) {
519        lua_Debug ar;
520        if (lua_getstack(L, 2, &ar) && lua_getinfo(L, "nS", &ar)) {
521            lua_pushstring(L, ar.short_src);
522            lua_pushinteger(L, ar.linedefined);
523            if (ar.name) {
524                lua_pushstring(L, ar.name);
525            } else if (! strcmp(ar.what, "C")) {
526                lua_pushliteral(L, "<anonymous>");
527            } else if (ar.namewhat) {
528                lua_pushstring(L, ar.namewhat);
529            } else if (ar.what) {
530                lua_pushstring(L, ar.what);
531            } else {
532                lua_pushliteral(L, "<unknown>");
533            }
534            return 3;
535        }
536    }
537    return 0;
538}
539*/
540
541/*tex
542    I can make it faster if needed but then I need to patch the two lua modules (add some simple
543    helpers) which for now doesn't make much sense. This is an undocumented feature.
544*/
545
546static int lualib_get_debug_info(lua_State *L) 
547{
548    if (! lua_isthread(L, 1)) {
549        lua_Debug ar;
550        if (lua_getstack(L, 2, &ar) && lua_getinfo(L, "nS", &ar)) {
551            lua_pushstring(L, ar.name ? ar.name : (ar.namewhat ? ar.namewhat : (ar.what ? ar.what : "<unknown>")));
552            lua_pushstring(L, ar.short_src);
553            lua_pushinteger(L, ar.linedefined);
554            return 3;
555        }
556    }
557    return 0;
558}
559
560/*tex 
561
562    This is just a byproduct of using nibbles for storing math style variant (and presets) so I 
563    decoded to keep it. 
564
565*/
566
567static int lualib_set_nibble(lua_State *L) 
568{
569    unsigned int original = lmt_tounsigned(L, 1);
570    unsigned int position = lmt_tounsigned(L, 2);
571    if (position >= 1 && position <= 8) { 
572        unsigned int nibble = lmt_optunsigned(L, 3, 0);
573        position--;
574        lua_pushinteger(L, (original & ~(0xF << (4 * position))) | ((nibble & 0xF) << (4 * position)));   
575    } else { 
576        lua_pushinteger(L, original);   
577    }
578    return 1;
579}
580
581static int lualib_get_nibble(lua_State *L) 
582{
583    unsigned int position = lmt_tounsigned(L, 2);
584    if (position >= 1 && position <= 8) { 
585        unsigned int original = lmt_tounsigned(L, 1);
586        lua_pushinteger(L, (original >> (4 * --position)) & 0xF);
587    } else {
588        lua_pushinteger(L, 0);
589    }
590    return 1;
591}
592
593static int lualib_add_nibble(lua_State *L) 
594{
595    unsigned int position = lmt_tounsigned(L, 2);
596    unsigned int original = lmt_tounsigned(L, 1);
597    if (position >= 1 && position <= 8) { 
598        unsigned int nibble = ((original >> (4 * --position)) & 0xF);
599        if (nibble < 0xF) {
600            nibble++;
601            lua_pushinteger(L, (original & ~(0xF << (4 * position))) | ((nibble & 0xF) << (4 * position)));   
602            return 1;
603        } 
604    }
605    lua_pushinteger(L, original);   
606    return 1;
607}
608
609static int lualib_sub_nibble(lua_State *L) 
610{
611    unsigned int position = lmt_tounsigned(L, 2);
612    unsigned int original = lmt_tounsigned(L, 1);
613    if ((position >= 1) && (position <= 7)) { 
614        unsigned int nibble = ((original >> (4 * --position)) & 0xF);
615        if (nibble > 0) {
616            nibble--;
617            lua_pushinteger(L, (original & ~(0xF << (4 * position))) | ((nibble & 0xF) << (4 * position)));   
618            return 1;
619        } 
620    }
621    lua_pushinteger(L, original);   
622    return 1;
623}
624
625/* */
626
627static const struct luaL_Reg lualib_function_list[] = {
628    /* lua */
629    { "getstacktop",         lualib_get_stack_top       },
630 /* { "gethashchars",        lualib_get_hashchars       }, */
631    { "getdebuginfo",        lualib_get_debug_info      },
632    { "setexitcode",         lualib_set_exitcode        },
633    { "getexitcode",         lualib_get_exitcode        },
634    /* helpers */
635    { "getruntime",          lualib_get_runtime         },
636    { "getcurrenttime",      lualib_get_currenttime     },
637    { "getpreciseticks",     lualib_get_preciseticks    },
638    { "getpreciseseconds",   lualib_get_preciseseconds  },
639    /* engine */
640    { "getstartupfile",      lualib_get_startupfile     },
641    { "getversion",          lualib_get_version         },
642    /* bytecode */
643    { "getbytecode",         lualib_get_bytecode        },
644    { "setbytecode",         lualib_set_bytecode        },
645    { "callbytecode",        lualib_call_bytecode       },
646    { "getfunctionstable",   lualib_get_functions_table },
647 /* { "doingthe",            lualib_get_doing_the       }, */
648    /* table */
649    { "newtable",            lualib_new_table           },
650    { "newindex",            lualib_new_index           },
651    /* number */
652    { "setnibble",           lualib_set_nibble          },
653    { "getnibble",           lualib_get_nibble          },
654    { "addnibble",           lualib_add_nibble          },
655    { "subnibble",           lualib_sub_nibble          },
656    /* */
657    { NULL,                  NULL                       },
658};
659
660static const struct luaL_Reg lualib_function_list_only[] = {
661    /* lua */
662    { "getstacktop",         lualib_get_stack_top      },
663 /* { "gethashchars",        lualib_get_hashchars      }, */
664    { "setexitcode",         lualib_set_exitcode       },
665    { "getexitcode",         lualib_get_exitcode       },
666    /* helpers */
667    { "getruntime",          lualib_get_runtime        },
668    { "getcurrenttime",      lualib_get_currenttime    },
669    { "getpreciseticks",     lualib_get_preciseticks   },
670    { "getpreciseseconds",   lualib_get_preciseseconds },
671    /* engine */
672    { "getstartupfile",      lualib_get_startupfile    },
673    { "getversion",          lualib_get_version        },
674    /* table */
675    { "newtable",            lualib_new_table          },
676    { "newindex",            lualib_new_index          },
677    /* number */
678    { "setnibble",           lualib_set_nibble         },
679    { "getnibble",           lualib_get_nibble         },
680    { "addnibble",           lualib_add_nibble         },
681    { "subnibble",           lualib_sub_nibble         },
682    /* */
683    { NULL,                  NULL                      },
684};
685
686static int lualib_index_bytecode(lua_State *L)
687{
688    lua_remove(L, 1);
689    return lualib_get_bytecode(L);
690}
691
692static int lualib_newindex_bytecode(lua_State *L)
693{
694    lua_remove(L, 1);
695    return lualib_set_bytecode(L);
696}
697
698int luaopen_lua(lua_State *L)
699{
700    lua_newtable(L);
701    if (lmt_engine_state.lua_only) {
702        luaL_setfuncs(L, lualib_function_list_only, 0);
703    } else {
704        luaL_setfuncs(L, lualib_function_list, 0);
705        lmt_make_table(L, "bytecode", LUA_BYTECODES, lualib_index_bytecode, lualib_newindex_bytecode);
706        lua_newtable(L);
707        lua_setfield(L, LUA_REGISTRYINDEX, LUA_BYTECODES_INDIRECT);
708    }
709    lua_pushstring(L, LUA_VERSION);
710    lua_setfield(L, -2, "version");
711    if (lmt_engine_state.startup_filename) {
712        lua_pushstring(L, lmt_engine_state.startup_filename);
713        lua_setfield(L, -2, "startupfile");
714    }
715    clock_inittime();
716    return 1;
717}
718