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 
dumpBlock(DumpState * D,const void * b,size_t size)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 
dumpByte(DumpState * D,int y)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 
dumpSize(DumpState * D,size_t x)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 
dumpInt(DumpState * D,int x)73 static void dumpInt (DumpState *D, int x) {
74   dumpSize(D, x);
75 }
76 
77 
dumpNumber(DumpState * D,lua_Number x)78 static void dumpNumber (DumpState *D, lua_Number x) {
79   dumpVar(D, x);
80 }
81 
82 
dumpInteger(DumpState * D,lua_Integer x)83 static void dumpInteger (DumpState *D, lua_Integer x) {
84   dumpVar(D, x);
85 }
86 
87 
dumpString(DumpState * D,const TString * s)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 
dumpCode(DumpState * D,const Proto * f)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 
dumpConstants(DumpState * D,const Proto * f)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 
dumpProtos(DumpState * D,const Proto * f)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 
dumpUpvalues(DumpState * D,const Proto * f)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 
dumpDebug(DumpState * D,const Proto * f)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 
dumpFunction(DumpState * D,const Proto * f,TString * psource)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 
dumpHeader(DumpState * D)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 */
luaU_dump(lua_State * L,const Proto * f,lua_Writer w,void * data,int strip)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