Add Lua compiler

Redbean Lua Server Pages may now be stored in the zip as byte code. This
can improve performance, since redbean currently doesn't cache byte code
but it might be more useful for anyone wanting to create a closed source
redbean. The .lua extension should be used for byte code files. Lua will
tell them apart based on a magic number at the start of the file.

This change also improves some Lua error reporting conditions. See #97
This commit is contained in:
Justine Tunney 2021-08-09 13:09:14 -07:00
parent b703eee96e
commit 3bfb7580c5
16 changed files with 864 additions and 91 deletions

View file

@ -79,4 +79,7 @@ o/$(MODE)/%.zip.o: % ; @$(COMPILE) -AZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLA
o/$(MODE)/%-gcc.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $< o/$(MODE)/%-gcc.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
o/$(MODE)/%-clang.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $< || echo / need $(CLANG) >$@ o/$(MODE)/%-clang.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $< || echo / need $(CLANG) >$@
o/$(MODE)/%.lua: %.lua o/$(MODE)/third_party/lua/luac.com
@$(COMPILE) -ALUAC -T$@ o/$(MODE)/third_party/lua/luac.com -s -o $@ $<
o/$(MODE)/%-clang.asm: CC = $(CLANG) o/$(MODE)/%-clang.asm: CC = $(CLANG)

View file

@ -1,3 +1,26 @@
origin https://github.com/lua/lua/ DESCRIPTION
commit c03c527fd207b4ad8f5a8e0f4f2c176bd227c979
date Mon Feb 15 13:31:45 2021 -0300 Lua is a language designed for embedded use in native applications. It
has an impossibly elegant C API and the Lua language itself feels more
like Python compared to alternatives like Tcl except it's a great deal
faster and doesn't have strong opinions about character encoding.
PROVENANCE
https://github.com/lua/lua/
commit e7803f7dbcdc966ab1f9db143424ee811ab1a398
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Wed Mar 3 09:44:20 2021 -0300
New release number (5.4.3)
luac.c needed to be sourced from:
https://www.lua.org/ftp/lua-5.4.3.tar.gz
LOCAL MODIFICATIONS
The `\e` string literal escape sequence has been added, which is
equivalent to `\27` (the Lua version of `\033`) or the ASCII ESC
character. It may be used for teletypewriter control like having
bold text, which can be encoded elegantly as `\e[1mHELLO\e[0m`.

View file

@ -131,21 +131,21 @@ LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1,
while (lua_getstack(L1, level++, &ar)) { while (lua_getstack(L1, level++, &ar)) {
if (limit2show-- == 0) { /* too many levels? */ if (limit2show-- == 0) { /* too many levels? */
int n = last - level - LEVELS2 + 1; /* number of levels to skip */ int n = last - level - LEVELS2 + 1; /* number of levels to skip */
lua_pushfstring(L, "\n\t...\t(skipping %d levels)", n); lua_pushfstring(L, "\n...(skipping %d levels)", n);
luaL_addvalue(&b); /* add warning about skip */ luaL_addvalue(&b); /* add warning about skip */
level += n; /* and skip to last levels */ level += n; /* and skip to last levels */
} }
else { else {
lua_getinfo(L1, "Slnt", &ar); lua_getinfo(L1, "Slnt", &ar);
if (ar.currentline <= 0) if (ar.currentline <= 0)
lua_pushfstring(L, "\n\t%s: in ", ar.short_src); lua_pushfstring(L, "\n%s: in ", ar.short_src);
else else
lua_pushfstring(L, "\n\t%s:%d: in ", ar.short_src, ar.currentline); lua_pushfstring(L, "\n%s:%d: in ", ar.short_src, ar.currentline);
luaL_addvalue(&b); luaL_addvalue(&b);
pushfuncname(L, &ar); pushfuncname(L, &ar);
luaL_addvalue(&b); luaL_addvalue(&b);
if (ar.istailcall) if (ar.istailcall)
luaL_addstring(&b, "\n\t(...tail calls...)"); luaL_addstring(&b, "\n(...tail calls...)");
} }
} }
luaL_pushresult(&b); luaL_pushresult(&b);

View file

@ -15,6 +15,7 @@
#include "third_party/lua/lobject.h" #include "third_party/lua/lobject.h"
#include "third_party/lua/lprefix.h" #include "third_party/lua/lprefix.h"
#include "third_party/lua/lstate.h" #include "third_party/lua/lstate.h"
#include "third_party/lua/ltm.h"
#include "third_party/lua/lua.h" #include "third_party/lua/lua.h"
/* clang-format off */ /* clang-format off */

View file

