2021-10-02 23:39:04 +02:00
|
|
|
#include <string.h>
|
|
|
|
|
2020-11-29 11:45:32 +01:00
|
|
|
#include <lauxlib.h>
|
|
|
|
|
|
|
|
#include "compat.h"
|
|
|
|
|
|
|
|
static int lua_absindex (lua_State *L, int i) {
|
|
|
|
if (i < 0 && i > LUA_REGISTRYINDEX)
|
|
|
|
i += lua_gettop(L) + 1;
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
int luaL_getsubtable (lua_State *L, int i, const char *name) {
|
|
|
|
int abs_i = lua_absindex(L, i);
|
|
|
|
luaL_checkstack(L, 3, "not enough stack slots");
|
|
|
|
lua_pushstring(L, name);
|
|
|
|
lua_gettable(L, abs_i);
|
|
|
|
if (lua_istable(L, -1))
|
|
|
|
return 1;
|
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_newtable(L);
|
|
|
|
lua_pushstring(L, name);
|
|
|
|
lua_pushvalue(L, -2);
|
|
|
|
lua_settable(L, abs_i);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void luaL_requiref (lua_State *L, const char *modname, lua_CFunction openf, int glb) {
|
|
|
|
luaL_checkstack(L, 3, "not enough stack slots available");
|
|
|
|
luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
|
|
|
|
lua_getfield(L, -1, modname);
|
|
|
|
if (lua_isnil(L, -1)) {
|
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_pushcfunction(L, openf);
|
|
|
|
lua_pushstring(L, modname);
|
|
|
|
lua_call(L, 1, 1);
|
|
|
|
lua_pushvalue(L, -1);
|
|
|
|
lua_setfield(L, -3, modname);
|
|
|
|
}
|
|
|
|
if (glb) {
|
|
|
|
lua_pushvalue(L, -1);
|
|
|
|
lua_setglobal(L, modname);
|
|
|
|
}
|
|
|
|
lua_replace(L, -2);
|
|
|
|
}
|
|
|
|
|
|
|
|
void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
|
|
|
|
luaL_checkstack(L, nup+1, "too many upvalues");
|
|
|
|
for (; l->name != NULL; l++) { /* fill the table with given functions */
|
|
|
|
int i;
|
|
|
|
lua_pushstring(L, l->name);
|
|
|
|
for (i = 0; i < nup; i++) /* copy upvalues to the top */
|
|
|
|
lua_pushvalue(L, -(nup + 1));
|
|
|
|
lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
|
|
|
|
lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */
|
|
|
|
}
|
|
|
|
lua_pop(L, nup); /* remove upvalues */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void luaL_setmetatable (lua_State *L, const char *tname) {
|
|
|
|
luaL_checkstack(L, 1, "not enough stack slots");
|
|
|
|
luaL_getmetatable(L, tname);
|
|
|
|
lua_setmetatable(L, -2);
|
|
|
|
}
|
|
|
|
|
2021-10-02 23:39:04 +02:00
|
|
|
void luaL_buffinit (lua_State *L, luaL_Buffer_52 *B) {
|
|
|
|
/* make it crash if used via pointer to a 5.1-style luaL_Buffer */
|
|
|
|
B->b.p = NULL;
|
|
|
|
B->b.L = NULL;
|
|
|
|
B->b.lvl = 0;
|
|
|
|
/* reuse the buffer from the 5.1-style luaL_Buffer though! */
|
|
|
|
B->ptr = B->b.buffer;
|
|
|
|
B->capacity = LUAL_BUFFERSIZE;
|
|
|
|
B->nelems = 0;
|
|
|
|
B->L2 = L;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char *luaL_prepbuffsize (luaL_Buffer_52 *B, size_t s) {
|
|
|
|
if (B->capacity - B->nelems < s) { /* needs to grow */
|
|
|
|
char* newptr = NULL;
|
|
|
|
size_t newcap = B->capacity * 2;
|
|
|
|
if (newcap - B->nelems < s)
|
|
|
|
newcap = B->nelems + s;
|
|
|
|
if (newcap < B->capacity) /* overflow */
|
|
|
|
luaL_error(B->L2, "buffer too large");
|
|
|
|
newptr = lua_newuserdata(B->L2, newcap);
|
|
|
|
memcpy(newptr, B->ptr, B->nelems);
|
|
|
|
if (B->ptr != B->b.buffer)
|
|
|
|
lua_replace(B->L2, -2); /* remove old buffer */
|
|
|
|
B->ptr = newptr;
|
|
|
|
B->capacity = newcap;
|
|
|
|
}
|
|
|
|
return B->ptr+B->nelems;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void luaL_addlstring (luaL_Buffer_52 *B, const char *s, size_t l) {
|
|
|
|
memcpy(luaL_prepbuffsize(B, l), s, l);
|
|
|
|
luaL_addsize(B, l);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void luaL_addvalue (luaL_Buffer_52 *B) {
|
|
|
|
size_t len = 0;
|
|
|
|
const char *s = lua_tolstring(B->L2, -1, &len);
|
|
|
|
if (!s)
|
|
|
|
luaL_error(B->L2, "cannot convert value to string");
|
|
|
|
if (B->ptr != B->b.buffer)
|
|
|
|
lua_insert(B->L2, -2); /* userdata buffer must be at stack top */
|
|
|
|
luaL_addlstring(B, s, len);
|
|
|
|
lua_remove(B->L2, B->ptr != B->b.buffer ? -2 : -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void luaL_pushresult (luaL_Buffer_52 *B) {
|
|
|
|
lua_pushlstring(B->L2, B->ptr, B->nelems);
|
|
|
|
if (B->ptr != B->b.buffer)
|
|
|
|
lua_replace(B->L2, -2); /* remove userdata buffer */
|
|
|
|
}
|
|
|
|
|
|
|
|
#define lua_number2unsigned(i,n) ((i)=(lua_Unsigned)(n))
|
|
|
|
#define lua_unsigned2number(u) \
|
|
|
|
(((u) <= (lua_Unsigned)INT_MAX) ? (lua_Number)(int)(u) : (lua_Number)(u))
|
|
|
|
|
|
|
|
lua_Unsigned luaL_checkunsigned (lua_State *L, int i) {
|
|
|
|
lua_Unsigned result;
|
|
|
|
lua_Number n = lua_tonumber(L, i);
|
|
|
|
if (n == 0 && !lua_isnumber(L, i))
|
|
|
|
luaL_checktype(L, i, LUA_TNUMBER);
|
|
|
|
lua_number2unsigned(result, n);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
lua_Unsigned luaL_optunsigned (lua_State *L, int i, lua_Unsigned def) {
|
|
|
|
return luaL_opt(L, luaL_checkunsigned, i, def);
|
|
|
|
}
|
|
|
|
|
|
|
|
void lua_pushunsigned (lua_State *L, lua_Unsigned n) {
|
|
|
|
lua_pushnumber(L, lua_unsigned2number(n));
|
|
|
|
}
|
|
|
|
|