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 23typedef 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 41static 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 53static 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 65static 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 77static void dumpInt (DumpState *D, int x) { 78 dumpSize(D, x); 79} 80 81 82static void dumpNumber (DumpState *D, lua_Number x) { 83 dumpVar(D, x); 84} 85 86 87static void dumpInteger (DumpState *D, lua_Integer x) { 88 dumpVar(D, x); 89} 90 91 92static 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 104static void dumpCode (DumpState *D, const Proto *f) { 105 dumpInt(D, f->sizecode); 106 dumpVector(D, f->code, f->sizecode); 107} 108 109 110static void dumpFunction(DumpState *D, const Proto *f, TString *psource); 111 112static 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 138static 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 147static 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 158static 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 183static 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 201static 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*/ 217int 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