@ -20,26 +20,6 @@
/* clang-format off */ /* clang-format off */
/*
** Computes ceil(log2(x))
*/
int luaO_ceillog2 (unsigned int x) {
static const lu_byte log_2[256] = { /* log_2[i] = ceil(log2(i - 1)) */
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
};
int l = 0;
x--;
while (x >= 256) { l += 8; x >>= 8; }
return l + log_2[x];
}
static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, static lua_Integer intarith (lua_State *L, int op, lua_Integer v1,
lua_Integer v2) { lua_Integer v2) {

View file

@ -7,6 +7,7 @@
#ifndef lobject_h #ifndef lobject_h
#define lobject_h #define lobject_h
#include "libc/nexgen32e/bsr.h"
#include "third_party/lua/llimits.h" #include "third_party/lua/llimits.h"
#include "third_party/lua/lua.h" #include "third_party/lua/lua.h"
@ -15,17 +16,14 @@
/* /*
** Extra types for collectable non-values ** Extra types for collectable non-values
*/ */
#define LUA_TUPVAL LUA_NUMTYPES /* upvalues */ #define LUA_TUPVAL LUA_NUMTYPES /* upvalues */
#define LUA_TPROTO (LUA_NUMTYPES+1) /* function prototypes */ #define LUA_TPROTO (LUA_NUMTYPES + 1) /* function prototypes */
#define LUA_TDEADKEY (LUA_NUMTYPES+2) /* removed keys in tables */ #define LUA_TDEADKEY (LUA_NUMTYPES + 2) /* removed keys in tables */
/* /*
** number of all possible types (including LUA_TNONE but excluding DEADKEY) ** number of all possible types (including LUA_TNONE but excluding DEADKEY)
*/ */
#define LUA_TOTALTYPES (LUA_TPROTO + 2) #define LUA_TOTALTYPES (LUA_TPROTO + 2)
/* /*
** tags for Tagged Values have the following use of bits: ** tags for Tagged Values have the following use of bits:
@ -778,7 +776,6 @@ typedef struct Table {
#define UTF8BUFFSZ 8 #define UTF8BUFFSZ 8
LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x); LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x);
LUAI_FUNC int luaO_ceillog2 (unsigned int x);
LUAI_FUNC int luaO_rawarith (lua_State *L, int op, const TValue *p1, LUAI_FUNC int luaO_rawarith (lua_State *L, int op, const TValue *p1,
const TValue *p2, TValue *res); const TValue *p2, TValue *res);
LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1, LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1,
@ -791,6 +788,11 @@ LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t srclen); LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t srclen);
/*
** Computes ceil(log2(x))
*/
static inline int luaO_ceillog2 (unsigned int x) {
return --x ? bsr(x) + 1 : 0;
}
#endif #endif

View file

@ -9,9 +9,9 @@
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "third_party/lua/lobject.h" #include "third_party/lua/lobject.h"
#include "third_party/lua/ltm.h"
#include "third_party/lua/lua.h" #include "third_party/lua/lua.h"
#include "third_party/lua/lzio.h" #include "third_party/lua/lzio.h"
#include "third_party/lua/tms.h"
/* clang-format off */ /* clang-format off */

35
third_party/lua/ltm.h vendored
View file

@ -9,43 +9,10 @@
#include "third_party/lua/lobject.h" #include "third_party/lua/lobject.h"
#include "third_party/lua/luaconf.h" #include "third_party/lua/luaconf.h"
#include "third_party/lua/tms.h"
/* clang-format off */ /* clang-format off */
/*
* WARNING: if you change the order of this enumeration,
* grep "ORDER TM" and "ORDER OP"
*/
typedef enum {
TM_INDEX,
TM_NEWINDEX,
TM_GC,
TM_MODE,
TM_LEN,
TM_EQ, /* last tag method with fast access */
TM_ADD,
TM_SUB,
TM_MUL,
TM_MOD,
TM_POW,
TM_DIV,
TM_IDIV,
TM_BAND,
TM_BOR,
TM_BXOR,
TM_SHL,
TM_SHR,
TM_UNM,
TM_BNOT,
TM_LT,
TM_LE,
TM_CONCAT,
TM_CALL,
TM_CLOSE,
TM_N /* number of elements in the enum */
} TMS;
/* /*
** Mask with 1 in all fast-access methods. A 1 in any of these bits ** Mask with 1 in all fast-access methods. A 1 in any of these bits
** in the flag of a (meta)table means the metatable does not have the ** in the flag of a (meta)table means the metatable does not have the

View file

@ -14,7 +14,8 @@ THIRD_PARTY_LUA_OBJS = \
$(THIRD_PARTY_LUA_SRCS:%.c=o/$(MODE)/%.o) $(THIRD_PARTY_LUA_SRCS:%.c=o/$(MODE)/%.o)
THIRD_PARTY_LUA_COMS = \ THIRD_PARTY_LUA_COMS = \
o/$(MODE)/third_party/lua/lua.com o/$(MODE)/third_party/lua/lua.com \
o/$(MODE)/third_party/lua/luac.com
THIRD_PARTY_LUA_CHECKS = \ THIRD_PARTY_LUA_CHECKS = \
$(THIRD_PARTY_LUA_A).pkg \ $(THIRD_PARTY_LUA_A).pkg \
@ -41,7 +42,7 @@ THIRD_PARTY_LUA_DEPS := \
$(THIRD_PARTY_LUA_A): \ $(THIRD_PARTY_LUA_A): \
third_party/lua/ \ third_party/lua/ \
$(THIRD_PARTY_LUA_A).pkg \ $(THIRD_PARTY_LUA_A).pkg \
$(filter-out %/lua.o,$(THIRD_PARTY_LUA_OBJS)) $(filter-out %.main.o,$(THIRD_PARTY_LUA_OBJS))
$(THIRD_PARTY_LUA_A).pkg: \ $(THIRD_PARTY_LUA_A).pkg: \
$(THIRD_PARTY_LUA_OBJS) \ $(THIRD_PARTY_LUA_OBJS) \
@ -56,6 +57,15 @@ o/$(MODE)/third_party/lua/lua.com.dbg: \
$(APE) $(APE)
-@$(APELINK) -@$(APELINK)
o/$(MODE)/third_party/lua/luac.com.dbg: \
$(THIRD_PARTY_LUA_DEPS) \
$(THIRD_PARTY_LUA_A) \
$(THIRD_PARTY_LUA_A).pkg \
o/$(MODE)/third_party/lua/luac.o \
$(CRT) \
$(APE)
-@$(APELINK)
o/$(MODE)/third_party/lua/lauxlib.o: \ o/$(MODE)/third_party/lua/lauxlib.o: \
OVERRIDE_CFLAGS += \ OVERRIDE_CFLAGS += \
-DSTACK_FRAME_UNLIMITED -DSTACK_FRAME_UNLIMITED

724
third_party/lua/luac.main.c vendored Normal file
View file

@ -0,0 +1,724 @@
/*
** $Id: luac.c $
** Lua compiler (saves bytecodes to files; also lists bytecodes)
** See Copyright Notice in lua.h
*/
#define luac_c
#define LUA_CORE
#include "libc/calls/calls.h"
#include "libc/calls/sigbits.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/errno.h"
#include "libc/sysv/consts/exit.h"
#include "third_party/lua/lauxlib.h"
#include "third_party/lua/ldebug.h"
#include "third_party/lua/lobject.h"
#include "third_party/lua/lopcodes.h"
#include "third_party/lua/lopnames.inc"
#include "third_party/lua/lprefix.h"
#include "third_party/lua/lstate.h"
#include "third_party/lua/lua.h"
#include "third_party/lua/lualib.h"
#include "third_party/lua/lundump.h"
/* clang-format off */
static void PrintFunction(const Proto* f, int full);
#define luaU_print PrintFunction
#define PROGNAME "luac" /* default program name */
#define OUTPUT PROGNAME ".out" /* default output file */
static int listing=0; /* list bytecodes? */
static int dumping=1; /* dump bytecodes? */
static int stripping=0; /* strip debug information? */
static char Output[]={ OUTPUT }; /* default output file name */
static const char* output=Output; /* actual output file name */
static const char* progname=PROGNAME; /* actual program name */
static TString **tmname;
static void fatal(const char* message)
{
fprintf(stderr,"%s: %s\n",progname,message);
exit(EXIT_FAILURE);
}
static void cannot(const char* what)
{
fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno));
exit(EXIT_FAILURE);
}
static void usage(const char* message)
{
if (*message=='-')
fprintf(stderr,"%s: unrecognized option '%s'\n",progname,message);
else
fprintf(stderr,"%s: %s\n",progname,message);
fprintf(stderr,
"usage: %s [options] [filenames]\n"
"Available options are:\n"
" -l list (use -l -l for full listing)\n"
" -o name output to file 'name' (default is \"%s\")\n"
" -p parse only\n"
" -s strip debug information\n"
" -v show version information\n"
" -- stop handling options\n"
" - stop handling options and process stdin\n"
,progname,Output);
exit(EXIT_FAILURE);
}
#define IS(s) (strcmp(argv[i],s)==0)
static int doargs(int argc, char* argv[])
{
int i;
int version=0;
if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0];
for (i=1; i<argc; i++)
{
if (*argv[i]!='-') /* end of options; keep it */
break;
else if (IS("--")) /* end of options; skip it */
{
++i;
if (version) ++version;
break;
}
else if (IS("-")) /* end of options; use stdin */
break;
else if (IS("-l")) /* list */
++listing;
else if (IS("-o")) /* output file */
{
output=argv[++i];
if (output==NULL || *output==0 || (*output=='-' && output[1]!=0))
usage("'-o' needs argument");
if (IS("-")) output=NULL;
}
else if (IS("-p")) /* parse only */
dumping=0;
else if (IS("-s")) /* strip debug information */
stripping=1;
else if (IS("-v")) /* show version */
++version;
else /* unknown option */
usage(argv[i]);
}
if (i==argc && (listing || !dumping))
{
dumping=0;
argv[--i]=Output;
}
if (version)
{
printf("%s\n",LUA_COPYRIGHT);
if (version==argc-1) exit(EXIT_SUCCESS);
}
return i;
}
#define FUNCTION "(function()end)();"
static const char* reader(lua_State* L, void* ud, size_t* size)
{
UNUSED(L);
if ((*(int*)ud)--)
{
*size=sizeof(FUNCTION)-1;
return FUNCTION;
}
else
{
*size=0;
return NULL;
}
}
#define toproto(L,i) getproto(s2v(L->top+(i)))
static const Proto* combine(lua_State* L, int n)
{
if (n==1)
return toproto(L,-1);
else
{
Proto* f;
int i=n;
if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1));
f=toproto(L,-1);
for (i=0; i<n; i++)
{
f->p[i]=toproto(L,i-n-1);
if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0;
}
f->sizelineinfo=0;
return f;
}
}
static int writer(lua_State* L, const void* p, size_t size, void* u)
{
UNUSED(L);
return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0);
}
static int pmain(lua_State* L)
{
int argc=(int)lua_tointeger(L,1);
char** argv=(char**)lua_touserdata(L,2);
const Proto* f;
int i;
tmname=G(L)->tmname;
if (!lua_checkstack(L,argc)) fatal("too many input files");
for (i=0; i<argc; i++)
{
const char* filename=IS("-") ? NULL : argv[i];
if (luaL_loadfile(L,filename)!=LUA_OK) fatal(lua_tostring(L,-1));
}
f=combine(L,argc);
if (listing) luaU_print(f,listing>1);
if (dumping)
{
FILE* D= (output==NULL) ? stdout : fopen(output,"wb");
if (D==NULL) cannot("open");
lua_lock(L);
luaU_dump(L,f,writer,D,stripping);
lua_unlock(L);
if (ferror(D)) cannot("write");
if (fclose(D)) cannot("close");
}
return 0;
}
int main(int argc, char* argv[])
{
lua_State* L;
int i=doargs(argc,argv);
argc-=i; argv+=i;
if (argc<=0) usage("no input files given");
L=luaL_newstate();
if (L==NULL) fatal("cannot create state: not enough memory");
lua_pushcfunction(L,&pmain);
lua_pushinteger(L,argc);
lua_pushlightuserdata(L,argv);
if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1));
lua_close(L);
return EXIT_SUCCESS;
}
/*
** print bytecodes
*/
#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-")
#define VOID(p) ((const void*)(p))
#define eventname(i) (getstr(tmname[i]))
static void PrintString(const TString* ts)
{
const char* s=getstr(ts);
size_t i,n=tsslen(ts);
printf("\"");
for (i=0; i<n; i++)
{
int c=(int)(unsigned char)s[i];
switch (c)
{
case '"':
printf("\\\"");
break;
case '\\':
printf("\\\\");
break;
case '\a':
printf("\\a");
break;
case '\b':
printf("\\b");
break;
case '\f':
printf("\\f");
break;
case '\n':
printf("\\n");
break;
case '\r':
printf("\\r");
break;
case '\t':
printf("\\t");
break;
case '\v':
printf("\\v");
break;
default:
if (isprint(c)) printf("%c",c); else printf("\\%03d",c);
break;
}
}
printf("\"");
}
static void PrintType(const Proto* f, int i)
{
const TValue* o=&f->k[i];
switch (ttypetag(o))
{
case LUA_VNIL:
printf("N");
break;
case LUA_VFALSE:
case LUA_VTRUE:
printf("B");
break;
case LUA_VNUMFLT:
printf("F");
break;
case LUA_VNUMINT:
printf("I");
break;
case LUA_VSHRSTR:
case LUA_VLNGSTR:
printf("S");
break;
default: /* cannot happen */
printf("?%d",ttypetag(o));
break;
}
printf("\t");
}
static void PrintConstant(const Proto* f, int i)
{
const TValue* o=&f->k[i];
switch (ttypetag(o))
{
case LUA_VNIL:
printf("nil");
break;
case LUA_VFALSE:
printf("false");
break;
case LUA_VTRUE:
printf("true");
break;
case LUA_VNUMFLT:
{
char buff[100];
sprintf(buff,LUA_NUMBER_FMT,fltvalue(o));
printf("%s",buff);
if (buff[strspn(buff,"-0123456789")]=='\0') printf(".0");
break;
}
case LUA_VNUMINT:
printf(LUA_INTEGER_FMT,ivalue(o));
break;
case LUA_VSHRSTR:
case LUA_VLNGSTR:
PrintString(tsvalue(o));
break;
default: /* cannot happen */
printf("?%d",ttypetag(o));
break;
}
}
#define COMMENT "\t; "
#define EXTRAARG GETARG_Ax(code[pc+1])
#define EXTRAARGC (EXTRAARG*(MAXARG_C+1))
#define ISK (isk ? "k" : "")
static void PrintCode(const Proto* f)
{
const Instruction* code=f->code;
int pc,n=f->sizecode;
for (pc=0; pc<n; pc++)
{
Instruction i=code[pc];
OpCode o=GET_OPCODE(i);
int a=GETARG_A(i);
int b=GETARG_B(i);
int c=GETARG_C(i);
int ax=GETARG_Ax(i);
int bx=GETARG_Bx(i);
int sb=GETARG_sB(i);
int sc=GETARG_sC(i);
int sbx=GETARG_sBx(i);
int isk=GETARG_k(i);
int line=luaG_getfuncline(f,pc);
printf("\t%d\t",pc+1);
if (line>0) printf("[%d]\t",line); else printf("[-]\t");
printf("%-9s\t",opnames[o]);
switch (o)
{
case OP_MOVE:
printf("%d %d",a,b);
break;
case OP_LOADI:
printf("%d %d",a,sbx);
break;
case OP_LOADF:
printf("%d %d",a,sbx);
break;
case OP_LOADK:
printf("%d %d",a,bx);
printf(COMMENT); PrintConstant(f,bx);
break;
case OP_LOADKX:
printf("%d",a);
printf(COMMENT); PrintConstant(f,EXTRAARG);
break;
case OP_LOADFALSE:
printf("%d",a);
break;
case OP_LFALSESKIP:
printf("%d",a);
break;
case OP_LOADTRUE:
printf("%d",a);
break;
case OP_LOADNIL:
printf("%d %d",a,b);
printf(COMMENT "%d out",b+1);
break;
case OP_GETUPVAL:
printf("%d %d",a,b);
printf(COMMENT "%s",UPVALNAME(b));
break;
case OP_SETUPVAL:
printf("%d %d",a,b);
printf(COMMENT "%s",UPVALNAME(b));
break;
case OP_GETTABUP:
printf("%d %d %d",a,b,c);
printf(COMMENT "%s",UPVALNAME(b));
printf(" "); PrintConstant(f,c);
break;
case OP_GETTABLE:
printf("%d %d %d",a,b,c);
break;
case OP_GETI:
printf("%d %d %d",a,b,c);
break;
case OP_GETFIELD:
printf("%d %d %d",a,b,c);
printf(COMMENT); PrintConstant(f,c);
break;
case OP_SETTABUP:
printf("%d %d %d%s",a,b,c,ISK);
printf(COMMENT "%s",UPVALNAME(a));
printf(" "); PrintConstant(f,b);
if (isk) { printf(" "); PrintConstant(f,c); }
break;
case OP_SETTABLE:
printf("%d %d %d%s",a,b,c,ISK);
if (isk) { printf(COMMENT); PrintConstant(f,c); }
break;
case OP_SETI:
printf("%d %d %d%s",a,b,c,ISK);
if (isk) { printf(COMMENT); PrintConstant(f,c); }
break;
case OP_SETFIELD:
printf("%d %d %d%s",a,b,c,ISK);
printf(COMMENT); PrintConstant(f,b);
if (isk) { printf(" "); PrintConstant(f,c); }
break;
case OP_NEWTABLE:
printf("%d %d %d",a,b,c);
printf(COMMENT "%d",c+EXTRAARGC);
break;
case OP_SELF:
printf("%d %d %d%s",a,b,c,ISK);
if (isk) { printf(COMMENT); PrintConstant(f,c); }
break;
case OP_ADDI:
printf("%d %d %d",a,b,sc);
break;
case OP_ADDK:
printf("%d %d %d",a,b,c);
printf(COMMENT); PrintConstant(f,c);
break;
case OP_SUBK:
printf("%d %d %d",a,b,c);
printf(COMMENT); PrintConstant(f,c);
break;
case OP_MULK:
printf("%d %d %d",a,b,c);
printf(COMMENT); PrintConstant(f,c);
break;
case OP_MODK:
printf("%d %d %d",a,b,c);
printf(COMMENT); PrintConstant(f,c);
break;
case OP_POWK:
printf("%d %d %d",a,b,c);
printf(COMMENT); PrintConstant(f,c);
break;
case OP_DIVK:
printf("%d %d %d",a,b,c);
printf(COMMENT); PrintConstant(f,c);
break;
case OP_IDIVK:
printf("%d %d %d",a,b,c);
printf(COMMENT); PrintConstant(f,c);
break;
case OP_BANDK:
printf("%d %d %d",a,b,c);
printf(COMMENT); PrintConstant(f,c);
break;
case OP_BORK:
printf("%d %d %d",a,b,c);
printf(COMMENT); PrintConstant(f,c);
break;
case OP_BXORK:
printf("%d %d %d",a,b,c);
printf(COMMENT); PrintConstant(f,c);
break;
case OP_SHRI:
printf("%d %d %d",a,b,sc);
break;
case OP_SHLI:
printf("%d %d %d",a,b,sc);
break;
case OP_ADD:
printf("%d %d %d",a,b,c);
break;
case OP_SUB:
printf("%d %d %d",a,b,c);
break;
case OP_MUL:
printf("%d %d %d",a,b,c);
break;
case OP_MOD:
printf("%d %d %d",a,b,c);
break;
case OP_POW:
printf("%d %d %d",a,b,c);
break;
case OP_DIV:
printf("%d %d %d",a,b,c);
break;
case OP_IDIV:
printf("%d %d %d",a,b,c);
break;
case OP_BAND:
printf("%d %d %d",a,b,c);
break;
case OP_BOR:
printf("%d %d %d",a,b,c);
break;
case OP_BXOR:
printf("%d %d %d",a,b,c);
break;
case OP_SHL:
printf("%d %d %d",a,b,c);
break;
case OP_SHR:
printf("%d %d %d",a,b,c);
break;
case OP_MMBIN:
printf("%d %d %d",a,b,c);
printf(COMMENT "%s",eventname(c));
break;
case OP_MMBINI:
printf("%d %d %d %d",a,sb,c,isk);
printf(COMMENT "%s",eventname(c));
if (isk) printf(" flip");
break;
case OP_MMBINK:
printf("%d %d %d %d",a,b,c,isk);
printf(COMMENT "%s ",eventname(c)); PrintConstant(f,b);
if (isk) printf(" flip");
break;
case OP_UNM:
printf("%d %d",a,b);
break;
case OP_BNOT:
printf("%d %d",a,b);
break;
case OP_NOT:
printf("%d %d",a,b);
break;
case OP_LEN:
printf("%d %d",a,b);
break;
case OP_CONCAT:
printf("%d %d",a,b);
break;
case OP_CLOSE:
printf("%d",a);
break;
case OP_TBC:
printf("%d",a);
break;
case OP_JMP:
printf("%d",GETARG_sJ(i));
printf(COMMENT "to %d",GETARG_sJ(i)+pc+2);
break;
case OP_EQ:
printf("%d %d %d",a,b,isk);
break;
case OP_LT:
printf("%d %d %d",a,b,isk);
break;
case OP_LE:
printf("%d %d %d",a,b,isk);
break;
case OP_EQK:
printf("%d %d %d",a,b,isk);
printf(COMMENT); PrintConstant(f,b);
break;
case OP_EQI:
printf("%d %d %d",a,sb,isk);
break;
case OP_LTI:
printf("%d %d %d",a,sb,isk);
break;
case OP_LEI:
printf("%d %d %d",a,sb,isk);
break;
case OP_GTI:
printf("%d %d %d",a,sb,isk);
break;
case OP_GEI:
printf("%d %d %d",a,sb,isk);
break;
case OP_TEST:
printf("%d %d",a,isk);
break;
case OP_TESTSET:
printf("%d %d %d",a,b,isk);
break;
case OP_CALL:
printf("%d %d %d",a,b,c);
printf(COMMENT);
if (b==0) printf("all in "); else printf("%d in ",b-1);
if (c==0) printf("all out"); else printf("%d out",c-1);
break;
case OP_TAILCALL:
printf("%d %d %d",a,b,c);
printf(COMMENT "%d in",b-1);
break;
case OP_RETURN:
printf("%d %d %d",a,b,c);
printf(COMMENT);
if (b==0) printf("all out"); else printf("%d out",b-1);
break;
case OP_RETURN0:
break;
case OP_RETURN1:
printf("%d",a);
break;
case OP_FORLOOP:
printf("%d %d",a,bx);
printf(COMMENT "to %d",pc-bx+2);
break;
case OP_FORPREP:
printf("%d %d",a,bx);
printf(COMMENT "to %d",pc+bx+2);
break;
case OP_TFORPREP:
printf("%d %d",a,bx);
printf(COMMENT "to %d",pc+bx+2);
break;
case OP_TFORCALL:
printf("%d %d",a,c);
break;
case OP_TFORLOOP:
printf("%d %d",a,bx);
printf(COMMENT "to %d",pc-bx+2);
break;
case OP_SETLIST:
printf("%d %d %d",a,b,c);
if (isk) printf(COMMENT "%d",c+EXTRAARGC);
break;
case OP_CLOSURE:
printf("%d %d",a,bx);
printf(COMMENT "%p",VOID(f->p[bx]));
break;
case OP_VARARG:
printf("%d %d",a,c);
printf(COMMENT);
if (c==0) printf("all out"); else printf("%d out",c-1);
break;
case OP_VARARGPREP:
printf("%d",a);
break;
case OP_EXTRAARG:
printf("%d",ax);
break;
#if 0
default:
printf("%d %d %d",a,b,c);
printf(COMMENT "not handled");
break;
#endif
}
printf("\n");
}
}
#define SS(x) ((x==1)?"":"s")
#define S(x) (int)(x),SS(x)
static void PrintHeader(const Proto* f)
{
const char* s=f->source ? getstr(f->source) : "=?";
if (*s=='@' || *s=='=')
s++;
else if (*s==LUA_SIGNATURE[0])
s="(bstring)";
else
s="(string)";
printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n",
(f->linedefined==0)?"main":"function",s,
f->linedefined,f->lastlinedefined,
S(f->sizecode),VOID(f));
printf("%d%s param%s, %d slot%s, %d upvalue%s, ",
(int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams),
S(f->maxstacksize),S(f->sizeupvalues));
printf("%d local%s, %d constant%s, %d function%s\n",
S(f->sizelocvars),S(f->sizek),S(f->sizep));
}
static void PrintDebug(const Proto* f)
{
int i,n;
n=f->sizek;
printf("constants (%d) for %p:\n",n,VOID(f));
for (i=0; i<n; i++)
{
printf("\t%d\t",i);
PrintType(f,i);
PrintConstant(f,i);
printf("\n");
}
n=f->sizelocvars;
printf("locals (%d) for %p:\n",n,VOID(f));
for (i=0; i<n; i++)
{
printf("\t%d\t%s\t%d\t%d\n",
i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1);
}
n=f->sizeupvalues;
printf("upvalues (%d) for %p:\n",n,VOID(f));
for (i=0; i<n; i++)
{
printf("\t%d\t%s\t%d\t%d\n",
i,UPVALNAME(i),f->upvalues[i].instack,f->upvalues[i].idx);
}
}
static void PrintFunction(const Proto* f, int full)
{
int i,n=f->sizep;
PrintHeader(f);
PrintCode(f);
if (full) PrintDebug(f);
for (i=0; i<n; i++) PrintFunction(f->p[i],full);
}

