2 ** Auxiliary library for the Lua/C API.
3 ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h
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
24 #include "lj_vmevent.h"
30 /* -- I/O error handling -------------------------------------------------- */
32 LUALIB_API
int luaL_fileresult(lua_State
*L
, int stat
, const char *fname
)
35 setboolV(L
->top
++, 1);
38 int en
= errno
; /* Lua API calls may change this value. */
41 lua_pushfstring(L
, "%s: %s", fname
, strerror(en
));
43 lua_pushfstring(L
, "%s", strerror(en
));
44 setintV(L
->top
++, en
);
50 LUALIB_API
int luaL_execresult(lua_State
*L
, int stat
)
54 if (WIFSIGNALED(stat
)) {
55 stat
= WTERMSIG(stat
);
57 lua_pushliteral(L
, "signal");
60 stat
= WEXITSTATUS(stat
);
62 setboolV(L
->top
++, 1);
65 lua_pushliteral(L
, "exit");
69 setboolV(L
->top
++, 1);
72 lua_pushliteral(L
, "exit");
74 setintV(L
->top
++, stat
);
77 return luaL_fileresult(L
, 0, NULL
);
80 /* -- Module registration ------------------------------------------------- */
82 LUALIB_API
const char *luaL_findtable(lua_State
*L
, int idx
,
83 const char *fname
, int szhint
)
86 lua_pushvalue(L
, idx
);
88 e
= strchr(fname
, '.');
89 if (e
== NULL
) e
= fname
+ strlen(fname
);
90 lua_pushlstring(L
, fname
, (size_t)(e
- fname
));
92 if (lua_isnil(L
, -1)) { /* no such field? */
93 lua_pop(L
, 1); /* remove this nil */
94 lua_createtable(L
, 0, (*e
== '.' ? 1 : szhint
)); /* new table for field */
95 lua_pushlstring(L
, fname
, (size_t)(e
- fname
));
97 lua_settable(L
, -4); /* set new table into field */
98 } else if (!lua_istable(L
, -1)) { /* field has a non-table value? */
99 lua_pop(L
, 2); /* remove table and value */
100 return fname
; /* return problematic part of the name */
102 lua_remove(L
, -2); /* remove previous table */
108 static int libsize(const luaL_Reg
*l
)
111 for (; l
&& l
->name
; l
++) size
++;
115 LUALIB_API
void luaL_pushmodule(lua_State
*L
, const char *modname
, int sizehint
)
117 luaL_findtable(L
, LUA_REGISTRYINDEX
, "_LOADED", 16);
118 lua_getfield(L
, -1, modname
);
119 if (!lua_istable(L
, -1)) {
121 if (luaL_findtable(L
, LUA_GLOBALSINDEX
, modname
, sizehint
) != NULL
)
122 lj_err_callerv(L
, LJ_ERR_BADMODN
, modname
);
123 lua_pushvalue(L
, -1);
124 lua_setfield(L
, -3, modname
); /* _LOADED[modname] = new table. */
126 lua_remove(L
, -2); /* Remove _LOADED table. */
129 LUALIB_API
void luaL_openlib(lua_State
*L
, const char *libname
,
130 const luaL_Reg
*l
, int nup
)
134 luaL_pushmodule(L
, libname
, libsize(l
));
135 lua_insert(L
, -(nup
+ 1)); /* Move module table below upvalues. */
138 luaL_setfuncs(L
, l
, nup
);
140 lua_pop(L
, nup
); /* Remove upvalues. */
143 LUALIB_API
void luaL_register(lua_State
*L
, const char *libname
,
146 luaL_openlib(L
, libname
, l
, 0);
149 LUALIB_API
void luaL_setfuncs(lua_State
*L
, const luaL_Reg
*l
, int nup
)
151 luaL_checkstack(L
, nup
, "too many upvalues");
152 for (; l
->name
; l
++) {
154 for (i
= 0; i
< nup
; i
++) /* Copy upvalues to the top. */
155 lua_pushvalue(L
, -nup
);
156 lua_pushcclosure(L
, l
->func
, nup
);
157 lua_setfield(L
, -(nup
+ 2), l
->name
);
159 lua_pop(L
, nup
); /* Remove upvalues. */
162 LUALIB_API
const char *luaL_gsub(lua_State
*L
, const char *s
,
163 const char *p
, const char *r
)
166 size_t l
= strlen(p
);
168 luaL_buffinit(L
, &b
);
169 while ((wild
= strstr(s
, p
)) != NULL
) {
170 luaL_addlstring(&b
, s
, (size_t)(wild
- s
)); /* push prefix */
171 luaL_addstring(&b
, r
); /* push replacement in place of pattern */
172 s
= wild
+ l
; /* continue after `p' */
174 luaL_addstring(&b
, s
); /* push last suffix */
176 return lua_tostring(L
, -1);
179 /* -- Buffer handling ----------------------------------------------------- */
181 #define bufflen(B) ((size_t)((B)->p - (B)->buffer))
182 #define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B)))
184 static int emptybuffer(luaL_Buffer
*B
)
186 size_t l
= bufflen(B
);
188 return 0; /* put nothing on stack */
189 lua_pushlstring(B
->L
, B
->buffer
, l
);
195 static void adjuststack(luaL_Buffer
*B
)
199 int toget
= 1; /* number of levels to concat */
200 size_t toplen
= lua_strlen(L
, -1);
202 size_t l
= lua_strlen(L
, -(toget
+1));
203 if (!(B
->lvl
- toget
+ 1 >= LUA_MINSTACK
/2 || toplen
> l
))
207 } while (toget
< B
->lvl
);
208 lua_concat(L
, toget
);
209 B
->lvl
= B
->lvl
- toget
+ 1;
213 LUALIB_API
char *luaL_prepbuffer(luaL_Buffer
*B
)
220 LUALIB_API
void luaL_addlstring(luaL_Buffer
*B
, const char *s
, size_t l
)
222 if (l
<= bufffree(B
)) {
227 lua_pushlstring(B
->L
, s
, l
);
233 LUALIB_API
void luaL_addstring(luaL_Buffer
*B
, const char *s
)
235 luaL_addlstring(B
, s
, strlen(s
));
238 LUALIB_API
void luaL_pushresult(luaL_Buffer
*B
)
241 lua_concat(B
->L
, B
->lvl
);
245 LUALIB_API
void luaL_addvalue(luaL_Buffer
*B
)
249 const char *s
= lua_tolstring(L
, -1, &vl
);
250 if (vl
<= bufffree(B
)) { /* fit into buffer? */
251 memcpy(B
->p
, s
, vl
); /* put it there */
253 lua_pop(L
, 1); /* remove from stack */
256 lua_insert(L
, -2); /* put buffer before new value */
257 B
->lvl
++; /* add new value into B stack */
262 LUALIB_API
void luaL_buffinit(lua_State
*L
, luaL_Buffer
*B
)
269 /* -- Reference management ------------------------------------------------ */
271 #define FREELIST_REF 0
273 /* Convert a stack index to an absolute index. */
274 #define abs_index(L, i) \
275 ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1)
277 LUALIB_API
int luaL_ref(lua_State
*L
, int t
)
281 if (lua_isnil(L
, -1)) {
282 lua_pop(L
, 1); /* remove from stack */
283 return LUA_REFNIL
; /* `nil' has a unique fixed reference */
285 lua_rawgeti(L
, t
, FREELIST_REF
); /* get first free element */
286 ref
= (int)lua_tointeger(L
, -1); /* ref = t[FREELIST_REF] */
287 lua_pop(L
, 1); /* remove it from stack */
288 if (ref
!= 0) { /* any free element? */
289 lua_rawgeti(L
, t
, ref
); /* remove it from list */
290 lua_rawseti(L
, t
, FREELIST_REF
); /* (t[FREELIST_REF] = t[ref]) */
291 } else { /* no free elements */
292 ref
= (int)lua_objlen(L
, t
);
293 ref
++; /* create new reference */
295 lua_rawseti(L
, t
, ref
);
299 LUALIB_API
void luaL_unref(lua_State
*L
, int t
, int ref
)
303 lua_rawgeti(L
, t
, FREELIST_REF
);
304 lua_rawseti(L
, t
, ref
); /* t[ref] = t[FREELIST_REF] */
305 lua_pushinteger(L
, ref
);
306 lua_rawseti(L
, t
, FREELIST_REF
); /* t[FREELIST_REF] = ref */
310 /* -- Default allocator and panic function -------------------------------- */
312 static int panic(lua_State
*L
)
314 const char *s
= lua_tostring(L
, -1);
315 fputs("PANIC: unprotected error in call to Lua API (", stderr
);
316 fputs(s
? s
: "?", stderr
);
317 fputc(')', stderr
); fputc('\n', stderr
);
322 #ifndef LUAJIT_DISABLE_VMEVENT
323 static int error_finalizer(lua_State
*L
)
325 const char *s
= lua_tostring(L
, -1);
326 fputs("ERROR in finalizer: ", stderr
);
327 fputs(s
? s
: "?", stderr
);
334 #ifdef LUAJIT_USE_SYSMALLOC
336 #if LJ_64 && !LJ_GC64 && !defined(LUAJIT_USE_VALGRIND)
337 #error "Must use builtin allocator for 64 bit target"
340 static void *mem_alloc(void *ud
, void *ptr
, size_t osize
, size_t nsize
)
348 return realloc(ptr
, nsize
);
352 LUALIB_API lua_State
*luaL_newstate(void)
354 lua_State
*L
= lua_newstate(mem_alloc
, NULL
);
357 #ifndef LUAJIT_DISABLE_VMEVENT
358 luaL_findtable(L
, LUA_REGISTRYINDEX
, LJ_VMEVENTS_REGKEY
, LJ_VMEVENTS_HSIZE
);
359 lua_pushcfunction(L
, error_finalizer
);
360 lua_rawseti(L
, -2, VMEVENT_HASH(LJ_VMEVENT_ERRFIN
));
361 G(L
)->vmevmask
= VMEVENT_MASK(LJ_VMEVENT_ERRFIN
);
370 LUALIB_API lua_State
*luaL_newstate(void)
373 #if LJ_64 && !LJ_GC64
374 L
= lj_state_newstate(LJ_ALLOCF_INTERNAL
, NULL
);
376 L
= lua_newstate(LJ_ALLOCF_INTERNAL
, NULL
);
380 #ifndef LUAJIT_DISABLE_VMEVENT
381 luaL_findtable(L
, LUA_REGISTRYINDEX
, LJ_VMEVENTS_REGKEY
, LJ_VMEVENTS_HSIZE
);
382 lua_pushcfunction(L
, error_finalizer
);
383 lua_rawseti(L
, -2, VMEVENT_HASH(LJ_VMEVENT_ERRFIN
));
384 G(L
)->vmevmask
= VMEVENT_MASK(LJ_VMEVENT_ERRFIN
);
391 #if LJ_64 && !LJ_GC64
392 LUA_API lua_State
*lua_newstate(lua_Alloc f
, void *ud
)
394 UNUSED(f
); UNUSED(ud
);
395 fputs("Must use luaL_newstate() for 64 bit target\n", stderr
);