lua/lundump.c

Go to the documentation of this file.
00001 /*
00002 ** $Id: lundump.c,v 1.71 2011/12/07 10:39:12 lhf Exp $
00003 ** load precompiled Lua chunks
00004 ** See Copyright Notice in lua.h
00005 */
00006 
00007 #include <string.h>
00008 
00009 #define lundump_c
00010 #define LUA_CORE
00011 
00012 #include "lua.h"
00013 
00014 #include "ldebug.h"
00015 #include "ldo.h"
00016 #include "lfunc.h"
00017 #include "lmem.h"
00018 #include "lobject.h"
00019 #include "lstring.h"
00020 #include "lundump.h"
00021 #include "lzio.h"
00022 
00023 typedef struct {
00024  lua_State* L;
00025  ZIO* Z;
00026  Mbuffer* b;
00027  const char* name;
00028 } LoadState;
00029 
00030 static void error(LoadState* S, const char* why)
00031 {
00032  luaO_pushfstring(S->L,"%s: %s precompiled chunk",S->name,why);
00033  luaD_throw(S->L,LUA_ERRSYNTAX);
00034 }
00035 
00036 #define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size))
00037 #define LoadByte(S)     (lu_byte)LoadChar(S)
00038 #define LoadVar(S,x)        LoadMem(S,&x,1,sizeof(x))
00039 #define LoadVector(S,b,n,size)  LoadMem(S,b,n,size)
00040 
00041 #if !defined(luai_verifycode)
00042 #define luai_verifycode(L,b,f)  (f)
00043 #endif
00044 
00045 static void LoadBlock(LoadState* S, void* b, size_t size)
00046 {
00047  if (luaZ_read(S->Z,b,size)!=0) error(S,"truncated");
00048 }
00049 
00050 static int LoadChar(LoadState* S)
00051 {
00052  char x;
00053  LoadVar(S,x);
00054  return x;
00055 }
00056 
00057 static int LoadInt(LoadState* S)
00058 {
00059  int x;
00060  LoadVar(S,x);
00061  if (x<0) error(S,"corrupted");
00062  return x;
00063 }
00064 
00065 static lua_Number LoadNumber(LoadState* S)
00066 {
00067  lua_Number x;
00068  LoadVar(S,x);
00069  return x;
00070 }
00071 
00072 static TString* LoadString(LoadState* S)
00073 {
00074  size_t size;
00075  LoadVar(S,size);
00076  if (size==0)
00077   return NULL;
00078  else
00079  {
00080   char* s=luaZ_openspace(S->L,S->b,size);
00081   LoadBlock(S,s,size*sizeof(char));
00082   return luaS_newlstr(S->L,s,size-1);       /* remove trailing '\0' */
00083  }
00084 }
00085 
00086 static void LoadCode(LoadState* S, Proto* f)
00087 {
00088  int n=LoadInt(S);
00089  f->code=luaM_newvector(S->L,n,Instruction);
00090  f->sizecode=n;
00091  LoadVector(S,f->code,n,sizeof(Instruction));
00092 }
00093 
00094 static Proto* LoadFunction(LoadState* S);
00095 
00096 static void LoadConstants(LoadState* S, Proto* f)
00097 {
00098  int i,n;
00099  n=LoadInt(S);
00100  f->k=luaM_newvector(S->L,n,TValue);
00101  f->sizek=n;
00102  for (i=0; i<n; i++) setnilvalue(&f->k[i]);
00103  for (i=0; i<n; i++)
00104  {
00105   TValue* o=&f->k[i];
00106   int t=LoadChar(S);
00107   switch (t)
00108   {
00109    case LUA_TNIL:
00110     setnilvalue(o);
00111     break;
00112    case LUA_TBOOLEAN:
00113     setbvalue(o,LoadChar(S));
00114     break;
00115    case LUA_TNUMBER:
00116     setnvalue(o,LoadNumber(S));
00117     break;
00118    case LUA_TSTRING:
00119     setsvalue2n(S->L,o,LoadString(S));
00120     break;
00121   }
00122  }
00123  n=LoadInt(S);
00124  f->p=luaM_newvector(S->L,n,Proto*);
00125  f->sizep=n;
00126  for (i=0; i<n; i++) f->p[i]=NULL;
00127  for (i=0; i<n; i++) f->p[i]=LoadFunction(S);
00128 }
00129 
00130 static void LoadUpvalues(LoadState* S, Proto* f)
00131 {
00132  int i,n;
00133  n=LoadInt(S);
00134  f->upvalues=luaM_newvector(S->L,n,Upvaldesc);
00135  f->sizeupvalues=n;
00136  for (i=0; i<n; i++) f->upvalues[i].name=NULL;
00137  for (i=0; i<n; i++)
00138  {
00139   f->upvalues[i].instack=LoadByte(S);
00140   f->upvalues[i].idx=LoadByte(S);
00141  }
00142 }
00143 
00144 static void LoadDebug(LoadState* S, Proto* f)
00145 {
00146  int i,n;
00147  f->source=LoadString(S);
00148  n=LoadInt(S);
00149  f->lineinfo=luaM_newvector(S->L,n,int);
00150  f->sizelineinfo=n;
00151  LoadVector(S,f->lineinfo,n,sizeof(int));
00152  n=LoadInt(S);
00153  f->locvars=luaM_newvector(S->L,n,LocVar);
00154  f->sizelocvars=n;
00155  for (i=0; i<n; i++) f->locvars[i].varname=NULL;
00156  for (i=0; i<n; i++)
00157  {
00158   f->locvars[i].varname=LoadString(S);
00159   f->locvars[i].startpc=LoadInt(S);
00160   f->locvars[i].endpc=LoadInt(S);
00161  }
00162  n=LoadInt(S);
00163  for (i=0; i<n; i++) f->upvalues[i].name=LoadString(S);
00164 }
00165 
00166 static Proto* LoadFunction(LoadState* S)
00167 {
00168  Proto* f=luaF_newproto(S->L);
00169  setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
00170  f->linedefined=LoadInt(S);
00171  f->lastlinedefined=LoadInt(S);
00172  f->numparams=LoadByte(S);
00173  f->is_vararg=LoadByte(S);
00174  f->maxstacksize=LoadByte(S);
00175  LoadCode(S,f);
00176  LoadConstants(S,f);
00177  LoadUpvalues(S,f);
00178  LoadDebug(S,f);
00179  S->L->top--;
00180  return f;
00181 }
00182 
00183 /* the code below must be consistent with the code in luaU_header */
00184 #define N0  LUAC_HEADERSIZE
00185 #define N1  (sizeof(LUA_SIGNATURE)-sizeof(char))
00186 #define N2  N1+2
00187 #define N3  N2+6
00188 
00189 static void LoadHeader(LoadState* S)
00190 {
00191  lu_byte h[LUAC_HEADERSIZE];
00192  lu_byte s[LUAC_HEADERSIZE];
00193  luaU_header(h);
00194  memcpy(s,h,sizeof(char));          /* first char already read */
00195  LoadBlock(S,s+sizeof(char),LUAC_HEADERSIZE-sizeof(char));
00196  if (memcmp(h,s,N0)==0) return;
00197  if (memcmp(h,s,N1)!=0) error(S,"not a");
00198  if (memcmp(h,s,N2)!=0) error(S,"version mismatch in");
00199  if (memcmp(h,s,N3)!=0) error(S,"incompatible"); else error(S,"corrupted");
00200 }
00201 
00202 /*
00203 ** load precompiled chunk
00204 */
00205 Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
00206 {
00207  LoadState S;
00208  if (*name=='@' || *name=='=')
00209   S.name=name+1;
00210  else if (*name==LUA_SIGNATURE[0])
00211   S.name="binary string";
00212  else
00213   S.name=name;
00214  S.L=L;
00215  S.Z=Z;
00216  S.b=buff;
00217  LoadHeader(&S);
00218  return luai_verifycode(L,buff,LoadFunction(&S));
00219 }
00220 
00221 #define MYINT(s)    (s[0]-'0')
00222 #define VERSION     MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR)
00223 #define FORMAT      0       /* this is the official format */
00224 
00225 /*
00226 * make header for precompiled chunks
00227 * if you change the code below be sure to update LoadHeader and FORMAT above
00228 * and LUAC_HEADERSIZE in lundump.h
00229 */
00230 void luaU_header (lu_byte* h)
00231 {
00232  int x=1;
00233  memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-sizeof(char));
00234  h+=sizeof(LUA_SIGNATURE)-sizeof(char);
00235  *h++=cast_byte(VERSION);
00236  *h++=cast_byte(FORMAT);
00237  *h++=cast_byte(*(char*)&x);            /* endianness */
00238  *h++=cast_byte(sizeof(int));
00239  *h++=cast_byte(sizeof(size_t));
00240  *h++=cast_byte(sizeof(Instruction));
00241  *h++=cast_byte(sizeof(lua_Number));
00242  *h++=cast_byte(((lua_Number)0.5)==0);      /* is lua_Number integral? */
00243  memcpy(h,LUAC_TAIL,sizeof(LUAC_TAIL)-sizeof(char));
00244 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:05 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs