diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1998-03-26 11:50:19 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1998-03-26 11:50:19 -0300 |
commit | 439236773b9d36208375bb8eed251bcd393f7b24 (patch) | |
tree | 6946da44c969c715c09b9d3170e99dfd898d7c54 | |
parent | 2a2b64d6ac2ea7839dac41cc84be1c7a5a18bee7 (diff) | |
download | lua-439236773b9d36208375bb8eed251bcd393f7b24.tar.gz lua-439236773b9d36208375bb8eed251bcd393f7b24.tar.bz2 lua-439236773b9d36208375bb8eed251bcd393f7b24.zip |
changes by lhf
-rw-r--r-- | lundump.c | 251 | ||||
-rw-r--r-- | lundump.h | 42 |
2 files changed, 143 insertions, 150 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lundump.c,v 1.4 1998/01/13 20:05:24 lhf Exp $ | 2 | ** $Id: lundump.c,v 1.7 1998/03/05 15:45:08 lhf Exp lhf $ |
3 | ** load bytecodes from files | 3 | ** load bytecodes from files |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -11,15 +11,31 @@ | |||
11 | #include "lstring.h" | 11 | #include "lstring.h" |
12 | #include "lundump.h" | 12 | #include "lundump.h" |
13 | 13 | ||
14 | typedef struct { | 14 | #define LoadBlock(b,size,Z) ezread(Z,b,size) |
15 | ZIO* Z; | 15 | #define LoadNative(t,D) LoadBlock(&t,sizeof(t),D) |
16 | int SwapNumber; | 16 | |
17 | int LoadFloat; | 17 | /* LUA_NUMBER */ |
18 | } Sundump; | 18 | /* if you change the definition of real, make sure you set ID_NUMBER |
19 | * accordingly lundump.h, specially if sizeof(long)!=4. | ||
20 | * for types other than the ones listed below, you'll have to write your own | ||
21 | * dump and undump routines. | ||
22 | */ | ||
23 | |||
24 | #if ID_NUMBER==ID_REAL4 | ||
25 | #define LoadNumber LoadFloat | ||
26 | #elif ID_NUMBER==ID_REAL8 | ||
27 | #define LoadNumber LoadDouble | ||
28 | #elif ID_NUMBER==ID_INT4 | ||
29 | #define LoadNumber LoadLong | ||
30 | #elif ID_NUMBER==ID_NATIVE | ||
31 | #define LoadNumber LoadNative | ||
32 | #else | ||
33 | #define LoadNumber LoadWhat | ||
34 | #endif | ||
19 | 35 | ||
20 | static void unexpectedEOZ(ZIO* Z) | 36 | static void unexpectedEOZ(ZIO* Z) |
21 | { | 37 | { |
22 | luaL_verror("unexpected end of binary file %s",Z->name); | 38 | luaL_verror("unexpected end of file in %s",zname(Z)); |
23 | } | 39 | } |
24 | 40 | ||
25 | static int ezgetc(ZIO* Z) | 41 | static int ezgetc(ZIO* Z) |
@@ -29,91 +45,77 @@ static int ezgetc(ZIO* Z) | |||
29 | return c; | 45 | return c; |
30 | } | 46 | } |
31 | 47 | ||
32 | static int ezread(ZIO* Z, void* b, int n) | 48 | static void ezread(ZIO* Z, void* b, int n) |
33 | { | 49 | { |
34 | int r=zread(Z,b,n); | 50 | int r=zread(Z,b,n); |
35 | if (r!=0) unexpectedEOZ(Z); | 51 | if (r!=0) unexpectedEOZ(Z); |
36 | return r; | ||
37 | } | 52 | } |
38 | 53 | ||
39 | static int LoadWord(ZIO* Z) | 54 | static unsigned int LoadWord(ZIO* Z) |
40 | { | 55 | { |
41 | int hi=ezgetc(Z); | 56 | unsigned int hi=ezgetc(Z); |
42 | int lo=ezgetc(Z); | 57 | unsigned int lo=ezgetc(Z); |
43 | return (hi<<8)|lo; | 58 | return (hi<<8)|lo; |
44 | } | 59 | } |
45 | 60 | ||
46 | static void* LoadBlock(int size, ZIO* Z) | 61 | static unsigned long LoadLong(ZIO* Z) |
47 | { | 62 | { |
48 | void* b=luaM_malloc(size); | 63 | unsigned long hi=LoadWord(Z); |
49 | ezread(Z,b,size); | 64 | unsigned long lo=LoadWord(Z); |
50 | return b; | 65 | return (hi<<16)|lo; |
51 | } | 66 | } |
52 | 67 | ||
53 | static int LoadSize(ZIO* Z) | 68 | /* LUA_NUMBER */ |
69 | /* assumes sizeof(long)==4 and sizeof(float)==4 (IEEE) */ | ||
70 | static float LoadFloat(ZIO* Z) | ||
54 | { | 71 | { |
55 | int hi=LoadWord(Z); | 72 | long l=LoadLong(Z); |
56 | int lo=LoadWord(Z); | 73 | float f=*(float*)&l; |
57 | int s=(hi<<16)|lo; | 74 | return f; |
58 | if (hi!=0 && s==lo) | ||
59 | luaL_verror("code too long (%ld bytes)",(hi<<16)|(long)lo); | ||
60 | return s; | ||
61 | } | 75 | } |
62 | 76 | ||
63 | static char* LoadString(ZIO* Z) | 77 | /* LUA_NUMBER */ |
78 | /* assumes sizeof(long)==4 and sizeof(double)==8 (IEEE) */ | ||
79 | static double LoadDouble(ZIO* Z) | ||
64 | { | 80 | { |
65 | int size=LoadWord(Z); | 81 | long l[2]; |
66 | if (size==0) | 82 | double f; |
67 | return NULL; | 83 | int x=1; |
68 | else | 84 | if (*(char*)&x==1) /* little-endian */ |
69 | { | 85 | { |
70 | char* b=luaL_openspace(size); | 86 | l[1]=LoadLong(Z); |
71 | ezread(Z,b,size); | 87 | l[0]=LoadLong(Z); |
72 | return b; | ||
73 | } | 88 | } |
89 | else /* big-endian */ | ||
90 | { | ||
91 | l[0]=LoadLong(Z); | ||
92 | l[1]=LoadLong(Z); | ||
93 | } | ||
94 | f=*(double*)l; | ||
95 | return f; | ||
74 | } | 96 | } |
75 | 97 | ||
76 | static TaggedString* LoadTString(ZIO* Z) | 98 | static Byte* LoadCode(ZIO* Z) |
77 | { | ||
78 | char* s=LoadString(Z); | ||
79 | return (s==NULL) ? NULL : luaS_new(s); | ||
80 | } | ||
81 | |||
82 | static void SwapFloat(float* f) | ||
83 | { | ||
84 | Byte* p=(Byte*)f; | ||
85 | Byte* q=p+sizeof(float)-1; | ||
86 | Byte t; | ||
87 | t=*p; *p++=*q; *q--=t; | ||
88 | t=*p; *p++=*q; *q--=t; | ||
89 | } | ||
90 | |||
91 | static void SwapDouble(double* f) | ||
92 | { | 99 | { |
93 | Byte* p=(Byte*)f; | 100 | long size=LoadLong(Z); |
94 | Byte* q=p+sizeof(double)-1; | 101 | unsigned int s=size; |
95 | Byte t; | 102 | void* b; |
96 | t=*p; *p++=*q; *q--=t; | 103 | if (s!=size) luaL_verror("code too long (%ld bytes) in %s",size,zname(Z)); |
97 | t=*p; *p++=*q; *q--=t; | 104 | b=luaM_malloc(size); |
98 | t=*p; *p++=*q; *q--=t; | 105 | LoadBlock(b,size,Z); |
99 | t=*p; *p++=*q; *q--=t; | 106 | return b; |
100 | } | 107 | } |
101 | 108 | ||
102 | static real LoadNumber(Sundump* S) | 109 | static TaggedString* LoadTString(ZIO* Z) |
103 | { | 110 | { |
104 | if (S->LoadFloat) | 111 | int size=LoadWord(Z); |
105 | { | 112 | if (size==0) |
106 | float f; | 113 | return NULL; |
107 | ezread(S->Z,&f,sizeof(f)); | ||
108 | if (S->SwapNumber) SwapFloat(&f); | ||
109 | return f; | ||
110 | } | ||
111 | else | 114 | else |
112 | { | 115 | { |
113 | double f; | 116 | char* s=luaL_openspace(size); |
114 | ezread(S->Z,&f,sizeof(f)); | 117 | LoadBlock(s,size,Z); |
115 | if (S->SwapNumber) SwapDouble(&f); | 118 | return luaS_newlstr(s,size-1); |
116 | return f; | ||
117 | } | 119 | } |
118 | } | 120 | } |
119 | 121 | ||
@@ -131,63 +133,51 @@ static void LoadLocals(TProtoFunc* tf, ZIO* Z) | |||
131 | tf->locvars[i].varname=NULL; | 133 | tf->locvars[i].varname=NULL; |
132 | } | 134 | } |
133 | 135 | ||
134 | static void LoadConstants(TProtoFunc* tf, Sundump* S) | 136 | static TProtoFunc* LoadFunction(ZIO* Z); |
137 | |||
138 | static void LoadConstants(TProtoFunc* tf, ZIO* Z) | ||
135 | { | 139 | { |
136 | int i,n=LoadWord(S->Z); | 140 | int i,n=LoadWord(Z); |
137 | tf->nconsts=n; | 141 | tf->nconsts=n; |
138 | if (n==0) return; | 142 | if (n==0) return; |
139 | tf->consts=luaM_newvector(n,TObject); | 143 | tf->consts=luaM_newvector(n,TObject); |
140 | for (i=0; i<n; i++) | 144 | for (i=0; i<n; i++) |
141 | { | 145 | { |
142 | TObject* o=tf->consts+i; | 146 | TObject* o=tf->consts+i; |
143 | int c=ezgetc(S->Z); | 147 | int c=ezgetc(Z); |
144 | switch (c) | 148 | switch (c) |
145 | { | 149 | { |
146 | case ID_NUM: | 150 | case ID_NUM: |
147 | ttype(o)=LUA_T_NUMBER; | 151 | ttype(o)=LUA_T_NUMBER; |
148 | nvalue(o)=LoadNumber(S); | 152 | #if ID_NUMBER==ID_NATIVE |
153 | LoadNative(nvalue(o),Z) | ||
154 | #else | ||
155 | nvalue(o)=LoadNumber(Z); | ||
156 | #endif | ||
149 | break; | 157 | break; |
150 | case ID_STR: | 158 | case ID_STR: |
151 | ttype(o)=LUA_T_STRING; | 159 | ttype(o)=LUA_T_STRING; |
152 | tsvalue(o)=LoadTString(S->Z); | 160 | tsvalue(o)=LoadTString(Z); |
153 | break; | 161 | break; |
154 | case ID_FUN: | 162 | case ID_FUN: |
155 | ttype(o)=LUA_T_PROTO; | 163 | ttype(o)=LUA_T_PROTO; |
156 | tfvalue(o)=NULL; | 164 | tfvalue(o)=LoadFunction(Z); |
157 | break; | 165 | break; |
158 | #ifdef DEBUG | 166 | default: |
159 | default: /* cannot happen */ | 167 | luaL_verror("bad constant #%d in %s: type=%d ('%c')",i,zname(Z),c,c); |
160 | luaL_verror("internal error in LoadConstants: " | ||
161 | "bad constant #%d type=%d ('%c')\n",i,c,c); | ||
162 | break; | 168 | break; |
163 | #endif | ||
164 | } | 169 | } |
165 | } | 170 | } |
166 | } | 171 | } |
167 | 172 | ||
168 | static TProtoFunc* LoadFunction(Sundump* S); | 173 | static TProtoFunc* LoadFunction(ZIO* Z) |
169 | |||
170 | static void LoadFunctions(TProtoFunc* tf, Sundump* S) | ||
171 | { | ||
172 | while (zgetc(S->Z)==ID_FUNCTION) | ||
173 | { | ||
174 | int i=LoadWord(S->Z); | ||
175 | TProtoFunc* t=LoadFunction(S); | ||
176 | TObject* o=tf->consts+i; | ||
177 | tfvalue(o)=t; | ||
178 | } | ||
179 | } | ||
180 | |||
181 | static TProtoFunc* LoadFunction(Sundump* S) | ||
182 | { | 174 | { |
183 | ZIO* Z=S->Z; | ||
184 | TProtoFunc* tf=luaF_newproto(); | 175 | TProtoFunc* tf=luaF_newproto(); |
185 | tf->lineDefined=LoadWord(Z); | 176 | tf->lineDefined=LoadWord(Z); |
186 | tf->fileName=LoadTString(Z); | 177 | tf->fileName=LoadTString(Z); |
187 | tf->code=LoadBlock(LoadSize(Z),Z); | 178 | tf->code=LoadCode(Z); |
188 | LoadConstants(tf,S); | ||
189 | LoadLocals(tf,Z); | 179 | LoadLocals(tf,Z); |
190 | LoadFunctions(tf,S); | 180 | LoadConstants(tf,Z); |
191 | return tf; | 181 | return tf; |
192 | } | 182 | } |
193 | 183 | ||
@@ -196,61 +186,42 @@ static void LoadSignature(ZIO* Z) | |||
196 | char* s=SIGNATURE; | 186 | char* s=SIGNATURE; |
197 | while (*s!=0 && ezgetc(Z)==*s) | 187 | while (*s!=0 && ezgetc(Z)==*s) |
198 | ++s; | 188 | ++s; |
199 | if (*s!=0) luaL_verror("bad signature in binary file %s",Z->name); | 189 | if (*s!=0) luaL_verror("bad signature in %s",zname(Z)); |
200 | } | 190 | } |
201 | 191 | ||
202 | static void LoadHeader(Sundump* S) | 192 | static void LoadHeader(ZIO* Z) |
203 | { | 193 | { |
204 | ZIO* Z=S->Z; | 194 | int version,id,sizeofR; |
205 | int version,sizeofR; | 195 | real f=-TEST_NUMBER,tf=TEST_NUMBER; |
206 | LoadSignature(Z); | 196 | LoadSignature(Z); |
207 | version=ezgetc(Z); | 197 | version=ezgetc(Z); |
208 | if (version>VERSION) | 198 | if (version>VERSION) |
209 | luaL_verror( | 199 | luaL_verror( |
210 | "binary file %s too new: version=0x%02x; expected at most 0x%02x", | 200 | "%s too new: version=0x%02x; expected at most 0x%02x", |
211 | Z->name,version,VERSION); | 201 | zname(Z),version,VERSION); |
212 | if (version<0x31) /* major change in 3.1 */ | 202 | if (version<0x31) /* major change in 3.1 */ |
213 | luaL_verror( | 203 | luaL_verror( |
214 | "binary file %s too old: version=0x%02x; expected at least 0x%02x", | 204 | "%s too old: version=0x%02x; expected at least 0x%02x", |
215 | Z->name,version,0x31); | 205 | zname(Z),version,0x31); |
216 | sizeofR=ezgetc(Z); /* test float representation */ | 206 | id=ezgetc(Z); /* test number representation */ |
217 | if (sizeofR==sizeof(float)) | 207 | sizeofR=ezgetc(Z); |
208 | if (id!=ID_NUMBER || sizeofR!=sizeof(real)) | ||
218 | { | 209 | { |
219 | float f,tf=TEST_FLOAT; | 210 | luaL_verror("unknown number representation in %s: " |
220 | ezread(Z,&f,sizeof(f)); | 211 | "read 0x%02x %d; expected 0x%02x %d", |
221 | if (f!=tf) | 212 | zname(Z),id,sizeofR,ID_NUMBER,sizeof(real)); |
222 | { | ||
223 | SwapFloat(&f); | ||
224 | if (f!=tf) | ||
225 | luaL_verror("unknown float representation in binary file %s",Z->name); | ||
226 | S->SwapNumber=1; | ||
227 | } | ||
228 | S->LoadFloat=1; | ||
229 | } | 213 | } |
230 | else if (sizeofR==sizeof(double)) | 214 | f=LoadNumber(Z); |
231 | { | 215 | if (f!=tf) |
232 | double f,tf=TEST_FLOAT; | 216 | luaL_verror("unknown number representation in %s: " |
233 | ezread(Z,&f,sizeof(f)); | 217 | "read %g; expected %g", /* LUA_NUMBER */ |
234 | if (f!=tf) | 218 | zname(Z),(double)f,(double)tf); |
235 | { | ||
236 | SwapDouble(&f); | ||
237 | if (f!=tf) | ||
238 | luaL_verror("unknown float representation in binary file %s",Z->name); | ||
239 | S->SwapNumber=1; | ||
240 | } | ||
241 | S->LoadFloat=0; | ||
242 | } | ||
243 | else | ||
244 | luaL_verror( | ||
245 | "floats in binary file %s have %d bytes; " | ||
246 | "expected %d (float) or %d (double)", | ||
247 | Z->name,sizeofR,sizeof(float),sizeof(double)); | ||
248 | } | 219 | } |
249 | 220 | ||
250 | static TProtoFunc* LoadChunk(Sundump* S) | 221 | static TProtoFunc* LoadChunk(ZIO* Z) |
251 | { | 222 | { |
252 | LoadHeader(S); | 223 | LoadHeader(Z); |
253 | return LoadFunction(S); | 224 | return LoadFunction(Z); |
254 | } | 225 | } |
255 | 226 | ||
256 | /* | 227 | /* |
@@ -260,13 +231,9 @@ static TProtoFunc* LoadChunk(Sundump* S) | |||
260 | TProtoFunc* luaU_undump1(ZIO* Z) | 231 | TProtoFunc* luaU_undump1(ZIO* Z) |
261 | { | 232 | { |
262 | int c=zgetc(Z); | 233 | int c=zgetc(Z); |
263 | Sundump S; | ||
264 | S.Z=Z; | ||
265 | S.SwapNumber=0; | ||
266 | S.LoadFloat=1; | ||
267 | if (c==ID_CHUNK) | 234 | if (c==ID_CHUNK) |
268 | return LoadChunk(&S); | 235 | return LoadChunk(Z); |
269 | else if (c!=EOZ) | 236 | else if (c!=EOZ) |
270 | luaL_verror("%s is not a lua binary file",Z->name); | 237 | luaL_verror("%s is not a Lua binary file",zname(Z)); |
271 | return NULL; | 238 | return NULL; |
272 | } | 239 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lundump.h,v 1.4 1998/01/13 20:05:24 lhf Exp $ | 2 | ** $Id: lundump.h,v 1.5 1998/02/06 20:05:39 lhf Exp lhf $ |
3 | ** load pre-compiled Lua chunks | 3 | ** load pre-compiled Lua chunks |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -10,18 +10,44 @@ | |||
10 | #include "lobject.h" | 10 | #include "lobject.h" |
11 | #include "lzio.h" | 11 | #include "lzio.h" |
12 | 12 | ||
13 | TProtoFunc* luaU_undump1(ZIO* Z); /* load one chunk */ | ||
14 | |||
15 | #define SIGNATURE "Lua" | ||
16 | #define VERSION 0x31 /* last format change was in 3.1 */ | ||
17 | |||
18 | #define IsMain(f) (f->lineDefined==0) | ||
19 | |||
13 | #define ID_CHUNK 27 /* ESC */ | 20 | #define ID_CHUNK 27 /* ESC */ |
14 | #define ID_FUNCTION '#' | ||
15 | #define ID_END '$' | ||
16 | #define ID_NUM 'N' | 21 | #define ID_NUM 'N' |
17 | #define ID_STR 'S' | 22 | #define ID_STR 'S' |
18 | #define ID_FUN 'F' | 23 | #define ID_FUN 'F' |
19 | #define SIGNATURE "Lua" | ||
20 | #define VERSION 0x31 /* last format change was in 3.1 */ | ||
21 | #define TEST_FLOAT 0.123456789e-23 /* a float for testing representation */ | ||
22 | 24 | ||
23 | #define IsMain(f) (f->lineDefined==0) | 25 | #define ID_INT4 'l' |
26 | #define ID_REAL4 'f' | ||
27 | #define ID_REAL8 'd' | ||
28 | #define ID_NATIVE '?' | ||
24 | 29 | ||
25 | TProtoFunc* luaU_undump1(ZIO* Z); /* load one chunk */ | 30 | /* |
31 | * use a multiple of PI for testing number representation. | ||
32 | * multiplying by 10E8 gives notrivial integer values. | ||
33 | */ | ||
34 | #define TEST_NUMBER 3.14159265358979323846E8 | ||
35 | |||
36 | /* LUA_NUMBER */ | ||
37 | /* if you change the definition of real, make sure you set ID_NUMBER | ||
38 | * accordingly, specially if sizeof(long)!=4. | ||
39 | * for types other than the ones listed below, you'll have to write your own | ||
40 | * dump and undump routines. | ||
41 | */ | ||
42 | |||
43 | #if real==float | ||
44 | #define ID_NUMBER ID_REAL4 | ||
45 | #elif real==double | ||
46 | #define ID_NUMBER ID_REAL8 | ||
47 | #elif real==long | ||
48 | #define ID_NUMBER ID_INT4 | ||
49 | #else | ||
50 | #define ID_NUMBER ID_NATIVE | ||
51 | #endif | ||
26 | 52 | ||
27 | #endif | 53 | #endif |