diff --git a/undump.c b/undump.c index 539a506d..e7a8ebd9 100644 --- a/undump.c +++ b/undump.c @@ -3,24 +3,134 @@ ** load bytecodes from files */ -char* rcs_undump="$Id: undump.c,v 1.9 1996/03/06 16:01:08 lhf Exp lhf $"; +char* rcs_undump="$Id: undump.c,v 1.10 1996/03/06 21:40:10 lhf Exp lhf $"; #include #include -#include "luac.h" +#include "undump.h" static int swapword=0; static int swapfloat=0; +static TFunc* Main=NULL; /* functions in a chunk */ +static TFunc* lastF=NULL; static void warn(char* s) /* TODO: remove */ { fprintf(stderr,"undump: %s\n",s); } -static void panic(char* s) /* TODO: remove */ +static void FixCode(Byte* code, Byte* end) /* swap words */ { - warn(s); - exit(1); + Byte* p; + for (p=code; p!=end;) + { + OpCode op=(OpCode)*p; + switch (op) + { + case PUSHNIL: + case PUSH0: + case PUSH1: + case PUSH2: + case PUSHLOCAL0: + case PUSHLOCAL1: + case PUSHLOCAL2: + case PUSHLOCAL3: + case PUSHLOCAL4: + case PUSHLOCAL5: + case PUSHLOCAL6: + case PUSHLOCAL7: + case PUSHLOCAL8: + case PUSHLOCAL9: + case PUSHINDEXED: + case STORELOCAL0: + case STORELOCAL1: + case STORELOCAL2: + case STORELOCAL3: + case STORELOCAL4: + case STORELOCAL5: + case STORELOCAL6: + case STORELOCAL7: + case STORELOCAL8: + case STORELOCAL9: + case STOREINDEXED0: + case ADJUST0: + case EQOP: + case LTOP: + case LEOP: + case GTOP: + case GEOP: + case ADDOP: + case SUBOP: + case MULTOP: + case DIVOP: + case POWOP: + case CONCOP: + case MINUSOP: + case NOTOP: + case POP: + case RETCODE0: + p++; + break; + case PUSHBYTE: + case PUSHLOCAL: + case STORELOCAL: + case STOREINDEXED: + case STORELIST0: + case ADJUST: + case RETCODE: + p+=2; + break; + case STORELIST: + case CALLFUNC: + p+=3; + break; + case PUSHFUNCTION: + p+=5; + break; + case PUSHWORD: + case PUSHSELF: + case CREATEARRAY: + case ONTJMP: + case ONFJMP: + case JMP: + case UPJMP: + case IFFJMP: + case IFFUPJMP: + case SETLINE: + case PUSHSTRING: + case PUSHGLOBAL: + case STOREGLOBAL: + { + Byte t; + t=p[1]; p[1]=p[2]; p[2]=t; + p+=3; + break; + } + case PUSHFLOAT: + { + Byte t; + t=p[1]; p[1]=p[4]; p[4]=t; + t=p[2]; p[2]=p[3]; p[3]=t; + p+=5; + break; + } + case STORERECORD: + { + int n=*++p; + p++; + while (n--) + { + Byte t; + t=p[0]; p[0]=p[1]; p[1]=t; + p+=2; + } + break; + } + default: + lua_error("corrupt binary file"); + break; + } + } } static void Unthread(Byte* code, int i, int v) @@ -62,7 +172,7 @@ static int LoadSize(FILE* D) Word hi=LoadWord(D); Word lo=LoadWord(D); int s=(hi<<16)|lo; - if ((Word)s != s) panic("code too long"); + if ((Word)s != s) lua_error("code too long"); return s; } @@ -71,9 +181,6 @@ static char* LoadString(FILE* D) return LoadBlock(LoadWord(D),D); } -static TFunc* Main=NULL; -static TFunc* lastF=NULL; - static void LoadFunction(FILE* D) { TFunc* tf=new(TFunc); @@ -132,7 +239,7 @@ static void LoadSignature(FILE* D) char* s=SIGNATURE; while (*s!=0 && getc(D)==*s) ++s; - if (*s!=0) panic("bad signature"); + if (*s!=0) lua_error("bad signature"); } static void LoadHeader(FILE* D) /* TODO: error handling */ @@ -141,17 +248,24 @@ static void LoadHeader(FILE* D) /* TODO: error handling */ float f,tf=TEST_FLOAT; LoadSignature(D); getc(D); /* skip version */ - fread(&w,sizeof(w),1,D); /* a word for testing byte ordering */ + fread(&w,sizeof(w),1,D); /* test word */ if (w!=tw) { swapword=1; warn("different byte order"); } - fread(&f,sizeof(f),1,D); /* a float for testing byte ordering */ + fread(&f,sizeof(f),1,D); /* test float */ if (f!=tf) { - swapfloat=1; /* TODO: only one test? */ - if (f!=tf) warn("different float representation"); + Byte* p=&f; /* TODO: need union? */ + Byte t; + swapfloat=1; + t=p[0]; p[0]=p[3]; p[3]=t; + t=p[1]; p[1]=p[2]; p[2]=t; + if (f!=tf) /* TODO: try another perm? */ + lua_error("different float representation"); + else + warn("different byte order in floats"); } } @@ -163,39 +277,51 @@ static void LoadChunk(FILE* D) int c=getc(D); if (c==ID_FUN) LoadFunction(D); else { ungetc(c,D); break; } } -#if 1 - { /* TODO: run Main? */ - TFunc* tf; - for (tf=Main; tf!=NULL; tf=tf->next) - PrintFunction(tf); - } -#endif } -void luaI_undump(FILE* D) +/* +** load one chunk from a file. +** return list of functions found, headed by main, or NULL at EOF. +*/ +TFunc* luaI_undump1(FILE* D) { while (1) { int c=getc(D); if (c==ID_CHUNK) + { LoadChunk(D); + return Main; + } else if (c==EOF) - break; + return NULL; else - panic("not a lua binary file"); + lua_error("not a lua binary file"); } } -int main(int argc, char* argv[]) +/* +** load and run all chunks in a file +*/ +void luaI_undump(FILE* D) { - char* fn=(argc>1)? argv[1] : "luac.out"; - FILE* f=freopen(fn,"rb",stdin); - if (f==NULL) + TFunc* m; + while ((m=luaI_undump1(D))) { - fprintf(stderr,"undump: cannot open "); - perror(fn); - exit(1); +#if 0 + luaI_dorun(m); + luaI_freefunc(m); /* TODO: free others? */ +#endif } - luaI_undump(stdin); - return 0; +} + +char* luaI_buffer(int n) +{ + static int size=0; + static char* buffer=NULL; + if (buffer==NULL) + buffer=luaI_malloc(n); + else if (n>size) + buffer=luaI_realloc(buffer,size=n); + return buffer; }