root/lib_aux.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. luaL_fileresult
  2. luaL_execresult
  3. luaL_findtable
  4. libsize
  5. luaL_pushmodule
  6. luaL_openlib
  7. luaL_register
  8. luaL_setfuncs
  9. luaL_gsub
  10. emptybuffer
  11. adjuststack
  12. luaL_prepbuffer
  13. luaL_addlstring
  14. luaL_addstring
  15. luaL_pushresult
  16. luaL_addvalue
  17. luaL_buffinit
  18. luaL_ref
  19. luaL_unref
  20. panic
  21. mem_alloc
  22. luaL_newstate
  23. luaL_newstate
  24. lua_newstate

   1 /*
   2 ** Auxiliary library for the Lua/C API.
   3 ** Copyright (C) 2005-2017 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 
   9 #include <errno.h>
  10 #include <stdarg.h>
  11 #include <stdio.h>
  12 
  13 #define lib_aux_c
  14 #define LUA_LIB
  15 
  16 #include "lua.h"
  17 #include "lauxlib.h"
  18 
  19 #include "lj_obj.h"
  20 #include "lj_err.h"
  21 #include "lj_state.h"
  22 #include "lj_trace.h"
  23 #include "lj_lib.h"
  24 
  25 #if LJ_TARGET_POSIX
  26 #include <sys/wait.h>
  27 #endif
  28 
  29 /* -- I/O error handling -------------------------------------------------- */
  30 
  31 LUALIB_API int luaL_fileresult(lua_State *L, int stat, const char *fname)
  32 {
  33   if (stat) {
  34     setboolV(L->top++, 1);
  35     return 1;
  36   } else {
  37     int en = errno;  /* Lua API calls may change this value. */
  38     setnilV(L->top++);
  39     if (fname)
  40       lua_pushfstring(L, "%s: %s", fname, strerror(en));
  41     else
  42       lua_pushfstring(L, "%s", strerror(en));
  43     setintV(L->top++, en);
  44     lj_trace_abort(G(L));
  45     return 3;
  46   }
  47 }
  48 
  49 LUALIB_API int luaL_execresult(lua_State *L, int stat)
  50 {
  51   if (stat != -1) {
  52 #if LJ_TARGET_POSIX
  53     if (WIFSIGNALED(stat)) {
  54       stat = WTERMSIG(stat);
  55       setnilV(L->top++);
  56       lua_pushliteral(L, "signal");
  57     } else {
  58       if (WIFEXITED(stat))
  59         stat = WEXITSTATUS(stat);
  60       if (stat == 0)
  61         setboolV(L->top++, 1);
  62       else
  63         setnilV(L->top++);
  64       lua_pushliteral(L, "exit");
  65     }
  66 #else
  67     if (stat == 0)
  68       setboolV(L->top++, 1);
  69     else
  70       setnilV(L->top++);
  71     lua_pushliteral(L, "exit");
  72 #endif
  73     setintV(L->top++, stat);
  74     return 3;
  75   }
  76   return luaL_fileresult(L, 0, NULL);
  77 }
  78 
  79 /* -- Module registration ------------------------------------------------- */
  80 
  81 LUALIB_API const char *luaL_findtable(lua_State *L, int idx,
  82                                       const char *fname, int szhint)
  83 {
  84   const char *e;
  85   lua_pushvalue(L, idx);
  86   do {
  87     e = strchr(fname, '.');
  88     if (e == NULL) e = fname + strlen(fname);
  89     lua_pushlstring(L, fname, (size_t)(e - fname));
  90     lua_rawget(L, -2);
  91     if (lua_isnil(L, -1)) {  /* no such field? */
  92       lua_pop(L, 1);  /* remove this nil */
  93       lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
  94       lua_pushlstring(L, fname, (size_t)(e - fname));
  95       lua_pushvalue(L, -2);
  96       lua_settable(L, -4);  /* set new table into field */
  97     } else if (!lua_istable(L, -1)) {  /* field has a non-table value? */
  98       lua_pop(L, 2);  /* remove table and value */
  99       return fname;  /* return problematic part of the name */
 100     }
 101     lua_remove(L, -2);  /* remove previous table */
 102     fname = e + 1;
 103   } while (*e == '.');
 104   return NULL;
 105 }
 106 
 107 static int libsize(const luaL_Reg *l)
 108 {
 109   int size = 0;
 110   for (; l && l->name; l++) size++;
 111   return size;
 112 }
 113 
 114 LUALIB_API void luaL_pushmodule(lua_State *L, const char *modname, int sizehint)
 115 {
 116   luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 16);
 117   lua_getfield(L, -1, modname);
 118   if (!lua_istable(L, -1)) {
 119     lua_pop(L, 1);
 120     if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, sizehint) != NULL)
 121       lj_err_callerv(L, LJ_ERR_BADMODN, modname);
 122     lua_pushvalue(L, -1);
 123     lua_setfield(L, -3, modname);  /* _LOADED[modname] = new table. */
 124   }
 125   lua_remove(L, -2);  /* Remove _LOADED table. */
 126 }
 127 
 128 LUALIB_API void luaL_openlib(lua_State *L, const char *libname,
 129                              const luaL_Reg *l, int nup)
 130 {
 131   lj_lib_checkfpu(L);
 132   if (libname) {
 133     luaL_pushmodule(L, libname, libsize(l));
 134     lua_insert(L, -(nup + 1));  /* Move module table below upvalues. */
 135   }
 136   if (l)
 137     luaL_setfuncs(L, l, nup);
 138   else
 139     lua_pop(L, nup);  /* Remove upvalues. */
 140 }
 141 
 142 LUALIB_API void luaL_register(lua_State *L, const char *libname,
 143                               const luaL_Reg *l)
 144 {
 145   luaL_openlib(L, libname, l, 0);
 146 }
 147 
 148 LUALIB_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup)
 149 {
 150   luaL_checkstack(L, nup, "too many upvalues");
 151   for (; l->name; l++) {
 152     int i;
 153     for (i = 0; i < nup; i++)  /* Copy upvalues to the top. */
 154       lua_pushvalue(L, -nup);
 155     lua_pushcclosure(L, l->func, nup);
 156     lua_setfield(L, -(nup + 2), l->name);
 157   }
 158   lua_pop(L, nup);  /* Remove upvalues. */
 159 }
 160 
 161 LUALIB_API const char *luaL_gsub(lua_State *L, const char *s,
 162                                  const char *p, const char *r)
 163 {
 164   const char *wild;
 165   size_t l = strlen(p);
 166   luaL_Buffer b;
 167   luaL_buffinit(L, &b);
 168   while ((wild = strstr(s, p)) != NULL) {
 169     luaL_addlstring(&b, s, (size_t)(wild - s));  /* push prefix */
 170     luaL_addstring(&b, r);  /* push replacement in place of pattern */
 171     s = wild + l;  /* continue after `p' */
 172   }
 173   luaL_addstring(&b, s);  /* push last suffix */
 174   luaL_pushresult(&b);
 175   return lua_tostring(L, -1);
 176 }
 177 
 178 /* -- Buffer handling ----------------------------------------------------- */
 179 
 180 #define bufflen(B)      ((size_t)((B)->p - (B)->buffer))
 181 #define bufffree(B)     ((size_t)(LUAL_BUFFERSIZE - bufflen(B)))
 182 
 183 static int emptybuffer(luaL_Buffer *B)
 184 {
 185   size_t l = bufflen(B);
 186   if (l == 0)
 187     return 0;  /* put nothing on stack */
 188   lua_pushlstring(B->L, B->buffer, l);
 189   B->p = B->buffer;
 190   B->lvl++;
 191   return 1;
 192 }
 193 
 194 static void adjuststack(luaL_Buffer *B)
 195 {
 196   if (B->lvl > 1) {
 197     lua_State *L = B->L;
 198     int toget = 1;  /* number of levels to concat */
 199     size_t toplen = lua_strlen(L, -1);
 200     do {
 201       size_t l = lua_strlen(L, -(toget+1));
 202       if (!(B->lvl - toget + 1 >= LUA_MINSTACK/2 || toplen > l))
 203         break;
 204       toplen += l;
 205       toget++;
 206     } while (toget < B->lvl);
 207     lua_concat(L, toget);
 208     B->lvl = B->lvl - toget + 1;
 209   }
 210 }
 211 
 212 LUALIB_API char *luaL_prepbuffer(luaL_Buffer *B)
 213 {
 214   if (emptybuffer(B))
 215     adjuststack(B);
 216   return B->buffer;
 217 }
 218 
 219 LUALIB_API void luaL_addlstring(luaL_Buffer *B, const char *s, size_t l)
 220 {
 221   while (l--)
 222     luaL_addchar(B, *s++);
 223 }
 224 
 225 LUALIB_API void luaL_addstring(luaL_Buffer *B, const char *s)
 226 {
 227   luaL_addlstring(B, s, strlen(s));
 228 }
 229 
 230 LUALIB_API void luaL_pushresult(luaL_Buffer *B)
 231 {
 232   emptybuffer(B);
 233   lua_concat(B->L, B->lvl);
 234   B->lvl = 1;
 235 }
 236 
 237 LUALIB_API void luaL_addvalue(luaL_Buffer *B)
 238 {
 239   lua_State *L = B->L;
 240   size_t vl;
 241   const char *s = lua_tolstring(L, -1, &vl);
 242   if (vl <= bufffree(B)) {  /* fit into buffer? */
 243     memcpy(B->p, s, vl);  /* put it there */
 244     B->p += vl;
 245     lua_pop(L, 1);  /* remove from stack */
 246   } else {
 247     if (emptybuffer(B))
 248       lua_insert(L, -2);  /* put buffer before new value */
 249     B->lvl++;  /* add new value into B stack */
 250     adjuststack(B);
 251   }
 252 }
 253 
 254 LUALIB_API void luaL_buffinit(lua_State *L, luaL_Buffer *B)
 255 {
 256   B->L = L;
 257   B->p = B->buffer;
 258   B->lvl = 0;
 259 }
 260 
 261 /* -- Reference management ------------------------------------------------ */
 262 
 263 #define FREELIST_REF    0
 264 
 265 /* Convert a stack index to an absolute index. */
 266 #define abs_index(L, i) \
 267   ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1)
 268 
 269 LUALIB_API int luaL_ref(lua_State *L, int t)
 270 {
 271   int ref;
 272   t = abs_index(L, t);
 273   if (lua_isnil(L, -1)) {
 274     lua_pop(L, 1);  /* remove from stack */
 275     return LUA_REFNIL;  /* `nil' has a unique fixed reference */
 276   }
 277   lua_rawgeti(L, t, FREELIST_REF);  /* get first free element */
 278   ref = (int)lua_tointeger(L, -1);  /* ref = t[FREELIST_REF] */
 279   lua_pop(L, 1);  /* remove it from stack */
 280   if (ref != 0) {  /* any free element? */
 281     lua_rawgeti(L, t, ref);  /* remove it from list */
 282     lua_rawseti(L, t, FREELIST_REF);  /* (t[FREELIST_REF] = t[ref]) */
 283   } else {  /* no free elements */
 284     ref = (int)lua_objlen(L, t);
 285     ref++;  /* create new reference */
 286   }
 287   lua_rawseti(L, t, ref);
 288   return ref;
 289 }
 290 
 291 LUALIB_API void luaL_unref(lua_State *L, int t, int ref)
 292 {
 293   if (ref >= 0) {
 294     t = abs_index(L, t);
 295     lua_rawgeti(L, t, FREELIST_REF);
 296     lua_rawseti(L, t, ref);  /* t[ref] = t[FREELIST_REF] */
 297     lua_pushinteger(L, ref);
 298     lua_rawseti(L, t, FREELIST_REF);  /* t[FREELIST_REF] = ref */
 299   }
 300 }
 301 
 302 /* -- Default allocator and panic function -------------------------------- */
 303 
 304 static int panic(lua_State *L)
 305 {
 306   const char *s = lua_tostring(L, -1);
 307   fputs("PANIC: unprotected error in call to Lua API (", stderr);
 308   fputs(s ? s : "?", stderr);
 309   fputc(')', stderr); fputc('\n', stderr);
 310   fflush(stderr);
 311   return 0;
 312 }
 313 
 314 #ifdef LUAJIT_USE_SYSMALLOC
 315 
 316 #if LJ_64 && !LJ_GC64 && !defined(LUAJIT_USE_VALGRIND)
 317 #error "Must use builtin allocator for 64 bit target"
 318 #endif
 319 
 320 static void *mem_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
 321 {
 322   (void)ud;
 323   (void)osize;
 324   if (nsize == 0) {
 325     free(ptr);
 326     return NULL;
 327   } else {
 328     return realloc(ptr, nsize);
 329   }
 330 }
 331 
 332 LUALIB_API lua_State *luaL_newstate(void)
 333 {
 334   lua_State *L = lua_newstate(mem_alloc, NULL);
 335   if (L) G(L)->panic = panic;
 336   return L;
 337 }
 338 
 339 #else
 340 
 341 #include "lj_alloc.h"
 342 
 343 LUALIB_API lua_State *luaL_newstate(void)
 344 {
 345   lua_State *L;
 346   void *ud = lj_alloc_create();
 347   if (ud == NULL) return NULL;
 348 #if LJ_64 && !LJ_GC64
 349   L = lj_state_newstate(lj_alloc_f, ud);
 350 #else
 351   L = lua_newstate(lj_alloc_f, ud);
 352 #endif
 353   if (L) G(L)->panic = panic;
 354   return L;
 355 }
 356 
 357 #if LJ_64 && !LJ_GC64
 358 LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud)
 359 {
 360   UNUSED(f); UNUSED(ud);
 361   fputs("Must use luaL_newstate() for 64 bit target\n", stderr);
 362   return NULL;
 363 }
 364 #endif
 365 
 366 #endif
 367 

/* [<][>][^][v][top][bottom][index][help] */