rpm
4.5
|
00001 /* 00002 ** $Id: lundump.c,v 1.1 2004/03/16 21:58:30 niemeyer Exp $ 00003 ** load pre-compiled Lua chunks 00004 ** See Copyright Notice in lua.h 00005 */ 00006 00007 #define lundump_c 00008 00009 #include "lua.h" 00010 00011 #include "ldebug.h" 00012 #include "lfunc.h" 00013 #include "lmem.h" 00014 #include "lopcodes.h" 00015 #include "lstring.h" 00016 #include "lundump.h" 00017 #include "lzio.h" 00018 00019 #define LoadByte (lu_byte) ezgetc 00020 00021 typedef struct { 00022 lua_State* L; 00023 ZIO* Z; 00024 Mbuffer* b; 00025 int swap; 00026 /*@observer@*/ 00027 const char* name; 00028 } LoadState; 00029 00030 static void unexpectedEOZ (LoadState* S) 00031 /*@modifies S @*/ 00032 { 00033 luaG_runerror(S->L,"unexpected end of file in %s",S->name); 00034 } 00035 00036 static int ezgetc (LoadState* S) 00037 /*@modifies S @*/ 00038 { 00039 int c=zgetc(S->Z); 00040 if (c==EOZ) unexpectedEOZ(S); 00041 return c; 00042 } 00043 00044 static void ezread (LoadState* S, void* b, int n) 00045 /*@modifies S, *b @*/ 00046 { 00047 int r=luaZ_read(S->Z,b,n); 00048 if (r!=0) unexpectedEOZ(S); 00049 } 00050 00051 static void LoadBlock (LoadState* S, void* b, size_t size) 00052 /*@modifies S, *b @*/ 00053 { 00054 if (S->swap) 00055 { 00056 char* p=(char*) b+size-1; 00057 int n=size; 00058 while (n--) *p--=(char)ezgetc(S); 00059 } 00060 else 00061 ezread(S,b,size); 00062 } 00063 00064 static void LoadVector (LoadState* S, void* b, int m, size_t size) 00065 /*@modifies S, *b @*/ 00066 { 00067 if (S->swap) 00068 { 00069 char* q=(char*) b; 00070 while (m--) 00071 { 00072 char* p=q+size-1; 00073 int n=size; 00074 while (n--) *p--=(char)ezgetc(S); 00075 q+=size; 00076 } 00077 } 00078 else 00079 ezread(S,b,m*size); 00080 } 00081 00082 static int LoadInt (LoadState* S) 00083 /*@modifies S @*/ 00084 { 00085 int x; 00086 LoadBlock(S,&x,sizeof(x)); 00087 if (x<0) luaG_runerror(S->L,"bad integer in %s",S->name); 00088 return x; 00089 } 00090 00091 static size_t LoadSize (LoadState* S) 00092 /*@modifies S @*/ 00093 { 00094 size_t x; 00095 LoadBlock(S,&x,sizeof(x)); 00096 return x; 00097 } 00098 00099 static lua_Number LoadNumber (LoadState* S) 00100 /*@modifies S @*/ 00101 { 00102 lua_Number x; 00103 LoadBlock(S,&x,sizeof(x)); 00104 return x; 00105 } 00106 00107 /*@null@*/ 00108 static TString* LoadString (LoadState* S) 00109 /*@modifies S @*/ 00110 { 00111 size_t size=LoadSize(S); 00112 if (size==0) 00113 return NULL; 00114 else 00115 { 00116 char* s=luaZ_openspace(S->L,S->b,size); 00117 ezread(S,s,size); 00118 return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ 00119 } 00120 } 00121 00122 static void LoadCode (LoadState* S, Proto* f) 00123 /*@modifies S, f @*/ 00124 { 00125 int size=LoadInt(S); 00126 f->code=luaM_newvector(S->L,size,Instruction); 00127 f->sizecode=size; 00128 LoadVector(S,f->code,size,sizeof(*f->code)); 00129 } 00130 00131 static void LoadLocals (LoadState* S, Proto* f) 00132 /*@modifies S, f @*/ 00133 { 00134 int i,n; 00135 n=LoadInt(S); 00136 f->locvars=luaM_newvector(S->L,n,LocVar); 00137 f->sizelocvars=n; 00138 for (i=0; i<n; i++) 00139 { 00140 f->locvars[i].varname=LoadString(S); 00141 f->locvars[i].startpc=LoadInt(S); 00142 f->locvars[i].endpc=LoadInt(S); 00143 } 00144 } 00145 00146 static void LoadLines (LoadState* S, Proto* f) 00147 /*@modifies S, f @*/ 00148 { 00149 int size=LoadInt(S); 00150 f->lineinfo=luaM_newvector(S->L,size,int); 00151 f->sizelineinfo=size; 00152 LoadVector(S,f->lineinfo,size,sizeof(*f->lineinfo)); 00153 } 00154 00155 static void LoadUpvalues (LoadState* S, Proto* f) 00156 /*@modifies S, f @*/ 00157 { 00158 int i,n; 00159 n=LoadInt(S); 00160 if (n!=0 && n!=f->nups) 00161 luaG_runerror(S->L,"bad nupvalues in %s: read %d; expected %d", 00162 S->name,n,f->nups); 00163 f->upvalues=luaM_newvector(S->L,n,TString*); 00164 f->sizeupvalues=n; 00165 for (i=0; i<n; i++) f->upvalues[i]=LoadString(S); 00166 } 00167 00168 /*@null@*/ 00169 static Proto* LoadFunction (LoadState* S, /*@null@*/ TString* p) 00170 /*@modifies S @*/; 00171 00172 static void LoadConstants (LoadState* S, Proto* f) 00173 /*@modifies S, f @*/ 00174 { 00175 int i,n; 00176 n=LoadInt(S); 00177 f->k=luaM_newvector(S->L,n,TObject); 00178 f->sizek=n; 00179 for (i=0; i<n; i++) 00180 { 00181 TObject* o=&f->k[i]; 00182 int t=LoadByte(S); 00183 switch (t) 00184 { 00185 case LUA_TNUMBER: 00186 setnvalue(o,LoadNumber(S)); 00187 break; 00188 case LUA_TSTRING: 00189 setsvalue2n(o,LoadString(S)); 00190 break; 00191 case LUA_TNIL: 00192 setnilvalue(o); 00193 break; 00194 default: 00195 luaG_runerror(S->L,"bad constant type (%d) in %s",t,S->name); 00196 break; 00197 } 00198 } 00199 n=LoadInt(S); 00200 f->p=luaM_newvector(S->L,n,Proto*); 00201 f->sizep=n; 00202 for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source); 00203 } 00204 00205 static Proto* LoadFunction (LoadState* S, TString* p) 00206 /*@modifies S @*/ 00207 { 00208 Proto* f=luaF_newproto(S->L); 00209 f->source=LoadString(S); if (f->source==NULL) f->source=p; 00210 f->lineDefined=LoadInt(S); 00211 f->nups=LoadByte(S); 00212 f->numparams=LoadByte(S); 00213 f->is_vararg=LoadByte(S); 00214 f->maxstacksize=LoadByte(S); 00215 LoadLines(S,f); 00216 LoadLocals(S,f); 00217 LoadUpvalues(S,f); 00218 LoadConstants(S,f); 00219 LoadCode(S,f); 00220 #ifndef TRUST_BINARIES 00221 if (!luaG_checkcode(f)) luaG_runerror(S->L,"bad code in %s",S->name); 00222 #endif 00223 return f; 00224 } 00225 00226 static void LoadSignature (LoadState* S) 00227 /*@modifies S @*/ 00228 { 00229 const char* s=LUA_SIGNATURE; 00230 while (*s!=0 && ezgetc(S)==*s) 00231 ++s; 00232 if (*s!=0) luaG_runerror(S->L,"bad signature in %s",S->name); 00233 } 00234 00235 static void TestSize (LoadState* S, int s, const char* what) 00236 /*@modifies S @*/ 00237 { 00238 int r=LoadByte(S); 00239 if (r!=s) 00240 luaG_runerror(S->L,"virtual machine mismatch in %s: " 00241 "size of %s is %d but read %d",S->name,what,s,r); 00242 } 00243 00244 #define TESTSIZE(s,w) TestSize(S,s,w) 00245 #define V(v) v/16,v%16 00246 00247 static void LoadHeader (LoadState* S) 00248 /*@modifies S @*/ 00249 { 00250 int version; 00251 lua_Number x,tx=TEST_NUMBER; 00252 LoadSignature(S); 00253 version=LoadByte(S); 00254 if (version>VERSION) 00255 luaG_runerror(S->L,"%s too new: " 00256 "read version %d.%d; expected at most %d.%d", 00257 S->name,V(version),V(VERSION)); 00258 if (version<VERSION0) /* check last major change */ 00259 luaG_runerror(S->L,"%s too old: " 00260 "read version %d.%d; expected at least %d.%d", 00261 S->name,V(version),V(VERSION0)); 00262 S->swap=(luaU_endianness()!=LoadByte(S)); /* need to swap bytes? */ 00263 TESTSIZE(sizeof(int),"int"); 00264 TESTSIZE(sizeof(size_t), "size_t"); 00265 TESTSIZE(sizeof(Instruction), "Instruction"); 00266 TESTSIZE(SIZE_OP, "OP"); 00267 TESTSIZE(SIZE_A, "A"); 00268 TESTSIZE(SIZE_B, "B"); 00269 TESTSIZE(SIZE_C, "C"); 00270 TESTSIZE(sizeof(lua_Number), "number"); 00271 x=LoadNumber(S); 00272 if ((long)x!=(long)tx) /* disregard errors in last bits of fraction */ 00273 luaG_runerror(S->L,"unknown number format in %s",S->name); 00274 } 00275 00276 /*@null@*/ 00277 static Proto* LoadChunk (LoadState* S) 00278 /*@modifies S @*/ 00279 { 00280 LoadHeader(S); 00281 return LoadFunction(S,NULL); 00282 } 00283 00284 /* 00285 ** load precompiled chunk 00286 */ 00287 Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff) 00288 { 00289 LoadState S; 00290 const char* s=zname(Z); 00291 if (*s=='@' || *s=='=') 00292 S.name=s+1; 00293 else if (*s==LUA_SIGNATURE[0]) 00294 S.name="binary string"; 00295 else 00296 S.name=s; 00297 S.L=L; 00298 S.Z=Z; 00299 S.b=buff; 00300 return LoadChunk(&S); 00301 } 00302 00303 /* 00304 ** find byte order 00305 */ 00306 int luaU_endianness (void) 00307 { 00308 int x=1; 00309 return *(char*)&x; 00310 }