41
third_party/lua/tms.h vendored Normal file
View file

@ -0,0 +1,41 @@
#ifndef COSMOPOLITAN_THIRD_PARTY_LUA_TMS_H_
#define COSMOPOLITAN_THIRD_PARTY_LUA_TMS_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/*
* WARNING: if you change the order of this enumeration,
* grep "ORDER TM" and "ORDER OP"
*/
typedef enum {
TM_INDEX,
TM_NEWINDEX,
TM_GC,
TM_MODE,
TM_LEN,
TM_EQ, /* last tag method with fast access */
TM_ADD,
TM_SUB,
TM_MUL,
TM_MOD,
TM_POW,
TM_DIV,
TM_IDIV,
TM_BAND,
TM_BOR,
TM_BXOR,
TM_SHL,
TM_SHR,
TM_UNM,
TM_BNOT,
TM_LT,
TM_LE,
TM_CONCAT,
TM_CALL,
TM_CLOSE,
TM_N /* number of elements in the enum */
} TMS;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_THIRD_PARTY_LUA_TMS_H_ */

View file

@ -0,0 +1,2 @@
Write('This Lua Server Page is stored in ZIP\r\n')
Write('as compressed byte code, see luac.com and net.mk\r\n')

View file

@ -0,0 +1,2 @@
Write('This Lua Server Page is stored in ZIP\r\n')
Write('as normal Lua code that is compressed\r\n')

