1/*	$NetBSD$	*/
2
3/*
4** Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp
5** save precompiled Lua chunks
6** See Copyright Notice in lua.h
7*/
8
9#include <stddef.h>
10
11#define ldump_c
12#define LUA_CORE
13
14#include "lua.h"
15
16#include "lobject.h"
17#include "lstate.h"
18#include "lundump.h"
19
20typedef struct {
21 lua_State* L;
22 lua_Writer writer;
23 void* data;
24 int strip;
25 int status;
26} DumpState;
27
28#define DumpMem(b,n,size,D)	DumpBlock(b,(n)*(size),D)
29#define DumpVar(x,D)	 	DumpMem(&x,1,sizeof(x),D)
30
31static void DumpBlock(const void* b, size_t size, DumpState* D)
32{
33 if (D->status==0)
34 {
35  lua_unlock(D->L);
36  D->status=(*D->writer)(D->L,b,size,D->data);
37  lua_lock(D->L);
38 }
39}
40
41static void DumpChar(int y, DumpState* D)
42{
43 char x=(char)y;
44 DumpVar(x,D);
45}
46
47static void DumpInt(int x, DumpState* D)
48{
49 DumpVar(x,D);
50}
51
52static void DumpNumber(lua_Number x, DumpState* D)
53{
54 DumpVar(x,D);
55}
56
57static void DumpVector(const void* b, int n, size_t size, DumpState* D)
58{
59 DumpInt(n,D);
60 DumpMem(b,n,size,D);
61}
62
63static void DumpString(const TString* s, DumpState* D)
64{
65 if (s==NULL || getstr(s)==NULL)
66 {
67  size_t size=0;
68  DumpVar(size,D);
69 }
70 else
71 {
72  size_t size=s->tsv.len+1;		/* include trailing '\0' */
73  DumpVar(size,D);
74  DumpBlock(getstr(s),size,D);
75 }
76}
77
78#define DumpCode(f,D)	 DumpVector(f->code,f->sizecode,sizeof(Instruction),D)
79
80static void DumpFunction(const Proto* f, const TString* p, DumpState* D);
81
82static void DumpConstants(const Proto* f, DumpState* D)
83{
84 int i,n=f->sizek;
85 DumpInt(n,D);
86 for (i=0; i<n; i++)
87 {
88  const TValue* o=&f->k[i];
89  DumpChar(ttype(o),D);
90  switch (ttype(o))
91  {
92   case LUA_TNIL:
93	break;
94   case LUA_TBOOLEAN:
95	DumpChar(bvalue(o),D);
96	break;
97   case LUA_TNUMBER:
98	DumpNumber(nvalue(o),D);
99	break;
100   case LUA_TSTRING:
101	DumpString(rawtsvalue(o),D);
102	break;
103   default:
104	lua_assert(0);			/* cannot happen */
105	break;
106  }
107 }
108 n=f->sizep;
109 DumpInt(n,D);
110 for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D);
111}
112
113static void DumpDebug(const Proto* f, DumpState* D)
114{
115 int i,n;
116 n= (D->strip) ? 0 : f->sizelineinfo;
117 DumpVector(f->lineinfo,n,sizeof(int),D);
118 n= (D->strip) ? 0 : f->sizelocvars;
119 DumpInt(n,D);
120 for (i=0; i<n; i++)
121 {
122  DumpString(f->locvars[i].varname,D);
123  DumpInt(f->locvars[i].startpc,D);
124  DumpInt(f->locvars[i].endpc,D);
125 }
126 n= (D->strip) ? 0 : f->sizeupvalues;
127 DumpInt(n,D);
128 for (i=0; i<n; i++) DumpString(f->upvalues[i],D);
129}
130
131static void DumpFunction(const Proto* f, const TString* p, DumpState* D)
132{
133 DumpString((f->source==p || D->strip) ? NULL : f->source,D);
134 DumpInt(f->linedefined,D);
135 DumpInt(f->lastlinedefined,D);
136 DumpChar(f->nups,D);
137 DumpChar(f->numparams,D);
138 DumpChar(f->is_vararg,D);
139 DumpChar(f->maxstacksize,D);
140 DumpCode(f,D);
141 DumpConstants(f,D);
142 DumpDebug(f,D);
143}
144
145static void DumpHeader(DumpState* D)
146{
147 char h[LUAC_HEADERSIZE];
148 luaU_header(h);
149 DumpBlock(h,LUAC_HEADERSIZE,D);
150}
151
152/*
153** dump Lua function as precompiled chunk
154*/
155int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)
156{
157 DumpState D;
158 D.L=L;
159 D.writer=w;
160 D.data=data;
161 D.strip=strip;
162 D.status=0;
163 DumpHeader(&D);
164 DumpFunction(f,NULL,&D);
165 return D.status;
166}
167