1 /*
2 ** $Id: ldump.c,v 2.37.1.1 2017/04/19 17:20:42 roberto Exp $
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(v,n,D) DumpBlock(v,(n)*sizeof((v)[0]),D)
36
37 #define DumpLiteral(s,D) DumpBlock(s, sizeof(s) - sizeof(char), D)
38
39
DumpBlock(const void * b,size_t size,DumpState * D)40 static void DumpBlock (const void *b, size_t size, DumpState *D) {
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(x,D) DumpVector(&x,1,D)
50
51
DumpByte(int y,DumpState * D)52 static void DumpByte (int y, DumpState *D) {
53 lu_byte x = (lu_byte)y;
54 DumpVar(x, D);
55 }
56
57
DumpInt(int x,DumpState * D)58 static void DumpInt (int x, DumpState *D) {
59 DumpVar(x, D);
60 }
61
62
DumpNumber(lua_Number x,DumpState * D)63 static void DumpNumber (lua_Number x, DumpState *D) {
64 DumpVar(x, D);
65 }
66
67
DumpInteger(lua_Integer x,DumpState * D)68 static void DumpInteger (lua_Integer x, DumpState *D) {
69 DumpVar(x, D);
70 }
71
72
DumpString(const TString * s,DumpState * D)73 static void DumpString (const TString *s, DumpState *D) {
74 if (s == NULL)
75 DumpByte(0, D);
76 else {
77 size_t size = tsslen(s) + 1; /* include trailing '\0' */
78 const char *str = getstr(s);
79 if (size < 0xFF)
80 DumpByte(cast_int(size), D);
81 else {
82 DumpByte(0xFF, D);
83 DumpVar(size, D);
84 }
85 DumpVector(str, size - 1, D); /* no need to save '\0' */
86 }
87 }
88
89
DumpCode(const Proto * f,DumpState * D)90 static void DumpCode (const Proto *f, DumpState *D) {
91 DumpInt(f->sizecode, D);
92 DumpVector(f->code, f->sizecode, D);
93 }
94
95
96 static void DumpFunction(const Proto *f, TString *psource, DumpState *D);
97
DumpConstants(const Proto * f,DumpState * D)98 static void DumpConstants (const Proto *f, DumpState *D) {
99 int i;
100 int n = f->sizek;
101 DumpInt(n, D);
102 for (i = 0; i < n; i++) {
103 const TValue *o = &f->k[i];
104 DumpByte(ttype(o), D);
105 switch (ttype(o)) {
106 case LUA_TNIL:
107 break;
108 case LUA_TBOOLEAN:
109 DumpByte(bvalue(o), D);
110 break;
111 case LUA_TNUMFLT:
112 DumpNumber(fltvalue(o), D);
113 break;
114 case LUA_TNUMINT:
115 DumpInteger(ivalue(o), D);
116 break;
117 case LUA_TSHRSTR:
118 case LUA_TLNGSTR:
119 DumpString(tsvalue(o), D);
120 break;
121 default:
122 lua_assert(0);
123 }
124 }
125 }
126
127
DumpProtos(const Proto * f,DumpState * D)128 static void DumpProtos (const Proto *f, DumpState *D) {
129 int i;
130 int n = f->sizep;
131 DumpInt(n, D);
132 for (i = 0; i < n; i++)
133 DumpFunction(f->p[i], f->source, D);
134 }
135
136
DumpUpvalues(const Proto * f,DumpState * D)137 static void DumpUpvalues (const Proto *f, DumpState *D) {
138 int i, n = f->sizeupvalues;
139 DumpInt(n, D);
140 for (i = 0; i < n; i++) {
141 DumpByte(f->upvalues[i].instack, D);
142 DumpByte(f->upvalues[i].idx, D);
143 }
144 }
145
146
DumpDebug(const Proto * f,DumpState * D)147 static void DumpDebug (const Proto *f, DumpState *D) {
148 int i, n;
149 n = (D->strip) ? 0 : f->sizelineinfo;
150 DumpInt(n, D);
151 DumpVector(f->lineinfo, n, D);
152 n = (D->strip) ? 0 : f->sizelocvars;
153 DumpInt(n, D);
154 for (i = 0; i < n; i++) {
155 DumpString(f->locvars[i].varname, D);
156 DumpInt(f->locvars[i].startpc, D);
157 DumpInt(f->locvars[i].endpc, D);
158 }
159 n = (D->strip) ? 0 : f->sizeupvalues;
160 DumpInt(n, D);
161 for (i = 0; i < n; i++)
162 DumpString(f->upvalues[i].name, D);
163 }
164
165
DumpFunction(const Proto * f,TString * psource,DumpState * D)166 static void DumpFunction (const Proto *f, TString *psource, DumpState *D) {
167 if (D->strip || f->source == psource)
168 DumpString(NULL, D); /* no debug info or same source as its parent */
169 else
170 DumpString(f->source, D);
171 DumpInt(f->linedefined, D);
172 DumpInt(f->lastlinedefined, D);
173 DumpByte(f->numparams, D);
174 DumpByte(f->is_vararg, D);
175 DumpByte(f->maxstacksize, D);
176 DumpCode(f, D);
177 DumpConstants(f, D);
178 DumpUpvalues(f, D);
179 DumpProtos(f, D);
180 DumpDebug(f, D);
181 }
182
183
DumpHeader(DumpState * D)184 static void DumpHeader (DumpState *D) {
185 DumpLiteral(LUA_SIGNATURE, D);
186 DumpByte(LUAC_VERSION, D);
187 DumpByte(LUAC_FORMAT, D);
188 DumpLiteral(LUAC_DATA, D);
189 DumpByte(sizeof(int), D);
190 DumpByte(sizeof(size_t), D);
191 DumpByte(sizeof(Instruction), D);
192 DumpByte(sizeof(lua_Integer), D);
193 DumpByte(sizeof(lua_Number), D);
194 DumpInteger(LUAC_INT, D);
195 DumpNumber(LUAC_NUM, D);
196 }
197
198
199 /*
200 ** dump Lua function as precompiled chunk
201 */
luaU_dump(lua_State * L,const Proto * f,lua_Writer w,void * data,int strip)202 int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data,
203 int strip) {
204 DumpState D;
205 D.L = L;
206 D.writer = w;
207 D.data = data;
208 D.strip = strip;
209 D.status = 0;
210 DumpHeader(&D);
211 DumpByte(f->sizeupvalues, &D);
212 DumpFunction(f, NULL, &D);
213 return D.status;
214 }
215
216