1% luastuff.w
2%
3% Copyright 2006-2013 Taco Hoekwater <taco@@luatex.org>
4%
5% This file is part of LuaTeX.
6%
7% LuaTeX is free software; you can redistribute it and/or modify it under
8% the terms of the GNU General Public License as published by the Free
9% Software Foundation; either version 2 of the License, or (at your
10% option) any later version.
11%
12% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
13% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14% FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15% License for more details.
16%
17% You should have received a copy of the GNU General Public License along
18% with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
19
20@ @c
21
22
23#include "ptexlib.h"
24#include "lua/luatex-api.h"
25#include "lua/lauxlib_bridge.h"
26
27@ @c
28lua_State *Luas = NULL;
29
30int luastate_bytes = 0;
31
32int lua_active = 0;
33
34@ @c
35void make_table(lua_State * L, const char *tab, const char *mttab, const char *getfunc,
36                const char *setfunc)
37{
38    /* make the table *//* |[{<tex>}]| */
39    lua_pushstring(L, tab);     /* |[{<tex>},"dimen"]| */
40    lua_newtable(L);            /* |[{<tex>},"dimen",{}]| */
41    lua_settable(L, -3);        /* |[{<tex>}]| */
42    /* fetch it back */
43    lua_pushstring(L, tab);     /* |[{<tex>},"dimen"]| */
44    lua_gettable(L, -2);        /* |[{<tex>},{<dimen>}]| */
45    /* make the meta entries */
46    luaL_newmetatable(L, mttab);  /* |[{<tex>},{<dimen>},{<dimen_m>}]| */
47    lua_pushstring(L, "__index");       /* |[{<tex>},{<dimen>},{<dimen_m>},"__index"]| */
48    lua_pushstring(L, getfunc); /* |[{<tex>},{<dimen>},{<dimen_m>},"__index","getdimen"]| */
49    lua_gettable(L, -5);        /* |[{<tex>},{<dimen>},{<dimen_m>},"__index",<tex.getdimen>]| */
50    lua_settable(L, -3);        /* |[{<tex>},{<dimen>},{<dimen_m>}]|  */
51    lua_pushstring(L, "__newindex");    /* |[{<tex>},{<dimen>},{<dimen_m>},"__newindex"]| */
52    lua_pushstring(L, setfunc); /* |[{<tex>},{<dimen>},{<dimen_m>},"__newindex","setdimen"]| */
53    lua_gettable(L, -5);        /* |[{<tex>},{<dimen>},{<dimen_m>},"__newindex",<tex.setdimen>]| */
54    lua_settable(L, -3);        /* |[{<tex>},{<dimen>},{<dimen_m>}]| */
55    lua_setmetatable(L, -2);    /* |[{<tex>},{<dimen>}]| : assign the metatable */
56    lua_pop(L, 1);              /* |[{<tex>}]| : clean the stack */
57}
58
59@ @c
60static
61const char *getS(lua_State * L, void *ud, size_t * size)
62{
63    LoadS *ls = (LoadS *) ud;
64    (void) L;
65    if (ls->size == 0)
66        return NULL;
67    *size = ls->size;
68    ls->size = 0;
69    return ls->s;
70}
71
72@ @c
73#if 0 /* currently unused */
74static void *my_luaalloc(void *ud, void *ptr, size_t osize, size_t nsize)
75{
76    void *ret = NULL;
77    (void) ud;                  /* for -Wunused */
78    if (nsize == 0)
79        free(ptr);
80    else
81        ret = realloc(ptr, nsize);
82    luastate_bytes += (int) (nsize - osize);
83    return ret;
84}
85#endif
86
87@ @c
88static int my_luapanic(lua_State * L)
89{
90    (void) L;                   /* to avoid warnings */
91    fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n",
92            lua_tostring(L, -1));
93    return 0;
94}
95
96@ @c
97void luafunctioncall(int slot)
98{
99    int i ;
100    int stacktop = lua_gettop(Luas);
101    lua_active++;
102    lua_rawgeti(Luas, LUA_REGISTRYINDEX, lua_key_index(lua_functions));
103    lua_gettable(Luas, LUA_REGISTRYINDEX);
104    lua_rawgeti(Luas, -1,slot);
105    if (lua_isfunction(Luas,-1)) {
106        int base = lua_gettop(Luas); /* function index */
107        lua_pushnumber(Luas, slot);
108        lua_pushcfunction(Luas, lua_traceback); /* push traceback function */
109        lua_insert(Luas, base); /* put it under chunk  */
110        i = lua_pcall(Luas, 1, 0, base);
111        lua_remove(Luas, base); /* remove traceback function */
112        if (i != 0) {
113            lua_gc(Luas, LUA_GCCOLLECT, 0);
114            Luas = luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1));
115        }
116    }
117    lua_settop(Luas,stacktop);
118    lua_active--;
119}
120
121
122
123
124@ @c
125static const luaL_Reg lualibs[] = {
126    {"", luaopen_base},
127    {"package", luaopen_package},
128    /*{"coroutine", luaopen_coroutine},*/
129    {"table", luaopen_table},
130    {"io", open_iolibext},
131    {"os", luaopen_os},
132    {"string", luaopen_string},
133    {"math", luaopen_math},
134    {"debug", luaopen_debug},
135    {"unicode", luaopen_unicode},
136    {"zip", luaopen_zip},
137    {"bit32", luaopen_bit32},
138    {"md5", luaopen_md5},
139    {"lfs", luaopen_lfs},
140    {"profiler", luaopen_profiler},
141    {"jit", luaopen_jit},
142    {"ffi", luaopen_ffi},
143    {"bit",	luaopen_bit },
144    {NULL, NULL}
145};
146static const luaL_Reg lualibs_nofenv[] = {
147    {"lpeg", luaopen_lpeg},
148    {NULL, NULL}
149};
150
151
152@ @c
153static void do_openlibs(lua_State * L)
154{
155    const luaL_Reg *lib = lualibs;
156    for (; lib->func; lib++) {
157        lua_pushcfunction(L, lib->func);
158        lua_pushstring(L, lib->name);
159        lua_call(L, 1, 0);
160    }
161    lib = lualibs_nofenv;
162    for (; lib->func; lib++) {
163        lua_pushcfunction(L, lib->func);
164        lua_newtable(L);
165        lua_setfenv(L,-2);
166        lua_pushstring(L, lib->name);
167        lua_call(L, 1, 0);
168    }
169}
170
171@ @c
172static int load_aux (lua_State *L, int status) {
173  if (status == 0)  /* OK? */
174    return 1;
175  else {
176    lua_pushnil(L);
177    lua_insert(L, -2);  /* put before error message */
178    return 2;  /* return nil plus error message */
179  }
180}
181
182@ @c
183static int luatex_loadfile (lua_State *L) {
184  int status = 0;
185  const char *fname = luaL_optstring(L, 1, NULL);
186  const char *mode = luaL_optstring(L, 2, NULL);
187  int env = !lua_isnone(L, 3);  /* 'env' parameter? */
188  if (!lua_only && !fname && interaction == batch_mode) {
189     lua_pushnil(L);
190     lua_pushstring(L, "reading from stdin is disabled in batch mode");
191     return 2;  /* return nil plus error message */
192  }
193  status = luaL_loadfilex(L, fname, mode);
194  if (status == LUA_OK) {
195    recorder_record_input(fname);
196    if (env) {  /* 'env' parameter? */
197      lua_pushvalue(L, 3);
198      lua_setupvalue(L, -2, 1);  /* set it as 1st upvalue of loaded chunk */
199    }
200  }
201  return load_aux(L, status);
202}
203
204@ @c
205static int luatex_dofile (lua_State *L) {
206  const char *fname = luaL_optstring(L, 1, NULL);
207  int n = lua_gettop(L);
208  if (!lua_only && !fname) {
209      if (interaction == batch_mode) {
210	  lua_pushnil(L);
211	  lua_pushstring(L, "reading from stdin is disabled in batch mode");
212	  return 2;  /* return nil plus error message */
213      } else {
214	  tprint_nl("lua> ");
215      }
216  }
217  if (luaL_loadfile(L, fname) != 0) lua_error(L);
218  recorder_record_input(fname);
219  lua_call(L, 0, LUA_MULTRET);
220  return lua_gettop(L) - n;
221}
222
223
224@ @c
225void luainterpreter(void)
226{
227    lua_State *L;
228
229    if (jithash_hashname==NULL){
230	/* default lua51 */
231	luajittex_choose_hash_function = 0;
232        jithash_hashname = (char *) xmalloc(strlen("lua51")+1);
233        jithash_hashname = strcpy ( jithash_hashname, "lua51");
234    } else {
235      if (strcmp((const char*)jithash_hashname,"lua51")==0){
236	luajittex_choose_hash_function = 0;
237      }else if (strcmp((const char*)jithash_hashname,"luajit20")==0){
238	luajittex_choose_hash_function = 1;
239      } else {
240	/* default lua51 */
241	luajittex_choose_hash_function = 0;
242	jithash_hashname = strcpy ( jithash_hashname, "lua51");
243      }
244    }
245
246
247    L = luaL_newstate() ;
248    /*L = lua_newstate(my_luaalloc, NULL);*/
249    if (L == NULL) {
250        fprintf(stderr, "Can't create the Lua state.\n");
251        return;
252    }
253    lua_atpanic(L, &my_luapanic);
254
255    do_openlibs(L);             /* does all the 'simple' libraries */
256
257    if (luajiton){
258     luaJIT_setmode(L, 0, LUAJIT_MODE_ENGINE|LUAJIT_MODE_ON);
259    }
260    else {
261       luaJIT_setmode(L, 0, LUAJIT_MODE_ENGINE|LUAJIT_MODE_OFF);
262    }
263
264
265    lua_pushcfunction(L,luatex_dofile);
266    lua_setglobal(L, "dofile");
267    lua_pushcfunction(L,luatex_loadfile);
268    lua_setglobal(L, "loadfile");
269
270    luatex_md5_lua_open(L);
271
272    open_oslibext(L, safer_option);
273/*
274    open_iolibext(L);
275*/
276    open_strlibext(L);
277    open_lfslibext(L);
278
279    /* luasockets */
280    /* socket and mime are a bit tricky to open because
281     they use a load-time  dependency that has to be
282     worked around for luatex, where the C module is
283     loaded way before the lua module.
284     */
285    if (!nosocket_option) {
286        lua_getglobal(L, "package");
287        lua_getfield(L, -1, "loaded");
288        if (!lua_istable(L, -1)) {
289            lua_newtable(L);
290            lua_setfield(L, -2, "loaded");
291            lua_getfield(L, -1, "loaded");
292        }
293        luaopen_socket_core(L);
294        lua_setfield(L, -2, "socket.core");
295        lua_pushnil(L);
296        lua_setfield(L, -2, "socket");  /* package.loaded.socket = nil */
297
298        luaopen_mime_core(L);
299        lua_setfield(L, -2, "mime.core");
300        lua_pushnil(L);
301        lua_setfield(L, -2, "mime");    /* package.loaded.mime = nil */
302        lua_pop(L, 2);          /* pop the tables */
303
304        luatex_socketlua_open(L);       /* preload the pure lua modules */
305    }
306    /* zlib. slightly odd calling convention */
307    luaopen_zlib(L);
308    lua_setglobal(L, "zlib");
309    luaopen_gzip(L);
310
311    /* our own libraries */
312    luaopen_ff(L);
313    luaopen_tex(L);
314    luaopen_newtoken(L);
315    luaopen_token(L);
316    luaopen_node(L);
317    luaopen_texio(L);
318    luaopen_kpse(L);
319    luaopen_callback(L);
320    luaopen_lua(L, startup_filename);
321    luaopen_stats(L);
322    luaopen_font(L);
323    luaopen_lang(L);
324    luaopen_mplib(L);
325    luaopen_vf(L);
326
327    /* |luaopen_pdf(L);| */
328    /* environment table at |LUA_ENVIRONINDEX| needs to load this way: */
329    lua_pushcfunction(L, luaopen_pdf);
330    lua_pushstring(L, "pdf");
331    lua_call(L, 1, 0);
332
333    /* |luaopen_img(L);| */
334    lua_pushcfunction(L, luaopen_img);
335    lua_pushstring(L, "img");
336    lua_call(L, 1, 0);
337
338    /* |luaopen_epdf(L);| */
339    lua_pushcfunction(L, luaopen_epdf);
340    lua_pushstring(L, "epdf");
341    lua_call(L, 1, 0);
342
343    /* |luaopen_pdfscanner(L);| */
344    lua_pushcfunction(L, luaopen_pdfscanner);
345    lua_pushstring(L, "pdfscanner");
346    lua_call(L, 1, 0);
347
348    lua_createtable(L, 0, 0);
349    lua_setglobal(L, "texconfig");
350
351    if (safer_option) {
352        /* disable some stuff if --safer */
353        (void) hide_lua_value(L, "os", "execute");
354        (void) hide_lua_value(L, "os", "rename");
355        (void) hide_lua_value(L, "os", "remove");
356        (void) hide_lua_value(L, "io", "popen");
357        /* make io.open only read files */
358        luaL_checkstack(L, 2, "out of stack space");
359        lua_getglobal(L, "io");
360        lua_getfield(L, -1, "open_ro");
361        lua_setfield(L, -2, "open");
362        (void) hide_lua_value(L, "io", "tmpfile");
363        (void) hide_lua_value(L, "io", "output");
364        (void) hide_lua_value(L, "lfs", "chdir");
365        (void) hide_lua_value(L, "lfs", "lock");
366        (void) hide_lua_value(L, "lfs", "touch");
367        (void) hide_lua_value(L, "lfs", "rmdir");
368        (void) hide_lua_value(L, "lfs", "mkdir");
369    }
370    /* fprintf(stdout, "\nLuajitTeX default hash function type:%s\n", */
371    /* 		                                jithash_hashname); */
372    Luas = L;
373}
374
375@ @c
376int hide_lua_table(lua_State * L, const char *name)
377{
378    int r = 0;
379    lua_getglobal(L, name);
380    if (lua_istable(L, -1)) {
381        r = luaL_ref(L, LUA_REGISTRYINDEX);
382        lua_pushnil(L);
383        lua_setglobal(L, name);
384    }
385    return r;
386}
387
388@ @c
389void unhide_lua_table(lua_State * L, const char *name, int r)
390{
391    lua_rawgeti(L, LUA_REGISTRYINDEX, r);
392    lua_setglobal(L, name);
393    luaL_unref(L, LUA_REGISTRYINDEX, r);
394}
395
396@ @c
397int hide_lua_value(lua_State * L, const char *name, const char *item)
398{
399    int r = 0;
400    lua_getglobal(L, name);
401    if (lua_istable(L, -1)) {
402        lua_getfield(L, -1, item);
403        r = luaL_ref(L, LUA_REGISTRYINDEX);
404        lua_pushnil(L);
405        lua_setfield(L, -2, item);
406    }
407    return r;
408}
409
410@ @c
411void unhide_lua_value(lua_State * L, const char *name, const char *item, int r)
412{
413    lua_getglobal(L, name);
414    if (lua_istable(L, -1)) {
415        lua_rawgeti(L, LUA_REGISTRYINDEX, r);
416        lua_setfield(L, -2, item);
417        luaL_unref(L, LUA_REGISTRYINDEX, r);
418    }
419}
420
421
422@ @c
423int lua_traceback(lua_State * L)
424{
425    lua_getglobal(L, "debug");
426    if (!lua_istable(L, -1)) {
427        lua_pop(L, 1);
428        return 1;
429    }
430    lua_getfield(L, -1, "traceback");
431    if (!lua_isfunction(L, -1)) {
432        lua_pop(L, 2);
433        return 1;
434    }
435    lua_pushvalue(L, 1);        /* pass error message */
436    lua_pushinteger(L, 2);      /* skip this function and traceback */
437    lua_call(L, 2, 1);          /* call debug.traceback */
438    return 1;
439}
440
441@ @c
442static void luacall(int p, int nameptr, boolean is_string) /* hh-ls: optimized lua_id resolving */
443{
444    LoadS ls;
445    int i;
446    size_t ll = 0;
447    char *lua_id;
448    char *s = NULL;
449
450    if (Luas == NULL) {
451        luainterpreter();
452    }
453    lua_active++;
454    if (is_string) {
455        const char *ss = NULL;
456        lua_rawgeti(Luas, LUA_REGISTRYINDEX, p);
457        if (lua_isfunction(Luas,-1)) {
458            int base = lua_gettop(Luas);        /* function index */
459            lua_checkstack(Luas, 1);
460            lua_pushcfunction(Luas, lua_traceback);     /* push traceback function */
461            lua_insert(Luas, base);     /* put it under chunk  */
462            i = lua_pcall(Luas, 0, 0, base);
463            lua_remove(Luas, base);     /* remove traceback function */
464            if (i != 0) {
465                lua_gc(Luas, LUA_GCCOLLECT, 0);
466                Luas = luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1));
467            }
468            lua_active--;
469            return ;
470        }
471        ss = lua_tolstring(Luas, -1, &ll);
472        s = xmalloc(ll+1);
473        memcpy(s,ss,ll+1);
474        lua_pop(Luas,1);
475    } else {
476        int l = 0;
477        s = tokenlist_to_cstring(p, 1, &l);
478        ll = (size_t)l;
479    }
480    ls.s = s;
481    ls.size = ll;
482    if (ls.size > 0) {
483        if (nameptr > 0) {
484            int l = 0; /* not used */
485            lua_id = tokenlist_to_cstring(nameptr, 1, &l);
486            i = lua_load(Luas, getS, &ls, lua_id);
487	    xfree(lua_id);
488        } else if (nameptr < 0) {
489            lua_id = get_lua_name((nameptr + 65536));
490            if (lua_id != NULL) {
491                i = lua_load(Luas, getS, &ls, lua_id);
492            } else {
493                i = lua_load(Luas, getS, &ls, "=[\\latelua]");
494            }
495        } else {
496            i = lua_load(Luas, getS, &ls, "=[\\latelua]");
497        }
498        if (i != 0) {
499            Luas = luatex_error(Luas, (i == LUA_ERRSYNTAX ? 0 : 1));
500        } else {
501            int base = lua_gettop(Luas);        /* function index */
502            lua_checkstack(Luas, 1);
503            lua_pushcfunction(Luas, lua_traceback);     /* push traceback function */
504            lua_insert(Luas, base);     /* put it under chunk  */
505            i = lua_pcall(Luas, 0, 0, base);
506            lua_remove(Luas, base);     /* remove traceback function */
507            if (i != 0) {
508                lua_gc(Luas, LUA_GCCOLLECT, 0);
509                Luas = luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1));
510            }
511        }
512        xfree(ls.s);
513    }
514    lua_active--;
515}
516
517
518@ @c
519void late_lua(PDF pdf, halfword p)
520{
521    (void) pdf;
522    if (late_lua_type(p)==normal) {
523        expand_macros_in_tokenlist(p);      /* sets |def_ref| */
524        luacall(def_ref, late_lua_name(p), false);
525        flush_list(def_ref);
526    } else {
527        luacall(late_lua_data(p), late_lua_name(p), true);
528    }
529}
530
531@ @c
532void luatokencall(int p, int nameptr) /* hh-ls: optimized lua_id resolving */
533{
534    LoadS ls;
535    int i, l;
536    char *s = NULL;
537    char *lua_id;
538    assert(Luas);
539    l = 0;
540    lua_active++;
541    s = tokenlist_to_cstring(p, 1, &l);
542    ls.s = s;
543    ls.size = (size_t) l;
544    if (ls.size > 0) {
545        if (nameptr > 0) {
546            lua_id = tokenlist_to_cstring(nameptr, 1, &l);
547            i = lua_load(Luas, getS, &ls, lua_id);
548	    xfree(lua_id);
549        } else if (nameptr < 0) {
550            lua_id = get_lua_name((nameptr + 65536));
551            if (lua_id != NULL) {
552                i = lua_load(Luas, getS, &ls, lua_id);
553            } else {
554                i = lua_load(Luas, getS, &ls, "=[\\directlua]");
555            }
556        } else {
557            i = lua_load(Luas, getS, &ls, "=[\\directlua]");
558        }
559        xfree(s);
560        if (i != 0) {
561            Luas = luatex_error(Luas, (i == LUA_ERRSYNTAX ? 0 : 1));
562        } else {
563            int base = lua_gettop(Luas);        /* function index */
564            lua_checkstack(Luas, 1);
565            lua_pushcfunction(Luas, lua_traceback);     /* push traceback function */
566            lua_insert(Luas, base);     /* put it under chunk  */
567            i = lua_pcall(Luas, 0, 0, base);
568            lua_remove(Luas, base);     /* remove traceback function */
569            if (i != 0) {
570                lua_gc(Luas, LUA_GCCOLLECT, 0);
571                Luas = luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1));
572            }
573        }
574    }
575    lua_active--;
576}
577
578@ @c
579lua_State *luatex_error(lua_State * L, int is_fatal)
580{
581
582    const_lstring luaerr;
583    char *err = NULL;
584    if (lua_isstring(L, -1)) {
585        luaerr.s = lua_tolstring(L, -1, &luaerr.l);
586        err = (char *) xmalloc((unsigned) (luaerr.l + 1));
587        snprintf(err, (luaerr.l + 1), "%s", luaerr.s);
588	last_lua_error = err;
589    }
590    if (is_fatal > 0) {
591        /* Normally a memory error from lua.
592           The pool may overflow during the |maketexlstring()|, but we
593           are crashing anyway so we may as well abort on the pool size */
594        lua_fatal_error(err);
595        /* never reached */
596        xfree(err);
597        lua_close(L);
598        return (lua_State *) NULL;
599    } else {
600        lua_norm_error(err);
601	/* last_lua_error = err so no need to xfree(err) */
602        return L;
603    }
604}
605
606@ @c
607void preset_environment(lua_State * L, const parm_struct * p, const char *s)
608{
609    int i;
610    assert(L != NULL);
611    /* double call with same s gives assert(0) */
612    lua_pushstring(L, s);       /* s */
613    lua_gettable(L, LUA_REGISTRYINDEX); /* t */
614    assert(lua_isnil(L, -1));
615    lua_pop(L, 1);              /* - */
616    lua_pushstring(L, s);       /* s */
617    lua_newtable(L);            /* t s */
618    for (i = 1, ++p; p->name != NULL; i++, p++) {
619        assert(i == p->idx);
620        lua_pushstring(L, p->name);     /* k t s */
621        lua_pushinteger(L, p->idx);     /* v k t s */
622        lua_settable(L, -3);    /* t s */
623    }
624    lua_settable(L, LUA_REGISTRYINDEX); /* - */
625}
626
627
628@ @c
629/*
630int luaL_typerror (void *LL, int narg, const char *tname)
631{
632  lua_State *L = (lua_State *)LL;
633  const char *msg = lua_pushfstring(L, "%s expected, got %s",
634                                    tname, luaL_typename(L, narg));
635  return luaL_argerror(L, narg, msg);
636}
637*/
638
639
640/*
641
642
643Compatibility layer for luatex lua5.2
644
645*/
646
647
648
649@ @c
650LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) {
651  void *p = lua_touserdata(L, ud);
652  if (p != NULL) {  /* value is a userdata? */
653    if (lua_getmetatable(L, ud)) {  /* does it have a metatable? */
654      luaL_getmetatable(L, tname);  /* get correct metatable */
655      if (!lua_rawequal(L, -1, -2))  /* not the same? */
656        p = NULL;  /* value is a userdata with wrong metatable */
657      lua_pop(L, 2);  /* remove both metatables */
658      return p;
659    }
660  }
661  return NULL;  /* value is not a userdata with a metatable */
662}
663
664@ @c
665/* It's not ok. See lua-users.org/wiki/CompatibilityWithLuaFive for another solution */
666LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
667  /*luaL_checkversion(L);*/
668  luaL_checkstack(L, nup, "too many upvalues");
669  for (; l->name != NULL; l++) {  /* fill the table with given functions */
670    int i;
671    for (i = 0; i < nup; i++)  /* copy upvalues to the top */
672      lua_pushvalue(L, -nup);
673    lua_pushcclosure(L, l->func, nup);  /* closure with those upvalues */
674    lua_setfield(L, -(nup + 2), l->name);
675  }
676  lua_pop(L, nup);  /* remove upvalues */
677}
678
679
680@ @c
681LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) {
682  lua_State *L = B->L;
683  if (sz > LUAL_BUFFERSIZE )
684	luaL_error(L, "buffer too large");
685  return luaL_prepbuffer(B) ;
686}
687
688@ @c
689LUA_API int lua_compare (lua_State *L, int o1, int o2, int op) {
690  /*StkId o1, o2;*/
691  int i = 0;
692  lua_lock(L);  /* may call tag method */
693  /* o1 = index2addr(L, index1); */
694  /* o2 = index2addr(L, index2); */
695  /*if (isvalid(o1) && isvalid(o2)) {*/
696    switch (op) {
697      case LUA_OPEQ: i = lua_equal(L, o1, o2); break;
698      case LUA_OPLT: i = lua_lessthan(L, o1, o2); break;
699      case LUA_OPLE: i = (lua_lessthan(L, o1, o2) || lua_equal(L, o1, o2)) ; break;
700      default: luaL_error(L, "invalid option");
701    }
702  /*}*/
703  lua_unlock(L);
704  return i;
705}
706
707