1 /* $NetBSD: ldump.c,v 1.2 2014/07/19 18:38:34 lneto Exp $ */ 2 3 /* 4 ** $Id: ldump.c,v 1.2 2014/07/19 18:38:34 lneto Exp $ 5 ** save precompiled Lua chunks 6 ** See Copyright Notice in lua.h 7 */ 8 9 #ifndef _KERNEL 10 #include <stddef.h> 11 #endif 12 13 #define ldump_c 14 #define LUA_CORE 15 16 #include "lua.h" 17 18 #include "lobject.h" 19 #include "lstate.h" 20 #include "lundump.h" 21 22 23 typedef struct { 24 lua_State *L; 25 lua_Writer writer; 26 void *data; 27 int strip; 28 int status; 29 } DumpState; 30 31 32 /* 33 ** All high-level dumps go through DumpVector; you can change it to 34 ** change the endianness of the result 35 */ 36 #define DumpVector(v,n,D) DumpBlock(v,(n)*sizeof((v)[0]),D) 37 38 #define DumpLiteral(s,D) DumpBlock(s, sizeof(s) - sizeof(char), D) 39 40 41 static void DumpBlock (const void *b, size_t size, DumpState *D) { 42 if (D->status == 0) { 43 lua_unlock(D->L); 44 D->status = (*D->writer)(D->L, b, size, D->data); 45 lua_lock(D->L); 46 } 47 } 48 49 50 #define DumpVar(x,D) DumpVector(&x,1,D) 51 52 53 static void DumpByte (int y, DumpState *D) { 54 lu_byte x = (lu_byte)y; 55 DumpVar(x, D); 56 } 57 58 59 static void DumpInt (int x, DumpState *D) { 60 DumpVar(x, D); 61 } 62 63 64 static void DumpNumber (lua_Number x, DumpState *D) { 65 DumpVar(x, D); 66 } 67 68 69 static void DumpInteger (lua_Integer x, DumpState *D) { 70 DumpVar(x, D); 71 } 72 73 74 static void DumpString (const TString *s, DumpState *D) { 75 if (s == NULL) 76 DumpByte(0, D); 77 else { 78 size_t size = s->tsv.len + 1; /* include trailing '\0' */ 79 if (size < 0xFF) 80 DumpByte(cast_int(size), D); 81 else { 82 DumpByte(0xFF, D); 83 DumpVar(size, D); 84 } 85 DumpVector(getstr(s), size - 1, D); /* no need to save '\0' */ 86 } 87 } 88 89 90 static void DumpCode (const Proto *f, DumpState *D) { 91 DumpInt(f->sizecode, D); 92 DumpVector(f->code, f->sizecode, D); 93 } 94 95 96 static void DumpFunction(const Proto *f, TString *psource, DumpState *D); 97 98 static void DumpConstants (const Proto *f, DumpState *D) { 99 int i; 100 int n = f->sizek; 101 DumpInt(n, D); 102 for (i = 0; i < n; i++) { 103 const TValue *o = &f->k[i]; 104 DumpByte(ttype(o), D); 105 switch (ttype(o)) { 106 case LUA_TNIL: 107 break; 108 case LUA_TBOOLEAN: 109 DumpByte(bvalue(o), D); 110 break; 111 #ifndef _KERNEL 112 case LUA_TNUMFLT: 113 DumpNumber(fltvalue(o), D); 114 break; 115 #endif 116 case LUA_TNUMINT: 117 DumpInteger(ivalue(o), D); 118 break; 119 case LUA_TSHRSTR: 120 case LUA_TLNGSTR: 121 DumpString(rawtsvalue(o), D); 122 break; 123 default: 124 lua_assert(0); 125 } 126 } 127 } 128 129 130 static void DumpProtos (const Proto *f, DumpState *D) { 131 int i; 132 int n = f->sizep; 133 DumpInt(n, D); 134 for (i = 0; i < n; i++) 135 DumpFunction(f->p[i], f->source, D); 136 } 137 138 139 static void DumpUpvalues (const Proto *f, DumpState *D) { 140 int i, n = f->sizeupvalues; 141 DumpInt(n, D); 142 for (i = 0; i < n; i++) { 143 DumpByte(f->upvalues[i].instack, D); 144 DumpByte(f->upvalues[i].idx, D); 145 } 146 } 147 148 149 static void DumpDebug (const Proto *f, DumpState *D) { 150 int i, n; 151 n = (D->strip) ? 0 : f->sizelineinfo; 152 DumpInt(n, D); 153 DumpVector(f->lineinfo, n, D); 154 n = (D->strip) ? 0 : f->sizelocvars; 155 DumpInt(n, D); 156 for (i = 0; i < n; i++) { 157 DumpString(f->locvars[i].varname, D); 158 DumpInt(f->locvars[i].startpc, D); 159 DumpInt(f->locvars[i].endpc, D); 160 } 161 n = (D->strip) ? 0 : f->sizeupvalues; 162 DumpInt(n, D); 163 for (i = 0; i < n; i++) 164 DumpString(f->upvalues[i].name, D); 165 } 166 167 168 static void DumpFunction (const Proto *f, TString *psource, DumpState *D) { 169 if (D->strip || f->source == psource) 170 DumpString(NULL, D); /* no debug info or same source as its parent */ 171 else 172 DumpString(f->source, D); 173 DumpInt(f->linedefined, D); 174 DumpInt(f->lastlinedefined, D); 175 DumpByte(f->numparams, D); 176 DumpByte(f->is_vararg, D); 177 DumpByte(f->maxstacksize, D); 178 DumpCode(f, D); 179 DumpConstants(f, D); 180 DumpUpvalues(f, D); 181 DumpProtos(f, D); 182 DumpDebug(f, D); 183 } 184 185 186 static void DumpHeader (DumpState *D) { 187 DumpLiteral(LUA_SIGNATURE, D); 188 DumpByte(LUAC_VERSION, D); 189 DumpByte(LUAC_FORMAT, D); 190 DumpLiteral(LUAC_DATA, D); 191 DumpByte(sizeof(int), D); 192 DumpByte(sizeof(size_t), D); 193 DumpByte(sizeof(Instruction), D); 194 DumpByte(sizeof(lua_Integer), D); 195 DumpByte(sizeof(lua_Number), D); 196 DumpInteger(LUAC_INT, D); 197 DumpNumber(LUAC_NUM, D); 198 } 199 200 201 /* 202 ** dump Lua function as precompiled chunk 203 */ 204 int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data, 205 int strip) { 206 DumpState D; 207 D.L = L; 208 D.writer = w; 209 D.data = data; 210 D.strip = strip; 211 D.status = 0; 212 DumpHeader(&D); 213 DumpByte(f->sizeupvalues, &D); 214 DumpFunction(f, NULL, &D); 215 return D.status; 216 } 217 218