A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 812 lines 23 kB view raw
1/* 2** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $ 3** Auxiliary functions for building Lua libraries 4** See Copyright Notice in lua.h 5*/ 6 7 8#include <ctype.h> 9#include <errno.h> 10#include <stdarg.h> 11#include <stdio.h> 12#include <stdlib.h> 13#include <string.h> 14#include "lstring.h" /* ROCKLUA ADDED */ 15 16/* This file uses only the official API of Lua. 17** Any function declared here could be written as an application function. 18** Note ** luaS_newlloc breaks this guarantee ROCKLUA ADDED 19*/ 20 21#define lauxlib_c 22#define LUA_LIB 23 24#include "lua.h" 25 26#include "lauxlib.h" 27 28 29#define FREELIST_REF 0 /* free list of references */ 30 31 32/* convert a stack index to positive */ 33#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ 34 lua_gettop(L) + (i) + 1) 35 36#ifndef LUA_OOM 37 #define LUA_OOM(L) {} 38#endif 39/* 40** {====================================================== 41** Error-report functions 42** ======================================================= 43*/ 44 45 46LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { 47 lua_Debug ar; 48 if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ 49 return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); 50 lua_getinfo(L, "n", &ar); 51 if (strcmp(ar.namewhat, "method") == 0) { 52 narg--; /* do not count `self' */ 53 if (narg == 0) /* error is in the self argument itself? */ 54 return luaL_error(L, "calling " LUA_QS " on bad self (%s)", 55 ar.name, extramsg); 56 } 57 if (ar.name == NULL) 58 ar.name = "?"; 59 return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", 60 narg, ar.name, extramsg); 61} 62 63 64LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { 65 const char *msg = lua_pushfstring(L, "%s expected, got %s", 66 tname, luaL_typename(L, narg)); 67 return luaL_argerror(L, narg, msg); 68} 69 70 71static void tag_error (lua_State *L, int narg, int tag) { 72 luaL_typerror(L, narg, lua_typename(L, tag)); 73} 74 75 76LUALIB_API void luaL_where (lua_State *L, int level) { 77 lua_Debug ar; 78 if (lua_getstack(L, level, &ar)) { /* check function at level */ 79 lua_getinfo(L, "Sl", &ar); /* get info about it */ 80 if (ar.currentline > 0) { /* is there info? */ 81 lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); 82 return; 83 } 84 } 85 lua_pushliteral(L, ""); /* else, no information available... */ 86} 87 88 89LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { 90 va_list argp; 91 va_start(argp, fmt); 92 luaL_where(L, 1); 93 lua_pushvfstring(L, fmt, argp); 94 va_end(argp); 95 lua_concat(L, 2); 96 return lua_error(L); 97} 98 99/* }====================================================== */ 100 101 102LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, 103 const char *const lst[]) { 104 const char *name = (def) ? luaL_optstring(L, narg, def) : 105 luaL_checkstring(L, narg); 106 int i; 107 for (i=0; lst[i]; i++) 108 if (strcmp(lst[i], name) == 0) 109 return i; 110 return luaL_argerror(L, narg, 111 lua_pushfstring(L, "invalid option " LUA_QS, name)); 112} 113 114 115LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { 116 lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ 117 if (!lua_isnil(L, -1)) /* name already in use? */ 118 return 0; /* leave previous value on top, but return 0 */ 119 lua_pop(L, 1); 120 lua_newtable(L); /* create metatable */ 121 lua_pushvalue(L, -1); 122 lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ 123 return 1; 124} 125 126 127LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { 128 void *p = lua_touserdata(L, ud); 129 if (p != NULL) { /* value is a userdata? */ 130 if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ 131 lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ 132 if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ 133 lua_pop(L, 2); /* remove both metatables */ 134 return p; 135 } 136 } 137 } 138 luaL_typerror(L, ud, tname); /* else error */ 139 return NULL; /* to avoid warnings */ 140} 141 142 143LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { 144 if (!lua_checkstack(L, space)) 145 luaL_error(L, "stack overflow (%s)", mes); 146} 147 148 149LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { 150 if (lua_type(L, narg) != t) 151 tag_error(L, narg, t); 152} 153 154 155LUALIB_API void luaL_checkany (lua_State *L, int narg) { 156 if (lua_type(L, narg) == LUA_TNONE) 157 luaL_argerror(L, narg, "value expected"); 158} 159 160 161LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { 162 const char *s = lua_tolstring(L, narg, len); 163 if (!s) tag_error(L, narg, LUA_TSTRING); 164 return s; 165} 166 167 168LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, 169 const char *def, size_t *len) { 170 if (lua_isnoneornil(L, narg)) { 171 if (len) 172 *len = (def ? strlen(def) : 0); 173 return def; 174 } 175 else return luaL_checklstring(L, narg, len); 176} 177 178 179LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { 180 lua_Number d = lua_tonumber(L, narg); 181 if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ 182 tag_error(L, narg, LUA_TNUMBER); 183 return d; 184} 185 186 187LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { 188 return luaL_opt(L, luaL_checknumber, narg, def); 189} 190 191 192LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { 193 lua_Integer d = lua_tointeger(L, narg); 194 if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ 195 tag_error(L, narg, LUA_TNUMBER); 196 return d; 197} 198 199 200LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, 201 lua_Integer def) { 202 return luaL_opt(L, luaL_checkinteger, narg, def); 203} 204 205/* ROCKLUA ADDED */ 206LUALIB_API int luaL_checkboolean (lua_State *L, int narg) { 207 int b = lua_toboolean(L, narg); 208 if( b == 0 && !lua_isboolean(L, narg)) 209 tag_error(L, narg, LUA_TBOOLEAN); 210 return b; 211} 212 213/* ROCKLUA ADDED */ 214LUALIB_API int luaL_optboolean (lua_State *L, int narg, int def) { 215 return luaL_opt(L, luaL_checkboolean, narg, def); 216} 217 218 219LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { 220 if (!lua_getmetatable(L, obj)) /* no metatable? */ 221 return 0; 222 lua_pushstring(L, event); 223 lua_rawget(L, -2); 224 if (lua_isnil(L, -1)) { 225 lua_pop(L, 2); /* remove metatable and metafield */ 226 return 0; 227 } 228 else { 229 lua_remove(L, -2); /* remove only metatable */ 230 return 1; 231 } 232} 233 234 235LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { 236 obj = abs_index(L, obj); 237 if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ 238 return 0; 239 lua_pushvalue(L, obj); 240 lua_call(L, 1, 1); 241 return 1; 242} 243 244 245 /* ROCKLUA ADDED */ 246static int libsize_storenames (lua_State *L, const char* libname, const luaL_Reg *l) { 247 int size = 0; 248 if (libname) 249 luaS_newlloc(L, libname, TSTR_INBIN); 250 for (; l->name; l++) { 251 size++; 252 luaS_newlloc(L, l->name, TSTR_INBIN); 253 } 254 return size; 255} 256 257 258#if 0 259LUALIB_API void (luaL_register) (lua_State *L, const char *libname, 260 const luaL_Reg *l) { 261 luaI_openlib(L, libname, l, 0); 262} 263#else /* late bind cfunction tables to save ram */ 264static int latebind_func_index(lua_State *L) 265{ 266 const luaL_Reg *llib; 267 /* name @ top of stack 1(basetable;name)-1*/ 268 const char *name = lua_tostring(L, -1); 269 270 lua_pushstring (L, "__latebind");/* basetable;name;__latebind;*/ 271 if(lua_istable(L, -3)) 272 lua_rawget (L, -3);/* basetable;name;__latebind(t);*/ 273 274 luaL_argcheck(L, lua_istable(L, -3) && lua_istable(L, -1), 1, 275 "__latebind table expected"); 276 /* (btable;name;__latebind(t)) */ 277 278 /* lookup late bound func(s), lua_objlen allows check of multiple luaL_Reg */ 279 for(int i = lua_objlen(L, -1); i > 0; i--) { 280 lua_rawgeti (L, -1, i);/* btable;name;__lb(t);llib*/ 281 llib = (const luaL_Reg *) lua_touserdata (L, -1); 282 lua_pop(L, 1); /* (btable;name;__lb(t);llib) -> (btable;name;__lb(t)) */ 283 284 if(!llib) 285 continue; 286 287 for (; llib->name; llib++) { 288 if(!name || strcmp(name, llib->name) == 0) { 289 /* don't overwrite existing keys within basetable */ 290 lua_pushstring(L, llib->name); /* (btable;name;__lb(t);llib->name) */ 291 lua_rawget(L, -4); /* (btable;name;__lb(t);btable[func]?) */ 292 293 if(lua_isnil(L, -1)) { 294 /* if function is used it is added to the base table */ 295 lua_pop(L, 1); 296 lua_pushcclosure(L, llib->func, 0); /* (btable;name;__lb(t);llib->func) */ 297 } 298 299 if(!name) /* nil name binds all functions in table immediately */ 300 lua_setfield(L, -4, llib->name); /* (btable;name;mtable) */ 301 else { 302 lua_pushvalue(L, -1); /* dupe closure or existing func */ 303 /* (btable;name;__lb(t);llib->func;llib->func) */ 304 lua_setfield(L, -5, llib->name); /* (btable;name;__lb(t);llib->func) */ 305 /* returns the closure */ 306 return 1; 307 } 308 } 309 } 310 } 311 312 lua_pop(L, 2); /* (btable;name;__lb(t)) -> (btable) */ 313 if(!name) { 314 lua_pushnil(L); /* remove metatable (btable;name;__lb(t);nil)*/ 315 lua_setmetatable(L, -2); 316 lua_pushnil(L); /* remove __latebind table*/ 317 lua_setfield (L, -2, "__latebind"); 318 } 319 320 return 0; 321} 322 323 324static int latebind_func_pairs(lua_State *L) 325{ 326 /* basetable @ top of stack 1(basetable)-1 */ 327 luaL_argcheck(L, lua_istable(L, 1), 1, "table expected"); 328 329#if 0 330 lua_getglobal(L, "next"); /* function to be called / returned (btable;next) */ 331 lua_createtable(L, 0, 15); /* btable;next;newtable; */ 332 lua_pushnil(L); /* nil name retrieves all unbound latebound functions */ 333 lua_pushnil(L); /* first key */ 334#else 335 /* this way is more RAM efficient in testing */ 336 if(luaL_dostring(L, "return next, {}, nil, nil")!= 0) 337 lua_error(L); 338#endif 339 /* (btable;next;ntable;nil;nil) */ 340 /* clone base table */ 341 while(lua_next(L, 1) > 0) { 342 /* (btable;next;ntable;nil;k;v) */ 343 lua_pushvalue(L, -2); /* dupe key Stk = (..;k;v -> ..k;v;k)*/ 344 lua_insert(L, -2); /* Stk = (..k;k;v) */ 345 lua_rawset(L, -5); /* btable;next;ntable;nil;k */ 346 } 347 /* fill the new table with all the latebound functions */ 348 /* nil name retrieves all unbound latebound functions */ 349 latebind_func_index(L);/* (btable;next;ntable;nil) -> (btable;next;ntable) */ 350 lua_pushnil(L); /*nil initial key for next*/ 351 /* stack = (btable;next;ntable;nil) */ 352 return 3; /*(next,ntable,nil)*/ 353} 354 355 356LUALIB_API void (luaL_register) (lua_State *L, const char *libname, 357 const luaL_Reg *l) { 358 if(!libname) 359 { 360 /* if there is no libname register normally */ 361 luaI_openlib(L, libname, l, 0); 362 return; 363 } 364 365 /* store empty table instead of passed luaL_Reg table */ 366 static const struct luaL_reg late_lib [] = 367 { 368 {NULL, NULL} 369 }; 370 371 static const struct luaL_reg late_meta [] = 372 { 373 {"__index", latebind_func_index}, 374 {"__pairs", latebind_func_pairs}, 375 {"__call", latebind_func_index}, /* allows t("func") -- nil binds all */ 376 {NULL, NULL} 377 }; 378 379 libsize_storenames(L, libname, l); /* store func names */ 380 luaI_openlib(L, libname, late_lib, 0); /* basetable; */ 381 382 luaL_findtable(L, -1,"__latebind", 0); /* create table if doesn't exist */ 383 /* basetable;__latebind(t); */ 384 /* save pointer to real luaL_reg */ 385 lua_pushlightuserdata (L, (void *) l); /*basetable;__lb(t);userdata;*/ 386 lua_rawseti(L, -2, lua_objlen(L, -2) + 1); /*lb(t)[n] = userdata */ 387 388 lua_pop(L, 1);/* (basetable;__latebind(t)) -> (basetable) */ 389 390 if(luaL_newmetatable(L, "META_LATEBIND")) 391 { 392 luaI_openlib(L, NULL, late_meta, 0); /*basetable;metatable*/ 393 lua_pushvalue(L, -1); /* dupe the metatable (basetable;mt;mt) */ 394 lua_setfield (L, -2, "__metatable"); /* metatable[__metatable] = metatable */ 395 } 396 397 lua_setmetatable(L, -2); /* (basetable;mt) -> (basetable+mtable) */ 398 /* base table is top of stack (basetable) */ 399} 400#endif 401 402#if 0 403static int libsize (const luaL_Reg *l) { 404 int size = 0; 405 for (; l->name; l++) size++; 406 return size; 407} 408#endif 409 410LUALIB_API void luaI_openlib (lua_State *L, const char *libname, 411 const luaL_Reg *l, int nup) { 412 int size = libsize_storenames(L, libname, l); 413 if (libname) { 414 /* check whether lib already exists */ 415 luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); 416 lua_getfield(L, -1, libname); /* get _LOADED[libname] */ 417 if (!lua_istable(L, -1)) { /* not found? */ 418 lua_pop(L, 1); /* remove previous result */ 419 /* try global variable (and create one if it does not exist) */ 420 if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL) 421 luaL_error(L, "name conflict for module " LUA_QS, libname); 422 lua_pushvalue(L, -1); 423 lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ 424 } 425 lua_remove(L, -2); /* remove _LOADED table */ 426 lua_insert(L, -(nup+1)); /* move library table to below upvalues */ 427 } 428 for (; l->name; l++) { 429 int i; 430 for (i=0; i<nup; i++) /* copy upvalues to the top */ 431 lua_pushvalue(L, -nup); 432 lua_pushcclosure(L, l->func, nup); 433 lua_setfield(L, -(nup+2), l->name); 434 } 435 lua_pop(L, nup); /* remove upvalues */ 436} 437 438 439 440/* 441** {====================================================== 442** getn-setn: size for arrays 443** ======================================================= 444*/ 445 446#if defined(LUA_COMPAT_GETN) 447 448static int checkint (lua_State *L, int topop) { 449 int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1; 450 lua_pop(L, topop); 451 return n; 452} 453 454 455static void getsizes (lua_State *L) { 456 lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); 457 if (lua_isnil(L, -1)) { /* no `size' table? */ 458 lua_pop(L, 1); /* remove nil */ 459 lua_newtable(L); /* create it */ 460 lua_pushvalue(L, -1); /* `size' will be its own metatable */ 461 lua_setmetatable(L, -2); 462 lua_pushliteral(L, "kv"); 463 lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */ 464 lua_pushvalue(L, -1); 465 lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */ 466 } 467} 468 469 470LUALIB_API void luaL_setn (lua_State *L, int t, int n) { 471 t = abs_index(L, t); 472 lua_pushliteral(L, "n"); 473 lua_rawget(L, t); 474 if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */ 475 lua_pushliteral(L, "n"); /* use it */ 476 lua_pushinteger(L, n); 477 lua_rawset(L, t); 478 } 479 else { /* use `sizes' */ 480 getsizes(L); 481 lua_pushvalue(L, t); 482 lua_pushinteger(L, n); 483 lua_rawset(L, -3); /* sizes[t] = n */ 484 lua_pop(L, 1); /* remove `sizes' */ 485 } 486} 487 488 489LUALIB_API int luaL_getn (lua_State *L, int t) { 490 int n; 491 t = abs_index(L, t); 492 lua_pushliteral(L, "n"); /* try t.n */ 493 lua_rawget(L, t); 494 if ((n = checkint(L, 1)) >= 0) return n; 495 getsizes(L); /* else try sizes[t] */ 496 lua_pushvalue(L, t); 497 lua_rawget(L, -2); 498 if ((n = checkint(L, 2)) >= 0) return n; 499 return (int)lua_objlen(L, t); 500} 501 502#endif 503 504/* }====================================================== */ 505 506 507 508LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, 509 const char *r) { 510 const char *wild; 511 size_t l = strlen(p); 512 luaL_Buffer b; 513 luaL_buffinit(L, &b); 514 while ((wild = strstr(s, p)) != NULL) { 515 luaL_addlstring(&b, s, wild - s); /* push prefix */ 516 luaL_addstring(&b, r); /* push replacement in place of pattern */ 517 s = wild + l; /* continue after `p' */ 518 } 519 luaL_addstring(&b, s); /* push last suffix */ 520 luaL_pushresult(&b); 521 return lua_tostring(L, -1); 522} 523 524 525LUALIB_API const char *luaL_findtable (lua_State *L, int idx, 526 const char *fname, int szhint) { 527 const char *e; 528 lua_pushvalue(L, idx); 529 do { 530 e = strchr(fname, '.'); 531 if (e == NULL) e = fname + strlen(fname); 532 lua_pushlstring(L, fname, e - fname); 533 lua_rawget(L, -2); 534 if (lua_isnil(L, -1)) { /* no such field? */ 535 lua_pop(L, 1); /* remove this nil */ 536 lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ 537 lua_pushlstring(L, fname, e - fname); 538 lua_pushvalue(L, -2); 539 lua_settable(L, -4); /* set new table into field */ 540 } 541 else if (!lua_istable(L, -1)) { /* field has a non-table value? */ 542 lua_pop(L, 2); /* remove table and value */ 543 return fname; /* return problematic part of the name */ 544 } 545 lua_remove(L, -2); /* remove previous table */ 546 fname = e + 1; 547 } while (*e == '.'); 548 return NULL; 549} 550 551 552 553/* 554** {====================================================== 555** Generic Buffer manipulation 556** ======================================================= 557*/ 558 559 560#define bufflen(B) ((B)->p - (B)->buffer) 561#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) 562 563#define LIMIT (LUA_MINSTACK/2) 564 565 566static int emptybuffer (luaL_Buffer *B) { 567 size_t l = bufflen(B); 568 if (l == 0) return 0; /* put nothing on stack */ 569 else { 570 lua_pushlstring(B->L, B->buffer, l); 571 B->p = B->buffer; 572 B->lvl++; 573 return 1; 574 } 575} 576 577 578static void adjuststack (luaL_Buffer *B) { 579 if (B->lvl > 1) { 580 lua_State *L = B->L; 581 int toget = 1; /* number of levels to concat */ 582 size_t toplen = lua_strlen(L, -1); 583 do { 584 size_t l = lua_strlen(L, -(toget+1)); 585 if (B->lvl - toget + 1 >= LIMIT || toplen > l) { 586 toplen += l; 587 toget++; 588 } 589 else break; 590 } while (toget < B->lvl); 591 lua_concat(L, toget); 592 B->lvl = B->lvl - toget + 1; 593 } 594} 595 596 597LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { 598 if (emptybuffer(B)) 599 adjuststack(B); 600 return B->buffer; 601} 602 603 604LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { 605 while (l--) 606 luaL_addchar(B, *s++); 607} 608 609 610LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { 611 luaL_addlstring(B, s, strlen(s)); 612} 613 614 615LUALIB_API void luaL_pushresult (luaL_Buffer *B) { 616 emptybuffer(B); 617 lua_concat(B->L, B->lvl); 618 B->lvl = 1; 619} 620 621 622LUALIB_API void luaL_addvalue (luaL_Buffer *B) { 623 lua_State *L = B->L; 624 size_t vl; 625 const char *s = lua_tolstring(L, -1, &vl); 626 if (vl <= bufffree(B)) { /* fit into buffer? */ 627 memcpy(B->p, s, vl); /* put it there */ 628 B->p += vl; 629 lua_pop(L, 1); /* remove from stack */ 630 } 631 else { 632 if (emptybuffer(B)) 633 lua_insert(L, -2); /* put buffer before new value */ 634 B->lvl++; /* add new value into B stack */ 635 adjuststack(B); 636 } 637} 638 639 640LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { 641 B->L = L; 642 B->p = B->buffer; 643 B->lvl = 0; 644} 645 646/* }====================================================== */ 647 648 649LUALIB_API int luaL_ref (lua_State *L, int t) { 650 int ref; 651 t = abs_index(L, t); 652 if (lua_isnil(L, -1)) { 653 lua_pop(L, 1); /* remove from stack */ 654 return LUA_REFNIL; /* `nil' has a unique fixed reference */ 655 } 656 lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ 657 ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */ 658 lua_pop(L, 1); /* remove it from stack */ 659 if (ref != 0) { /* any free element? */ 660 lua_rawgeti(L, t, ref); /* remove it from list */ 661 lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ 662 } 663 else { /* no free elements */ 664 ref = (int)lua_objlen(L, t); 665 ref++; /* create new reference */ 666 } 667 lua_rawseti(L, t, ref); 668 return ref; 669} 670 671 672LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { 673 if (ref >= 0) { 674 t = abs_index(L, t); 675 lua_rawgeti(L, t, FREELIST_REF); 676 lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ 677 lua_pushinteger(L, ref); 678 lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ 679 } 680} 681 682 683 684/* 685** {====================================================== 686** Load functions 687** ======================================================= 688*/ 689 690typedef struct LoadF { 691 int extraline; 692 int f; 693 char buff[LUAL_BUFFERSIZE]; 694} LoadF; 695 696static const char *getF (lua_State *L, void *ud, size_t *size) { 697 LoadF *lf = (LoadF *)ud; 698 (void)L; 699 if (lf->extraline) { 700 lf->extraline = 0; 701 *size = 1; 702 return "\n"; 703 } 704 *size = rb->read(lf->f, lf->buff, LUAL_BUFFERSIZE); 705 return (*size > 0) ? lf->buff : NULL; 706} 707 708 709static int errfile (lua_State *L, const char *what, int fnameindex) { 710 const char *serr = strerror(errno); 711 const char *filename = lua_tostring(L, fnameindex) + 1; 712 lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); 713 lua_remove(L, fnameindex); 714 return LUA_ERRFILE; 715} 716 717LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { 718 LoadF lf; 719 int status; 720 int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ 721 lf.extraline = 0; 722 lf.f = rb->open(filename, O_RDONLY); 723 lua_pushfstring(L, "@%s", filename); 724 if (lf.f < 0) return errfile(L, "open", fnameindex); 725 status = lua_load(L, getF, &lf, lua_tostring(L, -1)); 726 rb->close(lf.f); 727 lua_remove(L, fnameindex); 728 return status; 729} 730 731 732typedef struct LoadS { 733 const char *s; 734 size_t size; 735} LoadS; 736 737 738static const char *getS (lua_State *L, void *ud, size_t *size) { 739 LoadS *ls = (LoadS *)ud; 740 (void)L; 741 if (ls->size == 0) return NULL; 742 *size = ls->size; 743 ls->size = 0; 744 return ls->s; 745} 746 747 748LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, 749 const char *name) { 750 LoadS ls; 751 ls.s = buff; 752 ls.size = size; 753 return lua_load(L, getS, &ls, name); 754} 755 756 757LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) { 758 return luaL_loadbuffer(L, s, strlen(s), s); 759} 760 761 762 763/* }====================================================== */ 764 765 766static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { 767 (void) osize; 768 lua_State *L = (lua_State *)ud; 769 void *nptr; 770 771 if (nsize == 0) { 772 free(ptr); 773 return NULL; 774 } 775 776 nptr = realloc(ptr, nsize); 777 if (nptr == NULL) { 778 if(L != NULL) 779 { 780 luaC_fullgc(L); /* emergency full collection. */ 781 nptr = realloc(ptr, nsize); /* try allocation again */ 782 } 783 784 if (nptr == NULL) { 785 LUA_OOM(L); /* if defined.. signal OOM condition */ 786 nptr = realloc(ptr, nsize); /* try allocation again */ 787 } 788 } 789 790 return nptr; 791} 792 793 794static int panic (lua_State *L) { 795 DEBUGF("PANIC: unprotected error in call to Lua API (%s)\n", 796 lua_tostring(L, -1)); 797 rb->splashf(5 * HZ, "PANIC: unprotected error in call to Lua API (%s)", 798 lua_tostring(L, -1)); 799 800 return 0; 801} 802 803 804LUALIB_API lua_State *luaL_newstate (void) { 805 lua_State *L = lua_newstate(l_alloc, NULL); 806 if (L){ 807 lua_setallocf(L, l_alloc, L); /* allocator needs lua_State. */ 808 lua_atpanic(L, &panic); 809 } 810 return L; 811} 812