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_openlib
  6. luaL_register
  7. luaL_gsub
  8. emptybuffer
  9. adjuststack
  10. luaL_prepbuffer
  11. luaL_addlstring
  12. luaL_addstring
  13. luaL_pushresult
  14. luaL_addvalue
  15. luaL_buffinit
  16. luaL_ref
  17. luaL_unref
  18. panic
  19. mem_alloc
  20. luaL_newstate
  21. luaL_newstate
  22. 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->name; l++) size++;
 111   return size;
 112 }
 113 
 114 LUALIB_API void luaL_openlib(lua_State *L, const char *libname,
 115                              const luaL_Reg *l, int nup)
 116 {
 117   lj_lib_checkfpu(L);
 118   if (libname) {
 119     int size = libsize(l);
 120     /* check whether lib already exists */
 121     luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 16);
 122     lua_getfield(L, -1, libname);  /* get _LOADED[libname] */
 123     if (!lua_istable(L, -1)) {  /* not found? */
 124       lua_pop(L, 1);  /* remove previous result */
 125       /* try global variable (and create one if it does not exist) */
 126       if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL)
 127         lj_err_callerv(L, LJ_ERR_BADMODN, libname);
 128       lua_pushvalue(L, -1);
 129       lua_setfield(L, -3, libname);  /* _LOADED[libname] = new table */
 130     }
 131     lua_remove(L, -2);  /* remove _LOADED table */
 132     lua_insert(L, -(nup+1));  /* move library table to below upvalues */
 133   }
 134   for (; l->name; l++) {
 135     int i;
 136     for (i = 0; i < nup; i++)  /* copy upvalues to the top */
 137       lua_pushvalue(L, -nup);
 138     lua_pushcclosure(L, l->func, nup);
 139     lua_setfield(L, -(nup+2), l->name);
 140   }
 141   lua_pop(L, nup);  /* remove upvalues */
 142 }
 143 
 144 LUALIB_API void luaL_register(lua_State *L, const char *libname,
 145                               const luaL_Reg *l)
 146 {
 147   luaL_openlib(L, libname, l, 0);
 148 }
 149 
 150 LUALIB_API const char *luaL_gsub(lua_State *L, const char *s,
 151                                  const char *p, const char *r)
 152 {
 153   const char *wild;
 154   size_t l = strlen(p);
 155   luaL_Buffer b;
 156   luaL_buffinit(L, &b);
 157   while ((wild = strstr(s, p)) != NULL) {
 158     luaL_addlstring(&b, s, (size_t)(wild - s));  /* push prefix */
 159     luaL_addstring(&b, r);  /* push replacement in place of pattern */
 160     s = wild + l;  /* continue after `p' */
 161   }
 162   luaL_addstring(&b, s);  /* push last suffix */
 163   luaL_pushresult(&b);
 164   return lua_tostring(L, -1);
 165 }
 166 
 167 /* -- Buffer handling ----------------------------------------------------- */
 168 
 169 #define bufflen(B)      ((size_t)((B)->p - (B)->buffer))
 170 #define bufffree(B)     ((size_t)(LUAL_BUFFERSIZE - bufflen(B)))
 171 
 172 static int emptybuffer(luaL_Buffer *B)
 173 {
 174   size_t l = bufflen(B);
 175   if (l == 0)
 176     return 0;  /* put nothing on stack */
 177   lua_pushlstring(B->L, B->buffer, l);
 178   B->p = B->buffer;
 179   B->lvl++;
 180   return 1;
 181 }
 182 
 183 static void adjuststack(luaL_Buffer *B)
 184 {
 185   if (B->lvl > 1) {
 186     lua_State *L = B->L;
 187     int toget = 1;  /* number of levels to concat */
 188     size_t toplen = lua_strlen(L, -1);
 189     do {
 190       size_t l = lua_strlen(L, -(toget+1));
 191       if (!(B->lvl - toget + 1 >= LUA_MINSTACK/2 || toplen > l))
 192         break;
 193       toplen += l;
 194       toget++;
 195     } while (toget < B->lvl);
 196     lua_concat(L, toget);
 197     B->lvl = B->lvl - toget + 1;
 198   }
 199 }
 200 
 201 LUALIB_API char *luaL_prepbuffer(luaL_Buffer *B)
 202 {
 203   if (emptybuffer(B))
 204     adjuststack(B);
 205   return B->buffer;
 206 }
 207 
 208 LUALIB_API void luaL_addlstring(luaL_Buffer *B, const char *s, size_t l)
 209 {
 210   while (l--)
 211     luaL_addchar(B, *s++);
 212 }
 213 
 214 LUALIB_API void luaL_addstring(luaL_Buffer *B, const char *s)
 215 {
 216   luaL_addlstring(B, s, strlen(s));
 217 }
 218 
 219 LUALIB_API void luaL_pushresult(luaL_Buffer *B)
 220 {
 221   emptybuffer(B);
 222   lua_concat(B->L, B->lvl);
 223   B->lvl = 1;
 224 }
 225 
 226 LUALIB_API void luaL_addvalue(luaL_Buffer *B)
 227 {
 228   lua_State *L = B->L;
 229   size_t vl;
 230   const char *s = lua_tolstring(L, -1, &vl);
 231   if (vl <= bufffree(B)) {  /* fit into buffer? */
 232     memcpy(B->p, s, vl);  /* put it there */
 233     B->p += vl;
 234     lua_pop(L, 1);  /* remove from stack */
 235   } else {
 236     if (emptybuffer(B))
 237       lua_insert(L, -2);  /* put buffer before new value */
 238     B->lvl++;  /* add new value into B stack */
 239     adjuststack(B);
 240   }
 241 }
 242 
 243 LUALIB_API void luaL_buffinit(lua_State *L, luaL_Buffer *B)
 244 {
 245   B->L = L;
 246   B->p = B->buffer;
 247   B->lvl = 0;
 248 }
 249 
 250 /* -- Reference management ------------------------------------------------ */
 251 
 252 #define FREELIST_REF    0
 253 
 254 /* Convert a stack index to an absolute index. */
 255 #define abs_index(L, i) \
 256   ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1)
 257 
 258 LUALIB_API int luaL_ref(lua_State *L, int t)
 259 {
 260   int ref;
 261   t = abs_index(L, t);
 262   if (lua_isnil(L, -1)) {
 263     lua_pop(L, 1);  /* remove from stack */
 264     return LUA_REFNIL;  /* `nil' has a unique fixed reference */
 265   }
 266   lua_rawgeti(L, t, FREELIST_REF);  /* get first free element */
 267   ref = (int)lua_tointeger(L, -1);  /* ref = t[FREELIST_REF] */
 268   lua_pop(L, 1);  /* remove it from stack */
 269   if (ref != 0) {  /* any free element? */
 270     lua_rawgeti(L, t, ref);  /* remove it from list */
 271     lua_rawseti(L, t, FREELIST_REF);  /* (t[FREELIST_REF] = t[ref]) */
 272   } else {  /* no free elements */
 273     ref = (int)lua_objlen(L, t);
 274     ref++;  /* create new reference */
 275   }
 276   lua_rawseti(L, t, ref);
 277   return ref;
 278 }
 279 
 280 LUALIB_API void luaL_unref(lua_State *L, int t, int ref)
 281 {
 282   if (ref >= 0) {
 283     t = abs_index(L, t);
 284     lua_rawgeti(L, t, FREELIST_REF);
 285     lua_rawseti(L, t, ref);  /* t[ref] = t[FREELIST_REF] */
 286     lua_pushinteger(L, ref);
 287     lua_rawseti(L, t, FREELIST_REF);  /* t[FREELIST_REF] = ref */
 288   }
 289 }
 290 
 291 /* -- Default allocator and panic function -------------------------------- */
 292 
 293 static int panic(lua_State *L)
 294 {
 295   const char *s = lua_tostring(L, -1);
 296   fputs("PANIC: unprotected error in call to Lua API (", stderr);
 297   fputs(s ? s : "?", stderr);
 298   fputc(')', stderr); fputc('\n', stderr);
 299   fflush(stderr);
 300   return 0;
 301 }
 302 
 303 #ifdef LUAJIT_USE_SYSMALLOC
 304 
 305 #if LJ_64 && !defined(LUAJIT_USE_VALGRIND)
 306 #error "Must use builtin allocator for 64 bit target"
 307 #endif
 308 
 309 static void *mem_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
 310 {
 311   (void)ud;
 312   (void)osize;
 313   if (nsize == 0) {
 314     free(ptr);
 315     return NULL;
 316   } else {
 317     return realloc(ptr, nsize);
 318   }
 319 }
 320 
 321 LUALIB_API lua_State *luaL_newstate(void)
 322 {
 323   lua_State *L = lua_newstate(mem_alloc, NULL);
 324   if (L) G(L)->panic = panic;
 325   return L;
 326 }
 327 
 328 #else
 329 
 330 #include "lj_alloc.h"
 331 
 332 LUALIB_API lua_State *luaL_newstate(void)
 333 {
 334   lua_State *L;
 335   void *ud = lj_alloc_create();
 336   if (ud == NULL) return NULL;
 337 #if LJ_64
 338   L = lj_state_newstate(lj_alloc_f, ud);
 339 #else
 340   L = lua_newstate(lj_alloc_f, ud);
 341 #endif
 342   if (L) G(L)->panic = panic;
 343   return L;
 344 }
 345 
 346 #if LJ_64
 347 LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud)
 348 {
 349   UNUSED(f); UNUSED(ud);
 350   fputs("Must use luaL_newstate() for 64 bit target\n", stderr);
 351   return NULL;
 352 }
 353 #endif
 354 
 355 #endif
 356 

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