123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- /*
- ** undump.c
- ** load bytecodes from files
- */
- char* rcs_undump="$Id: undump.c,v 1.13 1996/03/12 20:00:40 lhf Exp lhf $";
- #include <stdio.h>
- #include <string.h>
- #include "opcode.h"
- #include "mem.h"
- #include "table.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 */
- {
- #if 0
- fprintf(stderr,"undump: %s\n",s);
- #endif
- }
- static void FixCode(Byte* code, Byte* end) /* swap words */
- {
- 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)
- {
- while (i!=0)
- {
- CodeWord c;
- Byte* p=code+i;
- get_word(c,p);
- i=c.w;
- c.w=v;
- p[-2]=c.m.c1;
- p[-1]=c.m.c2;
- }
- }
- static int LoadWord(FILE* D)
- {
- Word w;
- fread(&w,sizeof(w),1,D);
- if (swapword)
- {
- Byte* p=(Byte*)&w; /* TODO: need union? */
- Byte t;
- t=p[0]; p[0]=p[1]; p[1]=t;
- }
- return w;
- }
- static int LoadSize(FILE* D)
- {
- Word hi=LoadWord(D);
- Word lo=LoadWord(D);
- int s=(hi<<16)|lo;
- if ((Word)s != s) lua_error("code too long");
- return s;
- }
- static char* LoadBlock(int size, FILE* D)
- {
- char* b=luaI_malloc(size);
- fread(b,size,1,D);
- return b;
- }
- static char* LoadString(FILE* D)
- {
- int size=LoadWord(D);
- char *b=luaI_buffer(size);
- fread(b,size,1,D);
- return b;
- }
- static char* LoadNewString(FILE* D)
- {
- return LoadBlock(LoadWord(D),D);
- }
- static void LoadFunction(FILE* D)
- {
- TFunc* tf=new(TFunc);
- tf->next=NULL;
- tf->locvars=NULL;
- tf->size=LoadSize(D);
- tf->lineDefined=LoadWord(D);
- if (IsMain(tf)) /* new main */
- {
- tf->fileName=LoadNewString(D);
- Main=lastF=tf;
- }
- else /* fix PUSHFUNCTION */
- {
- CodeCode c;
- Byte* p;
- tf->marked=LoadWord(D);
- tf->fileName=Main->fileName;
- p=Main->code+tf->marked;
- c.tf=tf;
- *p++=c.m.c1; *p++=c.m.c2; *p++=c.m.c3; *p++=c.m.c4;
- lastF=lastF->next=tf;
- }
- tf->code=LoadBlock(tf->size,D);
- if (swapword || swapfloat) FixCode(tf->code,tf->code+tf->size);
- while (1) /* unthread */
- {
- int c=getc(D);
- if (c==ID_VAR) /* global var */
- {
- int i=LoadWord(D);
- char* s=LoadString(D);
- int v=luaI_findsymbolbyname(s);
- Unthread(tf->code,i,v);
- }
- else if (c==ID_STR) /* constant string */
- {
- int i=LoadWord(D);
- char* s=LoadString(D);
- int v=luaI_findconstantbyname(s);
- Unthread(tf->code,i,v);
- }
- else
- {
- ungetc(c,D);
- break;
- }
- }
- }
- static void LoadSignature(FILE* D)
- {
- char* s=SIGNATURE;
- while (*s!=0 && getc(D)==*s)
- ++s;
- if (*s!=0) lua_error("bad signature");
- }
- static void LoadHeader(FILE* D) /* TODO: error handling */
- {
- Word w,tw=TEST_WORD;
- float f,tf=TEST_FLOAT;
- LoadSignature(D);
- getc(D); /* skip version */
- fread(&w,sizeof(w),1,D); /* test word */
- if (w!=tw)
- {
- swapword=1;
- warn("different byte order");
- }
- fread(&f,sizeof(f),1,D); /* test float */
- if (f!=tf)
- {
- Byte* p=(Byte*)&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");
- }
- }
- static void LoadChunk(FILE* D)
- {
- LoadHeader(D);
- while (1)
- {
- int c=getc(D);
- if (c==ID_FUN) LoadFunction(D); else { ungetc(c,D); break; }
- }
- }
- /*
- ** 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)
- return NULL;
- else
- lua_error("not a lua binary file");
- }
- }
- /*
- ** load and run all chunks in a file
- */
- int luaI_undump(FILE* D)
- {
- TFunc* m;
- while ((m=luaI_undump1(D)))
- {
- int status=luaI_dorun(m);
- luaI_freefunc(m);
- if (status!=0) return status;
- }
- return 0;
- }
|