xref: /freebsd-src/contrib/lua/src/ldump.c (revision a9490b81b032b43cdb3c8c76b4d01bbad9ff82c1)
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