mudgangster

Tiny, scriptable MUD client
Log | Files | Refs | README

ldump.cc (4478B)


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