1/* 2** $Id: ldump.c,v 2.17 2012/01/23 23:02:10 roberto Exp $ 3** save precompiled Lua chunks 4** See Copyright Notice in lua.h 5*/ 6 7#include <stddef.h> 8 9#define ldump_c 10#define LUA_CORE 11 12#include "lua.h" 13 14#include "lobject.h" 15#include "lstate.h" 16#include "lundump.h" 17 18typedef struct { 19 lua_State* L; 20 lua_Writer writer; 21 void* data; 22 int strip; 23 int status; 24} DumpState; 25 26#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) 27#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) 28 29static void DumpBlock(const void* b, size_t size, DumpState* D) 30{ 31 if (D->status==0) 32 { 33 lua_unlock(D->L); 34 D->status=(*D->writer)(D->L,b,size,D->data); 35 lua_lock(D->L); 36 } 37} 38 39static void DumpChar(int y, DumpState* D) 40{ 41 char x=(char)y; 42 DumpVar(x,D); 43} 44 45static void DumpInt(int x, DumpState* D) 46{ 47 DumpVar(x,D); 48} 49 50static void DumpNumber(lua_Number x, DumpState* D) 51{ 52 DumpVar(x,D); 53} 54 55static void DumpVector(const void* b, int n, size_t size, DumpState* D) 56{ 57 DumpInt(n,D); 58 DumpMem(b,n,size,D); 59} 60 61static void DumpString(const TString* s, DumpState* D) 62{ 63 if (s==NULL) 64 { 65 size_t size=0; 66 DumpVar(size,D); 67 } 68 else 69 { 70 size_t size=s->tsv.len+1; /* include trailing '\0' */ 71 DumpVar(size,D); 72 DumpBlock(getstr(s),size*sizeof(char),D); 73 } 74} 75 76#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) 77 78static void DumpFunction(const Proto* f, DumpState* D); 79 80static void DumpConstants(const Proto* f, DumpState* D) 81{ 82 int i,n=f->sizek; 83 DumpInt(n,D); 84 for (i=0; i<n; i++) 85 { 86 const TValue* o=&f->k[i]; 87 DumpChar(ttypenv(o),D); 88 switch (ttypenv(o)) 89 { 90 case LUA_TNIL: 91 break; 92 case LUA_TBOOLEAN: 93 DumpChar(bvalue(o),D); 94 break; 95 case LUA_TNUMBER: 96 DumpNumber(nvalue(o),D); 97 break; 98 case LUA_TSTRING: 99 DumpString(rawtsvalue(o),D); 100 break; 101 default: lua_assert(0); 102 } 103 } 104 n=f->sizep; 105 DumpInt(n,D); 106 for (i=0; i<n; i++) DumpFunction(f->p[i],D); 107} 108 109static void DumpUpvalues(const Proto* f, DumpState* D) 110{ 111 int i,n=f->sizeupvalues; 112 DumpInt(n,D); 113 for (i=0; i<n; i++) 114 { 115 DumpChar(f->upvalues[i].instack,D); 116 DumpChar(f->upvalues[i].idx,D); 117 } 118} 119 120static void DumpDebug(const Proto* f, DumpState* D) 121{ 122 int i,n; 123 DumpString((D->strip) ? NULL : f->source,D); 124 n= (D->strip) ? 0 : f->sizelineinfo; 125 DumpVector(f->lineinfo,n,sizeof(int),D); 126 n= (D->strip) ? 0 : f->sizelocvars; 127 DumpInt(n,D); 128 for (i=0; i<n; i++) 129 { 130 DumpString(f->locvars[i].varname,D); 131 DumpInt(f->locvars[i].startpc,D); 132 DumpInt(f->locvars[i].endpc,D); 133 } 134 n= (D->strip) ? 0 : f->sizeupvalues; 135 DumpInt(n,D); 136 for (i=0; i<n; i++) DumpString(f->upvalues[i].name,D); 137} 138 139static void DumpFunction(const Proto* f, DumpState* D) 140{ 141 DumpInt(f->linedefined,D); 142 DumpInt(f->lastlinedefined,D); 143 DumpChar(f->numparams,D); 144 DumpChar(f->is_vararg,D); 145 DumpChar(f->maxstacksize,D); 146 DumpCode(f,D); 147 DumpConstants(f,D); 148 DumpUpvalues(f,D); 149 DumpDebug(f,D); 150} 151 152static void DumpHeader(DumpState* D) 153{ 154 lu_byte h[LUAC_HEADERSIZE]; 155 luaU_header(h); 156 DumpBlock(h,LUAC_HEADERSIZE,D); 157} 158 159/* 160** dump Lua function as precompiled chunk 161*/ 162int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) 163{ 164 DumpState D; 165 D.L=L; 166 D.writer=w; 167 D.data=data; 168 D.strip=strip; 169 D.status=0; 170 DumpHeader(&D); 171 DumpFunction(f,&D); 172 return D.status; 173} 174