summaryrefslogtreecommitdiff
path: root/lundump.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>1998-01-14 13:49:01 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>1998-01-14 13:49:01 -0200
commit981fddea022b6cad7768223353b4e7386080c271 (patch)
treec596f191df4b59c85ea056fca3933ad1f14e984b /lundump.c
parent81b953f27e2c218e9d772cc5f653f541c451d516 (diff)
downloadlua-981fddea022b6cad7768223353b4e7386080c271.tar.gz
lua-981fddea022b6cad7768223353b4e7386080c271.tar.bz2
lua-981fddea022b6cad7768223353b4e7386080c271.zip
module to load bytecodes from files.v3.1-alpha
Diffstat (limited to 'lundump.c')
-rw-r--r--lundump.c272
1 files changed, 272 insertions, 0 deletions
diff --git a/lundump.c b/lundump.c
new file mode 100644
index 00000000..32d7359a
--- /dev/null
+++ b/lundump.c
@@ -0,0 +1,272 @@
1/*
2** $Id: lundump.c,v 1.4 1998/01/13 20:05:24 lhf Exp $
3** load bytecodes from files
4** See Copyright Notice in lua.h
5*/
6
7#include <stdio.h>
8#include "lauxlib.h"
9#include "lfunc.h"
10#include "lmem.h"
11#include "lstring.h"
12#include "lundump.h"
13
14typedef struct {
15 ZIO* Z;
16 int SwapNumber;
17 int LoadFloat;
18} Sundump;
19
20static void unexpectedEOZ(ZIO* Z)
21{
22 luaL_verror("unexpected end of binary file %s",Z->name);
23}
24
25static int ezgetc(ZIO* Z)
26{
27 int c=zgetc(Z);
28 if (c==EOZ) unexpectedEOZ(Z);
29 return c;
30}
31
32static int ezread(ZIO* Z, void* b, int n)
33{
34 int r=zread(Z,b,n);
35 if (r!=0) unexpectedEOZ(Z);
36 return r;
37}
38
39static int LoadWord(ZIO* Z)
40{
41 int hi=ezgetc(Z);
42 int lo=ezgetc(Z);
43 return (hi<<8)|lo;
44}
45
46static void* LoadBlock(int size, ZIO* Z)
47{
48 void* b=luaM_malloc(size);
49 ezread(Z,b,size);
50 return b;
51}
52
53static int LoadSize(ZIO* Z)
54{
55 int hi=LoadWord(Z);
56 int lo=LoadWord(Z);
57 int s=(hi<<16)|lo;
58 if (hi!=0 && s==lo)
59 luaL_verror("code too long (%ld bytes)",(hi<<16)|(long)lo);
60 return s;
61}
62
63static char* LoadString(ZIO* Z)
64{
65 int size=LoadWord(Z);
66 if (size==0)
67 return NULL;
68 else
69 {
70 char* b=luaL_openspace(size);
71 ezread(Z,b,size);
72 return b;
73 }
74}
75
76static TaggedString* LoadTString(ZIO* Z)
77{
78 char* s=LoadString(Z);
79 return (s==NULL) ? NULL : luaS_new(s);
80}
81
82static 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
91static void SwapDouble(double* f)
92{
93 Byte* p=(Byte*)f;
94 Byte* q=p+sizeof(double)-1;
95 Byte t;
96 t=*p; *p++=*q; *q--=t;
97 t=*p; *p++=*q; *q--=t;
98 t=*p; *p++=*q; *q--=t;
99 t=*p; *p++=*q; *q--=t;
100}
101
102static real LoadNumber(Sundump* S)
103{
104 if (S->LoadFloat)
105 {
106 float f;
107 ezread(S->Z,&f,sizeof(f));
108 if (S->SwapNumber) SwapFloat(&f);
109 return f;
110 }
111 else
112 {
113 double f;
114 ezread(S->Z,&f,sizeof(f));
115 if (S->SwapNumber) SwapDouble(&f);
116 return f;
117 }
118}
119
120static void LoadLocals(TProtoFunc* tf, ZIO* Z)
121{
122 int i,n=LoadWord(Z);
123 if (n==0) return;
124 tf->locvars=luaM_newvector(n+1,LocVar);
125 for (i=0; i<n; i++)
126 {
127 tf->locvars[i].line=LoadWord(Z);
128 tf->locvars[i].varname=LoadTString(Z);
129 }
130 tf->locvars[i].line=-1; /* flag end of vector */
131 tf->locvars[i].varname=NULL;
132}
133
134static void LoadConstants(TProtoFunc* tf, Sundump* S)
135{
136 int i,n=LoadWord(S->Z);
137 tf->nconsts=n;
138 if (n==0) return;
139 tf->consts=luaM_newvector(n,TObject);
140 for (i=0; i<n; i++)
141 {
142 TObject* o=tf->consts+i;
143 int c=ezgetc(S->Z);
144 switch (c)
145 {
146 case ID_NUM:
147 ttype(o)=LUA_T_NUMBER;
148 nvalue(o)=LoadNumber(S);
149 break;
150 case ID_STR:
151 ttype(o)=LUA_T_STRING;
152 tsvalue(o)=LoadTString(S->Z);
153 break;
154 case ID_FUN:
155 ttype(o)=LUA_T_PROTO;
156 tfvalue(o)=NULL;
157 break;
158#ifdef DEBUG
159 default: /* cannot happen */
160 luaL_verror("internal error in LoadConstants: "
161 "bad constant #%d type=%d ('%c')\n",i,c,c);
162 break;
163#endif
164 }
165 }
166}
167
168static TProtoFunc* LoadFunction(Sundump* S);
169
170static 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
181static TProtoFunc* LoadFunction(Sundump* S)
182{
183 ZIO* Z=S->Z;
184 TProtoFunc* tf=luaF_newproto();
185 tf->lineDefined=LoadWord(Z);
186 tf->fileName=LoadTString(Z);
187 tf->code=LoadBlock(LoadSize(Z),Z);
188 LoadConstants(tf,S);
189 LoadLocals(tf,Z);
190 LoadFunctions(tf,S);
191 return tf;
192}
193
194static void LoadSignature(ZIO* Z)
195{
196 char* s=SIGNATURE;
197 while (*s!=0 && ezgetc(Z)==*s)
198 ++s;
199 if (*s!=0) luaL_verror("bad signature in binary file %s",Z->name);
200}
201
202static void LoadHeader(Sundump* S)
203{
204 ZIO* Z=S->Z;
205 int version,sizeofR;
206 LoadSignature(Z);
207 version=ezgetc(Z);
208 if (version>VERSION)
209 luaL_verror(
210 "binary file %s too new: version=0x%02x; expected at most 0x%02x",
211 Z->name,version,VERSION);
212 if (version<0x31) /* major change in 3.1 */
213 luaL_verror(
214 "binary file %s too old: version=0x%02x; expected at least 0x%02x",
215 Z->name,version,0x31);
216 sizeofR=ezgetc(Z); /* test float representation */
217 if (sizeofR==sizeof(float))
218 {
219 float f,tf=TEST_FLOAT;
220 ezread(Z,&f,sizeof(f));
221 if (f!=tf)
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 }
230 else if (sizeofR==sizeof(double))
231 {
232 double f,tf=TEST_FLOAT;
233 ezread(Z,&f,sizeof(f));
234 if (f!=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}
249
250static TProtoFunc* LoadChunk(Sundump* S)
251{
252 LoadHeader(S);
253 return LoadFunction(S);
254}
255
256/*
257** load one chunk from a file or buffer
258** return main if ok and NULL at EOF
259*/
260TProtoFunc* luaU_undump1(ZIO* Z)
261{
262 int c=zgetc(Z);
263 Sundump S;
264 S.Z=Z;
265 S.SwapNumber=0;
266 S.LoadFloat=1;
267 if (c==ID_CHUNK)
268 return LoadChunk(&S);
269 else if (c!=EOZ)
270 luaL_verror("%s is not a lua binary file",Z->name);
271 return NULL;
272}