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