mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-12-04 22:46:31 +00:00
Compare commits
4 Commits
c945c56482
...
93a09698a9
Author | SHA1 | Date | |
---|---|---|---|
93a09698a9 | |||
be49ec5af5 | |||
4fe437ea4e | |||
e854c5dbb3 |
109
src/cdump.c
109
src/cdump.c
@ -4,6 +4,7 @@
|
|||||||
#include "cmem.h"
|
#include "cmem.h"
|
||||||
#include "cobj.h"
|
#include "cobj.h"
|
||||||
#include "cvalue.h"
|
#include "cvalue.h"
|
||||||
|
#include "cvm.h"
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -13,7 +14,12 @@ typedef struct
|
|||||||
int writerStatus;
|
int writerStatus;
|
||||||
} DumpState;
|
} DumpState;
|
||||||
|
|
||||||
static void writeCValue(DumpState *dstate, CValue val);
|
static bool writeCValue(DumpState *dstate, CValue val);
|
||||||
|
|
||||||
|
#define check(e) \
|
||||||
|
if (!e) { \
|
||||||
|
return false; \
|
||||||
|
}
|
||||||
|
|
||||||
static void initDumpState(CState *state, DumpState *dstate, cosmo_Writer writer,
|
static void initDumpState(CState *state, DumpState *dstate, cosmo_Writer writer,
|
||||||
const void *userData)
|
const void *userData)
|
||||||
@ -24,82 +30,92 @@ static void initDumpState(CState *state, DumpState *dstate, cosmo_Writer writer,
|
|||||||
dstate->writerStatus = 0;
|
dstate->writerStatus = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeBlock(DumpState *dstate, const void *data, size_t size)
|
static bool writeBlock(DumpState *dstate, const void *data, size_t size)
|
||||||
{
|
{
|
||||||
if (dstate->writerStatus == 0) {
|
if (dstate->writerStatus == 0) {
|
||||||
dstate->writerStatus = dstate->writer(dstate->state, data, size, dstate->userData);
|
dstate->writerStatus = dstate->writer(dstate->state, data, size, dstate->userData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return dstate->writerStatus == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeu8(DumpState *dstate, uint8_t d)
|
static bool writeu8(DumpState *dstate, uint8_t d)
|
||||||
{
|
{
|
||||||
writeBlock(dstate, &d, sizeof(uint8_t));
|
return writeBlock(dstate, &d, sizeof(uint8_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeu32(DumpState *dstate, uint32_t d)
|
static bool writeu32(DumpState *dstate, uint32_t d)
|
||||||
{
|
{
|
||||||
writeBlock(dstate, &d, sizeof(uint32_t));
|
return writeBlock(dstate, &d, sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeSize(DumpState *dstate, size_t d)
|
static bool writeSize(DumpState *dstate, size_t d)
|
||||||
{
|
{
|
||||||
writeBlock(dstate, &d, sizeof(size_t));
|
return writeBlock(dstate, &d, sizeof(size_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeVector(DumpState *dstate, const void *data, size_t size, size_t count)
|
static bool writeVector(DumpState *dstate, const void *data, size_t size, size_t count)
|
||||||
{
|
{
|
||||||
writeSize(dstate, count);
|
check(writeSize(dstate, count));
|
||||||
writeBlock(dstate, data, size * count);
|
check(writeBlock(dstate, data, size * count));
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeHeader(DumpState *dstate)
|
static bool writeHeader(DumpState *dstate)
|
||||||
{
|
{
|
||||||
writeBlock(dstate, COSMO_MAGIC, COSMO_MAGIC_LEN);
|
check(writeBlock(dstate, COSMO_MAGIC, COSMO_MAGIC_LEN));
|
||||||
|
|
||||||
/* after the magic, we write some platform information */
|
/* after the magic, we write some platform information */
|
||||||
writeu8(dstate, cosmoD_isBigEndian());
|
check(writeu8(dstate, cosmoD_isBigEndian()));
|
||||||
writeu8(dstate, sizeof(cosmo_Number));
|
check(writeu8(dstate, sizeof(cosmo_Number)));
|
||||||
writeu8(dstate, sizeof(size_t));
|
check(writeu8(dstate, sizeof(size_t)));
|
||||||
writeu8(dstate, sizeof(int));
|
check(writeu8(dstate, sizeof(int)));
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeCObjString(DumpState *dstate, CObjString *obj)
|
static bool writeCObjString(DumpState *dstate, CObjString *obj)
|
||||||
{
|
{
|
||||||
if (obj == NULL) { /* this is in case cobjfunction's name or module strings are null */
|
if (obj == NULL) { /* this is in case cobjfunction's name or module strings are null */
|
||||||
writeu32(dstate, 0);
|
check(writeu32(dstate, 0));
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write string length */
|
/* write string length */
|
||||||
writeu32(dstate, obj->length);
|
check(writeu32(dstate, obj->length));
|
||||||
|
|
||||||
/* write string data */
|
/* write string data */
|
||||||
writeBlock(dstate, obj->str, obj->length);
|
check(writeBlock(dstate, obj->str, obj->length));
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeCObjFunction(DumpState *dstate, CObjFunction *obj)
|
static bool writeCObjFunction(DumpState *dstate, CObjFunction *obj)
|
||||||
{
|
{
|
||||||
writeCObjString(dstate, obj->name);
|
check(writeCObjString(dstate, obj->name));
|
||||||
writeCObjString(dstate, obj->module);
|
check(writeCObjString(dstate, obj->module));
|
||||||
|
|
||||||
writeu32(dstate, obj->args);
|
check(writeu32(dstate, obj->args));
|
||||||
writeu32(dstate, obj->upvals);
|
check(writeu32(dstate, obj->upvals));
|
||||||
writeu8(dstate, obj->variadic);
|
check(writeu8(dstate, obj->variadic));
|
||||||
|
|
||||||
/* write chunk info */
|
/* write chunk info */
|
||||||
writeVector(dstate, obj->chunk.buf, sizeof(uint8_t), obj->chunk.count);
|
check(writeVector(dstate, obj->chunk.buf, sizeof(uint8_t), obj->chunk.count));
|
||||||
|
|
||||||
/* write line info */
|
/* write line info */
|
||||||
writeVector(dstate, obj->chunk.lineInfo, sizeof(int), obj->chunk.count);
|
check(writeVector(dstate, obj->chunk.lineInfo, sizeof(int), obj->chunk.count));
|
||||||
|
|
||||||
/* write constants */
|
/* write constants */
|
||||||
writeSize(dstate, obj->chunk.constants.count);
|
check(writeSize(dstate, obj->chunk.constants.count));
|
||||||
for (int i = 0; i < obj->chunk.constants.count; i++) {
|
for (int i = 0; i < obj->chunk.constants.count; i++) {
|
||||||
writeCValue(dstate, obj->chunk.constants.values[i]);
|
check(writeCValue(dstate, obj->chunk.constants.values[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeCObj(DumpState *dstate, CObj *obj)
|
static bool writeCObj(DumpState *dstate, CObj *obj)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
we can kind of cheat here since our parser only emits a few very limited CObjs...
|
we can kind of cheat here since our parser only emits a few very limited CObjs...
|
||||||
@ -117,24 +133,27 @@ static void writeCObj(DumpState *dstate, CObj *obj)
|
|||||||
/* write object payload/body */
|
/* write object payload/body */
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case COBJ_STRING:
|
case COBJ_STRING:
|
||||||
writeCObjString(dstate, (CObjString *)obj);
|
check(writeCObjString(dstate, (CObjString *)obj));
|
||||||
break;
|
break;
|
||||||
case COBJ_FUNCTION:
|
case COBJ_FUNCTION:
|
||||||
writeCObjFunction(dstate, (CObjFunction *)obj);
|
check(writeCObjFunction(dstate, (CObjFunction *)obj));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
cosmoV_error(dstate->state, "invalid cobj type: %d", t);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define WRITE_VAR(dstate, type, expression) \
|
#define WRITE_VAR(dstate, type, expression) \
|
||||||
{ \
|
{ \
|
||||||
type _tmp = expression; \
|
type _tmp = expression; \
|
||||||
writeBlock(dstate, &_tmp, sizeof(_tmp)); \
|
check(writeBlock(dstate, &_tmp, sizeof(_tmp))); \
|
||||||
break; \
|
break; \
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeCValue(DumpState *dstate, CValue val)
|
static bool writeCValue(DumpState *dstate, CValue val)
|
||||||
{
|
{
|
||||||
CosmoType t = GET_TYPE(val);
|
CosmoType t = GET_TYPE(val);
|
||||||
|
|
||||||
@ -148,12 +167,16 @@ static void writeCValue(DumpState *dstate, CValue val)
|
|||||||
case COSMO_TBOOLEAN:
|
case COSMO_TBOOLEAN:
|
||||||
WRITE_VAR(dstate, bool, cosmoV_readBoolean(val))
|
WRITE_VAR(dstate, bool, cosmoV_readBoolean(val))
|
||||||
case COSMO_TREF:
|
case COSMO_TREF:
|
||||||
writeCObj(dstate, cosmoV_readRef(val));
|
check(writeCObj(dstate, cosmoV_readRef(val)));
|
||||||
|
break;
|
||||||
|
case COSMO_TNIL: /* no body */
|
||||||
break;
|
break;
|
||||||
case COSMO_TNIL: /* fallthrough, no body */
|
|
||||||
default:
|
default:
|
||||||
break;
|
cosmoV_error(dstate->state, "invalid value type: %d", t);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef WRITE_VAR
|
#undef WRITE_VAR
|
||||||
@ -174,8 +197,8 @@ int cosmoD_dump(CState *state, CObjFunction *func, cosmo_Writer writer, const vo
|
|||||||
DumpState dstate;
|
DumpState dstate;
|
||||||
initDumpState(state, &dstate, writer, userData);
|
initDumpState(state, &dstate, writer, userData);
|
||||||
|
|
||||||
writeHeader(&dstate);
|
check(writeHeader(&dstate));
|
||||||
writeCObjFunction(&dstate, func);
|
check(writeCObjFunction(&dstate, func));
|
||||||
|
|
||||||
return dstate.writerStatus;
|
return dstate.writerStatus;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@ static bool readCValue(UndumpState *udstate, CValue *val);
|
|||||||
|
|
||||||
#define check(e) \
|
#define check(e) \
|
||||||
if (!e) { \
|
if (!e) { \
|
||||||
printf("FAILED %d\n", __LINE__); \
|
|
||||||
return false; \
|
return false; \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,6 +32,7 @@ static void initUndumpState(CState *state, UndumpState *udstate, cosmo_Reader re
|
|||||||
static bool readBlock(UndumpState *udstate, void *data, size_t size)
|
static bool readBlock(UndumpState *udstate, void *data, size_t size)
|
||||||
{
|
{
|
||||||
if (udstate->readerStatus == 0) {
|
if (udstate->readerStatus == 0) {
|
||||||
|
/* if reader returns 1, we expect an error was thrown */
|
||||||
udstate->readerStatus = udstate->reader(udstate->state, data, size, udstate->userData);
|
udstate->readerStatus = udstate->reader(udstate->state, data, size, udstate->userData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ static bool checkHeader(UndumpState *udstate)
|
|||||||
uint8_t tmp;
|
uint8_t tmp;
|
||||||
|
|
||||||
/* check header */
|
/* check header */
|
||||||
readBlock(udstate, magic, COSMO_MAGIC_LEN);
|
check(readBlock(udstate, magic, COSMO_MAGIC_LEN));
|
||||||
if (memcmp(magic, COSMO_MAGIC, COSMO_MAGIC_LEN) != 0) {
|
if (memcmp(magic, COSMO_MAGIC, COSMO_MAGIC_LEN) != 0) {
|
||||||
cosmoV_error(udstate->state, "bad header!");
|
cosmoV_error(udstate->state, "bad header!");
|
||||||
return false;
|
return false;
|
||||||
@ -117,6 +117,9 @@ static bool readCObjFunction(UndumpState *udstate, CObjFunction **func)
|
|||||||
|
|
||||||
*func = cosmoO_newFunction(udstate->state);
|
*func = cosmoO_newFunction(udstate->state);
|
||||||
|
|
||||||
|
/* make sure our GC can see that we're currently using this function (and the values it uses) */
|
||||||
|
cosmoV_pushRef(udstate->state, (CObj *)*func);
|
||||||
|
|
||||||
check(readCObjString(udstate, &(*func)->name));
|
check(readCObjString(udstate, &(*func)->name));
|
||||||
check(readCObjString(udstate, &(*func)->module));
|
check(readCObjString(udstate, &(*func)->module));
|
||||||
|
|
||||||
@ -137,6 +140,8 @@ static bool readCObjFunction(UndumpState *udstate, CObjFunction **func)
|
|||||||
addConstant(udstate->state, &(*func)->chunk, val);
|
addConstant(udstate->state, &(*func)->chunk, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* pop function off stack */
|
||||||
|
cosmoV_pop(udstate->state);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,10 +173,10 @@ static bool readCObj(UndumpState *udstate, CObj **obj)
|
|||||||
|
|
||||||
static bool readCValue(UndumpState *udstate, CValue *val)
|
static bool readCValue(UndumpState *udstate, CValue *val)
|
||||||
{
|
{
|
||||||
uint8_t type;
|
uint8_t t;
|
||||||
check(readu8(udstate, &type));
|
check(readu8(udstate, &t));
|
||||||
|
|
||||||
switch (type) {
|
switch (t) {
|
||||||
case COSMO_TNUMBER:
|
case COSMO_TNUMBER:
|
||||||
READ_VAR(udstate, val, cosmo_Number, cosmoV_newNumber)
|
READ_VAR(udstate, val, cosmo_Number, cosmoV_newNumber)
|
||||||
case COSMO_TBOOLEAN:
|
case COSMO_TBOOLEAN:
|
||||||
@ -186,24 +191,26 @@ static bool readCValue(UndumpState *udstate, CValue *val)
|
|||||||
*val = cosmoV_newNil();
|
*val = cosmoV_newNil();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
cosmoV_error(udstate->state, "invalid value type: %d", t);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef READ_VAR
|
||||||
|
#undef check
|
||||||
|
|
||||||
int cosmoD_undump(CState *state, cosmo_Reader reader, const void *userData, CObjFunction **func)
|
int cosmoD_undump(CState *state, cosmo_Reader reader, const void *userData, CObjFunction **func)
|
||||||
{
|
{
|
||||||
UndumpState udstate;
|
UndumpState udstate;
|
||||||
initUndumpState(state, &udstate, reader, userData);
|
initUndumpState(state, &udstate, reader, userData);
|
||||||
|
|
||||||
if (!checkHeader(&udstate)) {
|
if (!checkHeader(&udstate)) {
|
||||||
cosmoV_pushNil(state);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!readCObjFunction(&udstate, func)) {
|
if (!readCObjFunction(&udstate, func)) {
|
||||||
cosmoV_pushNil(state);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user