diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..19cc30f190 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,170 @@ + +project(lua) + +cmake_minimum_required(VERSION 3.21) + +# +# Functions +# + +# 'message' wrapper +function(print what) + message(" ${what}") +endfunction() + + +# +# Paths +# + +# Local paths +set(DIR_ROOT "${PROJECT_SOURCE_DIR}") +set(DIR_INCLUDE "${DIR_ROOT}/include") +set(DIR_SOURCE "${DIR_ROOT}/source") +set(DIR_LIBRARY "${DIR_ROOT}/lib") +set(DIR_TEST "${DIR_ROOT}/test") + +# VCPKG paths +set(DIR_VCPKG_INSTALL "${DIR_VCPKG_ROOT}/installed/${VCPKG_TARGET_TRIPLET}") +set(DIR_VCPKG_INCLUDE "${DIR_VCPKG_INSTALL}/include") +set(DIR_VCPKG_LIBRARY "${DIR_VCPKG_INSTALL}/lib") +set(DIR_VCPKG_LIBRARY_DEBUG "${DIR_VCPKG_INSTALL}/debug/lib") + +# Binary output paths +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${DIR_LIBRARY}/deb") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${DIR_LIBRARY}/deb") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${DIR_ROOT}) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${DIR_LIBRARY}/rel") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${DIR_LIBRARY}/rel") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${DIR_ROOT}) + + +# +# CXX +# + +set(CMAKE_CXX_STANDARD 17) + +if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") # Clang + # +elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # GCC + set(COMPILER_FLAGS "-Wall -Wextra -ansi -pedantic -std=c++17") + set(COMPILER_FLAGS_DEBUG "-MTd") + set(COMPILER_FLAGS_RELEASE "-O3 -DNDEBUG -MT") +elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") # MSVC + set(COMPILER_FLAGS "") + set(COMPILER_FLAGS_DEBUG "/Zi /Ob0 /Od /RTC1 /MTd") + set(COMPILER_FLAGS_RELEASE "/O2 /Ob2 /DNDEBUG /MT") +endif () + +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COMPILER_FLAGS} ${COMPILER_FLAGS_DEBUG}") +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${COMPILER_FLAGS} ${COMPILER_FLAGS_RELEASE}") + + +# Dependencies + + +FUNCTION(DEBUG_WX_LIBS var) + SET(liblist "") + FOREACH (f ${var}) + STRING(REGEX REPLACE "${DIR_VCPKG_LIBRARY}/wx(.*)u(.*)//.lib" "${DIR_VCPKG_LIBRARY_DEBUG}/wx//1ud//2.lib" f ${f}) + LIST(APPEND liblist "${f}") + ENDFOREACH () + SET(wxWidgets_LIBRARIES "${liblist}" PARENT_SCOPE) +ENDFUNCTION() + +IF ("${CMAKE_BUILD_TYPE}" MATCHES "Debug") + DEBUG_WX_LIBS("${wxWidgets_LIBRARIES}") +ELSE () + +ENDIF () + + +# CMAKE + +set(INCLUDE_DIRECTORIES + ${DIR_INCLUDE} + ${DIR_SOURCE} + + ${DIR_VCPKG_INCLUDE}) + +include_directories(${INCLUDE_DIRECTORIES}) + +if (CMAKE_BUILD_TYPE EQUAL "DEBUG") + set(LIBRARY_DIRECTORIES + ${DIR_VCPKG_LIBRARY} + ${DIR_VCPKG_LIBRARY}/deb) +else() + set(LIBRARY_DIRECTORIES + ${DIR_VCPKG_LIBRARY} + ${DIR_VCPKG_LIBRARY}/rel) +endif() + +link_directories(${LIBRARY_DIRECTORIES}) + + +# Sources + +set(SOURCES + lutf8lib.c + lvm.c + lzio.c + lapi.c + lcode.c + lcorolib.c + lctype.c + ldebug.c + ldo.c + ldump.c + lfunc.c + lgc.c + linit.c + llex.c + lmem.c + loadlib.c + lobject.c + lopcodes.c + loslib.c + lparser.c + lstate.c + lstring.c + ltable.c + ltests.c + ltm.c + lundump.c + lvm.c + lzio.c +) + +set(SOURCES_LIB + lauxlib.c + lbaselib.c + ldblib.c + liolib.c + lmathlib.c + lstrlib.c + ltablib.c +) + +set(SOURCES_LUAC + dump.c + opt.c + print.c + stubs.c +) + +source_group("src" FILES ${SOURCES}) +source_group("src/lib" FILES ${SOURCES_LIB}) +source_group("src/luac" FILES ${SOURCES_LUAC}) + + +# Binaries + +add_library(lua ${SOURCES}) +add_library(lualib ${SOURCES_LIB}) + +add_executable(luai lua.c) +add_executable(luac luac.c ${SOURCES_LUAC}) + +target_link_libraries(luai lualib lua) +target_link_libraries(luac lualib lua) diff --git a/dump.c b/dump.c new file mode 100644 index 0000000000..149469ba11 --- /dev/null +++ b/dump.c @@ -0,0 +1,121 @@ +/* +** $Id: dump.c,v 1.30 2000/10/31 16:57:23 lhf Exp $ +** save bytecodes to file +** See Copyright Notice in lua.h +*/ + +#include +#include +#include + +#include "luac.h" + +#define DumpVector(b,n,size,D) fwrite(b,size,n,D) +#define DumpBlock(b,size,D) fwrite(b,size,1,D) +#define DumpByte fputc + +static void DumpInt(int x, FILE* D) +{ + DumpBlock(&x,sizeof(x),D); +} + +static void DumpSize(size_t x, FILE* D) +{ + DumpBlock(&x,sizeof(x),D); +} + +static void DumpNumber(Number x, FILE* D) +{ + DumpBlock(&x,sizeof(x),D); +} + +static void DumpString(const TString* s, FILE* D) +{ + if (s==NULL || s->str==NULL) + DumpSize(0,D); + else + { + size_t size=s->len+1; /* include trailing '\0' */ + DumpSize(size,D); + DumpBlock(s->str,size,D); + } +} + +static void DumpCode(const Proto* tf, FILE* D) +{ + DumpInt(tf->ncode,D); + DumpVector(tf->code,tf->ncode,sizeof(*tf->code),D); +} + +static void DumpLocals(const Proto* tf, FILE* D) +{ + int i,n=tf->nlocvars; + DumpInt(n,D); + for (i=0; ilocvars[i].varname,D); + DumpInt(tf->locvars[i].startpc,D); + DumpInt(tf->locvars[i].endpc,D); + } +} + +static void DumpLines(const Proto* tf, FILE* D) +{ + DumpInt(tf->nlineinfo,D); + DumpVector(tf->lineinfo,tf->nlineinfo,sizeof(*tf->lineinfo),D); +} + +static void DumpFunction(const Proto* tf, FILE* D); + +static void DumpConstants(const Proto* tf, FILE* D) +{ + int i,n; + DumpInt(n=tf->nkstr,D); + for (i=0; ikstr[i],D); + DumpInt(tf->nknum,D); + DumpVector(tf->knum,tf->nknum,sizeof(*tf->knum),D); + DumpInt(n=tf->nkproto,D); + for (i=0; ikproto[i],D); +} + +static void DumpFunction(const Proto* tf, FILE* D) +{ + DumpString(tf->source,D); + DumpInt(tf->lineDefined,D); + DumpInt(tf->numparams,D); + DumpByte(tf->is_vararg,D); + DumpInt(tf->maxstacksize,D); + DumpLocals(tf,D); + DumpLines(tf,D); + DumpConstants(tf,D); + DumpCode(tf,D); + if (ferror(D)) + { + perror("luac: write error"); + exit(1); + } +} + +static void DumpHeader(FILE* D) +{ + DumpByte(ID_CHUNK,D); + fputs(SIGNATURE,D); + DumpByte(VERSION,D); + DumpByte(luaU_endianess(),D); + DumpByte(sizeof(int),D); + DumpByte(sizeof(size_t),D); + DumpByte(sizeof(Instruction),D); + DumpByte(SIZE_INSTRUCTION,D); + DumpByte(SIZE_OP,D); + DumpByte(SIZE_B,D); + DumpByte(sizeof(Number),D); + DumpNumber(TEST_NUMBER,D); +} + +void luaU_dumpchunk(const Proto* Main, FILE* D) +{ + DumpHeader(D); + DumpFunction(Main,D); +} diff --git a/luac.c b/luac.c new file mode 100644 index 0000000000..8832de62d4 --- /dev/null +++ b/luac.c @@ -0,0 +1,203 @@ +/* +** $Id: luac.c,v 1.28 2000/11/06 20:06:27 lhf Exp $ +** lua compiler (saves bytecodes to files; also list binary files) +** See Copyright Notice in lua.h +*/ + +#include +#include +#include + +#include "lparser.h" +#include "lstate.h" +#include "lzio.h" +#include "luac.h" + +#define OUTPUT "luac.out" /* default output file */ + +static void usage(const char* message, const char* arg); +static int doargs(int argc, const char* argv[]); +static Proto* load(const char* filename); +static FILE* efopen(const char* name, const char* mode); +static void strip(Proto* tf); +static Proto* combine(Proto** P, int n); + +lua_State* lua_state=NULL; /* lazy! */ + +static int listing=0; /* list bytecodes? */ +static int dumping=1; /* dump bytecodes? */ +static int stripping=0; /* strip debug information? */ +static int testing=0; /* test integrity? */ +static const char* output=OUTPUT; /* output file name */ + +#define IS(s) (strcmp(argv[i],s)==0) + +int main(int argc, const char* argv[]) +{ + Proto** P,*tf; + int i=doargs(argc,argv); + argc-=i; argv+=i; + if (argc<=0) usage("no input files given",NULL); + L=lua_open(0); + P=luaM_newvector(L,argc,Proto*); + for (i=0; isource=luaS_new(L,"=(luac)"); + tf->maxstacksize=1; + tf->kproto=P; + tf->nkproto=n; + tf->ncode=2*n+1; + tf->code=luaM_newvector(L,tf->ncode,Instruction); + for (i=0; icode[pc++]=CREATE_AB(OP_CLOSURE,i,0); + tf->code[pc++]=CREATE_AB(OP_CALL,0,0); + } + tf->code[pc++]=OP_END; + return tf; + } +} + +static void strip(Proto* tf) +{ + int i,n=tf->nkproto; + tf->lineinfo=NULL; + tf->nlineinfo=0; + tf->source=luaS_new(L,"=(none)"); + tf->locvars=NULL; + tf->nlocvars=0; + for (i=0; ikproto[i]); +} + +static FILE* efopen(const char* name, const char* mode) +{ + FILE* f=fopen(name,mode); + if (f==NULL) + { + fprintf(stderr,"luac: cannot open %sput file ",*mode=='r' ? "in" : "out"); + perror(name); + exit(1); + } + return f; +} + +void luaU_testchunk(const Proto* Main) +{ + UNUSED(Main); + fprintf(stderr,"luac: -t not operational in this version\n"); + exit(1); +} diff --git a/luac.h b/luac.h new file mode 100644 index 0000000000..f8987cf2e2 --- /dev/null +++ b/luac.h @@ -0,0 +1,31 @@ +/* +** $Id: luac.h,v 1.18 2000/10/31 16:57:23 lhf Exp $ +** definitions for luac +** See Copyright Notice in lua.h +*/ + +#include "ldebug.h" +#include "lfunc.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstring.h" +#include "ltable.h" +#include "lundump.h" + +extern lua_State *lua_state; +#define L lua_state /* lazy! */ + +/* from dump.c */ +void luaU_dumpchunk(const Proto* Main, FILE* D); + +/* from opt.c */ +void luaU_optchunk(Proto* Main); + +/* from print.c */ +void luaU_printchunk(const Proto* Main); + +/* from test.c */ +void luaU_testchunk(const Proto* Main); + +#define Sizeof(x) ((int)sizeof(x)) diff --git a/opt.c b/opt.c new file mode 100644 index 0000000000..e51a086852 --- /dev/null +++ b/opt.c @@ -0,0 +1,127 @@ +/* +** $Id: opt.c,v 1.22 2000/10/31 16:57:23 lhf Exp $ +** optimize bytecodes +** See Copyright Notice in lua.h +*/ + +#include +#include +#include + +#include "luac.h" + +static int MapConstant(Hash* t, int j, const TObject* key) +{ + const TObject* o=luaH_get(L,t,key); + if (ttype(o)==LUA_TNUMBER) + return (int) nvalue(o); + else + { + TObject val; + ttype(&val)=LUA_TNUMBER; + nvalue(&val)=j; + *luaH_set(L,t,key)=val; + LUA_ASSERT(j>=0,"MapConstant returns negative!"); + return j; + } +} + +static int MapConstants(Proto* tf, Hash* map) +{ + int i,j,k,n,m=0; + TObject o; + j=0; n=tf->nknum; ttype(&o)=LUA_TNUMBER; + for (i=0; iknum[i]; + k=MapConstant(map,j,&o); + if (k==j) j++; + } + m=j; + j=0; n=tf->nkstr; ttype(&o)=LUA_TSTRING; + for (i=0; ikstr[i]; + k=MapConstant(map,j,&o); + if (k==j) j++; + } + return m+j; +} + +static void PackConstants(Proto* tf, Hash* map) +{ + int i,j,k,n; + TObject o; +#ifdef DEBUG + printf("%p before pack nknum=%d nkstr=%d\n",tf,tf->nknum,tf->nkstr); +#endif + j=0; n=tf->nknum; ttype(&o)=LUA_TNUMBER; + for (i=0; iknum[i]; + k=MapConstant(map,-1,&o); + if (k==j) tf->knum[j++]=tf->knum[i]; + } + tf->nknum=j; + j=0; n=tf->nkstr; ttype(&o)=LUA_TSTRING; + for (i=0; ikstr[i]; + k=MapConstant(map,-1,&o); + if (k==j) tf->kstr[j++]=tf->kstr[i]; + } + tf->nkstr=j; +#ifdef DEBUG + printf("%p after pack nknum=%d nkstr=%d\n",tf,tf->nknum,tf->nkstr); +#endif +} + +static void OptConstants(Proto* tf) +{ + Instruction* p; + int n=tf->nknum+tf->nkstr; + Hash* map=luaH_new(L,n); + int m=MapConstants(tf,map); +#ifdef DEBUG + printf("%p n=%d m=%d %s\n",tf,n,m,(m==n)?"nothing to optimize":"yes!"); +#endif + if (m==n) return; + for (p=tf->code;; p++) + { + Instruction i=*p; + int op=GET_OPCODE(i); + switch (op) + { + TObject o; + int j,k; + case OP_PUSHNUM: case OP_PUSHNEGNUM: + j=GETARG_U(i); + ttype(&o)=LUA_TNUMBER; nvalue(&o)=tf->knum[j]; + k=MapConstant(map,-1,&o); + if (k!=j) *p=CREATE_U(op,k); + break; + case OP_PUSHSTRING: case OP_GETGLOBAL: case OP_GETDOTTED: + case OP_PUSHSELF: case OP_SETGLOBAL: + j=GETARG_U(i); + ttype(&o)=LUA_TSTRING; tsvalue(&o)=tf->kstr[j]; + k=MapConstant(map,-1,&o); + if (k!=j) *p=CREATE_U(op,k); + break; + case OP_END: + PackConstants(tf,map); + luaH_free(L,map); + return; + default: + break; + } + } +} + +#define OptFunction luaU_optchunk + +void OptFunction(Proto* tf) +{ + int i,n=tf->nkproto; + OptConstants(tf); + for (i=0; ikproto[i]); +} diff --git a/print.c b/print.c new file mode 100644 index 0000000000..4ffc8b3d16 --- /dev/null +++ b/print.c @@ -0,0 +1,99 @@ +/* +** $Id: print.c,v 1.32 2000/11/06 20:04:36 lhf Exp $ +** print bytecodes +** See Copyright Notice in lua.h +*/ + +#include +#include + +#include "luac.h" + +/* macros used in print.h, included in PrintCode */ +#define P_OP(x) printf("%-11s\t",x) +#define P_NONE +#define P_AB printf("%d %d",GETARG_A(i),GETARG_B(i)) +#define P_F printf("%d %d\t; %p",GETARG_A(i),GETARG_B(i),tf->kproto[GETARG_A(i)]) +#define P_J printf("%d\t; to %d",GETARG_S(i),GETARG_S(i)+at+1) +#define P_Q PrintString(tf,GETARG_U(i)) +#define P_K printf("%d\t; %s",GETARG_U(i),tf->kstr[GETARG_U(i)]->str) +#define P_L PrintLocal(tf,GETARG_U(i),at-1) +#define P_N printf("%d\t; " NUMBER_FMT,GETARG_U(i),tf->knum[GETARG_U(i)]) +#define P_S printf("%d",GETARG_S(i)) +#define P_U printf("%u",GETARG_U(i)) + +static void PrintString(const Proto* tf, int n) +{ + const char* s=tf->kstr[n]->str; + printf("%d\t; ",n); + putchar('"'); + for (; *s; s++) + { + switch (*s) + { + 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: putchar(*s); break; + } + } + putchar('"'); +} + +static void PrintLocal(const Proto* tf, int n, int pc) +{ + const char* s=luaF_getlocalname(tf,n+1,pc); + printf("%u",n); + if (s!=NULL) printf("\t; %s",s); +} + +static void PrintCode(const Proto* tf) +{ + const Instruction* code=tf->code; + const Instruction* p=code; + for (;;) + { + int at=p-code+1; + Instruction i=*p; + int line=luaG_getline(tf->lineinfo,at-1,1,NULL); + printf("%6d\t",at); + if (line>=0) printf("[%d]\t",line); else printf("[-]\t"); + switch (GET_OPCODE(i)) { +#include "print.h" + } + printf("\n"); + if (i==OP_END) break; + p++; + } +} + +#define IsMain(tf) (tf->lineDefined==0) + +#define SS(x) (x==1)?"":"s" +#define S(x) x,SS(x) + +static void PrintHeader(const Proto* tf) +{ + printf("\n%s " SOURCE_FMT " (%d instruction%s/%d bytes at %p)\n", + IsMain(tf)?"main":"function",SOURCE, + S(tf->ncode),tf->ncode*Sizeof(Instruction),tf); + printf("%d%s param%s, %d stack%s, ", + tf->numparams,tf->is_vararg?"+":"",SS(tf->numparams),S(tf->maxstacksize)); + printf("%d local%s, %d string%s, %d number%s, %d function%s, %d line%s\n", + S(tf->nlocvars),S(tf->nkstr),S(tf->nknum),S(tf->nkproto),S(tf->nlineinfo)); +} + +#define PrintFunction luaU_printchunk + +void PrintFunction(const Proto* tf) +{ + int i,n=tf->nkproto; + PrintHeader(tf); + PrintCode(tf); + for (i=0; ikproto[i]); +} diff --git a/print.h b/print.h new file mode 100644 index 0000000000..5f74e14959 --- /dev/null +++ b/print.h @@ -0,0 +1,55 @@ +/* +** $Id: print.h,v 1.1 2000/11/06 20:03:12 lhf Exp $ +** extracted automatically from lopcodes.h by mkprint.lua -- DO NOT EDIT +** See Copyright Notice in lua.h +*/ + + case OP_END: P_OP("END"); P_NONE; break; + case OP_RETURN: P_OP("RETURN"); P_U; break; + case OP_CALL: P_OP("CALL"); P_AB; break; + case OP_TAILCALL: P_OP("TAILCALL"); P_AB; break; + case OP_PUSHNIL: P_OP("PUSHNIL"); P_U; break; + case OP_POP: P_OP("POP"); P_U; break; + case OP_PUSHINT: P_OP("PUSHINT"); P_S; break; + case OP_PUSHSTRING: P_OP("PUSHSTRING"); P_Q; break; + case OP_PUSHNUM: P_OP("PUSHNUM"); P_N; break; + case OP_PUSHNEGNUM: P_OP("PUSHNEGNUM"); P_N; break; + case OP_PUSHUPVALUE: P_OP("PUSHUPVALUE"); P_U; break; + case OP_GETLOCAL: P_OP("GETLOCAL"); P_L; break; + case OP_GETGLOBAL: P_OP("GETGLOBAL"); P_K; break; + case OP_GETTABLE: P_OP("GETTABLE"); P_NONE; break; + case OP_GETDOTTED: P_OP("GETDOTTED"); P_K; break; + case OP_GETINDEXED: P_OP("GETINDEXED"); P_L; break; + case OP_PUSHSELF: P_OP("PUSHSELF"); P_K; break; + case OP_CREATETABLE: P_OP("CREATETABLE"); P_U; break; + case OP_SETLOCAL: P_OP("SETLOCAL"); P_L; break; + case OP_SETGLOBAL: P_OP("SETGLOBAL"); P_K; break; + case OP_SETTABLE: P_OP("SETTABLE"); P_AB; break; + case OP_SETLIST: P_OP("SETLIST"); P_AB; break; + case OP_SETMAP: P_OP("SETMAP"); P_U; break; + case OP_ADD: P_OP("ADD"); P_NONE; break; + case OP_ADDI: P_OP("ADDI"); P_S; break; + case OP_SUB: P_OP("SUB"); P_NONE; break; + case OP_MULT: P_OP("MULT"); P_NONE; break; + case OP_DIV: P_OP("DIV"); P_NONE; break; + case OP_POW: P_OP("POW"); P_NONE; break; + case OP_CONCAT: P_OP("CONCAT"); P_U; break; + case OP_MINUS: P_OP("MINUS"); P_NONE; break; + case OP_NOT: P_OP("NOT"); P_NONE; break; + case OP_JMPNE: P_OP("JMPNE"); P_J; break; + case OP_JMPEQ: P_OP("JMPEQ"); P_J; break; + case OP_JMPLT: P_OP("JMPLT"); P_J; break; + case OP_JMPLE: P_OP("JMPLE"); P_J; break; + case OP_JMPGT: P_OP("JMPGT"); P_J; break; + case OP_JMPGE: P_OP("JMPGE"); P_J; break; + case OP_JMPT: P_OP("JMPT"); P_J; break; + case OP_JMPF: P_OP("JMPF"); P_J; break; + case OP_JMPONT: P_OP("JMPONT"); P_J; break; + case OP_JMPONF: P_OP("JMPONF"); P_J; break; + case OP_JMP: P_OP("JMP"); P_J; break; + case OP_PUSHNILJMP: P_OP("PUSHNILJMP"); P_NONE; break; + case OP_FORPREP: P_OP("FORPREP"); P_J; break; + case OP_FORLOOP: P_OP("FORLOOP"); P_J; break; + case OP_LFORPREP: P_OP("LFORPREP"); P_J; break; + case OP_LFORLOOP: P_OP("LFORLOOP"); P_J; break; + case OP_CLOSURE: P_OP("CLOSURE"); P_F; break; diff --git a/stubs.c b/stubs.c new file mode 100644 index 0000000000..74f509eb26 --- /dev/null +++ b/stubs.c @@ -0,0 +1,127 @@ +/* +** $Id: stubs.c,v 1.20 2000/10/31 16:57:23 lhf Exp $ +** avoid runtime modules in luac +** See Copyright Notice in lua.h +*/ + +#include +#include + +#include "ldo.h" +#include "llex.h" +#include "luac.h" +#undef L + +#ifndef NOSTUBS + +const char luac_ident[] = "$luac: " LUA_VERSION " " LUA_COPYRIGHT " $\n" + "$Authors: " LUA_AUTHORS " $"; + +/* +* avoid lapi ldebug ldo lgc lstate ltm lvm +* use only lcode lfunc llex lmem lobject lparser lstring ltable lzio +*/ + +/* simplified from ldo.c */ +void lua_error (lua_State* L, const char* s) { + UNUSED(L); + if (s) fprintf(stderr,"luac: %s\n",s); + exit(1); +} + +/* simplified from ldo.c */ +void luaD_breakrun (lua_State *L, int errcode) { + UNUSED(errcode); + lua_error(L,"memory allocation error"); +} + +/* simplified from lstate.c */ +lua_State *lua_open (int stacksize) { + lua_State *L = luaM_new(NULL, lua_State); + if (L == NULL) return NULL; /* memory allocation error */ + L->stack = NULL; + L->strt.size = L->udt.size = 0; + L->strt.nuse = L->udt.nuse = 0; + L->strt.hash = NULL; + L->udt.hash = NULL; + L->Mbuffer = NULL; + L->Mbuffsize = 0; + L->rootproto = NULL; + L->rootcl = NULL; + L->roottable = NULL; + L->TMtable = NULL; + L->last_tag = -1; + L->refArray = NULL; + L->refSize = 0; + L->refFree = NONEXT; + L->nblocks = sizeof(lua_State); + L->GCthreshold = MAX_INT; /* to avoid GC during pre-definitions */ + L->callhook = NULL; + L->linehook = NULL; + L->allowhooks = 1; + L->errorJmp = NULL; + if (stacksize == 0) + stacksize = DEFAULT_STACK_SIZE; + else + stacksize += LUA_MINSTACK; + L->gt = luaH_new(L, 10); /* table of globals */ + luaS_init(L); + luaX_init(L); + L->GCthreshold = 2*L->nblocks; + return L; +} + +/* copied from ldebug.c */ +int luaG_getline (int *lineinfo, int pc, int refline, int *prefi) { + int refi; + if (lineinfo == NULL || pc == -1) + return -1; /* no line info or function is not active */ + refi = prefi ? *prefi : 0; + if (lineinfo[refi] < 0) + refline += -lineinfo[refi++]; + LUA_ASSERT(lineinfo[refi] >= 0, "invalid line info"); + while (lineinfo[refi] > pc) { + refline--; + refi--; + if (lineinfo[refi] < 0) + refline -= -lineinfo[refi--]; + LUA_ASSERT(lineinfo[refi] >= 0, "invalid line info"); + } + for (;;) { + int nextline = refline + 1; + int nextref = refi + 1; + if (lineinfo[nextref] < 0) + nextline += -lineinfo[nextref++]; + LUA_ASSERT(lineinfo[nextref] >= 0, "invalid line info"); + if (lineinfo[nextref] > pc) + break; + refline = nextline; + refi = nextref; + } + if (prefi) *prefi = refi; + return refline; +} + +/* +* the code below avoids the lexer and the parser (llex lparser lcode). +* it is useful if you only want to load binary files. +* this works for interpreters like lua.c too. +*/ + +#ifdef NOPARSER + +#include "llex.h" +#include "lparser.h" + +void luaX_init(lua_State *L) { + UNUSED(L); +} + +Proto *luaY_parser(lua_State *L, ZIO *z) { + UNUSED(z); + lua_error(L,"parser not loaded"); + return NULL; +} + +#endif +#endif