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