/* * 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"); }