1 /* 2 ** $Id: ldump.c $ 3 ** save precompiled Lua chunks 4 ** See Copyright Notice in lua.h 5 */ 6 7 #define ldump_c 8 #define LUA_CORE 9 10 #include "lprefix.h" 11 12 13 #include <limits.h> 14 #include <stddef.h> 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(D,v,n) dumpBlock(D,v,(n)*sizeof((v)[0])) 37 38 #define dumpLiteral(D, s) dumpBlock(D,s,sizeof(s) - sizeof(char)) 39 40 41 static void dumpBlock (DumpState *D, const void *b, size_t size) { 42 if (D->status == 0 && size > 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(D,x) dumpVector(D,&x,1) 51 52 53 static void dumpByte (DumpState *D, int y) { 54 lu_byte x = (lu_byte)y; 55 dumpVar(D, x); 56 } 57 58 59 /* 60 ** 'dumpSize' buffer size: each byte can store up to 7 bits. (The "+6" 61 ** rounds up the division.) 62 */ 63 #define DIBS ((sizeof(size_t) * CHAR_BIT + 6) / 7) 64 65 static void dumpSize (DumpState *D, size_t x) { 66 lu_byte buff[DIBS]; 67 int n = 0; 68 do { 69 buff[DIBS - (++n)] = x & 0x7f; /* fill buffer in reverse order */ 70 x >>= 7; 71 } while (x != 0); 72 buff[DIBS - 1] |= 0x80; /* mark last byte */ 73 dumpVector(D, buff + DIBS - n, n); 74 } 75 76 77 static void dumpInt (DumpState *D, int x) { 78 dumpSize(D, x); 79 } 80 81 82 static void dumpNumber (DumpState *D, lua_Number x) { 83 dumpVar(D, x); 84 } 85 86 87 static void dumpInteger (DumpState *D, lua_Integer x) { 88 dumpVar(D, x); 89 } 90 91 92 static void dumpString (DumpState *D, const TString *s) { 93 if (s == NULL) 94 dumpSize(D, 0); 95 else { 96 size_t size = tsslen(s); 97 const char *str = getstr(s); 98 dumpSize(D, size + 1); 99 dumpVector(D, str, size); 100 } 101 } 102 103 104 static void dumpCode (DumpState *D, const Proto *f) { 105 dumpInt(D, f->sizecode); 106 dumpVector(D, f->code, f->sizecode); 107 } 108 109 110 static void dumpFunction(DumpState *D, const Proto *f, TString *psource); 111 112 static void dumpConstants (DumpState *D, const Proto *f) { 113 int i; 114 int n = f->sizek; 115 dumpInt(D, n); 116 for (i = 0; i < n; i++) { 117 const TValue *o = &f->k[i]; 118 int tt = ttypetag(o); 119 dumpByte(D, tt); 120 switch (tt) { 121 case LUA_VNUMFLT: 122 dumpNumber(D, fltvalue(o)); 123 break; 124 case LUA_VNUMINT: 125 dumpInteger(D, ivalue(o)); 126 break; 127 case LUA_VSHRSTR: 128 case LUA_VLNGSTR: 129 dumpString(D, tsvalue(o)); 130 break; 131 default: 132 lua_assert(tt == LUA_VNIL || tt == LUA_VFALSE || tt == LUA_VTRUE); 133 } 134 } 135 } 136 137 138 static void dumpProtos (DumpState *D, const Proto *f) { 139 int i; 140 int n = f->sizep; 141 dumpInt(D, n); 142 for (i = 0; i < n; i++) 143 dumpFunction(D, f->p[i], f->source); 144 } 145 146 147 static void dumpUpvalues (DumpState *D, const Proto *f) { 148 int i, n = f->sizeupvalues; 149 dumpInt(D, n); 150 for (i = 0; i < n; i++) { 151 dumpByte(D, f->upvalues[i].instack); 152 dumpByte(D, f->upvalues[i].idx); 153 dumpByte(D, f->upvalues[i].kind); 154 } 155 } 156 157 158 static void dumpDebug (DumpState *D, const Proto *f) { 159 int i, n; 160 n = (D->strip) ? 0 : f->sizelineinfo; 161 dumpInt(D, n); 162 dumpVector(D, f->lineinfo, n); 163 n = (D->strip) ? 0 : f->sizeabslineinfo; 164 dumpInt(D, n); 165 for (i = 0; i < n; i++) { 166 dumpInt(D, f->abslineinfo[i].pc); 167 dumpInt(D, f->abslineinfo[i].line); 168 } 169 n = (D->strip) ? 0 : f->sizelocvars; 170 dumpInt(D, n); 171 for (i = 0; i < n; i++) { 172 dumpString(D, f->locvars[i].varname); 173 dumpInt(D, f->locvars[i].startpc); 174 dumpInt(D, f->locvars[i].endpc); 175 } 176 n = (D->strip) ? 0 : f->sizeupvalues; 177 dumpInt(D, n); 178 for (i = 0; i < n; i++) 179 dumpString(D, f->upvalues[i].name); 180 } 181 182 183 static void dumpFunction (DumpState *D, const Proto *f, TString *psource) { 184 if (D->strip || f->source == psource) 185 dumpString(D, NULL); /* no debug info or same source as its parent */ 186 else 187 dumpString(D, f->source); 188 dumpInt(D, f->linedefined); 189 dumpInt(D, f->lastlinedefined); 190 dumpByte(D, f->numparams); 191 dumpByte(D, f->is_vararg); 192 dumpByte(D, f->maxstacksize); 193 dumpCode(D, f); 194 dumpConstants(D, f); 195 dumpUpvalues(D, f); 196 dumpProtos(D, f); 197 dumpDebug(D, f); 198 } 199 200 201 static void dumpHeader (DumpState *D) { 202 dumpLiteral(D, LUA_SIGNATURE); 203 dumpByte(D, LUAC_VERSION); 204 dumpByte(D, LUAC_FORMAT); 205 dumpLiteral(D, LUAC_DATA); 206 dumpByte(D, sizeof(Instruction)); 207 dumpByte(D, sizeof(lua_Integer)); 208 dumpByte(D, sizeof(lua_Number)); 209 dumpInteger(D, LUAC_INT); 210 dumpNumber(D, LUAC_NUM); 211 } 212 213 214 /* 215 ** dump Lua function as precompiled chunk 216 */ 217 int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data, 218 int strip) { 219 DumpState D; 220 D.L = L; 221 D.writer = w; 222 D.data = data; 223 D.strip = strip; 224 D.status = 0; 225 dumpHeader(&D); 226 dumpByte(&D, f->sizeupvalues); 227 dumpFunction(&D, f, NULL); 228 return D.status; 229 } 230 231