2 ** $Id: lundump.c,v 2.44 2015/11/02 16:09:30 roberto Exp $
3 ** load precompiled Lua chunks
4 ** See Copyright Notice in lua.h
27 #if !defined(luai_verifycode)
28 #define luai_verifycode(L,b,f) /* empty */
39 static l_noret error(LoadState *S, const char *why) {
40 luaO_pushfstring(S->L, "%s: %s precompiled chunk", S->name, why);
41 luaD_throw(S->L, LUA_ERRSYNTAX);
46 ** All high-level loads go through LoadVector; you can change it to
47 ** adapt to the endianness of the input
49 #define LoadVector(S,b,n) LoadBlock(S,b,(n)*sizeof((b)[0]))
51 static void LoadBlock (LoadState *S, void *b, size_t size) {
52 if (luaZ_read(S->Z, b, size) != 0)
53 error(S, "truncated");
57 #define LoadVar(S,x) LoadVector(S,&x,1)
60 static lu_byte LoadByte (LoadState *S) {
67 static int LoadInt (LoadState *S) {
74 static lua_Number LoadNumber (LoadState *S) {
81 static lua_Integer LoadInteger (LoadState *S) {
88 static TString *LoadString (LoadState *S) {
89 size_t size = LoadByte(S);
94 else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */
95 char buff[LUAI_MAXSHORTLEN];
96 LoadVector(S, buff, size);
97 return luaS_newlstr(S->L, buff, size);
99 else { /* long string */
100 TString *ts = luaS_createlngstrobj(S->L, size);
101 LoadVector(S, getstr(ts), size); /* load directly in final place */
107 static void LoadCode (LoadState *S, Proto *f) {
109 f->code = luaM_newvector(S->L, n, Instruction);
111 LoadVector(S, f->code, n);
115 static void LoadFunction(LoadState *S, Proto *f, TString *psource);
118 static void LoadConstants (LoadState *S, Proto *f) {
121 f->k = luaM_newvector(S->L, n, TValue);
123 for (i = 0; i < n; i++)
124 setnilvalue(&f->k[i]);
125 for (i = 0; i < n; i++) {
126 TValue *o = &f->k[i];
133 setbvalue(o, LoadByte(S));
136 setfltvalue(o, LoadNumber(S));
139 setivalue(o, LoadInteger(S));
143 setsvalue2n(S->L, o, LoadString(S));
152 static void LoadProtos (LoadState *S, Proto *f) {
155 f->p = luaM_newvector(S->L, n, Proto *);
157 for (i = 0; i < n; i++)
159 for (i = 0; i < n; i++) {
160 f->p[i] = luaF_newproto(S->L);
161 LoadFunction(S, f->p[i], f->source);
166 static void LoadUpvalues (LoadState *S, Proto *f) {
169 f->upvalues = luaM_newvector(S->L, n, Upvaldesc);
171 for (i = 0; i < n; i++)
172 f->upvalues[i].name = NULL;
173 for (i = 0; i < n; i++) {
174 f->upvalues[i].instack = LoadByte(S);
175 f->upvalues[i].idx = LoadByte(S);
180 static void LoadDebug (LoadState *S, Proto *f) {
183 f->lineinfo = luaM_newvector(S->L, n, int);
185 LoadVector(S, f->lineinfo, n);
187 f->locvars = luaM_newvector(S->L, n, LocVar);
189 for (i = 0; i < n; i++)
190 f->locvars[i].varname = NULL;
191 for (i = 0; i < n; i++) {
192 f->locvars[i].varname = LoadString(S);
193 f->locvars[i].startpc = LoadInt(S);
194 f->locvars[i].endpc = LoadInt(S);
197 for (i = 0; i < n; i++)
198 f->upvalues[i].name = LoadString(S);
202 static void LoadFunction (LoadState *S, Proto *f, TString *psource) {
203 f->source = LoadString(S);
204 if (f->source == NULL) /* no source in dump? */
205 f->source = psource; /* reuse parent's source */
206 f->linedefined = LoadInt(S);
207 f->lastlinedefined = LoadInt(S);
208 f->numparams = LoadByte(S);
209 f->is_vararg = LoadByte(S);
210 f->maxstacksize = LoadByte(S);
219 static void checkliteral (LoadState *S, const char *s, const char *msg) {
220 char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */
221 size_t len = strlen(s);
222 LoadVector(S, buff, len);
223 if (memcmp(s, buff, len) != 0)
228 static void fchecksize (LoadState *S, size_t size, const char *tname) {
229 if (LoadByte(S) != size)
230 error(S, luaO_pushfstring(S->L, "%s size mismatch in", tname));
234 #define checksize(S,t) fchecksize(S,sizeof(t),#t)
236 static void checkHeader (LoadState *S) {
237 checkliteral(S, LUA_SIGNATURE + 1, "not a"); /* 1st char already checked */
238 if (LoadByte(S) != LUAC_VERSION)
239 error(S, "version mismatch in");
240 if (LoadByte(S) != LUAC_FORMAT)
241 error(S, "format mismatch in");
242 checkliteral(S, LUAC_DATA, "corrupted");
244 checksize(S, size_t);
245 checksize(S, Instruction);
246 checksize(S, lua_Integer);
247 checksize(S, lua_Number);
248 if (LoadInteger(S) != LUAC_INT)
249 error(S, "endianness mismatch in");
250 if (LoadNumber(S) != LUAC_NUM)
251 error(S, "float format mismatch in");
256 ** load precompiled chunk
258 LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) {
261 if (*name == '@' || *name == '=')
263 else if (*name == LUA_SIGNATURE[0])
264 S.name = "binary string";
270 cl = luaF_newLclosure(L, LoadByte(&S));
271 setclLvalue(L, L->top, cl);
273 cl->p = luaF_newproto(L);
274 LoadFunction(&S, cl->p, NULL);
275 lua_assert(cl->nupvalues == cl->p->sizeupvalues);
276 luai_verifycode(L, buff, cl->p);