lpmoo-1.2/etc/
lpmoo-1.2/mudlib/
lpmoo-1.2/mudlib/etc/
lpmoo-1.2/mudlib/include/
lpmoo-1.2/mudlib/include/moo/
lpmoo-1.2/mudlib/lpc/
lpmoo-1.2/mudlib/std/auto/
lpmoo-1.2/mudlib/std/bfuns/
/*
 * 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");
}