1 /* $NetBSD: ldump.c,v 1.4 2015/10/08 13:21:00 mbalmer Exp $ */ 2 3 /* 4 ** Id: ldump.c,v 2.36 2015/03/30 15:43:51 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 = tsslen(s) + 1; /* include trailing '\0' */ 82 const char *str = getstr(s); 83 if (size < 0xFF) 84 DumpByte(cast_int(size), D); 85 else { 86 DumpByte(0xFF, D); 87 DumpVar(size, D); 88 } 89 DumpVector(str, size - 1, D); /* no need to save '\0' */ 90 } 91 } 92 93 94 static void DumpCode (const Proto *f, DumpState *D) { 95 DumpInt(f->sizecode, D); 96 DumpVector(f->code, f->sizecode, D); 97 } 98 99 100 static void DumpFunction(const Proto *f, TString *psource, DumpState *D); 101 102 static void DumpConstants (const Proto *f, DumpState *D) { 103 int i; 104 int n = f->sizek; 105 DumpInt(n, D); 106 for (i = 0; i < n; i++) { 107 const TValue *o = &f->k[i]; 108 DumpByte(ttype(o), D); 109 switch (ttype(o)) { 110 case LUA_TNIL: 111 break; 112 case LUA_TBOOLEAN: 113 DumpByte(bvalue(o), D); 114 break; 115 #ifndef _KERNEL 116 case LUA_TNUMFLT: 117 DumpNumber(fltvalue(o), D); 118 break; 119 #endif 120 case LUA_TNUMINT: 121 DumpInteger(ivalue(o), D); 122 break; 123 case LUA_TSHRSTR: 124 case LUA_TLNGSTR: 125 DumpString(tsvalue(o), D); 126 break; 127 default: 128 lua_assert(0); 129 } 130 } 131 } 132 133 134 static void DumpProtos (const Proto *f, DumpState *D) { 135 int i; 136 int n = f->sizep; 137 DumpInt(n, D); 138 for (i = 0; i < n; i++) 139 DumpFunction(f->p[i], f->source, D); 140 } 141 142 143 static void DumpUpvalues (const Proto *f, DumpState *D) { 144 int i, n = f->sizeupvalues; 145 DumpInt(n, D); 146 for (i = 0; i < n; i++) { 147 DumpByte(f->upvalues[i].instack, D); 148 DumpByte(f->upvalues[i].idx, D); 149 } 150 } 151 152 153 static void DumpDebug (const Proto *f, DumpState *D) { 154 int i, n; 155 n = (D->strip) ? 0 : f->sizelineinfo; 156 DumpInt(n, D); 157 DumpVector(f->lineinfo, n, D); 158 n = (D->strip) ? 0 : f->sizelocvars; 159 DumpInt(n, D); 160 for (i = 0; i < n; i++) { 161 DumpString(f->locvars[i].varname, D); 162 DumpInt(f->locvars[i].startpc, D); 163 DumpInt(f->locvars[i].endpc, D); 164 } 165 n = (D->strip) ? 0 : f->sizeupvalues; 166 DumpInt(n, D); 167 for (i = 0; i < n; i++) 168 DumpString(f->upvalues[i].name, D); 169 } 170 171 172 static void DumpFunction (const Proto *f, TString *psource, DumpState *D) { 173 if (D->strip || f->source == psource) 174 DumpString(NULL, D); /* no debug info or same source as its parent */ 175 else 176 DumpString(f->source, D); 177 DumpInt(f->linedefined, D); 178 DumpInt(f->lastlinedefined, D); 179 DumpByte(f->numparams, D); 180 DumpByte(f->is_vararg, D); 181 DumpByte(f->maxstacksize, D); 182 DumpCode(f, D); 183 DumpConstants(f, D); 184 DumpUpvalues(f, D); 185 DumpProtos(f, D); 186 DumpDebug(f, D); 187 } 188 189 190 static void DumpHeader (DumpState *D) { 191 DumpLiteral(LUA_SIGNATURE, D); 192 DumpByte(LUAC_VERSION, D); 193 DumpByte(LUAC_FORMAT, D); 194 DumpLiteral(LUAC_DATA, D); 195 DumpByte(sizeof(int), D); 196 DumpByte(sizeof(size_t), D); 197 DumpByte(sizeof(Instruction), D); 198 DumpByte(sizeof(lua_Integer), D); 199 DumpByte(sizeof(lua_Number), D); 200 DumpInteger(LUAC_INT, D); 201 DumpNumber(LUAC_NUM, D); 202 } 203 204 205 /* 206 ** dump Lua function as precompiled chunk 207 */ 208 int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data, 209 int strip) { 210 DumpState D; 211 D.L = L; 212 D.writer = w; 213 D.data = data; 214 D.strip = strip; 215 D.status = 0; 216 DumpHeader(&D); 217 DumpByte(f->sizeupvalues, &D); 218 DumpFunction(f, NULL, &D); 219 return D.status; 220 } 221 222