Initial commit
This commit is contained in:
187
engines/grim/lua/lundump.cpp
Normal file
187
engines/grim/lua/lundump.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
** load bytecodes from files
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#include "engines/grim/lua/lauxlib.h"
|
||||
#include "engines/grim/lua/lfunc.h"
|
||||
#include "engines/grim/lua/lmem.h"
|
||||
#include "engines/grim/lua/lstring.h"
|
||||
#include "engines/grim/lua/lundump.h"
|
||||
|
||||
namespace Grim {
|
||||
|
||||
static float conv_float(const byte *data) {
|
||||
float f;
|
||||
byte *fdata = (byte *)(&f);
|
||||
fdata[0] = data[3];
|
||||
fdata[1] = data[2];
|
||||
fdata[2] = data[1];
|
||||
fdata[3] = data[0];
|
||||
return f;
|
||||
}
|
||||
|
||||
static void unexpectedEOZ(ZIO *Z) {
|
||||
luaL_verror("unexpected end of file in %s", zname(Z));
|
||||
}
|
||||
|
||||
static int32 ezgetc(ZIO *Z) {
|
||||
int32 c = zgetc(Z);
|
||||
if (c == EOZ)
|
||||
unexpectedEOZ(Z);
|
||||
return c;
|
||||
}
|
||||
|
||||
static void ezread(ZIO *Z, void *b, int32 n) {
|
||||
int32 r = zread(Z, b, n);
|
||||
if (r)
|
||||
unexpectedEOZ(Z);
|
||||
}
|
||||
|
||||
static uint16 LoadWord(ZIO *Z) {
|
||||
uint16 hi = ezgetc(Z);
|
||||
uint16 lo = ezgetc(Z);
|
||||
return (hi << 8) | lo;
|
||||
}
|
||||
|
||||
static void *LoadBlock(int size, ZIO *Z) {
|
||||
void *b = luaM_malloc(size);
|
||||
ezread(Z, b, size);
|
||||
return b;
|
||||
}
|
||||
|
||||
static uint32 LoadSize(ZIO *Z) {
|
||||
uint32 hi = LoadWord(Z);
|
||||
uint32 lo = LoadWord(Z);
|
||||
return (hi << 16) | lo;
|
||||
}
|
||||
|
||||
static float LoadFloat(ZIO *Z) {
|
||||
uint32 l = LoadSize(Z);
|
||||
return conv_float((const byte *)&l);
|
||||
}
|
||||
|
||||
static TaggedString *LoadTString(ZIO *Z) {
|
||||
int32 size = LoadWord(Z);
|
||||
int32 i;
|
||||
|
||||
if (size == 0)
|
||||
return nullptr;
|
||||
else {
|
||||
char *s = luaL_openspace(size);
|
||||
ezread(Z, s, size);
|
||||
for (i = 0; i < size; i++)
|
||||
s[i] ^= 0xff;
|
||||
return luaS_new(s);
|
||||
}
|
||||
}
|
||||
|
||||
static void LoadLocals(TProtoFunc *tf, ZIO *Z) {
|
||||
int32 i, n = LoadWord(Z);
|
||||
if (n == 0)
|
||||
return;
|
||||
tf->locvars = luaM_newvector(n + 1, LocVar);
|
||||
for (i = 0; i < n; i++) {
|
||||
tf->locvars[i].line = LoadWord(Z);
|
||||
tf->locvars[i].varname = LoadTString(Z);
|
||||
}
|
||||
tf->locvars[i].line = -1; // flag end of vector
|
||||
tf->locvars[i].varname = nullptr;
|
||||
}
|
||||
|
||||
static void LoadConstants(TProtoFunc *tf, ZIO *Z) {
|
||||
int32 i, n = LoadWord(Z);
|
||||
tf->nconsts = n;
|
||||
if (n == 0)
|
||||
return;
|
||||
tf->consts = luaM_newvector(n, TObject);
|
||||
for (i = 0; i < n; i++) {
|
||||
TObject *o = tf->consts + i;
|
||||
int c = ezgetc(Z);
|
||||
switch (c) {
|
||||
case ID_NUM:
|
||||
ttype(o) = LUA_T_NUMBER;
|
||||
nvalue(o) = LoadFloat(Z);
|
||||
break;
|
||||
case ID_STR:
|
||||
ttype(o) = LUA_T_STRING;
|
||||
tsvalue(o) = LoadTString(Z);
|
||||
break;
|
||||
case ID_FUN:
|
||||
ttype(o) = LUA_T_PROTO;
|
||||
tfvalue(o) = nullptr;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void LoadFunctions(TProtoFunc *tf, ZIO *Z);
|
||||
|
||||
static TProtoFunc *LoadFunction(ZIO *Z) {
|
||||
TProtoFunc *tf = luaF_newproto();
|
||||
tf->lineDefined = LoadWord(Z);
|
||||
tf->fileName = LoadTString(Z);
|
||||
tf->code = (byte *)LoadBlock(LoadSize(Z), Z);
|
||||
LoadConstants(tf, Z);
|
||||
LoadLocals(tf, Z);
|
||||
LoadFunctions(tf, Z);
|
||||
|
||||
return tf;
|
||||
}
|
||||
|
||||
static void LoadFunctions(TProtoFunc *tf, ZIO *Z) {
|
||||
while (ezgetc(Z) == ID_FUNCTION) {
|
||||
int32 i = LoadWord(Z);
|
||||
TProtoFunc *t = LoadFunction(Z);
|
||||
TObject *o = tf->consts + i;
|
||||
tfvalue(o) = t;
|
||||
}
|
||||
}
|
||||
|
||||
static void LoadSignature(ZIO *Z) {
|
||||
const char *s = SIGNATURE;
|
||||
|
||||
while (*s && ezgetc(Z) == *s)
|
||||
++s;
|
||||
if (*s)
|
||||
luaL_verror("bad signature in %s", zname(Z));
|
||||
}
|
||||
|
||||
static void LoadHeader(ZIO *Z) {
|
||||
int32 version, sizeofR;
|
||||
|
||||
LoadSignature(Z);
|
||||
version = ezgetc(Z);
|
||||
if (version > VERSION)
|
||||
luaL_verror("%s too new: version=0x%02x; expected at most 0x%02x", zname(Z), version, VERSION);
|
||||
if (version < VERSION) // check last major change
|
||||
luaL_verror("%s too old: version=0x%02x; expected at least 0x%02x", zname(Z), version, VERSION);
|
||||
sizeofR = ezgetc(Z); // test number representation
|
||||
if (sizeofR != sizeof(float))
|
||||
luaL_verror("number expected float in %s", zname(Z));
|
||||
ezgetc(Z);
|
||||
ezgetc(Z);
|
||||
ezgetc(Z);
|
||||
ezgetc(Z);
|
||||
}
|
||||
|
||||
static TProtoFunc *LoadChunk(ZIO *Z) {
|
||||
LoadHeader(Z);
|
||||
return LoadFunction(Z);
|
||||
}
|
||||
|
||||
/*
|
||||
** load one chunk from a file or buffer
|
||||
** return main if ok and NULL at EOF
|
||||
*/
|
||||
TProtoFunc *luaU_undump1(ZIO *Z) {
|
||||
int32 c = zgetc(Z);
|
||||
if (c == ID_CHUNK)
|
||||
return LoadChunk(Z);
|
||||
else if (c != EOZ)
|
||||
luaL_verror("%s is not a Lua binary file", zname(Z));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // end of namespace Grim
|
||||
Reference in New Issue
Block a user