lua/lundump.c

Go to the documentation of this file.
00001 /*
00002 ** $Id: lundump.c,v 1.2 2004/03/23 05:09:14 jbj Exp $
00003 ** load pre-compiled Lua chunks
00004 ** See Copyright Notice in lua.h
00005 */
00006 
00007 #define lundump_c
00008 
00009 #include "lua.h"
00010 
00011 #include "ldebug.h"
00012 #include "lfunc.h"
00013 #include "lmem.h"
00014 #include "lopcodes.h"
00015 #include "lstring.h"
00016 #include "lundump.h"
00017 #include "lzio.h"
00018 
00019 #define LoadByte        (lu_byte) ezgetc
00020 
00021 typedef struct {
00022  lua_State* L;
00023  ZIO* Z;
00024  Mbuffer* b;
00025  int swap;
00026 /*@observer@*/
00027  const char* name;
00028 } LoadState;
00029 
00030 static void unexpectedEOZ (LoadState* S)
00031         /*@modifies S @*/
00032 {
00033  luaG_runerror(S->L,"unexpected end of file in %s",S->name);
00034 }
00035 
00036 static int ezgetc (LoadState* S)
00037         /*@modifies S @*/
00038 {
00039  int c=zgetc(S->Z);
00040  if (c==EOZ) unexpectedEOZ(S);
00041  return c;
00042 }
00043 
00044 static void ezread (LoadState* S, void* b, int n)
00045         /*@modifies S, *b @*/
00046 {
00047  int r=luaZ_read(S->Z,b,n);
00048  if (r!=0) unexpectedEOZ(S);
00049 }
00050 
00051 static void LoadBlock (LoadState* S, void* b, size_t size)
00052         /*@modifies S, *b @*/
00053 {
00054  if (S->swap)
00055  {
00056   char* p=(char*) b+size-1;
00057   int n=size;
00058   while (n--) *p--=(char)ezgetc(S);
00059  }
00060  else
00061   ezread(S,b,size);
00062 }
00063 
00064 static void LoadVector (LoadState* S, void* b, int m, size_t size)
00065         /*@modifies S, *b @*/
00066 {
00067  if (S->swap)
00068  {
00069   char* q=(char*) b;
00070   while (m--)
00071   {
00072    char* p=q+size-1;
00073    int n=size;
00074    while (n--) *p--=(char)ezgetc(S);
00075    q+=size;
00076   }
00077  }
00078  else
00079   ezread(S,b,m*size);
00080 }
00081 
00082 static int LoadInt (LoadState* S)
00083         /*@modifies S @*/
00084 {
00085  int x;
00086  LoadBlock(S,&x,sizeof(x));
00087  if (x<0) luaG_runerror(S->L,"bad integer in %s",S->name);
00088  return x;
00089 }
00090 
00091 static size_t LoadSize (LoadState* S)
00092         /*@modifies S @*/
00093 {
00094  size_t x;
00095  LoadBlock(S,&x,sizeof(x));
00096  return x;
00097 }
00098 
00099 static lua_Number LoadNumber (LoadState* S)
00100         /*@modifies S @*/
00101 {
00102  lua_Number x;
00103  LoadBlock(S,&x,sizeof(x));
00104  return x;
00105 }
00106 
00107 /*@null@*/
00108 static TString* LoadString (LoadState* S)
00109         /*@modifies S @*/
00110 {
00111  size_t size=LoadSize(S);
00112  if (size==0)
00113   return NULL;
00114  else
00115  {
00116   char* s=luaZ_openspace(S->L,S->b,size);
00117   ezread(S,s,size);
00118   return luaS_newlstr(S->L,s,size-1);           /* remove trailing '\0' */
00119  }
00120 }
00121 
00122 static void LoadCode (LoadState* S, Proto* f)
00123         /*@modifies S, f @*/
00124 {
00125  int size=LoadInt(S);
00126  f->code=luaM_newvector(S->L,size,Instruction);
00127  f->sizecode=size;
00128  LoadVector(S,f->code,size,sizeof(*f->code));
00129 }
00130 
00131 static void LoadLocals (LoadState* S, Proto* f)
00132         /*@modifies S, f @*/
00133 {
00134  int i,n;
00135  n=LoadInt(S);
00136  f->locvars=luaM_newvector(S->L,n,LocVar);
00137  f->sizelocvars=n;
00138  for (i=0; i<n; i++)
00139  {
00140   f->locvars[i].varname=LoadString(S);
00141   f->locvars[i].startpc=LoadInt(S);
00142   f->locvars[i].endpc=LoadInt(S);
00143  }
00144 }
00145 
00146 static void LoadLines (LoadState* S, Proto* f)
00147         /*@modifies S, f @*/
00148 {
00149  int size=LoadInt(S);
00150  f->lineinfo=luaM_newvector(S->L,size,int);
00151  f->sizelineinfo=size;
00152  LoadVector(S,f->lineinfo,size,sizeof(*f->lineinfo));
00153 }
00154 
00155 static void LoadUpvalues (LoadState* S, Proto* f)
00156         /*@modifies S, f @*/
00157 {
00158  int i,n;
00159  n=LoadInt(S);
00160  if (n!=0 && n!=f->nups) 
00161   luaG_runerror(S->L,"bad nupvalues in %s: read %d; expected %d",
00162                 S->name,n,f->nups);
00163  f->upvalues=luaM_newvector(S->L,n,TString*);
00164  f->sizeupvalues=n;
00165  for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);
00166 }
00167 
00168 /*@null@*/
00169 static Proto* LoadFunction (LoadState* S, /*@null@*/ TString* p)
00170         /*@modifies S @*/;
00171 
00172 static void LoadConstants (LoadState* S, Proto* f)
00173         /*@modifies S, f @*/
00174 {
00175  int i,n;
00176  n=LoadInt(S);
00177  f->k=luaM_newvector(S->L,n,TObject);
00178  f->sizek=n;
00179  for (i=0; i<n; i++)
00180  {
00181   TObject* o=&f->k[i];
00182   int t=LoadByte(S);
00183   switch (t)
00184   {
00185    case LUA_TNUMBER:
00186         setnvalue(o,LoadNumber(S));
00187         break;
00188    case LUA_TSTRING:
00189         setsvalue2n(o,LoadString(S));
00190         break;
00191    case LUA_TNIL:
00192         setnilvalue(o);
00193         break;
00194    default:
00195         luaG_runerror(S->L,"bad constant type (%d) in %s",t,S->name);
00196         break;
00197   }
00198  }
00199  n=LoadInt(S);
00200  f->p=luaM_newvector(S->L,n,Proto*);
00201  f->sizep=n;
00202  for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);
00203 }
00204 
00205 static Proto* LoadFunction (LoadState* S, TString* p)
00206         /*@modifies S @*/
00207 {
00208  Proto* f=luaF_newproto(S->L);
00209  f->source=LoadString(S); if (f->source==NULL) f->source=p;
00210  f->lineDefined=LoadInt(S);
00211  f->nups=LoadByte(S);
00212  f->numparams=LoadByte(S);
00213  f->is_vararg=LoadByte(S);
00214  f->maxstacksize=LoadByte(S);
00215  LoadLines(S,f);
00216  LoadLocals(S,f);
00217  LoadUpvalues(S,f);
00218  LoadConstants(S,f);
00219  LoadCode(S,f);
00220 #ifndef TRUST_BINARIES
00221  if (!luaG_checkcode(f)) luaG_runerror(S->L,"bad code in %s",S->name);
00222 #endif
00223  return f;
00224 }
00225 
00226 static void LoadSignature (LoadState* S)
00227         /*@modifies S @*/
00228 {
00229  const char* s=LUA_SIGNATURE;
00230  while (*s!=0 && ezgetc(S)==*s)
00231   ++s;
00232  if (*s!=0) luaG_runerror(S->L,"bad signature in %s",S->name);
00233 }
00234 
00235 static void TestSize (LoadState* S, int s, const char* what)
00236         /*@modifies S @*/
00237 {
00238  int r=LoadByte(S);
00239  if (r!=s)
00240   luaG_runerror(S->L,"virtual machine mismatch in %s: "
00241         "size of %s is %d but read %d",S->name,what,s,r);
00242 }
00243 
00244 #define TESTSIZE(s,w)   TestSize(S,s,w)
00245 #define V(v)            v/16,v%16
00246 
00247 static void LoadHeader (LoadState* S)
00248         /*@modifies S @*/
00249 {
00250  int version;
00251  lua_Number x,tx=TEST_NUMBER;
00252  LoadSignature(S);
00253  version=LoadByte(S);
00254  if (version>VERSION)
00255   luaG_runerror(S->L,"%s too new: "
00256         "read version %d.%d; expected at most %d.%d",
00257         S->name,V(version),V(VERSION));
00258  if (version<VERSION0)                          /* check last major change */
00259   luaG_runerror(S->L,"%s too old: "
00260         "read version %d.%d; expected at least %d.%d",
00261         S->name,V(version),V(VERSION0));
00262  S->swap=(luaU_endianness()!=LoadByte(S));      /* need to swap bytes? */
00263  TESTSIZE(sizeof(int),"int");
00264  TESTSIZE(sizeof(size_t), "size_t");
00265  TESTSIZE(sizeof(Instruction), "Instruction");
00266  TESTSIZE(SIZE_OP, "OP");
00267  TESTSIZE(SIZE_A, "A");
00268  TESTSIZE(SIZE_B, "B");
00269  TESTSIZE(SIZE_C, "C");
00270  TESTSIZE(sizeof(lua_Number), "number");
00271  x=LoadNumber(S);
00272  if ((long)x!=(long)tx)         /* disregard errors in last bits of fraction */
00273   luaG_runerror(S->L,"unknown number format in %s",S->name);
00274 }
00275 
00276 /*@null@*/
00277 static Proto* LoadChunk (LoadState* S)
00278         /*@modifies S @*/
00279 {
00280  LoadHeader(S);
00281  return LoadFunction(S,NULL);
00282 }
00283 
00284 /*
00285 ** load precompiled chunk
00286 */
00287 Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff)
00288 {
00289  LoadState S;
00290  const char* s=zname(Z);
00291  if (*s=='@' || *s=='=')
00292   S.name=s+1;
00293  else if (*s==LUA_SIGNATURE[0])
00294   S.name="binary string";
00295  else
00296   S.name=s;
00297  S.L=L;
00298  S.Z=Z;
00299  S.b=buff;
00300  return LoadChunk(&S);
00301 }
00302 
00303 /*
00304 ** find byte order
00305 */
00306 int luaU_endianness (void)
00307 {
00308  int x=1;
00309  return *(char*)&x;
00310 }

Generated on Fri Oct 12 08:44:54 2007 for rpm by  doxygen 1.5.2