279 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			279 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
| ** $Id: lundump.c,v 2.44 2015/11/02 16:09:30 roberto Exp $
 | |
| ** load precompiled Lua chunks
 | |
| ** See Copyright Notice in lua.h
 | |
| */
 | |
| 
 | |
| #define lundump_c
 | |
| #define LUA_CORE
 | |
| 
 | |
| #include "lundump.h"
 | |
| #include "lprefix.h"
 | |
| 
 | |
| #include <string.h>
 | |
| 
 | |
| #include "lua.h"
 | |
| #include "ldebug.h"
 | |
| #include "ldo.h"
 | |
| #include "lfunc.h"
 | |
| #include "lmem.h"
 | |
| #include "lobject.h"
 | |
| #include "lstring.h"
 | |
| #include "lzio.h"
 | |
| 
 | |
| namespace NS_SLUA {
 | |
| 
 | |
| #if !defined(luai_verifycode)
 | |
| #define luai_verifycode(L,b,f)  /* empty */
 | |
| #endif
 | |
| 
 | |
| 
 | |
| typedef struct {
 | |
|   lua_State *L;
 | |
|   ZIO *Z;
 | |
|   const char *name;
 | |
| } LoadState;
 | |
| 
 | |
| 
 | |
| static l_noret error(LoadState *S, const char *why) {
 | |
|   luaO_pushfstring(S->L, "%s: %s precompiled chunk", S->name, why);
 | |
|   luaD_throw(S->L, LUA_ERRSYNTAX);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
| ** All high-level loads go through LoadVector; you can change it to
 | |
| ** adapt to the endianness of the input
 | |
| */
 | |
| #define LoadVector(S,b,n)	LoadBlock(S,b,(n)*sizeof((b)[0]))
 | |
| 
 | |
| static void LoadBlock (LoadState *S, void *b, size_t size) {
 | |
|   if (luaZ_read(S->Z, b, size) != 0)
 | |
|     error(S, "truncated");
 | |
| }
 | |
| 
 | |
| 
 | |
| #define LoadVar(S,x)		LoadVector(S,&x,1)
 | |
| 
 | |
| 
 | |
| static lu_byte LoadByte (LoadState *S) {
 | |
|   lu_byte x;
 | |
|   LoadVar(S, x);
 | |
|   return x;
 | |
| }
 | |
| 
 | |
| 
 | |
| static int LoadInt (LoadState *S) {
 | |
|   int x;
 | |
|   LoadVar(S, x);
 | |
|   return x;
 | |
| }
 | |
| 
 | |
| 
 | |
| static lua_Number LoadNumber (LoadState *S) {
 | |
|   lua_Number x;
 | |
|   LoadVar(S, x);
 | |
|   return x;
 | |
| }
 | |
| 
 | |
| 
 | |
| static lua_Integer LoadInteger (LoadState *S) {
 | |
|   lua_Integer x;
 | |
|   LoadVar(S, x);
 | |
|   return x;
 | |
| }
 | |
| 
 | |
| 
 | |
| static TString *LoadString (LoadState *S) {
 | |
|   int size = LoadByte(S);
 | |
|   if (size == 0xFF)
 | |
|     LoadVar(S, size);
 | |
|   if (size == 0)
 | |
|     return NULL;
 | |
|   else if (--size <= LUAI_MAXSHORTLEN) {  /* short string? */
 | |
|     char buff[LUAI_MAXSHORTLEN];
 | |
|     LoadVector(S, buff, size);
 | |
|     return luaS_newlstr(S->L, buff, size);
 | |
|   }
 | |
|   else {  /* long string */
 | |
|     TString *ts = luaS_createlngstrobj(S->L, size);
 | |
|     LoadVector(S, getstr(ts), size);  /* load directly in final place */
 | |
|     return ts;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| static void LoadCode (LoadState *S, Proto *f) {
 | |
|   int n = LoadInt(S);
 | |
|   f->code = luaM_newvector(S->L, n, Instruction);
 | |
|   f->sizecode = n;
 | |
|   LoadVector(S, f->code, n);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void LoadFunction(LoadState *S, Proto *f, TString *psource);
 | |
| 
 | |
| 
 | |
| static void LoadConstants (LoadState *S, Proto *f) {
 | |
|   int i;
 | |
|   int n = LoadInt(S);
 | |
|   f->k = luaM_newvector(S->L, n, TValue);
 | |
|   f->sizek = n;
 | |
|   for (i = 0; i < n; i++)
 | |
|     setnilvalue(&f->k[i]);
 | |
|   for (i = 0; i < n; i++) {
 | |
|     TValue *o = &f->k[i];
 | |
|     int t = LoadByte(S);
 | |
|     switch (t) {
 | |
|     case LUA_TNIL:
 | |
|       setnilvalue(o);
 | |
|       break;
 | |
|     case LUA_TBOOLEAN:
 | |
|       setbvalue(o, LoadByte(S));
 | |
|       break;
 | |
|     case LUA_TNUMFLT:
 | |
|       setfltvalue(o, LoadNumber(S));
 | |
|       break;
 | |
|     case LUA_TNUMINT:
 | |
|       setivalue(o, LoadInteger(S));
 | |
|       break;
 | |
|     case LUA_TSHRSTR:
 | |
|     case LUA_TLNGSTR:
 | |
|       setsvalue2n(S->L, o, LoadString(S));
 | |
|       break;
 | |
|     default:
 | |
|       lua_assert(0);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| static void LoadProtos (LoadState *S, Proto *f) {
 | |
|   int i;
 | |
|   int n = LoadInt(S);
 | |
|   f->p = luaM_newvector(S->L, n, Proto *);
 | |
|   f->sizep = n;
 | |
|   for (i = 0; i < n; i++)
 | |
|     f->p[i] = NULL;
 | |
|   for (i = 0; i < n; i++) {
 | |
|     f->p[i] = luaF_newproto(S->L);
 | |
|     LoadFunction(S, f->p[i], f->source);
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| static void LoadUpvalues (LoadState *S, Proto *f) {
 | |
|   int i, n;
 | |
|   n = LoadInt(S);
 | |
|   f->upvalues = luaM_newvector(S->L, n, Upvaldesc);
 | |
|   f->sizeupvalues = n;
 | |
|   for (i = 0; i < n; i++)
 | |
|     f->upvalues[i].name = NULL;
 | |
|   for (i = 0; i < n; i++) {
 | |
|     f->upvalues[i].instack = LoadByte(S);
 | |
|     f->upvalues[i].idx = LoadByte(S);
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| static void LoadDebug (LoadState *S, Proto *f) {
 | |
|   int i, n;
 | |
|   n = LoadInt(S);
 | |
|   f->lineinfo = luaM_newvector(S->L, n, int);
 | |
|   f->sizelineinfo = n;
 | |
|   LoadVector(S, f->lineinfo, n);
 | |
|   n = LoadInt(S);
 | |
|   f->locvars = luaM_newvector(S->L, n, LocVar);
 | |
|   f->sizelocvars = n;
 | |
|   for (i = 0; i < n; i++)
 | |
|     f->locvars[i].varname = NULL;
 | |
|   for (i = 0; i < n; i++) {
 | |
|     f->locvars[i].varname = LoadString(S);
 | |
|     f->locvars[i].startpc = LoadInt(S);
 | |
|     f->locvars[i].endpc = LoadInt(S);
 | |
|   }
 | |
|   n = LoadInt(S);
 | |
|   for (i = 0; i < n; i++)
 | |
|     f->upvalues[i].name = LoadString(S);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void LoadFunction (LoadState *S, Proto *f, TString *psource) {
 | |
|   f->source = LoadString(S);
 | |
|   if (f->source == NULL)  /* no source in dump? */
 | |
|     f->source = psource;  /* reuse parent's source */
 | |
|   f->linedefined = LoadInt(S);
 | |
|   f->lastlinedefined = LoadInt(S);
 | |
|   f->numparams = LoadByte(S);
 | |
|   f->is_vararg = LoadByte(S);
 | |
|   f->maxstacksize = LoadByte(S);
 | |
|   LoadCode(S, f);
 | |
|   LoadConstants(S, f);
 | |
|   LoadUpvalues(S, f);
 | |
|   LoadProtos(S, f);
 | |
|   LoadDebug(S, f);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void checkliteral (LoadState *S, const char *s, const char *msg) {
 | |
|   char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */
 | |
|   size_t len = strlen(s);
 | |
|   LoadVector(S, buff, len);
 | |
|   if (memcmp(s, buff, len) != 0)
 | |
|     error(S, msg);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void fchecksize (LoadState *S, size_t size, const char *tname) {
 | |
|   if (LoadByte(S) != size)
 | |
|     error(S, luaO_pushfstring(S->L, "%s size mismatch in", tname));
 | |
| }
 | |
| 
 | |
| 
 | |
| #define checksize(S,t)	fchecksize(S,sizeof(t),#t)
 | |
| 
 | |
| static void checkHeader (LoadState *S) {
 | |
|   checkliteral(S, LUA_SIGNATURE + 1, "not a");  /* 1st char already checked */
 | |
|   if (LoadByte(S) != LUAC_VERSION)
 | |
|     error(S, "version mismatch in");
 | |
|   if (LoadByte(S) != LUAC_FORMAT)
 | |
|     error(S, "format mismatch in");
 | |
|   checkliteral(S, LUAC_DATA, "corrupted");
 | |
|   checksize(S, int);
 | |
|   checksize(S, int);
 | |
|   checksize(S, Instruction);
 | |
|   checksize(S, lua_Integer);
 | |
|   checksize(S, lua_Number);
 | |
|   if (LoadInteger(S) != LUAC_INT)
 | |
|     error(S, "endianness mismatch in");
 | |
|   if (LoadNumber(S) != LUAC_NUM)
 | |
|     error(S, "float format mismatch in");
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
| ** load precompiled chunk
 | |
| */
 | |
| LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) {
 | |
|   LoadState S;
 | |
|   LClosure *cl;
 | |
|   if (*name == '@' || *name == '=')
 | |
|     S.name = name + 1;
 | |
|   else if (*name == LUA_SIGNATURE[0])
 | |
|     S.name = "binary string";
 | |
|   else
 | |
|     S.name = name;
 | |
|   S.L = L;
 | |
|   S.Z = Z;
 | |
|   checkHeader(&S);
 | |
|   cl = luaF_newLclosure(L, LoadByte(&S));
 | |
|   setclLvalue(L, L->top, cl);
 | |
|   luaD_inctop(L);
 | |
|   cl->p = luaF_newproto(L);
 | |
|   LoadFunction(&S, cl->p, NULL);
 | |
|   lua_assert(cl->nupvalues == cl->p->sizeupvalues);
 | |
|   luai_verifycode(L, buff, cl->p);
 | |
|   return cl;
 | |
| }
 | |
| 
 | |
| } // end NS_SLUA
 |