View file

@ -133,6 +133,8 @@ o/$(MODE)/tool/net/redbean-demo.com: \
tool/net/demo/seekable.txt \ tool/net/demo/seekable.txt \
tool/net/demo/virtualbean.html \ tool/net/demo/virtualbean.html \
tool/net/demo/printpayload.lua \ tool/net/demo/printpayload.lua \
tool/net/demo/opensource.lua \
o/$(MODE)/tool/net/demo/closedsource.lua \
tool/net/demo/fetch.lua \ tool/net/demo/fetch.lua \
tool/net/redbean.c \ tool/net/redbean.c \
net/http/parsehttpmessage.c \ net/http/parsehttpmessage.c \
@ -149,7 +151,7 @@ o/$(MODE)/tool/net/redbean-demo.com: \
@(cd o/$(MODE)/tool/net && ../../host/third_party/infozip/zip.com -qr redbean-demo.com .lua) @(cd o/$(MODE)/tool/net && ../../host/third_party/infozip/zip.com -qr redbean-demo.com .lua)
@$(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -qj $@ tool/net/demo/hello.lua tool/net/demo/sql.lua @$(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -qj $@ tool/net/demo/hello.lua tool/net/demo/sql.lua
@echo "&lt;-- check out this lua server page" | $(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -cqj $@ tool/net/demo/redbean.lua @echo "&lt;-- check out this lua server page" | $(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -cqj $@ tool/net/demo/redbean.lua
@$(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -qj $@ tool/net/demo/404.html tool/net/favicon.ico tool/net/redbean.png tool/net/demo/redbean-form.lua tool/net/demo/redbean-xhr.lua tool/net/demo/printpayload.lua tool/net/demo/fetch.lua @$(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -qj $@ tool/net/demo/404.html tool/net/favicon.ico tool/net/redbean.png tool/net/demo/redbean-form.lua tool/net/demo/redbean-xhr.lua tool/net/demo/printpayload.lua tool/net/demo/fetch.lua o/$(MODE)/tool/net/demo/closedsource.lua tool/net/demo/opensource.lua
@echo Uncompressed for HTTP Range requests | $(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -cqj0 $@ tool/net/demo/seekable.txt @echo Uncompressed for HTTP Range requests | $(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -cqj0 $@ tool/net/demo/seekable.txt
@$(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -q $@ tool/net/ tool/net/demo/ tool/net/demo/index.html tool/net/demo/redbean.css tool/net/redbean.c net/http/parsehttpmessage.c net/http/parseurl.c net/http/encodeurl.c test/net/http/parsehttpmessage_test.c test/net/http/parseurl_test.c @$(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -q $@ tool/net/ tool/net/demo/ tool/net/demo/index.html tool/net/demo/redbean.css tool/net/redbean.c net/http/parsehttpmessage.c net/http/parseurl.c net/http/encodeurl.c test/net/http/parsehttpmessage_test.c test/net/http/parseurl_test.c
@$(COMPILE) -AMKDIR -T$@ mkdir -p o/$(MODE)/tool/net/virtualbean.justine.lol/ @$(COMPILE) -AMKDIR -T$@ mkdir -p o/$(MODE)/tool/net/virtualbean.justine.lol/

View file

@ -3146,14 +3146,20 @@ static char *LuaOnHttpRequest(void) {
static char *ServeLua(struct Asset *a, const char *s, size_t n) { static char *ServeLua(struct Asset *a, const char *s, size_t n) {
char *code; char *code;
size_t codelen;
LockInc(&shared->c.dynamicrequests); LockInc(&shared->c.dynamicrequests);
effectivepath.p = s; effectivepath.p = s;
effectivepath.n = n; effectivepath.n = n;
if ((code = FreeLater(LoadAsset(a, NULL)))) { if ((code = FreeLater(LoadAsset(a, &codelen)))) {
if (luaL_dostring(L, code) == LUA_OK) { if (!luaL_loadbufferx(L, code, codelen, FreeLater(strndup(s, n)), 0) &&
!lua_pcall(L, 0, LUA_MULTRET, 0)) {
return CommitOutput(GetLuaResponse()); return CommitOutput(GetLuaResponse());
} else { } else {
WARNF("%s", lua_tostring(L, -1)); WARNF("failed to run lua code %s", lua_tostring(L, -1));
/*
* TODO: Print backtrace, and then serve Django-like error page if
* and only if IsLoopbackIp(GetRemoteAddr())
*/
lua_pop(L, 1); lua_pop(L, 1);
} }
} }
@ -4999,21 +5005,27 @@ static int LuaHidePath(lua_State *L) {
static int LuaLog(lua_State *L) { static int LuaLog(lua_State *L) {
int level; int level;
char *module;
lua_Debug ar; lua_Debug ar;
const char *msg; const char *msg, *module;
level = luaL_checkinteger(L, 1); level = luaL_checkinteger(L, 1);
if (LOGGABLE(level)) { if (LOGGABLE(level)) {
/*
* TODO: There needs to be some reasonable way to get the source
* filename and line number.
*/
msg = luaL_checkstring(L, 2); msg = luaL_checkstring(L, 2);
lua_getstack(L, 0, &ar); lua_getstack(L, 0, &ar);
lua_getinfo(L, "nSl", &ar); lua_getinfo(L, "nSl", &ar);
if (!strcmp(ar.name, "main")) { if (!strcmp(ar.name, "main")) {
module = strndup(effectivepath.p, effectivepath.n); if (ar.source) {
flogf(level, module, ar.currentline, NULL, "%s", msg); module = ar.source;
free(module); } else {
module = gc(strndup(effectivepath.p, effectivepath.n));
}
} else { } else {
flogf(level, ar.name, ar.currentline, NULL, "%s", msg); module = ar.name;
} }
flogf(level, module, ar.currentline, NULL, "%s", msg);
} }
return 0; return 0;
} }
@ -5298,21 +5310,25 @@ static int LuaRe(lua_State *L) {
} }
static bool LuaRun(const char *path, bool mandatory) { static bool LuaRun(const char *path, bool mandatory) {
size_t pathlen;
struct Asset *a; struct Asset *a;
const char *code; const char *code;
size_t pathlen, codelen;
pathlen = strlen(path); pathlen = strlen(path);
if ((a = GetAsset(path, pathlen))) { if ((a = GetAsset(path, pathlen))) {
if ((code = LoadAsset(a, NULL))) { if ((code = LoadAsset(a, &codelen))) {
effectivepath.p = path; effectivepath.p = path;
effectivepath.n = pathlen; effectivepath.n = pathlen;
DEBUGF("LuaRun(%`'s)", path); DEBUGF("LuaRun(%`'s)", path);
if (luaL_dostring(L, code) != LUA_OK) { if (luaL_loadbufferx(L, code, codelen, path, 0) ||
if (mandatory) { lua_pcall(L, 0, LUA_MULTRET, 0)) {
FATALF("%s %s", path, lua_tostring(L, -1)); /*
} else { * TODO: There needs to be some reasonable way to get a
WARNF("%s %s", path, lua_tostring(L, -1)); * backtrace. The best thing about Django was the
} * fabulous backtrace page (and the admin panel).
*/
/* luaL_traceback(L, L, lua_tostring(L, -1), 0); */
WARNF("script failed to run %s", lua_tostring(L, -1));
if (mandatory) exit(1);
lua_pop(L, 1); lua_pop(L, 1);
} }
free(code); free(code);