/*
* NAME: dbsaver.c
* DESCRIPTION: routines for saving a MOO db file
*/
# define DEBUG 0
inherit "/std/core";
inherit "/std/data";
# include <objects.h>
# include <moo/data.h>
# include <moo/perms.h>
# include <dgd/limits.h>
# include "dbloader.h"
# include "object.h"
object driver; /* the driver object */
string file; /* name of the output file */
string buffer; /* output buffer */
int vcount; /* verb count */
/*
* NAME: create()
* DESCRIPTION: initialize
*/
static
void create(void)
{
::create();
driver = load_object(DRIVER);
}
private
void flush(void)
{
write_file(file, buffer);
buffer = "";
}
private
void write(string data)
{
if (strlen(buffer) + strlen(data) > MAX_STRING_SIZE)
flush();
buffer += data;
}
private
void write_string(string data)
{
write(data);
write("\n");
}
# define write_num(x) write_string((string) (x))
# define write_objid(x) write_string((string) (x))
private
void write_verbdef(mixed *verb)
{
write_string(verb[VERB_NAMES]);
write_objid(verb[VERB_OWNER]);
write_num(verb[VERB_PERMS]); /* includes VERB_ARGS */
write_num(verb[VERB_PREP] >= 0 ? verb[VERB_PREP] - 1 : verb[VERB_PREP]);
}
private
void write_propdef(string name, mixed *prop)
{
string str;
str = prop[PROP_CNAME];
write_string(str ? str : name);
}
private
void write_var(MOOVAL var)
{
int i, sz, type;
MOOVAL *list, *keys, *values;
string buf;
write_num(type = TYPEOF(var));
switch (type)
{
case T_STW:
break;
case T_STR:
write_string(STRVAL(var));
break;
case T_OBJ:
write_num(OBJVAL(var));
break;
case T_ERR:
write_num(ERRVAL(var));
break;
case T_NUM:
write_num(NUMVAL(var));
break;
case T_LST:
list = LSTVAL(var);
write_num(sz = sizeof(list));
for (i = 0; i < sz; ++i)
write_var(list[i]);
break;
case T_FLT:
write_string(flt2internal(FLTVAL(var)));
break;
case T_TBL:
keys = LSTVAL(TKEYS(TBLVAL(var)));
values = LSTVAL(TVALUES(TBLVAL(var)));
write_num(sz = sizeof(keys));
for (i = 0; i < sz; ++i)
{
write_var(keys[i]);
write_var(values[i]);
}
break;
case T_BUF:
buf = BUFVAL(var);
write_num(sz = strlen(buf));
for (i = 0; i < sz; ++i)
write_num(buf[i]);
break;
default:
error("WRITE_VAR: Unknown type (" + type + ")");
}
}
private
void write_propval(mixed *prop)
{
mixed value;
value = prop[PROP_VALUE];
write_var(STWP(value) ? value : moo_int2ext(value));
write_objid(prop[PROP_OWNER]);
write_num(prop[PROP_PERMS]);
}
private
void write_object(int oid)
{
object ob, parent, location, *children, *contents;
int i, sz, count;
string *propnames;
mixed *verbs, *propvals;
mapping properties;
if (! (ob = MOOOBJ(oid)))
{
write_string("#" + oid + " recycled");
return;
}
write_string("#" + oid);
write_string(ob->get_name());
write_string("");
write_num(ob->get_flags());
write_objid(ob->get_owner());
location = ob->get_location();
write_objid(location ? OBJNUM(location) : -1);
contents = ob->get_contents();
if (! sizeof(contents))
write_objid(-1);
else
write_objid(OBJNUM(contents[0]));
if (location)
{
contents = location->get_contents();
for (i = 0; OBJNUM(contents[i++]) != oid; );
write_objid(i == sizeof(contents) ? -1 : OBJNUM(contents[i]));
}
else
write_objid(-1);
parent = ob->get_parent();
write_objid(parent ? OBJNUM(parent) : -1);
children = ob->get_children();
write_objid(sizeof(children) ? OBJNUM(children[0]) : -1);
if (! parent)
write_objid(-1);
else
{
children = parent->get_children();
for (i = 0; children[i++] != ob; );
write_objid(i == sizeof(children) ? -1 : OBJNUM(children[i]));
}
verbs = ob->get_verb_data();
write_num(sz = sizeof(verbs));
for (i = 0; i < sz; ++i)
write_verbdef(verbs[i]);
properties = ob->get_property_data();
propnames = map_indices(properties);
propvals = map_values(properties);
for (count = 0, i = 0, sz = sizeof(propvals); i < sz; ++i)
if (! INHERITED(propvals[i]))
++count;
write_num(count); /* propdefs */
for (i = 0; i < sz; ++i)
if (! INHERITED(propvals[i]))
write_propdef(propnames[i], propvals[i]);
count = sz;
write_num(count); /* propvals */
while (count > 0)
{
mapping props;
string *names;
mixed *values;
props = ob->get_property_data();
names = map_indices(props);
values = map_values(props);
for (i = 0, sz = sizeof(values); i < sz; ++i)
if (! INHERITED(values[i]))
{
write_propval(properties[names[i]]);
--count;
}
ob = ob->get_parent();
}
}
private
void write_program(string id, object vobj)
{
string *code;
int i, sz;
code = vobj->get_source(1, 0);
write_string(id);
for (i = 0, sz = sizeof(code); i < sz; ++i)
write_string(code[i]);
write_string(".");
}
private
void write_obj_programs(int oid)
{
object ob;
mixed *verbs;
int i, sz;
if (! (ob = MOOOBJ(oid)))
return;
verbs = ob->get_verb_data();
for (i = 0, sz = sizeof(verbs); i < sz; ++i)
{
object vobj;
if (! (vobj = verbs[i][VERB_OBJECT]))
continue;
write_program("#" + (string) oid + ":" + (string) i, vobj);
++vcount;
}
}
/*
* NAME: main()
* DESCRIPTION: write out a MOO db file
*/
void main(string dest)
{
int max_object, oid;
int i, sz;
object *players;
file = dest;
buffer = "";
vcount = 0;
remove_file(file);
driver->log("Writing text dump to " + file);
max_object = global->get_max_object();
players = global->all_players();
sz = sizeof(players);
write_num(max_object + 1);
write_string(" "); /* verb count; fill in later */
write_num(0);
write_num(sz);
for (i = 0; i < sz; ++i)
write_objid(OBJNUM(players[i]));
driver->log("Dumping object definitions...");
for (oid = 0; oid <= max_object; ++oid)
write_object(oid);
driver->log("Dumping verb programs...");
for (oid = 0; oid <= max_object; ++oid)
write_obj_programs(oid);
write_string("0 clocks");
write_string("0 queued tasks");
write_string("0 suspended tasks");
flush();
write_file(file, (string) vcount, strlen((string) (max_object + 1)) + 1);
driver->log("Text dump finished");
}