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 18 typedef 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 29 static 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 39 static void DumpChar(int y, DumpState* D) 40 { 41 char x=(char)y; 42 DumpVar(x,D); 43 } 44 45 static void DumpInt(int x, DumpState* D) 46 { 47 DumpVar(x,D); 48 } 49 50 static void DumpNumber(lua_Number x, DumpState* D) 51 { 52 DumpVar(x,D); 53 } 54 55 static 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 61 static 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 78 static void DumpFunction(const Proto* f, DumpState* D); 79 80 static 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 109 static 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 120 static 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 139 static 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 152 static 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 */ 162 int 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