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