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