mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-27 23:08:31 +00:00
Improve redbean
- Improve serialization - Add Benchmark() API to redbean - Refactor UNIX API to be assert() friendly - Make the redbean Lua REPL print data structures - Fix recent regressions in linenoise reverse search - Add -i flag so redbean can be a language interpreter
This commit is contained in:
parent
2046c0d2ae
commit
451e3f73d9
74 changed files with 1781 additions and 1024 deletions
4
third_party/lua/cosmo.h
vendored
4
third_party/lua/cosmo.h
vendored
|
@ -8,8 +8,8 @@ COSMOPOLITAN_C_START_
|
|||
|
||||
char *LuaFormatStack(lua_State *) dontdiscard;
|
||||
int LuaCallWithTrace(lua_State *, int, int, lua_State *);
|
||||
int LuaEncodeJsonData(lua_State *, char **, int, char *);
|
||||
int LuaEncodeLuaData(lua_State *, char **, int, char *);
|
||||
int LuaEncodeJsonData(lua_State *, char **, int, char *, int);
|
||||
int LuaEncodeLuaData(lua_State *, char **, int, char *, int);
|
||||
int LuaEncodeUrl(lua_State *);
|
||||
int LuaParseUrl(lua_State *);
|
||||
int LuaPushHeader(lua_State *, struct HttpMessage *, char *, int);
|
||||
|
|
13
third_party/lua/escapeluastring.c
vendored
13
third_party/lua/escapeluastring.c
vendored
|
@ -16,20 +16,25 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/stdio/append.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "third_party/lua/cosmo.h"
|
||||
#include "third_party/lua/lua.h"
|
||||
|
||||
void EscapeLuaString(char *s, size_t len, char **buf) {
|
||||
appendw(buf, '"');
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (s[i] == '\\' || s[i] == '\"' || s[i] == '\n' || s[i] == '\0' ||
|
||||
s[i] == '\r') {
|
||||
if (' ' <= s[i] && s[i] <= 0x7e) {
|
||||
appendw(buf, s[i]);
|
||||
} else if (s[i] == '\n') {
|
||||
appendw(buf, '\\' | 'n' << 8);
|
||||
} else if (s[i] == '\\' || s[i] == '\'' || s[i] == '\"') {
|
||||
appendw(buf, '\\' | s[i] << 8);
|
||||
} else {
|
||||
appendw(buf, '\\' | 'x' << 010 |
|
||||
"0123456789abcdef"[(s[i] & 0xF0) >> 4] << 020 |
|
||||
"0123456789abcdef"[(s[i] & 0x0F) >> 0] << 030);
|
||||
} else {
|
||||
appendd(buf, s + i, 1);
|
||||
}
|
||||
}
|
||||
appendw(buf, '"');
|
||||
|
|
57
third_party/lua/lrepl.c
vendored
57
third_party/lua/lrepl.c
vendored
|
@ -32,6 +32,7 @@
|
|||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/nomultics.internal.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
|
@ -50,6 +51,17 @@ Copyright 1994–2021 Lua.org, PUC-Rio.\"");
|
|||
asm(".include \"libc/disclaimer.inc\"");
|
||||
|
||||
|
||||
static const char *const kKeywordHints[] = {
|
||||
"else", //
|
||||
"elseif", //
|
||||
"function", //
|
||||
"function", //
|
||||
"repeat", //
|
||||
"then", //
|
||||
"until", //
|
||||
"while", //
|
||||
};
|
||||
|
||||
bool lua_repl_blocking;
|
||||
bool lua_repl_isterminal;
|
||||
linenoiseCompletionCallback *lua_repl_completions_callback;
|
||||
|
@ -74,46 +86,59 @@ static const char *g_historypath;
|
|||
#define LUA_MAXINPUT 512
|
||||
#endif
|
||||
|
||||
static void lua_readline_addcompletion(linenoiseCompletions *c, char *s) {
|
||||
char **p = c->cvec;
|
||||
size_t n = c->len + 1;
|
||||
if ((p = realloc(p, n * sizeof(*p)))) {
|
||||
p[n - 1] = s;
|
||||
|
||||
static void lua_readline_addcompletion (linenoiseCompletions *c, const char *s) {
|
||||
char **p, *t;
|
||||
if ((p = realloc(c->cvec, (c->len + 1) * sizeof(*p)))) {
|
||||
c->cvec = p;
|
||||
c->len = n;
|
||||
if ((t = strdup(s))) {
|
||||
c->cvec[c->len++] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lua_readline_completions(const char *p, linenoiseCompletions *c) {
|
||||
|
||||
void lua_readline_completions (const char *p, linenoiseCompletions *c) {
|
||||
int i;
|
||||
lua_State *L;
|
||||
const char *name;
|
||||
for (i = 0; i < ARRAYLEN(kKeywordHints); ++i) {
|
||||
if (startswithi(kKeywordHints[i], p)) {
|
||||
lua_readline_addcompletion(c, kKeywordHints[i]);
|
||||
}
|
||||
}
|
||||
L = globalL;
|
||||
lua_pushglobaltable(L);
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2) != 0) {
|
||||
name = lua_tostring(L, -2);
|
||||
if (startswithi(name, p)) {
|
||||
lua_readline_addcompletion(c, strdup(name));
|
||||
lua_readline_addcompletion(c, name);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
lua_repl_completions_callback(p, c);
|
||||
if (lua_repl_completions_callback) {
|
||||
lua_repl_completions_callback(p, c);
|
||||
}
|
||||
}
|
||||
|
||||
char *lua_readline_hint(const char *p, const char **ansi1, const char **ansi2) {
|
||||
char *h = 0;
|
||||
|
||||
char *lua_readline_hint (const char *p, const char **ansi1, const char **ansi2) {
|
||||
char *h;
|
||||
linenoiseCompletions c = {0};
|
||||
lua_readline_completions(p, &c);
|
||||
if (c.len == 1) h = strdup(c.cvec[0] + strlen(p));
|
||||
h = c.len == 1 ? strdup(c.cvec[0] + strlen(p)) : 0;
|
||||
linenoiseFreeCompletions(&c);
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
static void lua_freeline (lua_State *L, char *b) {
|
||||
free(b);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Return the string to be used as a prompt by the interpreter. Leave
|
||||
** the string (or nil, if using the default value) on the stack, to keep
|
||||
|
@ -129,6 +154,7 @@ static const char *get_prompt (lua_State *L, int firstline) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* mark in error messages for incomplete statements */
|
||||
#define EOFMARK "<eof>"
|
||||
#define marklen (sizeof(EOFMARK)/sizeof(char) - 1)
|
||||
|
@ -165,7 +191,7 @@ static ssize_t pushline (lua_State *L, int firstline) {
|
|||
prmt = strdup(get_prompt(L, firstline));
|
||||
lua_pop(L, 1); /* remove prompt */
|
||||
LUA_REPL_UNLOCK;
|
||||
rc = linenoiseEdit(lua_repl_linenoise, prmt, &b, !firstline || lua_repl_blocking);
|
||||
rc = linenoiseEdit(lua_repl_linenoise, 0, &b, !firstline || lua_repl_blocking);
|
||||
free(prmt);
|
||||
if (rc != -1) {
|
||||
if (b && *b) {
|
||||
|
@ -187,10 +213,11 @@ static ssize_t pushline (lua_State *L, int firstline) {
|
|||
l = strlen(b);
|
||||
if (l > 0 && b[l-1] == '\n') /* line ends with newline? */
|
||||
b[--l] = '\0'; /* remove it */
|
||||
if (firstline && b[0] == '=') /* for compatibility with 5.2, ... */
|
||||
if (firstline && b[0] == '=') { /* for compatibility with 5.2, ... */
|
||||
lua_pushfstring(L, "return %s", b + 1); /* change '=' to 'return' */
|
||||
else
|
||||
} else {
|
||||
lua_pushlstring(L, b, l);
|
||||
}
|
||||
lua_freeline(L, b);
|
||||
return 1;
|
||||
}
|
||||
|
|
10
third_party/lua/lua.mk
vendored
10
third_party/lua/lua.mk
vendored
|
@ -80,6 +80,14 @@ o/$(MODE)/third_party/lua/lua.com: \
|
|||
@$(COMPILE) -AZIP -T$@ o/$(MODE)/third_party/zip/zip.com -9qj $@ \
|
||||
o/$(MODE)/third_party/lua/.lua/.symtab
|
||||
|
||||
o//third_party/lua/lgc.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-O2
|
||||
|
||||
o/$(MODE)/third_party/lua/lvm.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-fno-gcse
|
||||
|
||||
o/$(MODE)/third_party/lua/lauxlib.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-DSTACK_FRAME_UNLIMITED
|
||||
|
@ -89,6 +97,8 @@ $(THIRD_PARTY_LUA_OBJS): \
|
|||
-ffunction-sections \
|
||||
-fdata-sections
|
||||
|
||||
$(THIRD_PARTY_LUA_OBJS): third_party/lua/lua.mk
|
||||
|
||||
.PHONY: o/$(MODE)/third_party/lua
|
||||
o/$(MODE)/third_party/lua: \
|
||||
$(THIRD_PARTY_LUA_BINS) \
|
||||
|
|
158
third_party/lua/luaencodejsondata.c
vendored
158
third_party/lua/luaencodejsondata.c
vendored
|
@ -16,6 +16,8 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/stdio/append.internal.h"
|
||||
#include "net/http/escape.h"
|
||||
|
@ -23,63 +25,115 @@
|
|||
#include "third_party/lua/lauxlib.h"
|
||||
#include "third_party/lua/lua.h"
|
||||
|
||||
int LuaEncodeJsonData(lua_State *L, char **buf, int level, char *numformat) {
|
||||
size_t idx = -1;
|
||||
size_t tbllen, buflen;
|
||||
int LuaEncodeJsonData(lua_State *L, char **buf, int level, char *numformat,
|
||||
int idx) {
|
||||
char *s;
|
||||
bool isarray;
|
||||
int t = lua_type(L, idx);
|
||||
if (level < 0) return luaL_argerror(L, 1, "too many nested tables");
|
||||
if (LUA_TSTRING == t) {
|
||||
appendw(buf, '"');
|
||||
appends(buf, gc(EscapeJsStringLiteral(lua_tostring(L, idx), -1, 0)));
|
||||
appendw(buf, '"');
|
||||
} else if (LUA_TNUMBER == t) {
|
||||
appendf(buf, numformat, lua_tonumber(L, idx));
|
||||
} else if (LUA_TBOOLEAN == t) {
|
||||
appends(buf, lua_toboolean(L, idx) ? "true" : "false");
|
||||
} else if (LUA_TTABLE == t) {
|
||||
tbllen = lua_rawlen(L, idx);
|
||||
// encode tables with numeric indices and empty tables as arrays
|
||||
isarray = tbllen > 0 || // integer keys present
|
||||
(lua_pushnil(L), lua_next(L, -2) == 0) || // no non-integer keys
|
||||
(lua_pop(L, 2), false); // pop key/value pushed by lua_next
|
||||
appendw(buf, isarray ? '[' : '{');
|
||||
if (isarray) {
|
||||
for (int i = 1; i <= tbllen; i++) {
|
||||
if (i > 1) appendw(buf, ',');
|
||||
lua_rawgeti(L, -1, i); // table/-2, value/-1
|
||||
LuaEncodeJsonData(L, buf, level - 1, numformat);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
} else {
|
||||
int i = 1;
|
||||
lua_pushnil(L); // push the first key
|
||||
while (lua_next(L, -2) != 0) {
|
||||
if (!lua_isstring(L, -2))
|
||||
return luaL_argerror(L, 1, "expected number or string as key value");
|
||||
if (i++ > 1) appendw(buf, ',');
|
||||
size_t tbllen, z;
|
||||
char ibuf[21], fmt[] = "%.14g";
|
||||
if (level > 0) {
|
||||
switch (lua_type(L, idx)) {
|
||||
case LUA_TSTRING:
|
||||
s = lua_tolstring(L, idx, &z);
|
||||
s = EscapeJsStringLiteral(s, z, &z);
|
||||
appendw(buf, '"');
|
||||
if (lua_type(L, -2) == LUA_TSTRING) {
|
||||
appends(buf, gc(EscapeJsStringLiteral(lua_tostring(L, -2), -1, 0)));
|
||||
appendd(buf, s, z);
|
||||
appendw(buf, '"');
|
||||
free(s);
|
||||
return 0;
|
||||
case LUA_TNIL:
|
||||
appendw(buf, READ32LE("null"));
|
||||
return 0;
|
||||
case LUA_TFUNCTION:
|
||||
appendf(buf, "\"func@%p\"", lua_touserdata(L, idx));
|
||||
return 0;
|
||||
case LUA_TUSERDATA:
|
||||
appendf(buf, "\"udata@%p\"", lua_touserdata(L, idx));
|
||||
return 0;
|
||||
case LUA_TLIGHTUSERDATA:
|
||||
appendf(buf, "\"light@%p\"", lua_touserdata(L, idx));
|
||||
return 0;
|
||||
case LUA_TTHREAD:
|
||||
appendf(buf, "\"thread@%p\"", lua_touserdata(L, idx));
|
||||
return 0;
|
||||
case LUA_TNUMBER:
|
||||
if (lua_isinteger(L, idx)) {
|
||||
appendd(buf, ibuf,
|
||||
FormatInt64(ibuf, luaL_checkinteger(L, idx)) - ibuf);
|
||||
} else {
|
||||
// we'd still prefer to use lua_tostring on a numeric index, but can't
|
||||
// use it in-place, as it breaks lua_next (changes numeric key to a
|
||||
// string)
|
||||
lua_pushvalue(L, -2); // table/-4, key/-3, value/-2, key/-1
|
||||
appends(buf, lua_tostring(L, idx)); // use the copy
|
||||
lua_remove(L, -1); // remove copied key: table/-3, key/-2, value/-1
|
||||
// TODO(jart): replace this api
|
||||
while (*numformat == '%' || *numformat == '.' ||
|
||||
isdigit(*numformat)) {
|
||||
++numformat;
|
||||
}
|
||||
switch (*numformat) {
|
||||
case 'a':
|
||||
case 'g':
|
||||
case 'f':
|
||||
fmt[4] = *numformat;
|
||||
break;
|
||||
default:
|
||||
return luaL_error(L, "numformat string not allowed");
|
||||
}
|
||||
appendf(buf, fmt, lua_tonumber(L, idx));
|
||||
}
|
||||
appendw(buf, '"' | ':' << 010);
|
||||
LuaEncodeJsonData(L, buf, level - 1, numformat);
|
||||
lua_pop(L, 1); // table/-2, key/-1
|
||||
}
|
||||
// stack: table/-1, as the key was popped by lua_next
|
||||
return 0;
|
||||
case LUA_TBOOLEAN:
|
||||
appends(buf, lua_toboolean(L, idx) ? "true" : "false");
|
||||
return 0;
|
||||
case LUA_TTABLE:
|
||||
tbllen = lua_rawlen(L, idx);
|
||||
// encode tables with numeric indices and empty tables as arrays
|
||||
isarray =
|
||||
tbllen > 0 || // integer keys present
|
||||
(lua_pushnil(L), lua_next(L, -2) == 0) || // no non-integer keys
|
||||
(lua_pop(L, 2), false); // pop key/value pushed by lua_next
|
||||
appendw(buf, isarray ? '[' : '{');
|
||||
if (isarray) {
|
||||
for (size_t i = 1; i <= tbllen; i++) {
|
||||
if (i > 1) appendw(buf, ',');
|
||||
lua_rawgeti(L, -1, i); // table/-2, value/-1
|
||||
LuaEncodeJsonData(L, buf, level - 1, numformat, -1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
} else {
|
||||
int i = 1;
|
||||
lua_pushnil(L); // push the first key
|
||||
while (lua_next(L, -2)) {
|
||||
if (!lua_isstring(L, -2)) {
|
||||
luaL_error(L, "expected number or string as key value");
|
||||
unreachable;
|
||||
}
|
||||
if (i++ > 1) appendw(buf, ',');
|
||||
appendw(buf, '"');
|
||||
if (lua_type(L, -2) == LUA_TSTRING) {
|
||||
s = lua_tolstring(L, -2, &z);
|
||||
s = EscapeJsStringLiteral(s, z, &z);
|
||||
appendd(buf, s, z);
|
||||
free(s);
|
||||
} else {
|
||||
// we'd still prefer to use lua_tostring on a numeric index, but
|
||||
// can't use it in-place, as it breaks lua_next (changes numeric
|
||||
// key to a string)
|
||||
lua_pushvalue(L, -2); // table/-4, key/-3, value/-2, key/-1
|
||||
s = lua_tolstring(L, idx, &z);
|
||||
appendd(buf, s, z); // use the copy
|
||||
lua_remove(L, -1); // remove copied key: tab/-3, key/-2, val/-1
|
||||
}
|
||||
appendw(buf, '"' | ':' << 010);
|
||||
LuaEncodeJsonData(L, buf, level - 1, numformat, -1);
|
||||
lua_pop(L, 1); // table/-2, key/-1
|
||||
}
|
||||
// stack: table/-1, as the key was popped by lua_next
|
||||
}
|
||||
appendw(buf, isarray ? ']' : '}');
|
||||
return 0;
|
||||
default:
|
||||
luaL_error(L, "can't serialize value of this type");
|
||||
unreachable;
|
||||
}
|
||||
appendw(buf, isarray ? ']' : '}');
|
||||
} else if (LUA_TNIL == t) {
|
||||
appendd(buf, "null", 4);
|
||||
} else {
|
||||
return luaL_argerror(L, 1, "can't serialize value of this type");
|
||||
luaL_error(L, "too many nested tables");
|
||||
unreachable;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
118
third_party/lua/luaencodeluadata.c
vendored
118
third_party/lua/luaencodeluadata.c
vendored
|
@ -16,51 +16,97 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/stdio/append.internal.h"
|
||||
#include "third_party/lua/cosmo.h"
|
||||
#include "third_party/lua/lauxlib.h"
|
||||
#include "third_party/lua/lua.h"
|
||||
|
||||
int LuaEncodeLuaData(lua_State *L, char **buf, int level, char *numformat) {
|
||||
size_t idx = -1;
|
||||
size_t tbllen, buflen, slen;
|
||||
int LuaEncodeLuaData(lua_State *L, char **buf, int level, char *numformat,
|
||||
int idx) {
|
||||
char *s;
|
||||
int ktype;
|
||||
int t = lua_type(L, idx);
|
||||
if (level < 0) return luaL_argerror(L, 1, "too many nested tables");
|
||||
if (LUA_TSTRING == t) {
|
||||
s = lua_tolstring(L, idx, &slen);
|
||||
EscapeLuaString(s, slen, buf);
|
||||
} else if (LUA_TNUMBER == t) {
|
||||
appendf(buf, numformat, lua_tonumber(L, idx));
|
||||
} else if (LUA_TBOOLEAN == t) {
|
||||
appends(buf, lua_toboolean(L, idx) ? "true" : "false");
|
||||
} else if (LUA_TTABLE == t) {
|
||||
appendw(buf, '{');
|
||||
int i = 0;
|
||||
lua_pushnil(L); // push the first key
|
||||
while (lua_next(L, -2) != 0) {
|
||||
ktype = lua_type(L, -2);
|
||||
if (ktype == LUA_TTABLE)
|
||||
return luaL_argerror(L, 1, "can't serialize key of this type");
|
||||
if (i++ > 0) appendd(buf, ",", 1);
|
||||
if (ktype != LUA_TNUMBER || floor(lua_tonumber(L, -2)) != i) {
|
||||
appendw(buf, '[');
|
||||
lua_pushvalue(L, -2); // table/-4, key/-3, value/-2, key/-1
|
||||
LuaEncodeLuaData(L, buf, level, numformat);
|
||||
lua_remove(L, -1); // remove copied key: table/-3, key/-2, value/-1
|
||||
appendw(buf, ']' | '=' << 010);
|
||||
}
|
||||
LuaEncodeLuaData(L, buf, level - 1, numformat);
|
||||
lua_pop(L, 1); // table/-2, key/-1
|
||||
lua_Integer i;
|
||||
size_t tbllen, buflen, slen;
|
||||
char ibuf[21], fmt[] = "%.14g";
|
||||
if (level > 0) {
|
||||
switch (lua_type(L, idx)) {
|
||||
case LUA_TNIL:
|
||||
appendw(buf, READ32LE("nil"));
|
||||
return 0;
|
||||
case LUA_TSTRING:
|
||||
s = lua_tolstring(L, idx, &slen);
|
||||
EscapeLuaString(s, slen, buf);
|
||||
return 0;
|
||||
case LUA_TFUNCTION:
|
||||
appendf(buf, "\"func@%p\"", lua_touserdata(L, idx));
|
||||
return 0;
|
||||
case LUA_TUSERDATA:
|
||||
appendf(buf, "\"udata@%p\"", lua_touserdata(L, idx));
|
||||
return 0;
|
||||
case LUA_TLIGHTUSERDATA:
|
||||
appendf(buf, "\"light@%p\"", lua_touserdata(L, idx));
|
||||
return 0;
|
||||
case LUA_TTHREAD:
|
||||
appendf(buf, "\"thread@%p\"", lua_touserdata(L, idx));
|
||||
return 0;
|
||||
case LUA_TNUMBER:
|
||||
if (lua_isinteger(L, idx)) {
|
||||
appendd(buf, ibuf,
|
||||
FormatInt64(ibuf, luaL_checkinteger(L, idx)) - ibuf);
|
||||
} else {
|
||||
// TODO(jart): replace this api
|
||||
while (*numformat == '%' || *numformat == '.' ||
|
||||
isdigit(*numformat)) {
|
||||
++numformat;
|
||||
}
|
||||
switch (*numformat) {
|
||||
case 'a':
|
||||
case 'g':
|
||||
case 'f':
|
||||
fmt[4] = *numformat;
|
||||
break;
|
||||
default:
|
||||
return luaL_error(L, "numformat string not allowed");
|
||||
}
|
||||
appendf(buf, fmt, lua_tonumber(L, idx));
|
||||
}
|
||||
return 0;
|
||||
case LUA_TBOOLEAN:
|
||||
if (lua_toboolean(L, idx)) {
|
||||
appendw(buf, READ32LE("true"));
|
||||
} else {
|
||||
appendw(buf, READ64LE("false\0\0"));
|
||||
}
|
||||
return 0;
|
||||
case LUA_TTABLE:
|
||||
i = 0;
|
||||
appendw(buf, '{');
|
||||
lua_pushnil(L); // push the first key
|
||||
while (lua_next(L, -2) != 0) {
|
||||
ktype = lua_type(L, -2);
|
||||
if (i++ > 0) appendw(buf, ',');
|
||||
if (ktype != LUA_TNUMBER || lua_tointeger(L, -2) != i) {
|
||||
appendw(buf, '[');
|
||||
lua_pushvalue(L, -2); // table/-4, key/-3, value/-2, key/-1
|
||||
LuaEncodeLuaData(L, buf, level - 1, numformat, -1);
|
||||
lua_remove(L, -1); // remove copied key: table/-3, key/-2, value/-1
|
||||
appendw(buf, ']' | '=' << 010);
|
||||
}
|
||||
LuaEncodeLuaData(L, buf, level - 1, numformat, -1);
|
||||
lua_pop(L, 1); // table/-2, key/-1
|
||||
}
|
||||
// stack: table/-1, as the key was popped by lua_next
|
||||
appendw(buf, '}');
|
||||
return 0;
|
||||
default:
|
||||
luaL_error(L, "can't serialize value of this type");
|
||||
unreachable;
|
||||
}
|
||||
// stack: table/-1, as the key was popped by lua_next
|
||||
appendw(buf, '}');
|
||||
} else if (LUA_TNIL == t) {
|
||||
appendd(buf, "nil", 3);
|
||||
} else {
|
||||
return luaL_argerror(L, 1, "can't serialize value of this type");
|
||||
luaL_error(L, "too many nested tables");
|
||||
unreachable;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
22
third_party/lua/luaformatstack.c
vendored
22
third_party/lua/luaformatstack.c
vendored
|
@ -18,31 +18,17 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdio/append.internal.h"
|
||||
#include "third_party/lua/cosmo.h"
|
||||
#include "third_party/lua/lauxlib.h"
|
||||
|
||||
dontdiscard char *LuaFormatStack(lua_State *L) {
|
||||
size_t l;
|
||||
int i, top;
|
||||
char *b = 0;
|
||||
char *p, *b = 0;
|
||||
top = lua_gettop(L);
|
||||
for (i = 1; i <= top; i++) {
|
||||
if (i > 1) appendw(&b, '\n');
|
||||
appendf(&b, "\t%d\t%s\t", i, luaL_typename(L, i));
|
||||
switch (lua_type(L, i)) {
|
||||
case LUA_TNUMBER:
|
||||
appendf(&b, "%g", lua_tonumber(L, i));
|
||||
break;
|
||||
case LUA_TSTRING:
|
||||
appends(&b, lua_tostring(L, i));
|
||||
break;
|
||||
case LUA_TBOOLEAN:
|
||||
appends(&b, lua_toboolean(L, i) ? "true" : "false");
|
||||
break;
|
||||
case LUA_TNIL:
|
||||
appends(&b, "nil");
|
||||
break;
|
||||
default:
|
||||
appendf(&b, "%p", lua_topointer(L, i));
|
||||
break;
|
||||
}
|
||||
LuaEncodeLuaData(L, &b, 64, "g", -1);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue