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   if (l <= bufffree(B)) {
 222     memcpy(B->p, s, l);
 223     B->p += l;
 224   } else {
 225     emptybuffer(B);
 226     lua_pushlstring(B->L, s, l);
 227     B->lvl++;
 228     adjuststack(B);
 229   }
 230 }
 231 
 232 LUALIB_API void luaL_addstring(luaL_Buffer *B, const char *s)
 233 {
 234   luaL_addlstring(B, s, strlen(s));
 235 }
 236 
 237 LUALIB_API void luaL_pushresult(luaL_Buffer *B)
 238 {
 239   emptybuffer(B);
 240   lua_concat(B->L, B->lvl);
 241   B->lvl = 1;
 242 }
 243 
 244 LUALIB_API void luaL_addvalue(luaL_Buffer *B)
 245 {
 246   lua_State *L = B->L;
 247   size_t vl;
 248   const char *s = lua_tolstring(L, -1, &vl);
 249   if (vl <= bufffree(B)) {  /* fit into buffer? */
 250     memcpy(B->p, s, vl);  /* put it there */
 251     B->p += vl;
 252     lua_pop(L, 1);  /* remove from stack */
 253   } else {
 254     if (emptybuffer(B))
 255       lua_insert(L, -2);  /* put buffer before new value */
 256     B->lvl++;  /* add new value into B stack */
 257     adjuststack(B);
 258   }
 259 }
 260 
 261 LUALIB_API void luaL_buffinit(lua_State *L, luaL_Buffer *B)
 262 {
 263   B->L = L;
 264   B->p = B->buffer;
 265   B->lvl = 0;
 266 }
 267 
 268 /* -- Reference management ------------------------------------------------ */
 269 
 270 #define FREELIST_REF    0
 271 
 272 /* Convert a stack index to an absolute index. */
 273 #define abs_index(L, i) \
 274   ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1)
 275 
 276 LUALIB_API int luaL_ref(lua_State *L, int t)
 277 {
 278   int ref;
 279   t = abs_index(L, t);
 280   if (lua_isnil(L, -1)) {
 281     lua_pop(L, 1);  /* remove from stack */
 282     return LUA_REFNIL;  /* `nil' has a unique fixed reference */
 283   }
 284   lua_rawgeti(L, t, FREELIST_REF);  /* get first free element */
 285   ref = (int)lua_tointeger(L, -1);  /* ref = t[FREELIST_REF] */
 286   lua_pop(L, 1);  /* remove it from stack */
 287   if (ref != 0) {  /* any free element? */
 288     lua_rawgeti(L, t, ref);  /* remove it from list */
 289     lua_rawseti(L, t, FREELIST_REF);  /* (t[FREELIST_REF] = t[ref]) */
 290   } else {  /* no free elements */
 291     ref = (int)lua_objlen(L, t);
 292     ref++;  /* create new reference */
 293   }
 294   lua_rawseti(L, t, ref);
 295   return ref;
 296 }
 297 
 298 LUALIB_API void luaL_unref(lua_State *L, int t, int ref)
 299 {
 300   if (ref >= 0) {
 301     t = abs_index(L, t);
 302     lua_rawgeti(L, t, FREELIST_REF);
 303     lua_rawseti(L, t, ref);  /* t[ref] = t[FREELIST_REF] */
 304     lua_pushinteger(L, ref);
 305     lua_rawseti(L, t, FREELIST_REF);  /* t[FREELIST_REF] = ref */
 306   }
 307 }
 308 
 309 /* -- Default allocator and panic function -------------------------------- */
 310 
 311 static int panic(lua_State *L)
 312 {
 313   const char *s = lua_tostring(L, -1);
 314   fputs("PANIC: unprotected error in call to Lua API (", stderr);
 315   fputs(s ? s : "?", stderr);
 316   fputc(')', stderr); fputc('\n', stderr);
 317   fflush(stderr);
 318   return 0;
 319 }
 320 
 321 #ifdef LUAJIT_USE_SYSMALLOC
 322 
 323 #if LJ_64 && !LJ_GC64 && !defined(LUAJIT_USE_VALGRIND)
 324 #error "Must use builtin allocator for 64 bit target"
 325 #endif
 326 
 327 static void *mem_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
 328 {
 329   (void)ud;
 330   (void)osize;
 331   if (nsize == 0) {
 332     free(ptr);
 333     return NULL;
 334   } else {
 335     return realloc(ptr, nsize);
 336   }
 337 }
 338 
 339 LUALIB_API lua_State *luaL_newstate(void)
 340 {
 341   lua_State *L = lua_newstate(mem_alloc, NULL);
 342   if (L) G(L)->panic = panic;
 343   return L;
 344 }
 345 
 346 #else
 347 
 348 #include "lj_alloc.h"
 349 
 350 LUALIB_API lua_State *luaL_newstate(void)
 351 {
 352   lua_State *L;
 353   void *ud = lj_alloc_create();
 354   if (ud == NULL) return NULL;
 355 #if LJ_64 && !LJ_GC64
 356   L = lj_state_newstate(lj_alloc_f, ud);
 357 #else
 358   L = lua_newstate(lj_alloc_f, ud);
 359 #endif
 360   if (L) G(L)->panic = panic;
 361   return L;
 362 }
 363 
 364 #if LJ_64 && !LJ_GC64
 365 LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud)
 366 {
 367   UNUSED(f); UNUSED(ud);
 368   fputs("Must use luaL_newstate() for 64 bit target\n", stderr);
 369   return NULL;
 370 }
 371 #endif
 372 
 373 #endif
 374 

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