diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-11-16 09:55:07 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-11-16 09:55:07 -0200 |
commit | 2753134a3800eb28185502d68c28d9225420bd04 (patch) | |
tree | baadf08136338a8a5b1d4a7545d786ccfe5fb43a /lundump.c | |
parent | cbbde11a8ab1cda25fa36533739e4ca1efd1916c (diff) | |
download | lua-2753134a3800eb28185502d68c28d9225420bd04.tar.gz lua-2753134a3800eb28185502d68c28d9225420bd04.tar.bz2 lua-2753134a3800eb28185502d68c28d9225420bd04.zip |
new versions by lhf
Diffstat (limited to 'lundump.c')
-rw-r--r-- | lundump.c | 287 |
1 files changed, 107 insertions, 180 deletions
@@ -1,9 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lundump.c,v 2.4 2005/05/05 20:47:02 roberto Exp roberto $ | 2 | ** $Id: lundump.c,v 1.58 2005/09/02 01:54:47 lhf Exp lhf $ |
3 | ** load pre-compiled Lua chunks | 3 | ** load precompiled Lua chunks |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <string.h> | ||
8 | |||
7 | #define lundump_c | 9 | #define lundump_c |
8 | #define LUA_CORE | 10 | #define LUA_CORE |
9 | 11 | ||
@@ -13,193 +15,152 @@ | |||
13 | #include "ldo.h" | 15 | #include "ldo.h" |
14 | #include "lfunc.h" | 16 | #include "lfunc.h" |
15 | #include "lmem.h" | 17 | #include "lmem.h" |
16 | #include "lopcodes.h" | 18 | #include "lobject.h" |
17 | #include "lstring.h" | 19 | #include "lstring.h" |
18 | #include "lundump.h" | 20 | #include "lundump.h" |
19 | #include "lzio.h" | 21 | #include "lzio.h" |
20 | 22 | ||
21 | #define LoadByte (lu_byte) ezgetc | ||
22 | |||
23 | typedef struct { | 23 | typedef struct { |
24 | lua_State* L; | 24 | lua_State* L; |
25 | ZIO* Z; | 25 | ZIO* Z; |
26 | Mbuffer* b; | 26 | Mbuffer* b; |
27 | int swap; | ||
28 | const char* name; | 27 | const char* name; |
29 | } LoadState; | 28 | } LoadState; |
30 | 29 | ||
31 | static void unexpectedEOZ (LoadState* S) | 30 | #ifdef LUAC_TRUST_BINARIES |
32 | { | 31 | #define IF(c,s) |
33 | luaG_runerror(S->L,"unexpected end of file in %s",S->name); | 32 | #else |
34 | } | 33 | #define IF(c,s) if (c) error(S,s) |
35 | 34 | ||
36 | static int ezgetc (LoadState* S) | 35 | static void error(LoadState* S, const char* why) |
37 | { | 36 | { |
38 | int c=zgetc(S->Z); | 37 | luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why); |
39 | if (c==EOZ) unexpectedEOZ(S); | 38 | luaD_throw(S->L,LUA_ERRSYNTAX); |
40 | return c; | ||
41 | } | 39 | } |
40 | #endif | ||
42 | 41 | ||
43 | static void ezread (LoadState* S, void* b, size_t n) | 42 | #define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) |
44 | { | 43 | #define LoadByte(S) (lu_byte)LoadChar(S) |
45 | size_t r=luaZ_read(S->Z,b,n); | 44 | #define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) |
46 | if (r!=0) unexpectedEOZ(S); | 45 | #define LoadVector(S,b,n,size) LoadMem(S,b,n,size) |
47 | } | ||
48 | 46 | ||
49 | static void LoadBlock (LoadState* S, void* b, size_t size) | 47 | static void LoadBlock(LoadState* S, void* b, size_t size) |
50 | { | 48 | { |
51 | if (S->swap) | 49 | size_t r=luaZ_read(S->Z,b,size); |
52 | { | 50 | IF (r!=0, "unexpected end"); |
53 | char* p=(char*) b+size-1; | ||
54 | size_t n=size; | ||
55 | while (n--) *p--=(char)ezgetc(S); | ||
56 | } | ||
57 | else | ||
58 | ezread(S,b,size); | ||
59 | } | 51 | } |
60 | 52 | ||
61 | static void LoadVector (LoadState* S, void* b, int m, size_t size) | 53 | static int LoadChar(LoadState* S) |
62 | { | 54 | { |
63 | if (S->swap) | 55 | char x; |
64 | { | 56 | LoadVar(S,x); |
65 | char* q=(char*) b; | ||
66 | while (m--) | ||
67 | { | ||
68 | char* p=q+size-1; | ||
69 | size_t n=size; | ||
70 | while (n--) *p--=(char)ezgetc(S); | ||
71 | q+=size; | ||
72 | } | ||
73 | } | ||
74 | else | ||
75 | ezread(S,b,m*size); | ||
76 | } | ||
77 | |||
78 | static int LoadInt (LoadState* S) | ||
79 | { | ||
80 | int x; | ||
81 | LoadBlock(S,&x,sizeof(x)); | ||
82 | if (x<0) luaG_runerror(S->L,"bad integer in %s",S->name); | ||
83 | return x; | 57 | return x; |
84 | } | 58 | } |
85 | 59 | ||
86 | static size_t LoadSize (LoadState* S) | 60 | static int LoadInt(LoadState* S) |
87 | { | 61 | { |
88 | size_t x; | 62 | int x; |
89 | LoadBlock(S,&x,sizeof(x)); | 63 | LoadVar(S,x); |
64 | IF (x<0, "bad integer"); | ||
90 | return x; | 65 | return x; |
91 | } | 66 | } |
92 | 67 | ||
93 | static lua_Number LoadNumber (LoadState* S) | 68 | static lua_Number LoadNumber(LoadState* S) |
94 | { | 69 | { |
95 | lua_Number x; | 70 | lua_Number x; |
96 | LoadBlock(S,&x,sizeof(x)); | 71 | LoadVar(S,x); |
97 | return x; | 72 | return x; |
98 | } | 73 | } |
99 | 74 | ||
100 | static TString* LoadString (LoadState* S) | 75 | static TString* LoadString(LoadState* S) |
101 | { | 76 | { |
102 | size_t size=LoadSize(S); | 77 | size_t size; |
78 | LoadVar(S,size); | ||
103 | if (size==0) | 79 | if (size==0) |
104 | return NULL; | 80 | return NULL; |
105 | else | 81 | else |
106 | { | 82 | { |
107 | char* s=luaZ_openspace(S->L,S->b,size); | 83 | char* s=luaZ_openspace(S->L,S->b,size); |
108 | ezread(S,s,size); | 84 | LoadBlock(S,s,size); |
109 | return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ | 85 | return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ |
110 | } | 86 | } |
111 | } | 87 | } |
112 | 88 | ||
113 | static void LoadCode (LoadState* S, Proto* f) | 89 | static void LoadCode(LoadState* S, Proto* f) |
114 | { | 90 | { |
115 | int size=LoadInt(S); | 91 | int n=LoadInt(S); |
116 | f->code=luaM_newvector(S->L,size,Instruction); | 92 | f->code=luaM_newvector(S->L,n,Instruction); |
117 | f->sizecode=size; | 93 | f->sizecode=n; |
118 | LoadVector(S,f->code,size,sizeof(*f->code)); | 94 | LoadVector(S,f->code,n,sizeof(Instruction)); |
119 | } | 95 | } |
120 | 96 | ||
121 | static void LoadLocals (LoadState* S, Proto* f) | 97 | static Proto* LoadFunction(LoadState* S, TString* p); |
122 | { | ||
123 | int i,n; | ||
124 | n=LoadInt(S); | ||
125 | f->locvars=luaM_newvector(S->L,n,LocVar); | ||
126 | f->sizelocvars=n; | ||
127 | for (i=0; i<n; i++) f->locvars[i].varname=NULL; | ||
128 | for (i=0; i<n; i++) | ||
129 | { | ||
130 | f->locvars[i].varname=LoadString(S); | ||
131 | f->locvars[i].startpc=LoadInt(S); | ||
132 | f->locvars[i].endpc=LoadInt(S); | ||
133 | } | ||
134 | } | ||
135 | |||
136 | static void LoadLines (LoadState* S, Proto* f) | ||
137 | { | ||
138 | int size=LoadInt(S); | ||
139 | f->lineinfo=luaM_newvector(S->L,size,int); | ||
140 | f->sizelineinfo=size; | ||
141 | LoadVector(S,f->lineinfo,size,sizeof(*f->lineinfo)); | ||
142 | } | ||
143 | 98 | ||
144 | static void LoadUpvalues (LoadState* S, Proto* f) | 99 | static void LoadConstants(LoadState* S, Proto* f) |
145 | { | 100 | { |
146 | int i,n; | 101 | int i,n; |
147 | n=LoadInt(S); | 102 | n=LoadInt(S); |
148 | if (n!=0 && n!=f->nups) | 103 | f->k=luaM_newvector(S->L,n,TValue); |
149 | luaG_runerror(S->L,"bad nupvalues in %s: read %d; expected %d", | ||
150 | S->name,n,f->nups); | ||
151 | f->upvalues=luaM_newvector(S->L,n,TString*); | ||
152 | f->sizeupvalues=n; | ||
153 | for (i=0; i<n; i++) f->upvalues[i]=NULL; | ||
154 | for (i=0; i<n; i++) f->upvalues[i]=LoadString(S); | ||
155 | } | ||
156 | |||
157 | static Proto* LoadFunction (LoadState* S, TString* p); | ||
158 | |||
159 | static void LoadConstants (LoadState* S, Proto* f) | ||
160 | { | ||
161 | int i,n; | ||
162 | lua_State *L=S->L; | ||
163 | n=LoadInt(S); | ||
164 | f->k=luaM_newvector(L,n,TValue); | ||
165 | f->sizek=n; | 104 | f->sizek=n; |
166 | for (i=0; i<n; i++) setnilvalue(&f->k[i]); | 105 | for (i=0; i<n; i++) setnilvalue(&f->k[i]); |
167 | for (i=0; i<n; i++) | 106 | for (i=0; i<n; i++) |
168 | { | 107 | { |
169 | TValue* o=&f->k[i]; | 108 | TValue* o=&f->k[i]; |
170 | int t=LoadByte(S); | 109 | int t=LoadChar(S); |
171 | switch (t) | 110 | switch (t) |
172 | { | 111 | { |
173 | case LUA_TNUMBER: | ||
174 | setnvalue(o,LoadNumber(S)); | ||
175 | break; | ||
176 | case LUA_TSTRING: | ||
177 | setsvalue2n(L, o,LoadString(S)); | ||
178 | break; | ||
179 | case LUA_TNIL: | 112 | case LUA_TNIL: |
180 | setnilvalue(o); | 113 | setnilvalue(o); |
181 | break; | 114 | break; |
182 | case LUA_TBOOLEAN: | 115 | case LUA_TBOOLEAN: |
183 | setbvalue(o, LoadByte(S)); | 116 | setbvalue(o,LoadChar(S)); |
117 | break; | ||
118 | case LUA_TNUMBER: | ||
119 | setnvalue(o,LoadNumber(S)); | ||
120 | break; | ||
121 | case LUA_TSTRING: | ||
122 | setsvalue2n(S->L,o,LoadString(S)); | ||
184 | break; | 123 | break; |
185 | default: | 124 | default: |
186 | luaG_runerror(L,"bad constant type (%d) in %s",t,S->name); | 125 | IF (1, "bad constant"); |
187 | break; | 126 | break; |
188 | } | 127 | } |
189 | } | 128 | } |
190 | n=LoadInt(S); | 129 | n=LoadInt(S); |
191 | f->p=luaM_newvector(L,n,Proto*); | 130 | f->p=luaM_newvector(S->L,n,Proto*); |
192 | f->sizep=n; | 131 | f->sizep=n; |
193 | for (i=0; i<n; i++) f->p[i]=NULL; | 132 | for (i=0; i<n; i++) f->p[i]=NULL; |
194 | for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source); | 133 | for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source); |
195 | } | 134 | } |
196 | 135 | ||
197 | static Proto* LoadFunction (LoadState* S, TString* p) | 136 | static void LoadDebug(LoadState* S, Proto* f) |
137 | { | ||
138 | int i,n; | ||
139 | n=LoadInt(S); | ||
140 | f->lineinfo=luaM_newvector(S->L,n,int); | ||
141 | f->sizelineinfo=n; | ||
142 | LoadVector(S,f->lineinfo,n,sizeof(int)); | ||
143 | n=LoadInt(S); | ||
144 | f->locvars=luaM_newvector(S->L,n,LocVar); | ||
145 | f->sizelocvars=n; | ||
146 | for (i=0; i<n; i++) f->locvars[i].varname=NULL; | ||
147 | for (i=0; i<n; i++) | ||
148 | { | ||
149 | f->locvars[i].varname=LoadString(S); | ||
150 | f->locvars[i].startpc=LoadInt(S); | ||
151 | f->locvars[i].endpc=LoadInt(S); | ||
152 | } | ||
153 | n=LoadInt(S); | ||
154 | f->upvalues=luaM_newvector(S->L,n,TString*); | ||
155 | f->sizeupvalues=n; | ||
156 | for (i=0; i<n; i++) f->upvalues[i]=NULL; | ||
157 | for (i=0; i<n; i++) f->upvalues[i]=LoadString(S); | ||
158 | } | ||
159 | |||
160 | static Proto* LoadFunction(LoadState* S, TString* p) | ||
198 | { | 161 | { |
199 | lua_State *L=S->L; | 162 | Proto* f=luaF_newproto(S->L); |
200 | Proto* f=luaF_newproto(L); | 163 | setptvalue2s(S->L,S->L->top,f); incr_top(S->L); |
201 | setptvalue2s(L, L->top, f); | ||
202 | incr_top(L); | ||
203 | f->source=LoadString(S); if (f->source==NULL) f->source=p; | 164 | f->source=LoadString(S); if (f->source==NULL) f->source=p; |
204 | f->linedefined=LoadInt(S); | 165 | f->linedefined=LoadInt(S); |
205 | f->lastlinedefined=LoadInt(S); | 166 | f->lastlinedefined=LoadInt(S); |
@@ -207,90 +168,56 @@ static Proto* LoadFunction (LoadState* S, TString* p) | |||
207 | f->numparams=LoadByte(S); | 168 | f->numparams=LoadByte(S); |
208 | f->is_vararg=LoadByte(S); | 169 | f->is_vararg=LoadByte(S); |
209 | f->maxstacksize=LoadByte(S); | 170 | f->maxstacksize=LoadByte(S); |
210 | LoadLines(S,f); | ||
211 | LoadLocals(S,f); | ||
212 | LoadUpvalues(S,f); | ||
213 | LoadConstants(S,f); | ||
214 | LoadCode(S,f); | 171 | LoadCode(S,f); |
215 | #ifndef TRUST_BINARIES | 172 | LoadConstants(S,f); |
216 | if (!luaG_checkcode(f)) luaG_runerror(L,"bad code in %s",S->name); | 173 | LoadDebug(S,f); |
217 | #endif | 174 | IF (!luaG_checkcode(f), "bad code"); |
218 | L->top--; | 175 | S->L->top--; |
219 | return f; | 176 | return f; |
220 | } | 177 | } |
221 | 178 | ||
222 | static void LoadSignature (LoadState* S) | 179 | static void LoadHeader(LoadState* S) |
223 | { | ||
224 | const char* s=LUA_SIGNATURE; | ||
225 | while (*s!=0 && ezgetc(S)==*s) | ||
226 | ++s; | ||
227 | if (*s!=0) luaG_runerror(S->L,"bad signature in %s",S->name); | ||
228 | } | ||
229 | |||
230 | static void TestSize (LoadState* S, int s, const char* what) | ||
231 | { | ||
232 | int r=LoadByte(S); | ||
233 | if (r!=s) | ||
234 | luaG_runerror(S->L,"virtual machine mismatch in %s: " | ||
235 | "size of %s is %d but read %d",S->name,what,s,r); | ||
236 | } | ||
237 | |||
238 | #define TESTSIZE(s,w) TestSize(S,s,w) | ||
239 | #define V(v) v/16,v%16 | ||
240 | |||
241 | static void LoadHeader (LoadState* S) | ||
242 | { | ||
243 | int version; | ||
244 | lua_Number x,tx=TEST_NUMBER; | ||
245 | LoadSignature(S); | ||
246 | version=LoadByte(S); | ||
247 | if (version>VERSION) | ||
248 | luaG_runerror(S->L,"%s too new: " | ||
249 | "read version %d.%d; expected at most %d.%d", | ||
250 | S->name,V(version),V(VERSION)); | ||
251 | if (version<VERSION0) /* check last major change */ | ||
252 | luaG_runerror(S->L,"%s too old: " | ||
253 | "read version %d.%d; expected at least %d.%d", | ||
254 | S->name,V(version),V(VERSION0)); | ||
255 | S->swap=(luaU_endianness()!=LoadByte(S)); /* need to swap bytes? */ | ||
256 | TESTSIZE(sizeof(int),"int"); | ||
257 | TESTSIZE(sizeof(size_t), "size_t"); | ||
258 | TESTSIZE(sizeof(Instruction), "Instruction"); | ||
259 | TESTSIZE(sizeof(lua_Number), "number"); | ||
260 | x=LoadNumber(S); | ||
261 | if ((long)x!=(long)tx) /* disregard errors in last bits of fraction */ | ||
262 | luaG_runerror(S->L,"unknown number format in %s",S->name); | ||
263 | } | ||
264 | |||
265 | static Proto* LoadChunk (LoadState* S) | ||
266 | { | 180 | { |
267 | LoadHeader(S); | 181 | char h[LUAC_HEADERSIZE]; |
268 | return LoadFunction(S,NULL); | 182 | char s[LUAC_HEADERSIZE]; |
183 | luaU_header(h); | ||
184 | LoadBlock(S,s,LUAC_HEADERSIZE); | ||
185 | IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); | ||
269 | } | 186 | } |
270 | 187 | ||
271 | /* | 188 | /* |
272 | ** load precompiled chunk | 189 | ** load precompiled chunk |
273 | */ | 190 | */ |
274 | Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char *s) | 191 | Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) |
275 | { | 192 | { |
276 | LoadState S; | 193 | LoadState S; |
277 | if (*s=='@' || *s=='=') | 194 | if (*name=='@' || *name=='=') |
278 | S.name=s+1; | 195 | S.name=name+1; |
279 | else if (*s==LUA_SIGNATURE[0]) | 196 | else if (*name==LUA_SIGNATURE[0]) |
280 | S.name="binary string"; | 197 | S.name="binary string"; |
281 | else | 198 | else |
282 | S.name=s; | 199 | S.name=name; |
283 | S.L=L; | 200 | S.L=L; |
284 | S.Z=Z; | 201 | S.Z=Z; |
285 | S.b=buff; | 202 | S.b=buff; |
286 | return LoadChunk(&S); | 203 | LoadHeader(&S); |
204 | return LoadFunction(&S,NULL); | ||
287 | } | 205 | } |
288 | 206 | ||
289 | /* | 207 | /* |
290 | ** find byte order | 208 | * make header |
291 | */ | 209 | */ |
292 | int luaU_endianness (void) | 210 | void luaU_header (char* h) |
293 | { | 211 | { |
294 | int x=1; | 212 | int x=1; |
295 | return *(char*)&x; | 213 | memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1); |
214 | h+=sizeof(LUA_SIGNATURE)-1; | ||
215 | *h++=(char)LUAC_VERSION; | ||
216 | *h++=(char)LUAC_FORMAT; | ||
217 | *h++=(char)*(char*)&x; /* endianness */ | ||
218 | *h++=(char)sizeof(int); | ||
219 | *h++=(char)sizeof(size_t); | ||
220 | *h++=(char)sizeof(Instruction); | ||
221 | *h++=(char)sizeof(lua_Number); | ||
222 | *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ | ||
296 | } | 223 | } |