18e3e3a7aSWarner Losh /*
20495ed39SKyle Evans ** $Id: ldump.c $
38e3e3a7aSWarner Losh ** save precompiled Lua chunks
48e3e3a7aSWarner Losh ** See Copyright Notice in lua.h
58e3e3a7aSWarner Losh */
68e3e3a7aSWarner Losh
78e3e3a7aSWarner Losh #define ldump_c
88e3e3a7aSWarner Losh #define LUA_CORE
98e3e3a7aSWarner Losh
108e3e3a7aSWarner Losh #include "lprefix.h"
118e3e3a7aSWarner Losh
128e3e3a7aSWarner Losh
13*a9490b81SWarner Losh #include <limits.h>
148e3e3a7aSWarner Losh #include <stddef.h>
158e3e3a7aSWarner Losh
168e3e3a7aSWarner Losh #include "lua.h"
178e3e3a7aSWarner Losh
188e3e3a7aSWarner Losh #include "lobject.h"
198e3e3a7aSWarner Losh #include "lstate.h"
208e3e3a7aSWarner Losh #include "lundump.h"
218e3e3a7aSWarner Losh
228e3e3a7aSWarner Losh
238e3e3a7aSWarner Losh typedef struct {
248e3e3a7aSWarner Losh lua_State *L;
258e3e3a7aSWarner Losh lua_Writer writer;
268e3e3a7aSWarner Losh void *data;
278e3e3a7aSWarner Losh int strip;
288e3e3a7aSWarner Losh int status;
298e3e3a7aSWarner Losh } DumpState;
308e3e3a7aSWarner Losh
318e3e3a7aSWarner Losh
328e3e3a7aSWarner Losh /*
330495ed39SKyle Evans ** All high-level dumps go through dumpVector; you can change it to
348e3e3a7aSWarner Losh ** change the endianness of the result
358e3e3a7aSWarner Losh */
360495ed39SKyle Evans #define dumpVector(D,v,n) dumpBlock(D,v,(n)*sizeof((v)[0]))
378e3e3a7aSWarner Losh
380495ed39SKyle Evans #define dumpLiteral(D, s) dumpBlock(D,s,sizeof(s) - sizeof(char))
398e3e3a7aSWarner Losh
408e3e3a7aSWarner Losh
dumpBlock(DumpState * D,const void * b,size_t size)410495ed39SKyle Evans static void dumpBlock (DumpState *D, const void *b, size_t size) {
428e3e3a7aSWarner Losh if (D->status == 0 && size > 0) {
438e3e3a7aSWarner Losh lua_unlock(D->L);
448e3e3a7aSWarner Losh D->status = (*D->writer)(D->L, b, size, D->data);
458e3e3a7aSWarner Losh lua_lock(D->L);
468e3e3a7aSWarner Losh }
478e3e3a7aSWarner Losh }
488e3e3a7aSWarner Losh
498e3e3a7aSWarner Losh
500495ed39SKyle Evans #define dumpVar(D,x) dumpVector(D,&x,1)
518e3e3a7aSWarner Losh
528e3e3a7aSWarner Losh
dumpByte(DumpState * D,int y)530495ed39SKyle Evans static void dumpByte (DumpState *D, int y) {
548e3e3a7aSWarner Losh lu_byte x = (lu_byte)y;
550495ed39SKyle Evans dumpVar(D, x);
568e3e3a7aSWarner Losh }
578e3e3a7aSWarner Losh
588e3e3a7aSWarner Losh
59*a9490b81SWarner Losh /*
60*a9490b81SWarner Losh ** 'dumpSize' buffer size: each byte can store up to 7 bits. (The "+6"
61*a9490b81SWarner Losh ** rounds up the division.)
62*a9490b81SWarner Losh */
63*a9490b81SWarner Losh #define DIBS ((sizeof(size_t) * CHAR_BIT + 6) / 7)
640495ed39SKyle Evans
dumpSize(DumpState * D,size_t x)650495ed39SKyle Evans static void dumpSize (DumpState *D, size_t x) {
660495ed39SKyle Evans lu_byte buff[DIBS];
670495ed39SKyle Evans int n = 0;
680495ed39SKyle Evans do {
690495ed39SKyle Evans buff[DIBS - (++n)] = x & 0x7f; /* fill buffer in reverse order */
700495ed39SKyle Evans x >>= 7;
710495ed39SKyle Evans } while (x != 0);
720495ed39SKyle Evans buff[DIBS - 1] |= 0x80; /* mark last byte */
730495ed39SKyle Evans dumpVector(D, buff + DIBS - n, n);
748e3e3a7aSWarner Losh }
758e3e3a7aSWarner Losh
768e3e3a7aSWarner Losh
dumpInt(DumpState * D,int x)770495ed39SKyle Evans static void dumpInt (DumpState *D, int x) {
780495ed39SKyle Evans dumpSize(D, x);
798e3e3a7aSWarner Losh }
808e3e3a7aSWarner Losh
818e3e3a7aSWarner Losh
dumpNumber(DumpState * D,lua_Number x)820495ed39SKyle Evans static void dumpNumber (DumpState *D, lua_Number x) {
830495ed39SKyle Evans dumpVar(D, x);
848e3e3a7aSWarner Losh }
858e3e3a7aSWarner Losh
868e3e3a7aSWarner Losh
dumpInteger(DumpState * D,lua_Integer x)870495ed39SKyle Evans static void dumpInteger (DumpState *D, lua_Integer x) {
880495ed39SKyle Evans dumpVar(D, x);
890495ed39SKyle Evans }
900495ed39SKyle Evans
910495ed39SKyle Evans
dumpString(DumpState * D,const TString * s)920495ed39SKyle Evans static void dumpString (DumpState *D, const TString *s) {
938e3e3a7aSWarner Losh if (s == NULL)
940495ed39SKyle Evans dumpSize(D, 0);
958e3e3a7aSWarner Losh else {
960495ed39SKyle Evans size_t size = tsslen(s);
978e3e3a7aSWarner Losh const char *str = getstr(s);
980495ed39SKyle Evans dumpSize(D, size + 1);
990495ed39SKyle Evans dumpVector(D, str, size);
1008e3e3a7aSWarner Losh }
1018e3e3a7aSWarner Losh }
1028e3e3a7aSWarner Losh
1038e3e3a7aSWarner Losh
dumpCode(DumpState * D,const Proto * f)1040495ed39SKyle Evans static void dumpCode (DumpState *D, const Proto *f) {
1050495ed39SKyle Evans dumpInt(D, f->sizecode);
1060495ed39SKyle Evans dumpVector(D, f->code, f->sizecode);
1078e3e3a7aSWarner Losh }
1088e3e3a7aSWarner Losh
1098e3e3a7aSWarner Losh
1100495ed39SKyle Evans static void dumpFunction(DumpState *D, const Proto *f, TString *psource);
1118e3e3a7aSWarner Losh
dumpConstants(DumpState * D,const Proto * f)1120495ed39SKyle Evans static void dumpConstants (DumpState *D, const Proto *f) {
1138e3e3a7aSWarner Losh int i;
1148e3e3a7aSWarner Losh int n = f->sizek;
1150495ed39SKyle Evans dumpInt(D, n);
1168e3e3a7aSWarner Losh for (i = 0; i < n; i++) {
1178e3e3a7aSWarner Losh const TValue *o = &f->k[i];
1180495ed39SKyle Evans int tt = ttypetag(o);
1190495ed39SKyle Evans dumpByte(D, tt);
1200495ed39SKyle Evans switch (tt) {
1210495ed39SKyle Evans case LUA_VNUMFLT:
1220495ed39SKyle Evans dumpNumber(D, fltvalue(o));
1238e3e3a7aSWarner Losh break;
1240495ed39SKyle Evans case LUA_VNUMINT:
1250495ed39SKyle Evans dumpInteger(D, ivalue(o));
1268e3e3a7aSWarner Losh break;
1270495ed39SKyle Evans case LUA_VSHRSTR:
1280495ed39SKyle Evans case LUA_VLNGSTR:
1290495ed39SKyle Evans dumpString(D, tsvalue(o));
1308e3e3a7aSWarner Losh break;
1318e3e3a7aSWarner Losh default:
1320495ed39SKyle Evans lua_assert(tt == LUA_VNIL || tt == LUA_VFALSE || tt == LUA_VTRUE);
1338e3e3a7aSWarner Losh }
1348e3e3a7aSWarner Losh }
1358e3e3a7aSWarner Losh }
1368e3e3a7aSWarner Losh
1378e3e3a7aSWarner Losh
dumpProtos(DumpState * D,const Proto * f)1380495ed39SKyle Evans static void dumpProtos (DumpState *D, const Proto *f) {
1398e3e3a7aSWarner Losh int i;
1408e3e3a7aSWarner Losh int n = f->sizep;
1410495ed39SKyle Evans dumpInt(D, n);
1428e3e3a7aSWarner Losh for (i = 0; i < n; i++)
1430495ed39SKyle Evans dumpFunction(D, f->p[i], f->source);
1448e3e3a7aSWarner Losh }
1458e3e3a7aSWarner Losh
1468e3e3a7aSWarner Losh
dumpUpvalues(DumpState * D,const Proto * f)1470495ed39SKyle Evans static void dumpUpvalues (DumpState *D, const Proto *f) {
1488e3e3a7aSWarner Losh int i, n = f->sizeupvalues;
1490495ed39SKyle Evans dumpInt(D, n);
1508e3e3a7aSWarner Losh for (i = 0; i < n; i++) {
1510495ed39SKyle Evans dumpByte(D, f->upvalues[i].instack);
1520495ed39SKyle Evans dumpByte(D, f->upvalues[i].idx);
1530495ed39SKyle Evans dumpByte(D, f->upvalues[i].kind);
1548e3e3a7aSWarner Losh }
1558e3e3a7aSWarner Losh }
1568e3e3a7aSWarner Losh
1578e3e3a7aSWarner Losh
dumpDebug(DumpState * D,const Proto * f)1580495ed39SKyle Evans static void dumpDebug (DumpState *D, const Proto *f) {
1598e3e3a7aSWarner Losh int i, n;
1608e3e3a7aSWarner Losh n = (D->strip) ? 0 : f->sizelineinfo;
1610495ed39SKyle Evans dumpInt(D, n);
1620495ed39SKyle Evans dumpVector(D, f->lineinfo, n);
1630495ed39SKyle Evans n = (D->strip) ? 0 : f->sizeabslineinfo;
1640495ed39SKyle Evans dumpInt(D, n);
1658e3e3a7aSWarner Losh for (i = 0; i < n; i++) {
1660495ed39SKyle Evans dumpInt(D, f->abslineinfo[i].pc);
1670495ed39SKyle Evans dumpInt(D, f->abslineinfo[i].line);
1680495ed39SKyle Evans }
1690495ed39SKyle Evans n = (D->strip) ? 0 : f->sizelocvars;
1700495ed39SKyle Evans dumpInt(D, n);
1710495ed39SKyle Evans for (i = 0; i < n; i++) {
1720495ed39SKyle Evans dumpString(D, f->locvars[i].varname);
1730495ed39SKyle Evans dumpInt(D, f->locvars[i].startpc);
1740495ed39SKyle Evans dumpInt(D, f->locvars[i].endpc);
1758e3e3a7aSWarner Losh }
1768e3e3a7aSWarner Losh n = (D->strip) ? 0 : f->sizeupvalues;
1770495ed39SKyle Evans dumpInt(D, n);
1788e3e3a7aSWarner Losh for (i = 0; i < n; i++)
1790495ed39SKyle Evans dumpString(D, f->upvalues[i].name);
1808e3e3a7aSWarner Losh }
1818e3e3a7aSWarner Losh
1828e3e3a7aSWarner Losh
dumpFunction(DumpState * D,const Proto * f,TString * psource)1830495ed39SKyle Evans static void dumpFunction (DumpState *D, const Proto *f, TString *psource) {
1848e3e3a7aSWarner Losh if (D->strip || f->source == psource)
1850495ed39SKyle Evans dumpString(D, NULL); /* no debug info or same source as its parent */
1868e3e3a7aSWarner Losh else
1870495ed39SKyle Evans dumpString(D, f->source);
1880495ed39SKyle Evans dumpInt(D, f->linedefined);
1890495ed39SKyle Evans dumpInt(D, f->lastlinedefined);
1900495ed39SKyle Evans dumpByte(D, f->numparams);
1910495ed39SKyle Evans dumpByte(D, f->is_vararg);
1920495ed39SKyle Evans dumpByte(D, f->maxstacksize);
1930495ed39SKyle Evans dumpCode(D, f);
1940495ed39SKyle Evans dumpConstants(D, f);
1950495ed39SKyle Evans dumpUpvalues(D, f);
1960495ed39SKyle Evans dumpProtos(D, f);
1970495ed39SKyle Evans dumpDebug(D, f);
1988e3e3a7aSWarner Losh }
1998e3e3a7aSWarner Losh
2008e3e3a7aSWarner Losh
dumpHeader(DumpState * D)2010495ed39SKyle Evans static void dumpHeader (DumpState *D) {
2020495ed39SKyle Evans dumpLiteral(D, LUA_SIGNATURE);
2030495ed39SKyle Evans dumpByte(D, LUAC_VERSION);
2040495ed39SKyle Evans dumpByte(D, LUAC_FORMAT);
2050495ed39SKyle Evans dumpLiteral(D, LUAC_DATA);
2060495ed39SKyle Evans dumpByte(D, sizeof(Instruction));
2070495ed39SKyle Evans dumpByte(D, sizeof(lua_Integer));
2080495ed39SKyle Evans dumpByte(D, sizeof(lua_Number));
2090495ed39SKyle Evans dumpInteger(D, LUAC_INT);
2100495ed39SKyle Evans dumpNumber(D, LUAC_NUM);
2118e3e3a7aSWarner Losh }
2128e3e3a7aSWarner Losh
2138e3e3a7aSWarner Losh
2148e3e3a7aSWarner Losh /*
2158e3e3a7aSWarner Losh ** dump Lua function as precompiled chunk
2168e3e3a7aSWarner Losh */
luaU_dump(lua_State * L,const Proto * f,lua_Writer w,void * data,int strip)2178e3e3a7aSWarner Losh int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data,
2188e3e3a7aSWarner Losh int strip) {
2198e3e3a7aSWarner Losh DumpState D;
2208e3e3a7aSWarner Losh D.L = L;
2218e3e3a7aSWarner Losh D.writer = w;
2228e3e3a7aSWarner Losh D.data = data;
2238e3e3a7aSWarner Losh D.strip = strip;
2248e3e3a7aSWarner Losh D.status = 0;
2250495ed39SKyle Evans dumpHeader(&D);
2260495ed39SKyle Evans dumpByte(&D, f->sizeupvalues);
2270495ed39SKyle Evans dumpFunction(&D, f, NULL);
2288e3e3a7aSWarner Losh return D.status;
2298e3e3a7aSWarner Losh }
2308e3e3a7aSWarner Losh
231