xref: /freebsd-src/contrib/lua/src/ldump.c (revision 8e3e3a7ae841ccf6f6ac30a2eeab85df5d7f04bc)
1*8e3e3a7aSWarner Losh /*
2*8e3e3a7aSWarner Losh ** $Id: ldump.c,v 2.37 2015/10/08 15:53:49 roberto Exp $
3*8e3e3a7aSWarner Losh ** save precompiled Lua chunks
4*8e3e3a7aSWarner Losh ** See Copyright Notice in lua.h
5*8e3e3a7aSWarner Losh */
6*8e3e3a7aSWarner Losh 
7*8e3e3a7aSWarner Losh #define ldump_c
8*8e3e3a7aSWarner Losh #define LUA_CORE
9*8e3e3a7aSWarner Losh 
10*8e3e3a7aSWarner Losh #include "lprefix.h"
11*8e3e3a7aSWarner Losh 
12*8e3e3a7aSWarner Losh 
13*8e3e3a7aSWarner Losh #include <stddef.h>
14*8e3e3a7aSWarner Losh 
15*8e3e3a7aSWarner Losh #include "lua.h"
16*8e3e3a7aSWarner Losh 
17*8e3e3a7aSWarner Losh #include "lobject.h"
18*8e3e3a7aSWarner Losh #include "lstate.h"
19*8e3e3a7aSWarner Losh #include "lundump.h"
20*8e3e3a7aSWarner Losh 
21*8e3e3a7aSWarner Losh 
22*8e3e3a7aSWarner Losh typedef struct {
23*8e3e3a7aSWarner Losh   lua_State *L;
24*8e3e3a7aSWarner Losh   lua_Writer writer;
25*8e3e3a7aSWarner Losh   void *data;
26*8e3e3a7aSWarner Losh   int strip;
27*8e3e3a7aSWarner Losh   int status;
28*8e3e3a7aSWarner Losh } DumpState;
29*8e3e3a7aSWarner Losh 
30*8e3e3a7aSWarner Losh 
31*8e3e3a7aSWarner Losh /*
32*8e3e3a7aSWarner Losh ** All high-level dumps go through DumpVector; you can change it to
33*8e3e3a7aSWarner Losh ** change the endianness of the result
34*8e3e3a7aSWarner Losh */
35*8e3e3a7aSWarner Losh #define DumpVector(v,n,D)	DumpBlock(v,(n)*sizeof((v)[0]),D)
36*8e3e3a7aSWarner Losh 
37*8e3e3a7aSWarner Losh #define DumpLiteral(s,D)	DumpBlock(s, sizeof(s) - sizeof(char), D)
38*8e3e3a7aSWarner Losh 
39*8e3e3a7aSWarner Losh 
40*8e3e3a7aSWarner Losh static void DumpBlock (const void *b, size_t size, DumpState *D) {
41*8e3e3a7aSWarner Losh   if (D->status == 0 && size > 0) {
42*8e3e3a7aSWarner Losh     lua_unlock(D->L);
43*8e3e3a7aSWarner Losh     D->status = (*D->writer)(D->L, b, size, D->data);
44*8e3e3a7aSWarner Losh     lua_lock(D->L);
45*8e3e3a7aSWarner Losh   }
46*8e3e3a7aSWarner Losh }
47*8e3e3a7aSWarner Losh 
48*8e3e3a7aSWarner Losh 
49*8e3e3a7aSWarner Losh #define DumpVar(x,D)		DumpVector(&x,1,D)
50*8e3e3a7aSWarner Losh 
51*8e3e3a7aSWarner Losh 
52*8e3e3a7aSWarner Losh static void DumpByte (int y, DumpState *D) {
53*8e3e3a7aSWarner Losh   lu_byte x = (lu_byte)y;
54*8e3e3a7aSWarner Losh   DumpVar(x, D);
55*8e3e3a7aSWarner Losh }
56*8e3e3a7aSWarner Losh 
57*8e3e3a7aSWarner Losh 
58*8e3e3a7aSWarner Losh static void DumpInt (int x, DumpState *D) {
59*8e3e3a7aSWarner Losh   DumpVar(x, D);
60*8e3e3a7aSWarner Losh }
61*8e3e3a7aSWarner Losh 
62*8e3e3a7aSWarner Losh 
63*8e3e3a7aSWarner Losh static void DumpNumber (lua_Number x, DumpState *D) {
64*8e3e3a7aSWarner Losh   DumpVar(x, D);
65*8e3e3a7aSWarner Losh }
66*8e3e3a7aSWarner Losh 
67*8e3e3a7aSWarner Losh 
68*8e3e3a7aSWarner Losh static void DumpInteger (lua_Integer x, DumpState *D) {
69*8e3e3a7aSWarner Losh   DumpVar(x, D);
70*8e3e3a7aSWarner Losh }
71*8e3e3a7aSWarner Losh 
72*8e3e3a7aSWarner Losh 
73*8e3e3a7aSWarner Losh static void DumpString (const TString *s, DumpState *D) {
74*8e3e3a7aSWarner Losh   if (s == NULL)
75*8e3e3a7aSWarner Losh     DumpByte(0, D);
76*8e3e3a7aSWarner Losh   else {
77*8e3e3a7aSWarner Losh     size_t size = tsslen(s) + 1;  /* include trailing '\0' */
78*8e3e3a7aSWarner Losh     const char *str = getstr(s);
79*8e3e3a7aSWarner Losh     if (size < 0xFF)
80*8e3e3a7aSWarner Losh       DumpByte(cast_int(size), D);
81*8e3e3a7aSWarner Losh     else {
82*8e3e3a7aSWarner Losh       DumpByte(0xFF, D);
83*8e3e3a7aSWarner Losh       DumpVar(size, D);
84*8e3e3a7aSWarner Losh     }
85*8e3e3a7aSWarner Losh     DumpVector(str, size - 1, D);  /* no need to save '\0' */
86*8e3e3a7aSWarner Losh   }
87*8e3e3a7aSWarner Losh }
88*8e3e3a7aSWarner Losh 
89*8e3e3a7aSWarner Losh 
90*8e3e3a7aSWarner Losh static void DumpCode (const Proto *f, DumpState *D) {
91*8e3e3a7aSWarner Losh   DumpInt(f->sizecode, D);
92*8e3e3a7aSWarner Losh   DumpVector(f->code, f->sizecode, D);
93*8e3e3a7aSWarner Losh }
94*8e3e3a7aSWarner Losh 
95*8e3e3a7aSWarner Losh 
96*8e3e3a7aSWarner Losh static void DumpFunction(const Proto *f, TString *psource, DumpState *D);
97*8e3e3a7aSWarner Losh 
98*8e3e3a7aSWarner Losh static void DumpConstants (const Proto *f, DumpState *D) {
99*8e3e3a7aSWarner Losh   int i;
100*8e3e3a7aSWarner Losh   int n = f->sizek;
101*8e3e3a7aSWarner Losh   DumpInt(n, D);
102*8e3e3a7aSWarner Losh   for (i = 0; i < n; i++) {
103*8e3e3a7aSWarner Losh     const TValue *o = &f->k[i];
104*8e3e3a7aSWarner Losh     DumpByte(ttype(o), D);
105*8e3e3a7aSWarner Losh     switch (ttype(o)) {
106*8e3e3a7aSWarner Losh     case LUA_TNIL:
107*8e3e3a7aSWarner Losh       break;
108*8e3e3a7aSWarner Losh     case LUA_TBOOLEAN:
109*8e3e3a7aSWarner Losh       DumpByte(bvalue(o), D);
110*8e3e3a7aSWarner Losh       break;
111*8e3e3a7aSWarner Losh     case LUA_TNUMFLT:
112*8e3e3a7aSWarner Losh       DumpNumber(fltvalue(o), D);
113*8e3e3a7aSWarner Losh       break;
114*8e3e3a7aSWarner Losh     case LUA_TNUMINT:
115*8e3e3a7aSWarner Losh       DumpInteger(ivalue(o), D);
116*8e3e3a7aSWarner Losh       break;
117*8e3e3a7aSWarner Losh     case LUA_TSHRSTR:
118*8e3e3a7aSWarner Losh     case LUA_TLNGSTR:
119*8e3e3a7aSWarner Losh       DumpString(tsvalue(o), D);
120*8e3e3a7aSWarner Losh       break;
121*8e3e3a7aSWarner Losh     default:
122*8e3e3a7aSWarner Losh       lua_assert(0);
123*8e3e3a7aSWarner Losh     }
124*8e3e3a7aSWarner Losh   }
125*8e3e3a7aSWarner Losh }
126*8e3e3a7aSWarner Losh 
127*8e3e3a7aSWarner Losh 
128*8e3e3a7aSWarner Losh static void DumpProtos (const Proto *f, DumpState *D) {
129*8e3e3a7aSWarner Losh   int i;
130*8e3e3a7aSWarner Losh   int n = f->sizep;
131*8e3e3a7aSWarner Losh   DumpInt(n, D);
132*8e3e3a7aSWarner Losh   for (i = 0; i < n; i++)
133*8e3e3a7aSWarner Losh     DumpFunction(f->p[i], f->source, D);
134*8e3e3a7aSWarner Losh }
135*8e3e3a7aSWarner Losh 
136*8e3e3a7aSWarner Losh 
137*8e3e3a7aSWarner Losh static void DumpUpvalues (const Proto *f, DumpState *D) {
138*8e3e3a7aSWarner Losh   int i, n = f->sizeupvalues;
139*8e3e3a7aSWarner Losh   DumpInt(n, D);
140*8e3e3a7aSWarner Losh   for (i = 0; i < n; i++) {
141*8e3e3a7aSWarner Losh     DumpByte(f->upvalues[i].instack, D);
142*8e3e3a7aSWarner Losh     DumpByte(f->upvalues[i].idx, D);
143*8e3e3a7aSWarner Losh   }
144*8e3e3a7aSWarner Losh }
145*8e3e3a7aSWarner Losh 
146*8e3e3a7aSWarner Losh 
147*8e3e3a7aSWarner Losh static void DumpDebug (const Proto *f, DumpState *D) {
148*8e3e3a7aSWarner Losh   int i, n;
149*8e3e3a7aSWarner Losh   n = (D->strip) ? 0 : f->sizelineinfo;
150*8e3e3a7aSWarner Losh   DumpInt(n, D);
151*8e3e3a7aSWarner Losh   DumpVector(f->lineinfo, n, D);
152*8e3e3a7aSWarner Losh   n = (D->strip) ? 0 : f->sizelocvars;
153*8e3e3a7aSWarner Losh   DumpInt(n, D);
154*8e3e3a7aSWarner Losh   for (i = 0; i < n; i++) {
155*8e3e3a7aSWarner Losh     DumpString(f->locvars[i].varname, D);
156*8e3e3a7aSWarner Losh     DumpInt(f->locvars[i].startpc, D);
157*8e3e3a7aSWarner Losh     DumpInt(f->locvars[i].endpc, D);
158*8e3e3a7aSWarner Losh   }
159*8e3e3a7aSWarner Losh   n = (D->strip) ? 0 : f->sizeupvalues;
160*8e3e3a7aSWarner Losh   DumpInt(n, D);
161*8e3e3a7aSWarner Losh   for (i = 0; i < n; i++)
162*8e3e3a7aSWarner Losh     DumpString(f->upvalues[i].name, D);
163*8e3e3a7aSWarner Losh }
164*8e3e3a7aSWarner Losh 
165*8e3e3a7aSWarner Losh 
166*8e3e3a7aSWarner Losh static void DumpFunction (const Proto *f, TString *psource, DumpState *D) {
167*8e3e3a7aSWarner Losh   if (D->strip || f->source == psource)
168*8e3e3a7aSWarner Losh     DumpString(NULL, D);  /* no debug info or same source as its parent */
169*8e3e3a7aSWarner Losh   else
170*8e3e3a7aSWarner Losh     DumpString(f->source, D);
171*8e3e3a7aSWarner Losh   DumpInt(f->linedefined, D);
172*8e3e3a7aSWarner Losh   DumpInt(f->lastlinedefined, D);
173*8e3e3a7aSWarner Losh   DumpByte(f->numparams, D);
174*8e3e3a7aSWarner Losh   DumpByte(f->is_vararg, D);
175*8e3e3a7aSWarner Losh   DumpByte(f->maxstacksize, D);
176*8e3e3a7aSWarner Losh   DumpCode(f, D);
177*8e3e3a7aSWarner Losh   DumpConstants(f, D);
178*8e3e3a7aSWarner Losh   DumpUpvalues(f, D);
179*8e3e3a7aSWarner Losh   DumpProtos(f, D);
180*8e3e3a7aSWarner Losh   DumpDebug(f, D);
181*8e3e3a7aSWarner Losh }
182*8e3e3a7aSWarner Losh 
183*8e3e3a7aSWarner Losh 
184*8e3e3a7aSWarner Losh static void DumpHeader (DumpState *D) {
185*8e3e3a7aSWarner Losh   DumpLiteral(LUA_SIGNATURE, D);
186*8e3e3a7aSWarner Losh   DumpByte(LUAC_VERSION, D);
187*8e3e3a7aSWarner Losh   DumpByte(LUAC_FORMAT, D);
188*8e3e3a7aSWarner Losh   DumpLiteral(LUAC_DATA, D);
189*8e3e3a7aSWarner Losh   DumpByte(sizeof(int), D);
190*8e3e3a7aSWarner Losh   DumpByte(sizeof(size_t), D);
191*8e3e3a7aSWarner Losh   DumpByte(sizeof(Instruction), D);
192*8e3e3a7aSWarner Losh   DumpByte(sizeof(lua_Integer), D);
193*8e3e3a7aSWarner Losh   DumpByte(sizeof(lua_Number), D);
194*8e3e3a7aSWarner Losh   DumpInteger(LUAC_INT, D);
195*8e3e3a7aSWarner Losh   DumpNumber(LUAC_NUM, D);
196*8e3e3a7aSWarner Losh }
197*8e3e3a7aSWarner Losh 
198*8e3e3a7aSWarner Losh 
199*8e3e3a7aSWarner Losh /*
200*8e3e3a7aSWarner Losh ** dump Lua function as precompiled chunk
201*8e3e3a7aSWarner Losh */
202*8e3e3a7aSWarner Losh int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data,
203*8e3e3a7aSWarner Losh               int strip) {
204*8e3e3a7aSWarner Losh   DumpState D;
205*8e3e3a7aSWarner Losh   D.L = L;
206*8e3e3a7aSWarner Losh   D.writer = w;
207*8e3e3a7aSWarner Losh   D.data = data;
208*8e3e3a7aSWarner Losh   D.strip = strip;
209*8e3e3a7aSWarner Losh   D.status = 0;
210*8e3e3a7aSWarner Losh   DumpHeader(&D);
211*8e3e3a7aSWarner Losh   DumpByte(f->sizeupvalues, &D);
212*8e3e3a7aSWarner Losh   DumpFunction(f, NULL, &D);
213*8e3e3a7aSWarner Losh   return D.status;
214*8e3e3a7aSWarner Losh }
215*8e3e3a7aSWarner Losh 
216