summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>1998-01-14 13:49:01 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>1998-01-14 13:49:01 -0200
commit981fddea022b6cad7768223353b4e7386080c271 (patch)
treec596f191df4b59c85ea056fca3933ad1f14e984b
parent81b953f27e2c218e9d772cc5f653f541c451d516 (diff)
downloadlua-github-3.1-alpha.tar.gz
module to load bytecodes from files.v3_1_Alphav3.1-alpha
-rw-r--r--lundump.c272
-rw-r--r--lundump.h27
-rw-r--r--undump.c318
-rw-r--r--undump.h30
4 files changed, 299 insertions, 348 deletions
diff --git a/lundump.c b/lundump.c
new file mode 100644
index 00000000..32d7359a
--- /dev/null
+++ b/lundump.c
@@ -0,0 +1,272 @@
+/*
+** $Id: lundump.c,v 1.4 1998/01/13 20:05:24 lhf Exp $
+** load bytecodes from files
+** See Copyright Notice in lua.h
+*/
+
+#include <stdio.h>
+#include "lauxlib.h"
+#include "lfunc.h"
+#include "lmem.h"
+#include "lstring.h"
+#include "lundump.h"
+
+typedef struct {
+ ZIO* Z;
+ int SwapNumber;
+ int LoadFloat;
+} Sundump;
+
+static void unexpectedEOZ(ZIO* Z)
+{
+ luaL_verror("unexpected end of binary file %s",Z->name);
+}
+
+static int ezgetc(ZIO* Z)
+{
+ int c=zgetc(Z);
+ if (c==EOZ) unexpectedEOZ(Z);
+ return c;
+}
+
+static int ezread(ZIO* Z, void* b, int n)
+{
+ int r=zread(Z,b,n);
+ if (r!=0) unexpectedEOZ(Z);
+ return r;
+}
+
+static int LoadWord(ZIO* Z)
+{
+ int hi=ezgetc(Z);
+ int lo=ezgetc(Z);
+ return (hi<<8)|lo;
+}
+
+static void* LoadBlock(int size, ZIO* Z)
+{
+ void* b=luaM_malloc(size);
+ ezread(Z,b,size);
+ return b;
+}
+
+static int LoadSize(ZIO* Z)
+{
+ int hi=LoadWord(Z);
+ int lo=LoadWord(Z);
+ int s=(hi<<16)|lo;
+ if (hi!=0 && s==lo)
+ luaL_verror("code too long (%ld bytes)",(hi<<16)|(long)lo);
+ return s;
+}
+
+static char* LoadString(ZIO* Z)
+{
+ int size=LoadWord(Z);
+ if (size==0)
+ return NULL;
+ else
+ {
+ char* b=luaL_openspace(size);
+ ezread(Z,b,size);
+ return b;
+ }
+}
+
+static TaggedString* LoadTString(ZIO* Z)
+{
+ char* s=LoadString(Z);
+ return (s==NULL) ? NULL : luaS_new(s);
+}
+
+static void SwapFloat(float* f)
+{
+ Byte* p=(Byte*)f;
+ Byte* q=p+sizeof(float)-1;
+ Byte t;
+ t=*p; *p++=*q; *q--=t;
+ t=*p; *p++=*q; *q--=t;
+}
+
+static void SwapDouble(double* f)
+{
+ Byte* p=(Byte*)f;
+ Byte* q=p+sizeof(double)-1;
+ Byte t;
+ t=*p; *p++=*q; *q--=t;
+ t=*p; *p++=*q; *q--=t;
+ t=*p; *p++=*q; *q--=t;
+ t=*p; *p++=*q; *q--=t;
+}
+
+static real LoadNumber(Sundump* S)
+{
+ if (S->LoadFloat)
+ {
+ float f;
+ ezread(S->Z,&f,sizeof(f));
+ if (S->SwapNumber) SwapFloat(&f);
+ return f;
+ }
+ else
+ {
+ double f;
+ ezread(S->Z,&f,sizeof(f));
+ if (S->SwapNumber) SwapDouble(&f);
+ return f;
+ }
+}
+
+static void LoadLocals(TProtoFunc* tf, ZIO* Z)
+{
+ int i,n=LoadWord(Z);
+ if (n==0) return;
+ tf->locvars=luaM_newvector(n+1,LocVar);
+ for (i=0; i<n; i++)
+ {
+ tf->locvars[i].line=LoadWord(Z);
+ tf->locvars[i].varname=LoadTString(Z);
+ }
+ tf->locvars[i].line=-1; /* flag end of vector */
+ tf->locvars[i].varname=NULL;
+}
+
+static void LoadConstants(TProtoFunc* tf, Sundump* S)
+{
+ int i,n=LoadWord(S->Z);
+ tf->nconsts=n;
+ if (n==0) return;
+ tf->consts=luaM_newvector(n,TObject);
+ for (i=0; i<n; i++)
+ {
+ TObject* o=tf->consts+i;
+ int c=ezgetc(S->Z);
+ switch (c)
+ {
+ case ID_NUM:
+ ttype(o)=LUA_T_NUMBER;
+ nvalue(o)=LoadNumber(S);
+ break;
+ case ID_STR:
+ ttype(o)=LUA_T_STRING;
+ tsvalue(o)=LoadTString(S->Z);
+ break;
+ case ID_FUN:
+ ttype(o)=LUA_T_PROTO;
+ tfvalue(o)=NULL;
+ break;
+#ifdef DEBUG
+ default: /* cannot happen */
+ luaL_verror("internal error in LoadConstants: "
+ "bad constant #%d type=%d ('%c')\n",i,c,c);
+ break;
+#endif
+ }
+ }
+}
+
+static TProtoFunc* LoadFunction(Sundump* S);
+
+static void LoadFunctions(TProtoFunc* tf, Sundump* S)
+{
+ while (zgetc(S->Z)==ID_FUNCTION)
+ {
+ int i=LoadWord(S->Z);
+ TProtoFunc* t=LoadFunction(S);
+ TObject* o=tf->consts+i;
+ tfvalue(o)=t;
+ }
+}
+
+static TProtoFunc* LoadFunction(Sundump* S)
+{
+ ZIO* Z=S->Z;
+ TProtoFunc* tf=luaF_newproto();
+ tf->lineDefined=LoadWord(Z);
+ tf->fileName=LoadTString(Z);
+ tf->code=LoadBlock(LoadSize(Z),Z);
+ LoadConstants(tf,S);
+ LoadLocals(tf,Z);
+ LoadFunctions(tf,S);
+ return tf;
+}
+
+static void LoadSignature(ZIO* Z)
+{
+ char* s=SIGNATURE;
+ while (*s!=0 && ezgetc(Z)==*s)
+ ++s;
+ if (*s!=0) luaL_verror("bad signature in binary file %s",Z->name);
+}
+
+static void LoadHeader(Sundump* S)
+{
+ ZIO* Z=S->Z;
+ int version,sizeofR;
+ LoadSignature(Z);
+ version=ezgetc(Z);
+ if (version>VERSION)
+ luaL_verror(
+ "binary file %s too new: version=0x%02x; expected at most 0x%02x",
+ Z->name,version,VERSION);
+ if (version<0x31) /* major change in 3.1 */
+ luaL_verror(
+ "binary file %s too old: version=0x%02x; expected at least 0x%02x",
+ Z->name,version,0x31);
+ sizeofR=ezgetc(Z); /* test float representation */
+ if (sizeofR==sizeof(float))
+ {
+ float f,tf=TEST_FLOAT;
+ ezread(Z,&f,sizeof(f));
+ if (f!=tf)
+ {
+ SwapFloat(&f);
+ if (f!=tf)
+ luaL_verror("unknown float representation in binary file %s",Z->name);
+ S->SwapNumber=1;
+ }
+ S->LoadFloat=1;
+ }
+ else if (sizeofR==sizeof(double))
+ {
+ double f,tf=TEST_FLOAT;
+ ezread(Z,&f,sizeof(f));
+ if (f!=tf)
+ {
+ SwapDouble(&f);
+ if (f!=tf)
+ luaL_verror("unknown float representation in binary file %s",Z->name);
+ S->SwapNumber=1;
+ }
+ S->LoadFloat=0;
+ }
+ else
+ luaL_verror(
+ "floats in binary file %s have %d bytes; "
+ "expected %d (float) or %d (double)",
+ Z->name,sizeofR,sizeof(float),sizeof(double));
+}
+
+static TProtoFunc* LoadChunk(Sundump* S)
+{
+ LoadHeader(S);
+ return LoadFunction(S);
+}
+
+/*
+** load one chunk from a file or buffer
+** return main if ok and NULL at EOF
+*/
+TProtoFunc* luaU_undump1(ZIO* Z)
+{
+ int c=zgetc(Z);
+ Sundump S;
+ S.Z=Z;
+ S.SwapNumber=0;
+ S.LoadFloat=1;
+ if (c==ID_CHUNK)
+ return LoadChunk(&S);
+ else if (c!=EOZ)
+ luaL_verror("%s is not a lua binary file",Z->name);
+ return NULL;
+}
diff --git a/lundump.h b/lundump.h
new file mode 100644
index 00000000..ea9e975c
--- /dev/null
+++ b/lundump.h
@@ -0,0 +1,27 @@
+/*
+** $Id: lundump.h,v 1.4 1998/01/13 20:05:24 lhf Exp $
+** load pre-compiled Lua chunks
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lundump_h
+#define lundump_h
+
+#include "lobject.h"
+#include "lzio.h"
+
+#define ID_CHUNK 27 /* ESC */
+#define ID_FUNCTION '#'
+#define ID_END '$'
+#define ID_NUM 'N'
+#define ID_STR 'S'
+#define ID_FUN 'F'
+#define SIGNATURE "Lua"
+#define VERSION 0x31 /* last format change was in 3.1 */
+#define TEST_FLOAT 0.123456789e-23 /* a float for testing representation */
+
+#define IsMain(f) (f->lineDefined==0)
+
+TProtoFunc* luaU_undump1(ZIO* Z); /* load one chunk */
+
+#endif
diff --git a/undump.c b/undump.c
deleted file mode 100644
index 80f131de..00000000
--- a/undump.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
-** undump.c
-** load bytecodes from files
-*/
-
-char* rcs_undump="$Id: undump.c,v 1.25 1997/07/29 19:44:02 roberto Exp roberto $";
-
-#include <stdio.h>
-#include <string.h>
-#include "auxlib.h"
-#include "opcode.h"
-#include "luamem.h"
-#include "table.h"
-#include "undump.h"
-#include "zio.h"
-
-static int swapword=0;
-static int swapfloat=0;
-static TFunc* Main=NULL; /* functions in a chunk */
-static TFunc* lastF=NULL;
-
-static void FixCode(Byte* code, Byte* end) /* swap words */
-{
- Byte* p;
- for (p=code; p!=end;)
- {
- int op=*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 RETCODE0:
- p++;
- break;
- case PUSHBYTE:
- case PUSHLOCAL:
- case STORELOCAL:
- case STOREINDEXED:
- case STORELIST0:
- case ADJUST:
- case RETCODE:
- case VARARGS:
- case STOREMAP:
- p+=2;
- break;
- case STORELIST:
- case CALLFUNC:
- p+=3;
- break;
- case PUSHWORD:
- case PUSHSELF:
- case CREATEARRAY:
- case ONTJMP:
- case ONFJMP:
- case JMP:
- case UPJMP:
- case IFFJMP:
- case IFFUPJMP:
- case SETLINE:
- case PUSHGLOBAL:
- case STOREGLOBAL:
- {
- Byte t;
- t=p[1]; p[1]=p[2]; p[2]=t;
- p+=3;
- 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:
- luaL_verror("corrupt binary file: bad opcode %d at %d\n",
- op,(int)(p-code));
- break;
- }
- }
-}
-
-static void Unthread(Byte* code, int i, int v)
-{
- while (i!=0)
- {
- Word w;
- Byte* p=code+i;
- memcpy(&w,p,sizeof(w));
- i=w; w=v;
- memcpy(p,&w,sizeof(w));
- }
-}
-
-static int LoadWord(ZIO* Z)
-{
- Word w;
- zread(Z,&w,sizeof(w));
- if (swapword)
- {
- Byte* p=(Byte*)&w;
- Byte t;
- t=p[0]; p[0]=p[1]; p[1]=t;
- }
- return w;
-}
-
-static int LoadSize(ZIO* Z)
-{
- Word hi=LoadWord(Z);
- Word lo=LoadWord(Z);
- int s=(hi<<16)|lo;
- if ((Word)s != s) lua_error("code too long");
- return s;
-}
-
-static void* LoadBlock(int size, ZIO* Z)
-{
- void* b=luaI_malloc(size);
- zread(Z,b,size);
- return b;
-}
-
-static char* LoadString(ZIO* Z)
-{
- int size=LoadWord(Z);
- char *b=luaI_buffer(size);
- zread(Z,b,size);
- return b;
-}
-
-static char* LoadNewString(ZIO* Z)
-{
- return LoadBlock(LoadWord(Z),Z);
-}
-
-static void LoadFunction(ZIO* Z)
-{
- int size;
- TFunc* tf=new(TFunc);
- tf->next=NULL;
- tf->locvars=NULL;
- size=LoadSize(Z);
- tf->lineDefined=LoadWord(Z);
- if (IsMain(tf)) /* new main */
- {
- tf->fileName=LoadNewString(Z);
- Main=lastF=tf;
- }
- else /* fix PUSHFUNCTION */
- {
- tf->marked=LoadWord(Z);
- tf->fileName=Main->fileName;
- memcpy(Main->code+tf->marked,&tf,sizeof(tf));
- lastF=lastF->next=tf;
- }
- tf->code=LoadBlock(size,Z);
- if (swapword || swapfloat) FixCode(tf->code,tf->code+size);
- while (1) /* unthread */
- {
- int c=zgetc(Z);
- if (c==ID_VAR) /* global var */
- {
- int i=LoadWord(Z);
- char* s=LoadString(Z);
- int v=luaI_findsymbolbyname(s);
- Unthread(tf->code,i,v);
- }
- else if (c==ID_STR) /* constant string */
- {
- int i=LoadWord(Z);
- char* s=LoadString(Z);
- int v; /*=luaI_findconstantbyname(s); ??????? */
- Unthread(tf->code,i,v);
- }
- else
- {
- zungetc(Z);
- break;
- }
- }
-}
-
-static void LoadSignature(ZIO* Z)
-{
- char* s=SIGNATURE;
- while (*s!=0 && zgetc(Z)==*s)
- ++s;
- if (*s!=0) lua_error("cannot load binary file: bad signature");
-}
-
-static void LoadHeader(ZIO* Z)
-{
- Word w,tw=TEST_WORD;
- float f,tf=TEST_FLOAT;
- int version;
- LoadSignature(Z);
- version=zgetc(Z);
- if (version>0x23) /* after 2.5 */
- {
- int oldsizeofW=zgetc(Z);
- int oldsizeofF=zgetc(Z);
- int oldsizeofP=zgetc(Z);
- if (oldsizeofW!=2)
- luaL_verror(
- "cannot load binary file created on machine with sizeof(Word)=%d; "
- "expected 2",oldsizeofW);
- if (oldsizeofF!=4)
- luaL_verror(
- "cannot load binary file created on machine with sizeof(float)=%d; "
- "expected 4\nnot an IEEE machine?",oldsizeofF);
- if (oldsizeofP!=sizeof(TFunc*)) /* TODO: pack? */
- luaL_verror(
- "cannot load binary file created on machine with sizeof(TFunc*)=%d; "
- "expected %d",oldsizeofP,(int)sizeof(TFunc*));
- }
- zread(Z,&w,sizeof(w)); /* test word */
- if (w!=tw)
- {
- swapword=1;
- }
- zread(Z,&f,sizeof(f)); /* test float */
- if (f!=tf)
- {
- Byte* p=(Byte*)&f;
- 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("cannot load binary file: unknown float representation");
- }
-}
-
-static void LoadChunk(ZIO* Z)
-{
- LoadHeader(Z);
- while (1)
- {
- int c=zgetc(Z);
- if (c==ID_FUN) LoadFunction(Z); else { zungetc(Z); break; }
- }
-}
-
-/*
-** load one chunk from a file.
-** return list of functions found, headed by main, or NULL at EOF.
-*/
-TFunc* luaI_undump1(ZIO* Z)
-{
- int c=zgetc(Z);
- if (c==ID_CHUNK)
- {
- LoadChunk(Z);
- return Main;
- }
- else if (c!=EOZ)
- lua_error("not a lua binary file");
- return NULL;
-}
-
-/*
-** load and run all chunks in a file
-*/
-int luaI_undump(ZIO* Z)
-{
- TFunc* m;
- while ((m=luaI_undump1(Z)))
- {
- int status=luaI_dorun(m);
-/* luaI_freefunc(m); ???*/
- if (status!=0) return status;
- }
- return 0;
-}
diff --git a/undump.h b/undump.h
deleted file mode 100644
index 86da43af..00000000
--- a/undump.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-** undump.h
-** definitions for lua decompiler
-** $Id: undump.h,v 1.5 1997/06/16 16:50:22 roberto Exp roberto $
-*/
-
-#ifndef undump_h
-#define undump_h
-
-#include "func.h"
-#include "zio.h"
-
-#define IsMain(f) (f->lineDefined==0)
-
-/* definitions for chunk headers */
-
-#define ID_CHUNK 27 /* ESC */
-#define ID_FUN 'F'
-#define ID_VAR 'V'
-#define ID_STR 'S'
-#define SIGNATURE "Lua"
-#define VERSION 0x25 /* last format change was in 2.5 */
-#define TEST_WORD 0x1234 /* a word for testing byte ordering */
-#define TEST_FLOAT 0.123456789e-23 /* a float for testing representation */
-
-
-TFunc* luaI_undump1(ZIO* Z);
-int luaI_undump(ZIO* Z); /* load all chunks */
-
-#endif