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