lib_aux.c 9.8 KB

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