Lua TeamLua 5.3.0-rc017ba73111 years agoHistory
277 lines · 5.9 KB · C
RawDownload
/*** $Id: lundump.c,v 2.41 2014/11/02 19:19:04 roberto Exp $** load precompiled Lua chunks** See Copyright Notice in lua.h*/ #define lundump_c#define LUA_CORE #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 "lundump.h"#include "lzio.h"  #if !defined(luai_verifycode)#define luai_verifycode(L,b,f)  /* empty */#endif  typedef struct {  lua_State *L;  ZIO *Z;  Mbuffer *b;  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) {  size_t size = LoadByte(S);  if (size == 0xFF)    LoadVar(S, size);  if (size == 0)    return NULL;  else {    char *s = luaZ_openspace(S->L, S->b, --size);    LoadVector(S, s, size);    return luaS_newlstr(S->L, s, size);  }}  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, size_t);  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, Mbuffer *buff,                      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;  S.b = buff;  checkHeader(&S);  cl = luaF_newLclosure(L, LoadByte(&S));  setclLvalue(L, L->top, cl);  incr_top(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;}