Line data Source code
1 : /*
2 : ** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $
3 : ** load precompiled Lua chunks
4 : ** See Copyright Notice in lua.h
5 : */
6 :
7 : #include <string.h>
8 :
9 : #define lundump_c
10 : #define LUA_CORE
11 :
12 : #include "lua.h"
13 :
14 : #include "ldebug.h"
15 : #include "ldo.h"
16 : #include "lfunc.h"
17 : #include "lmem.h"
18 : #include "lobject.h"
19 : #include "lstring.h"
20 : #include "lundump.h"
21 : #include "lzio.h"
22 :
23 : typedef struct {
24 : lua_State* L;
25 : ZIO* Z;
26 : Mbuffer* b;
27 : const char* name;
28 : } LoadState;
29 :
30 : #ifdef LUAC_TRUST_BINARIES
31 : #define IF(c,s)
32 : #define error(S,s)
33 : #else
34 : #define IF(c,s) if (c) error(S,s)
35 :
36 0 : static void error(LoadState* S, const char* why)
37 : {
38 0 : luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why);
39 0 : luaD_throw(S->L,LUA_ERRSYNTAX);
40 0 : }
41 : #endif
42 :
43 : #define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size))
44 : #define LoadByte(S) (lu_byte)LoadChar(S)
45 : #define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
46 : #define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
47 :
48 392 : static void LoadBlock(LoadState* S, void* b, size_t size)
49 : {
50 392 : size_t r=luaZ_read(S->Z,b,size);
51 392 : IF (r!=0, "unexpected end");
52 392 : }
53 :
54 96 : static int LoadChar(LoadState* S)
55 : {
56 : char x;
57 96 : LoadVar(S,x);
58 96 : return x;
59 : }
60 :
61 140 : static int LoadInt(LoadState* S)
62 : {
63 : int x;
64 140 : LoadVar(S,x);
65 140 : IF (x<0, "bad integer");
66 140 : return x;
67 : }
68 :
69 4 : static lua_Number LoadNumber(LoadState* S)
70 : {
71 : lua_Number x;
72 4 : LoadVar(S,x);
73 4 : return x;
74 : }
75 :
76 62 : static TString* LoadString(LoadState* S)
77 : {
78 : size_t size;
79 62 : LoadVar(S,size);
80 62 : if (size==0)
81 8 : return NULL;
82 : else
83 : {
84 54 : char* s=luaZ_openspace(S->L,S->b,size);
85 54 : LoadBlock(S,s,size);
86 54 : return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
87 : }
88 : }
89 :
90 14 : static void LoadCode(LoadState* S, Proto* f)
91 : {
92 14 : int n=LoadInt(S);
93 14 : f->code=luaM_newvector(S->L,n,Instruction);
94 14 : f->sizecode=n;
95 14 : LoadVector(S,f->code,n,sizeof(Instruction));
96 14 : }
97 :
98 : static Proto* LoadFunction(LoadState* S, TString* p);
99 :
100 14 : static void LoadConstants(LoadState* S, Proto* f)
101 : {
102 : int i,n;
103 14 : n=LoadInt(S);
104 14 : f->k=luaM_newvector(S->L,n,TValue);
105 14 : f->sizek=n;
106 52 : for (i=0; i<n; i++) setnilvalue(&f->k[i]);
107 52 : for (i=0; i<n; i++)
108 : {
109 38 : TValue* o=&f->k[i];
110 38 : int t=LoadChar(S);
111 38 : switch (t)
112 : {
113 0 : case LUA_TNIL:
114 0 : setnilvalue(o);
115 0 : break;
116 2 : case LUA_TBOOLEAN:
117 2 : setbvalue(o,LoadChar(S)!=0);
118 2 : break;
119 4 : case LUA_TNUMBER:
120 4 : setnvalue(o,LoadNumber(S));
121 4 : break;
122 32 : case LUA_TSTRING:
123 32 : setsvalue2n(S->L,o,LoadString(S));
124 32 : break;
125 0 : default:
126 0 : error(S,"bad constant");
127 0 : break;
128 : }
129 : }
130 14 : n=LoadInt(S);
131 14 : f->p=luaM_newvector(S->L,n,Proto*);
132 14 : f->sizep=n;
133 20 : for (i=0; i<n; i++) f->p[i]=NULL;
134 20 : for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);
135 14 : }
136 :
137 14 : static void LoadDebug(LoadState* S, Proto* f)
138 : {
139 : int i,n;
140 14 : n=LoadInt(S);
141 14 : f->lineinfo=luaM_newvector(S->L,n,int);
142 14 : f->sizelineinfo=n;
143 14 : LoadVector(S,f->lineinfo,n,sizeof(int));
144 14 : n=LoadInt(S);
145 14 : f->locvars=luaM_newvector(S->L,n,LocVar);
146 14 : f->sizelocvars=n;
147 28 : for (i=0; i<n; i++) f->locvars[i].varname=NULL;
148 28 : for (i=0; i<n; i++)
149 : {
150 14 : f->locvars[i].varname=LoadString(S);
151 14 : f->locvars[i].startpc=LoadInt(S);
152 14 : f->locvars[i].endpc=LoadInt(S);
153 : }
154 14 : n=LoadInt(S);
155 14 : f->upvalues=luaM_newvector(S->L,n,TString*);
156 14 : f->sizeupvalues=n;
157 16 : for (i=0; i<n; i++) f->upvalues[i]=NULL;
158 16 : for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);
159 14 : }
160 :
161 14 : static Proto* LoadFunction(LoadState* S, TString* p)
162 : {
163 : Proto* f;
164 14 : if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep");
165 14 : f=luaF_newproto(S->L);
166 14 : setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
167 14 : f->source=LoadString(S); if (f->source==NULL) f->source=p;
168 14 : f->linedefined=LoadInt(S);
169 14 : f->lastlinedefined=LoadInt(S);
170 14 : f->nups=LoadByte(S);
171 14 : f->numparams=LoadByte(S);
172 14 : f->is_vararg=LoadByte(S);
173 14 : f->maxstacksize=LoadByte(S);
174 14 : LoadCode(S,f);
175 14 : LoadConstants(S,f);
176 14 : LoadDebug(S,f);
177 14 : IF (!luaG_checkcode(f), "bad code");
178 14 : S->L->top--;
179 14 : S->L->nCcalls--;
180 14 : return f;
181 : }
182 :
183 8 : static void LoadHeader(LoadState* S)
184 : {
185 : char h[LUAC_HEADERSIZE];
186 : char s[LUAC_HEADERSIZE];
187 8 : luaU_header(h);
188 8 : LoadBlock(S,s,LUAC_HEADERSIZE);
189 8 : IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header");
190 8 : }
191 :
192 : /*
193 : ** load precompiled chunk
194 : */
195 8 : Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
196 : {
197 : LoadState S;
198 8 : if (*name=='@' || *name=='=')
199 7 : S.name=name+1;
200 1 : else if (*name==LUA_SIGNATURE[0])
201 1 : S.name="binary string";
202 : else
203 0 : S.name=name;
204 8 : S.L=L;
205 8 : S.Z=Z;
206 8 : S.b=buff;
207 8 : LoadHeader(&S);
208 8 : return LoadFunction(&S,luaS_newliteral(L,"=?"));
209 : }
210 :
211 : /*
212 : * make header
213 : */
214 17 : void luaU_header (char* h)
215 : {
216 17 : int x=1;
217 17 : memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);
218 17 : h+=sizeof(LUA_SIGNATURE)-1;
219 17 : *h++=(char)LUAC_VERSION;
220 17 : *h++=(char)LUAC_FORMAT;
221 17 : *h++=(char)*(char*)&x; /* endianness */
222 17 : *h++=(char)sizeof(int);
223 17 : *h++=(char)sizeof(size_t);
224 17 : *h++=(char)sizeof(Instruction);
225 17 : *h++=(char)sizeof(lua_Number);
226 17 : *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */
227 17 : }
|