From 981fddea022b6cad7768223353b4e7386080c271 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 14 Jan 1998 13:49:01 -0200 Subject: module to load bytecodes from files. --- lundump.c | 272 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 lundump.c (limited to 'lundump.c') 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 +#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; ilocvars[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; iconsts+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; +} -- cgit v1.2.3-55-g6feb