src/lib_aux.c - luajit-2.0-src

Functions defined

Macros defined

Source code

  1. /*
  2. ** Auxiliary library for the Lua/C API.
  3. ** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
  4. **
  5. ** Major parts taken verbatim or adapted from the Lua interpreter.
  6. ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
  7. */

  8. #include <errno.h>
  9. #include <stdarg.h>
  10. #include <stdio.h>

  11. #define lib_aux_c
  12. #define LUA_LIB

  13. #include "lua.h"
  14. #include "lauxlib.h"

  15. #include "lj_obj.h"
  16. #include "lj_err.h"
  17. #include "lj_state.h"
  18. #include "lj_trace.h"
  19. #include "lj_lib.h"

  20. #if LJ_TARGET_POSIX
  21. #include <sys/wait.h>
  22. #endif

  23. /* -- I/O error handling -------------------------------------------------- */

  24. LUALIB_API int luaL_fileresult(lua_State *L, int stat, const char *fname)
  25. {
  26.   if (stat) {
  27.     setboolV(L->top++, 1);
  28.     return 1;
  29.   } else {
  30.     int en = errno;  /* Lua API calls may change this value. */
  31.     setnilV(L->top++);
  32.     if (fname)
  33.       lua_pushfstring(L, "%s: %s", fname, strerror(en));
  34.     else
  35.       lua_pushfstring(L, "%s", strerror(en));
  36.     setintV(L->top++, en);
  37.     lj_trace_abort(G(L));
  38.     return 3;
  39.   }
  40. }

  41. LUALIB_API int luaL_execresult(lua_State *L, int stat)
  42. {
  43.   if (stat != -1) {
  44. #if LJ_TARGET_POSIX
  45.     if (WIFSIGNALED(stat)) {
  46.       stat = WTERMSIG(stat);
  47.       setnilV(L->top++);
  48.       lua_pushliteral(L, "signal");
  49.     } else {
  50.       if (WIFEXITED(stat))
  51.         stat = WEXITSTATUS(stat);
  52.       if (stat == 0)
  53.         setboolV(L->top++, 1);
  54.       else
  55.         setnilV(L->top++);
  56.       lua_pushliteral(L, "exit");
  57.     }
  58. #else
  59.     if (stat == 0)
  60.       setboolV(L->top++, 1);
  61.     else
  62.       setnilV(L->top++);
  63.     lua_pushliteral(L, "exit");
  64. #endif
  65.     setintV(L->top++, stat);
  66.     return 3;
  67.   }
  68.   return luaL_fileresult(L, 0, NULL);
  69. }

  70. /* -- Module registration ------------------------------------------------- */

  71. LUALIB_API const char *luaL_findtable(lua_State *L, int idx,
  72.                                       const char *fname, int szhint)
  73. {
  74.   const char *e;
  75.   lua_pushvalue(L, idx);
  76.   do {
  77.     e = strchr(fname, '.');
  78.     if (e == NULL) e = fname + strlen(fname);
  79.     lua_pushlstring(L, fname, (size_t)(e - fname));
  80.     lua_rawget(L, -2);
  81.     if (lua_isnil(L, -1)) {  /* no such field? */
  82.       lua_pop(L, 1);  /* remove this nil */
  83.       lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
  84.       lua_pushlstring(L, fname, (size_t)(e - fname));
  85.       lua_pushvalue(L, -2);
  86.       lua_settable(L, -4);  /* set new table into field */
  87.     } else if (!lua_istable(L, -1)) {  /* field has a non-table value? */
  88.       lua_pop(L, 2);  /* remove table and value */
  89.       return fname;  /* return problematic part of the name */
  90.     }
  91.     lua_remove(L, -2);  /* remove previous table */
  92.     fname = e + 1;
  93.   } while (*e == '.');
  94.   return NULL;
  95. }

  96. static int libsize(const luaL_Reg *l)
  97. {
  98.   int size = 0;
  99.   for (; l->name; l++) size++;
  100.   return size;
  101. }

  102. LUALIB_API void luaL_openlib(lua_State *L, const char *libname,
  103.                              const luaL_Reg *l, int nup)
  104. {
  105.   lj_lib_checkfpu(L);
  106.   if (libname) {
  107.     int size = libsize(l);
  108.     /* check whether lib already exists */
  109.     luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 16);
  110.     lua_getfield(L, -1, libname);  /* get _LOADED[libname] */
  111.     if (!lua_istable(L, -1)) {  /* not found? */
  112.       lua_pop(L, 1);  /* remove previous result */
  113.       /* try global variable (and create one if it does not exist) */
  114.       if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL)
  115.         lj_err_callerv(L, LJ_ERR_BADMODN, libname);
  116.       lua_pushvalue(L, -1);
  117.       lua_setfield(L, -3, libname);  /* _LOADED[libname] = new table */
  118.     }
  119.     lua_remove(L, -2);  /* remove _LOADED table */
  120.     lua_insert(L, -(nup+1));  /* move library table to below upvalues */
  121.   }
  122.   for (; l->name; l++) {
  123.     int i;
  124.     for (i = 0; i < nup; i++)  /* copy upvalues to the top */
  125.       lua_pushvalue(L, -nup);
  126.     lua_pushcclosure(L, l->func, nup);
  127.     lua_setfield(L, -(nup+2), l->name);
  128.   }
  129.   lua_pop(L, nup);  /* remove upvalues */
  130. }

  131. LUALIB_API void luaL_register(lua_State *L, const char *libname,
  132.                               const luaL_Reg *l)
  133. {
  134.   luaL_openlib(L, libname, l, 0);
  135. }

  136. LUALIB_API const char *luaL_gsub(lua_State *L, const char *s,
  137.                                  const char *p, const char *r)
  138. {
  139.   const char *wild;
  140.   size_t l = strlen(p);
  141.   luaL_Buffer b;
  142.   luaL_buffinit(L, &b);
  143.   while ((wild = strstr(s, p)) != NULL) {
  144.     luaL_addlstring(&b, s, (size_t)(wild - s));  /* push prefix */
  145.     luaL_addstring(&b, r);  /* push replacement in place of pattern */
  146.     s = wild + l;  /* continue after `p' */
  147.   }
  148.   luaL_addstring(&b, s);  /* push last suffix */
  149.   luaL_pushresult(&b);
  150.   return lua_tostring(L, -1);
  151. }

  152. /* -- Buffer handling ----------------------------------------------------- */

  153. #define bufflen(B)        ((size_t)((B)->p - (B)->buffer))
  154. #define bufffree(B)        ((size_t)(LUAL_BUFFERSIZE - bufflen(B)))

  155. static int emptybuffer(luaL_Buffer *B)
  156. {
  157.   size_t l = bufflen(B);
  158.   if (l == 0)
  159.     return 0/* put nothing on stack */
  160.   lua_pushlstring(B->L, B->buffer, l);
  161.   B->p = B->buffer;
  162.   B->lvl++;
  163.   return 1;
  164. }

  165. static void adjuststack(luaL_Buffer *B)
  166. {
  167.   if (B->lvl > 1) {
  168.     lua_State *L = B->L;
  169.     int toget = 1/* number of levels to concat */
  170.     size_t toplen = lua_strlen(L, -1);
  171.     do {
  172.       size_t l = lua_strlen(L, -(toget+1));
  173.       if (!(B->lvl - toget + 1 >= LUA_MINSTACK/2 || toplen > l))
  174.         break;
  175.       toplen += l;
  176.       toget++;
  177.     } while (toget < B->lvl);
  178.     lua_concat(L, toget);
  179.     B->lvl = B->lvl - toget + 1;
  180.   }
  181. }

  182. LUALIB_API char *luaL_prepbuffer(luaL_Buffer *B)
  183. {
  184.   if (emptybuffer(B))
  185.     adjuststack(B);
  186.   return B->buffer;
  187. }

  188. LUALIB_API void luaL_addlstring(luaL_Buffer *B, const char *s, size_t l)
  189. {
  190.   while (l--)
  191.     luaL_addchar(B, *s++);
  192. }

  193. LUALIB_API void luaL_addstring(luaL_Buffer *B, const char *s)
  194. {
  195.   luaL_addlstring(B, s, strlen(s));
  196. }

  197. LUALIB_API void luaL_pushresult(luaL_Buffer *B)
  198. {
  199.   emptybuffer(B);
  200.   lua_concat(B->L, B->lvl);
  201.   B->lvl = 1;
  202. }

  203. LUALIB_API void luaL_addvalue(luaL_Buffer *B)
  204. {
  205.   lua_State *L = B->L;
  206.   size_t vl;
  207.   const char *s = lua_tolstring(L, -1, &vl);
  208.   if (vl <= bufffree(B)) {  /* fit into buffer? */
  209.     memcpy(B->p, s, vl);  /* put it there */
  210.     B->p += vl;
  211.     lua_pop(L, 1);  /* remove from stack */
  212.   } else {
  213.     if (emptybuffer(B))
  214.       lua_insert(L, -2);  /* put buffer before new value */
  215.     B->lvl++;  /* add new value into B stack */
  216.     adjuststack(B);
  217.   }
  218. }

  219. LUALIB_API void luaL_buffinit(lua_State *L, luaL_Buffer *B)
  220. {
  221.   B->L = L;
  222.   B->p = B->buffer;
  223.   B->lvl = 0;
  224. }

  225. /* -- Reference management ------------------------------------------------ */

  226. #define FREELIST_REF        0

  227. /* Convert a stack index to an absolute index. */
  228. #define abs_index(L, i) \
  229.   ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1)

  230. LUALIB_API int luaL_ref(lua_State *L, int t)
  231. {
  232.   int ref;
  233.   t = abs_index(L, t);
  234.   if (lua_isnil(L, -1)) {
  235.     lua_pop(L, 1);  /* remove from stack */
  236.     return LUA_REFNIL/* `nil' has a unique fixed reference */
  237.   }
  238.   lua_rawgeti(L, t, FREELIST_REF);  /* get first free element */
  239.   ref = (int)lua_tointeger(L, -1);  /* ref = t[FREELIST_REF] */
  240.   lua_pop(L, 1);  /* remove it from stack */
  241.   if (ref != 0) {  /* any free element? */
  242.     lua_rawgeti(L, t, ref);  /* remove it from list */
  243.     lua_rawseti(L, t, FREELIST_REF);  /* (t[FREELIST_REF] = t[ref]) */
  244.   } else/* no free elements */
  245.     ref = (int)lua_objlen(L, t);
  246.     ref++;  /* create new reference */
  247.   }
  248.   lua_rawseti(L, t, ref);
  249.   return ref;
  250. }

  251. LUALIB_API void luaL_unref(lua_State *L, int t, int ref)
  252. {
  253.   if (ref >= 0) {
  254.     t = abs_index(L, t);
  255.     lua_rawgeti(L, t, FREELIST_REF);
  256.     lua_rawseti(L, t, ref);  /* t[ref] = t[FREELIST_REF] */
  257.     lua_pushinteger(L, ref);
  258.     lua_rawseti(L, t, FREELIST_REF);  /* t[FREELIST_REF] = ref */
  259.   }
  260. }

  261. /* -- Default allocator and panic function -------------------------------- */

  262. static int panic(lua_State *L)
  263. {
  264.   const char *s = lua_tostring(L, -1);
  265.   fputs("PANIC: unprotected error in call to Lua API (", stderr);
  266.   fputs(s ? s : "?", stderr);
  267.   fputc(')', stderr); fputc('\n', stderr);
  268.   fflush(stderr);
  269.   return 0;
  270. }

  271. #ifdef LUAJIT_USE_SYSMALLOC

  272. #if LJ_64 && !defined(LUAJIT_USE_VALGRIND)
  273. #error "Must use builtin allocator for 64 bit target"
  274. #endif

  275. static void *mem_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
  276. {
  277.   (void)ud;
  278.   (void)osize;
  279.   if (nsize == 0) {
  280.     free(ptr);
  281.     return NULL;
  282.   } else {
  283.     return realloc(ptr, nsize);
  284.   }
  285. }

  286. LUALIB_API lua_State *luaL_newstate(void)
  287. {
  288.   lua_State *L = lua_newstate(mem_alloc, NULL);
  289.   if (L) G(L)->panic = panic;
  290.   return L;
  291. }

  292. #else

  293. #include "lj_alloc.h"

  294. LUALIB_API lua_State *luaL_newstate(void)
  295. {
  296.   lua_State *L;
  297.   void *ud = lj_alloc_create();
  298.   if (ud == NULL) return NULL;
  299. #if LJ_64
  300.   L = lj_state_newstate(lj_alloc_f, ud);
  301. #else
  302.   L = lua_newstate(lj_alloc_f, ud);
  303. #endif
  304.   if (L) G(L)->panic = panic;
  305.   return L;
  306. }

  307. #if LJ_64
  308. LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud)
  309. {
  310.   UNUSED(f); UNUSED(ud);
  311.   fputs("Must use luaL_newstate() for 64 bit target\n", stderr);
  312.   return NULL;
  313. }
  314. #endif

  315. #endif