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