From 7c9aee64c250e6f56b5788479d62ff9cbc6ad634 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Tue, 30 Mar 1999 17:29:34 -0300 Subject: [PATCH] new version by lhf. --- lundump.c | 108 +++++++++++++++++++++++++++++++++++++----------------- lundump.h | 96 +++++++++++++++++++++++++++++------------------- 2 files changed, 134 insertions(+), 70 deletions(-) diff --git a/lundump.c b/lundump.c index 941f8ae8..a0079e26 100644 --- a/lundump.c +++ b/lundump.c @@ -1,13 +1,15 @@ /* -** $Id: lundump.c,v 1.6 1998/12/27 20:23:22 roberto Exp roberto $ +** $Id: lundump.c,v 1.17 1999/03/29 16:16:18 lhf Exp $ ** load bytecodes from files ** See Copyright Notice in lua.h */ #include +#include #include "lauxlib.h" #include "lfunc.h" #include "lmem.h" +#include "lopcodes.h" #include "lstring.h" #include "lundump.h" @@ -52,19 +54,18 @@ static unsigned long LoadLong (ZIO* Z) return (hi<<16)|lo; } -#if ID_NUMBER==ID_REAL4 -/* LUA_NUMBER */ +#if ID_NUMBER==ID_REAL4 /* LUA_NUMBER */ /* assumes sizeof(long)==4 and sizeof(float)==4 (IEEE) */ static float LoadFloat (ZIO* Z) { unsigned long l=LoadLong(Z); - float f=*(float*)&l; + float f; + memcpy(&f,&l,sizeof(f)); return f; } #endif -#if ID_NUMBER==ID_REAL8 -/* LUA_NUMBER */ +#if ID_NUMBER==ID_REAL8 /* LUA_NUMBER */ /* assumes sizeof(long)==4 and sizeof(double)==8 (IEEE) */ static double LoadDouble (ZIO* Z) { @@ -81,25 +82,34 @@ static double LoadDouble (ZIO* Z) l[0]=LoadLong(Z); l[1]=LoadLong(Z); } - f=*(double*)l; + memcpy(&f,l,sizeof(f)); return f; } #endif +static int LoadInt (ZIO* Z, char* message) +{ + unsigned long l=LoadLong(Z); + unsigned int i=l; + if (i!=l) luaL_verror(message,l,zname(Z)); + return i; +} + +#define PAD 5 /* two word operands plus opcode */ + static Byte* LoadCode (ZIO* Z) { - unsigned long size=LoadLong(Z); - unsigned int s=size; - void* b; - if (s!=size) luaL_verror("code too long (%ld bytes) in %s",size,zname(Z)); - b=luaM_malloc(size); + int size=LoadInt(Z,"code too long (%ld bytes) in %s"); + Byte* b=luaM_malloc(size+PAD); LoadBlock(b,size,Z); + if (b[size-1]!=ENDCODE) luaL_verror("bad code in %s",zname(Z)); + memset(b+size,ENDCODE,PAD); /* pad for safety */ return b; } static TaggedString* LoadTString (ZIO* Z) { - int size=LoadWord(Z); + long size=LoadLong(Z); if (size==0) return NULL; else @@ -112,46 +122,45 @@ static TaggedString* LoadTString (ZIO* Z) static void LoadLocals (TProtoFunc* tf, ZIO* Z) { - int i,n=LoadWord(Z); + int i,n=LoadInt(Z,"too many locals (%ld) in %s"); if (n==0) return; tf->locvars=luaM_newvector(n+1,LocVar); for (i=0; ilocvars[i].line=LoadWord(Z); + tf->locvars[i].line=LoadInt(Z,"too many lines (%ld) in %s"); tf->locvars[i].varname=LoadTString(Z); } tf->locvars[i].line=-1; /* flag end of vector */ tf->locvars[i].varname=NULL; } -static TProtoFunc* LoadFunction (ZIO* Z); +static TProtoFunc* LoadFunction(ZIO* Z); static void LoadConstants (TProtoFunc* tf, ZIO* Z) { - int i,n=LoadWord(Z); + int i,n=LoadInt(Z,"too many constants (%ld) in %s"); tf->nconsts=n; if (n==0) return; tf->consts=luaM_newvector(n,TObject); for (i=0; iconsts+i; - int c=ezgetc(Z); - switch (c) + ttype(o)=-ezgetc(Z); /* ttype(o) is negative - ORDER LUA_T */ + switch (ttype(o)) { - case ID_NUM: - ttype(o)=LUA_T_NUMBER; + case LUA_T_NUMBER: doLoadNumber(nvalue(o),Z); break; - case ID_STR: - ttype(o)=LUA_T_STRING; + case LUA_T_STRING: tsvalue(o)=LoadTString(Z); break; - case ID_FUN: - ttype(o)=LUA_T_PROTO; + case LUA_T_PROTO: tfvalue(o)=LoadFunction(Z); break; - default: - luaL_verror("bad constant #%d in %s: type=%d ('%c')",i,zname(Z),c,c); + case LUA_T_NIL: + break; + default: /* cannot happen */ + luaU_badconstant("load",i,o,tf); break; } } @@ -160,8 +169,9 @@ static void LoadConstants (TProtoFunc* tf, ZIO* Z) static TProtoFunc* LoadFunction (ZIO* Z) { TProtoFunc* tf=luaF_newproto(); - tf->lineDefined=LoadWord(Z); + tf->lineDefined=LoadInt(Z,"lineDefined too large (%ld) in %s"); tf->source=LoadTString(Z); + if (tf->source==NULL) tf->source=luaS_new(zname(Z)); tf->code=LoadCode(Z); LoadLocals(tf,Z); LoadConstants(tf,Z); @@ -180,6 +190,7 @@ static void LoadHeader (ZIO* Z) { int version,id,sizeofR; real f=-TEST_NUMBER,tf=TEST_NUMBER; + luaU_testnumber(); LoadSignature(Z); version=ezgetc(Z); if (version>VERSION) @@ -193,15 +204,14 @@ static void LoadHeader (ZIO* Z) id=ezgetc(Z); /* test number representation */ sizeofR=ezgetc(Z); if (id!=ID_NUMBER || sizeofR!=sizeof(real)) - { luaL_verror("unknown number signature in %s: " "read 0x%02x%02x; expected 0x%02x%02x", zname(Z),id,sizeofR,ID_NUMBER,sizeof(real)); - } doLoadNumber(f,Z); if (f!=tf) - luaL_verror("unknown number representation in %s: read %g; expected %g", - zname(Z),(double)f,(double)tf); /* LUA_NUMBER */ + luaL_verror("unknown number representation in %s: " + "read " NUMBER_FMT "; expected " NUMBER_FMT, + zname(Z),f,tf); } static TProtoFunc* LoadChunk (ZIO* Z) @@ -214,7 +224,7 @@ static TProtoFunc* LoadChunk (ZIO* Z) ** load one chunk from a file or buffer ** return main if ok and NULL at EOF */ -TProtoFunc* luaU_undump1 (ZIO* Z) +TProtoFunc* luaU_undump1(ZIO* Z) { int c=zgetc(Z); if (c==ID_CHUNK) @@ -223,3 +233,35 @@ TProtoFunc* luaU_undump1 (ZIO* Z) luaL_verror("%s is not a Lua binary file",zname(Z)); return NULL; } + +/* +** test number representation +*/ +void luaU_testnumber(void) +{ + if (sizeof(real)!=SIZEOF_NUMBER) + luaL_verror("numbers have %d bytes; expected %d. see lundump.h", + (int)sizeof(real),SIZEOF_NUMBER); +#if ID_NUMBER==ID_REAL4 || ID_NUMBER==ID_REAL8 + if (sizeof(long)!=4) + luaL_verror("longs have %d bytes; expected %d. see lundump.h", + (int)sizeof(long),4); +#endif + { + real t=TEST_NUMBER; + TYPEOF_NUMBER v=TEST_NUMBER; + if (t!=v) + luaL_verror("unsupported number type; expected %d-byte " NAMEOF_NUMBER "." + " see config and lundump.h",SIZEOF_NUMBER); + } +} + +/* +* handle constants that cannot happen +*/ +void luaU_badconstant(char* s, int i, TObject* o, TProtoFunc* tf) +{ + int t=ttype(o); + char* name= (t>0 || tlineDefined==0) +/* choose one definition for ID_NUMBER and move it to after #endif */ +#if 0 +#define ID_NUMBER ID_INT4 /* 4-byte integers */ +#define ID_NUMBER ID_REAL4 /* 4-byte reals */ +#define ID_NUMBER ID_REAL8 /* 8-byte reals */ +#define ID_NUMBER ID_NATIVE /* whatever your machine uses */ +#endif -#define ID_CHUNK 27 /* ESC */ -#define ID_NUM 'N' -#define ID_STR 'S' -#define ID_FUN 'F' +/* format for numbers in listings and error messages */ +#ifndef NUMBER_FMT +#define NUMBER_FMT "%.16g" /* LUA_NUMBER */ +#endif + +/* -- end of user configuration -- DO NOT CHANGE ANYTHING BELOW THIS LINE -- */ + + +TProtoFunc* luaU_undump1(ZIO* Z); /* load one chunk */ +void luaU_testnumber(void); /* test number representation */ +void luaU_badconstant(char* s, int i, TObject* o, TProtoFunc* tf); + /* handle cases that cannot happen */ + +/* definitions for headers of binary files */ +#define VERSION 0x32 /* last format change was in 3.2 */ +#define VERSION0 0x32 /* last major change was in 3.2 */ +#define ID_CHUNK 27 /* binary files start with ESC... */ +#define SIGNATURE "Lua" /* ...followed by this signature */ /* number representation */ #define ID_INT4 'l' /* 4-byte integers */ @@ -29,53 +58,46 @@ TProtoFunc *luaU_undump1 (ZIO* Z); /* load one chunk */ #define ID_REAL8 'd' /* 8-byte reals */ #define ID_NATIVE '?' /* whatever your machine uses */ -/* -* use a multiple of PI for testing number representation. -* multiplying by 1E8 gives notrivial integer values. -*/ -#define TEST_NUMBER 3.14159265358979323846E8 - -/* LUA_NUMBER -* choose one below for the number representation in precompiled chunks. -* the default is ID_REAL8 because the default for LUA_NUM_TYPE is double. -* if your machine does not use IEEE 754, use ID_NATIVE. -* the next version will support conversion to/from IEEE 754. -* -* if you change LUA_NUM_TYPE, make sure you set ID_NUMBER accordingly, -* specially if sizeof(long)!=4. -* for types other than the ones listed below, you'll have to write your own -* dump and undump routines. -*/ - +/* the default is ID_REAL8 because the default for LUA_NUM_TYPE is double */ #ifndef ID_NUMBER -#define ID_NUMBER ID_NATIVE +#define ID_NUMBER ID_REAL8 /* 8-byte reals */ #endif -#if 0 -#define ID_NUMBER ID_INT4 -#define ID_NUMBER ID_REAL4 -#define ID_NUMBER ID_REAL8 -#define ID_NUMBER ID_NATIVE -#endif - -#endif +/* a multiple of PI for testing number representation */ +/* multiplying by 1E8 gives non-trivial integer values */ +#define TEST_NUMBER 3.14159265358979323846E8 #if ID_NUMBER==ID_REAL4 #define DumpNumber DumpFloat #define LoadNumber LoadFloat #define SIZEOF_NUMBER 4 + #define TYPEOF_NUMBER float + #define NAMEOF_NUMBER "float" #elif ID_NUMBER==ID_REAL8 #define DumpNumber DumpDouble #define LoadNumber LoadDouble #define SIZEOF_NUMBER 8 + #define TYPEOF_NUMBER double + #define NAMEOF_NUMBER "double" #elif ID_NUMBER==ID_INT4 #define DumpNumber DumpLong #define LoadNumber LoadLong #define SIZEOF_NUMBER 4 + #define TYPEOF_NUMBER long + #define NAMEOF_NUMBER "long" #elif ID_NUMBER==ID_NATIVE #define DumpNumber DumpNative #define LoadNumber LoadNative #define SIZEOF_NUMBER sizeof(real) + #define TYPEOF_NUMBER real + #define NAMEOF_NUMBER "native" #else #error bad ID_NUMBER #endif + +/* formats for error messages */ +#define SOURCE "<%s:%d>" +#define IN " in %p " SOURCE +#define INLOC tf,tf->source->str,tf->lineDefined + +#endif