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