lib_aux.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /*
  2. ** Auxiliary library for the Lua/C API.
  3. ** Copyright (C) 2005-2016 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