mirror of https://github.com/lua/lua.git
Roberto Ierusalimschy
27 years ago
4 changed files with 299 additions and 348 deletions
@ -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; |
|||
} |
@ -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 |
@ -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; |
|||
} |
@ -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 |
Loading…
Reference in new issue