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