168 lines
5.2 KiB
Text
168 lines
5.2 KiB
Text
$Id$
|
|
|
|
pluto_persist() produces a "hunk" of objects. Here's the file format adhered
|
|
to by the function, and expected by pluto_unpersist().
|
|
|
|
As a developer, I feel that where file format information is given it is of
|
|
utmost importance that that information precisely and accurately reflects the
|
|
actual operation of the application. Therefore, if you find any discrepancy
|
|
between this and actual operation, please lambast me thoroughly over email.
|
|
|
|
Pseudo-C is used to express the file format. Padding is assumed to be
|
|
nonexistent. The keyword "one_of" is used to express a concept similar to
|
|
"union", except that its size is the size of the actual datatype chosen. Thus,
|
|
objects which contain, directly or indirectly, a one_of, may vary in size.
|
|
|
|
|
|
struct Object {
|
|
int firstTime; /* Whether this is the first time the object
|
|
is being referenced */
|
|
one_of {
|
|
RealObject o; /* if firstTime == 1 */
|
|
Reference r; /* if firstTime == 0 */
|
|
};
|
|
};
|
|
|
|
struct Reference {
|
|
int ref; /* The index the object was registered with */
|
|
};
|
|
|
|
struct RealObject {
|
|
int type; /* The type of the object */
|
|
one_of {
|
|
Boolean b; /* If type == LUA_TBOOLEAN */
|
|
LightUserData l; /* If type == LUA_TLIGHTUSERDATA */
|
|
Number n; /* If type == LUA_TNUMBER */
|
|
String s; /* If type == LUA_TSTRING */
|
|
Table t; /* If type == LUA_TTABLE */
|
|
Function f; /* If type == LUA_TFUNCTION */
|
|
Userdata u; /* If type == LUA_TUSERDATA */
|
|
Thread th; /* If type == LUA_TTHREAD */
|
|
Proto p; /* If type == LUA_TPROTO (from lobject.h) */
|
|
Upval uv; /* If type == LUA_TUPVAL (from lobject.h) */
|
|
}; /* The actual object */
|
|
};
|
|
|
|
struct Boolean {
|
|
int32 bvalue; /* 0 for false, 1 for true */
|
|
};
|
|
|
|
struct LightUserData {
|
|
void* luvalue; /* The actual, literal pointer */
|
|
};
|
|
|
|
struct Number {
|
|
lua_Number nvalue; /* The actual number */
|
|
};
|
|
|
|
struct String {
|
|
int length; /* The length of the string */
|
|
char str[length]; /* The actual string (not null terminated) */
|
|
};
|
|
|
|
struct Table {
|
|
int isspecial; /* 1 if SP is used; 0 otherwise */
|
|
one_of {
|
|
Closure c; /* if isspecial == 1; closure to refill the table */
|
|
LiteralTable t; /* if isspecial == 0; literal table info */
|
|
};
|
|
};
|
|
|
|
struct LiteralTable {
|
|
Object metatable; /* nil for default metatable */
|
|
Pair p[]; /* key/value pairs */
|
|
Object nil = nil; /* Nil reference to terminate */
|
|
};
|
|
|
|
struct Pair {
|
|
Object key;
|
|
Object value;
|
|
};
|
|
|
|
struct Function { /* Actually a closure */
|
|
lu_byte nups; /* Number of upvalues the function uses */
|
|
Object proto; /* The proto this function uses */
|
|
Object upvals[nups]; /* All upvalues */
|
|
Object fenv; /* The FEnv (nil for the global table)
|
|
};
|
|
|
|
struct Upval {
|
|
Object obj; /* The object this upval refers to */
|
|
}
|
|
|
|
struct Userdata {
|
|
int isSpecial; /* 1 for special persistence, 0 for literal
|
|
one_of {
|
|
LiteralUserdata lu; /* if is_special is 0 */
|
|
SpecialUserdata su; /* if is_special is 1 */
|
|
};
|
|
};
|
|
|
|
struct LiteralUserdata {
|
|
Object metatable; /* The metatable (nil for default) */
|
|
int length; /* Size of the data */
|
|
char data[length]; /* The actual data */
|
|
};
|
|
|
|
struct SpecialUserdata {
|
|
int length; /* The size of the data */
|
|
Object func; /* The closure used to fill the userdata */
|
|
};
|
|
|
|
struct Thread {
|
|
int stacksize; /* The size of the stack filled with objects,
|
|
* including the "nil" that is hidden below
|
|
* the bottom of the stack visible to C */
|
|
Object stack[stacksize];/* Indices of all stack values, bottom up */
|
|
int callinfosize; /* Number of elements in the CallInfo stack */
|
|
CallInfo callinfostack[callinfosize]; /* The CallInfo stack */
|
|
int base; /* base = L->base - L->stack; */
|
|
int top; /* top = L->top - L->stack; */
|
|
OpenUpval openupvals[]; /* Upvalues to open */
|
|
Object nil = nil; /* To terminate the open upvalues list */
|
|
};
|
|
|
|
struct OpenUpval {
|
|
Object upval; /* The upvalue */
|
|
int stackpos; /* The stack position to "reopen" it to */
|
|
|
|
};
|
|
|
|
struct CallInfo {
|
|
int base; /* base = ci->base - L->stack; */
|
|
int top; /* top = ci->top - L->stack; */
|
|
int pc; /* pc = ci->pc - proto->code; */
|
|
int state; /* flags used by the CallInfo */
|
|
};
|
|
|
|
struct Proto {
|
|
int sizek; /* Number of constants referenced */
|
|
Object k[sizek]; /* Constants referenced */
|
|
int sizep; /* Number of inner Protos referenced */
|
|
Object p[sizep]; /* Inner Protos referenced */
|
|
int sizecode; /* Number of instructions in code */
|
|
Instruction code[sizecode]; /* The proto's code */
|
|
ProtoDebug debuginfo; /* Debug information for the proto */
|
|
lu_byte nups; /* Number of upvalues used */
|
|
lu_byte numparams; /* Number of parameters taken */
|
|
lu_byte is_vararg; /* 1 if function accepts varargs, 0 otherwise */
|
|
lu_byte maxstacksize; /* Size of stack reserved for the function */
|
|
};
|
|
|
|
struct ProtoDebug {
|
|
int sizeupvals; /* Number of upvalue names */
|
|
Object upvals; /* Upvalue names */
|
|
int sizelocvars; /* Number of local variable names */
|
|
LocVar[sizelocvars]; /* Local variable names */
|
|
Object source; /* The source code */
|
|
int sizelineinfo; /* Number of opcode-line mappings */
|
|
int lineinfo[sizelineinfo]; /* opcode-line mappings */
|
|
int linedefined; /* Start of line range */
|
|
int lastlinedefined; /* End of line range */
|
|
};
|
|
|
|
struct LocVar {
|
|
Object name; /* Name of the local variable */
|
|
int startpc; /* Point where variable is active */
|
|
int endpc; /* Point where variable is dead */
|
|
};
|