// db_rw.cpp
//
// $Id: db_rw.cpp,v 1.9 2000/09/07 14:48:13 sdennis Exp $
//
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#ifdef STANDALONE
#undef MEMORY_BASED
#endif
#include "externs.h"
#include "mudconf.h"
#include "db.h"
#include "vattr.h"
#include "attrs.h"
#include "alloc.h"
#include "powers.h"
extern void FDECL(db_grow, (dbref));
extern struct object *db;
static int g_version;
static int g_format;
static int g_flags;
/*
* ---------------------------------------------------------------------------
* * getboolexp1: Get boolean subexpression from file.
*/
static BOOLEXP *getboolexp1(FILE *f)
{
BOOLEXP *b;
char *buff, *s;
int c, d, anum;
c = getc(f);
switch (c)
{
case '\n':
ungetc(c, f);
return TRUE_BOOLEXP;
case EOF:
// Unexpected EOF in boolexp.
//
Tiny_Assert(0);
break;
case '(':
b = alloc_bool("getboolexp1.openparen");
switch (c = getc(f)) {
case NOT_TOKEN:
b->type = BOOLEXP_NOT;
b->sub1 = getboolexp1(f);
if ((d = getc(f)) == '\n')
d = getc(f);
if (d != ')')
goto error;
return b;
case INDIR_TOKEN:
b->type = BOOLEXP_INDIR;
b->sub1 = getboolexp1(f);
if ((d = getc(f)) == '\n')
d = getc(f);
if (d != ')')
goto error;
return b;
case IS_TOKEN:
b->type = BOOLEXP_IS;
b->sub1 = getboolexp1(f);
if ((d = getc(f)) == '\n')
d = getc(f);
if (d != ')')
goto error;
return b;
case CARRY_TOKEN:
b->type = BOOLEXP_CARRY;
b->sub1 = getboolexp1(f);
if ((d = getc(f)) == '\n')
d = getc(f);
if (d != ')')
goto error;
return b;
case OWNER_TOKEN:
b->type = BOOLEXP_OWNER;
b->sub1 = getboolexp1(f);
if ((d = getc(f)) == '\n')
d = getc(f);
if (d != ')')
goto error;
return b;
default:
ungetc(c, f);
b->sub1 = getboolexp1(f);
if ((c = getc(f)) == '\n')
c = getc(f);
switch (c) {
case AND_TOKEN:
b->type = BOOLEXP_AND;
break;
case OR_TOKEN:
b->type = BOOLEXP_OR;
break;
default:
goto error;
}
b->sub2 = getboolexp1(f);
if ((d = getc(f)) == '\n')
d = getc(f);
if (d != ')')
goto error;
return b;
}
case '-':
// obsolete NOTHING key, eat it.
//
while ((c = getc(f)) != '\n')
{
Tiny_Assert(c != EOF);
}
ungetc(c, f);
return TRUE_BOOLEXP;
break;
case '"':
ungetc(c, f);
buff = alloc_lbuf("getboolexp_quoted");
StringCopy(buff, getstring_noalloc(f, 1));
c = fgetc(f);
if (c == EOF) {
free_lbuf(buff);
return TRUE_BOOLEXP;
}
b = alloc_bool("getboolexp1_quoted");
anum = mkattr(buff);
if (anum <= 0) {
free_bool(b);
free_lbuf(buff);
goto error;
}
free_lbuf(buff);
b->thing = anum;
// if last character is : then this is an attribute lock. A
// last character of / means an eval lock.
//
if ((c == ':') || (c == '/'))
{
if (c == '/')
b->type = BOOLEXP_EVAL;
else
b->type = BOOLEXP_ATR;
buff = alloc_lbuf("getboolexp1.attr_lock");
StringCopy(buff, getstring_noalloc(f, 1));
b->sub1 = (BOOLEXP *)StringClone(buff);
free_lbuf(buff);
}
return b;
default: // dbref or attribute.
ungetc(c, f);
b = alloc_bool("getboolexp1.default");
b->type = BOOLEXP_CONST;
b->thing = 0;
/*
* This is either an attribute, eval, or constant lock.
* Constant locks are of the form <num>, while
* attribute * and * * * * eval locks are of the form
* <anam-or-anum>:<string> or
* <aname-or-anum>/<string> respectively. The
* characters <nl>, |, and & terminate the string.
*/
if (Tiny_IsDigit[(unsigned int)c])
{
while (Tiny_IsDigit[(unsigned int)(c = getc(f))])
{
b->thing = b->thing * 10 + c - '0';
}
}
else if (Tiny_IsAlpha[(unsigned char)c])
{
buff = alloc_lbuf("getboolexp1.atr_name");
for (s = buff;
((c = getc(f)) != EOF) && (c != '\n') &&
(c != ':') && (c != '/');
*s++ = c) ;
if (c == EOF)
{
free_lbuf(buff);
free_bool(b);
goto error;
}
*s = '\0';
/*
* Look the name up as an attribute. If not found,
* create a new attribute.
*/
anum = mkattr(buff);
if (anum <= 0) {
free_bool(b);
free_lbuf(buff);
goto error;
}
free_lbuf(buff);
b->thing = anum;
} else {
free_bool(b);
goto error;
}
/*
* if last character is : then this is an attribute lock. A
* last character of / means an eval lock
*/
if ((c == ':') || (c == '/')) {
if (c == '/')
b->type = BOOLEXP_EVAL;
else
b->type = BOOLEXP_ATR;
buff = alloc_lbuf("getboolexp1.attr_lock");
for ( s = buff;
((c = getc(f)) != EOF)
&& (c != '\n')
&& (c != ')')
&& (c != OR_TOKEN)
&& (c != AND_TOKEN);
*s++ = c)
{
// Nothing
}
if (c == EOF)
goto error;
*s++ = 0;
b->sub1 = (BOOLEXP *)StringClone(buff);
free_lbuf(buff);
}
ungetc(c, f);
return b;
}
error:
// Bomb Out.
//
Tiny_Assert(0);
return TRUE_BOOLEXP;
}
/*
* ---------------------------------------------------------------------------
* * getboolexp: Read a boolean expression from the flat file.
*/
static BOOLEXP *getboolexp(FILE *f)
{
BOOLEXP *b;
char c;
b = getboolexp1(f);
c = getc(f);
Tiny_Assert(c == '\n');
// MUSH (except for PernMUSH) and MUSE can have an extra CR, MUD
// does not.
//
if ( ((g_format == F_MUSH) && (g_version != 2))
|| (g_format == F_MUSE)
|| (g_format == F_MUX))
{
if ((c = getc(f)) != '\n')
{
ungetc(c, f);
}
}
return b;
}
#ifdef STANDALONE
/*
* ---------------------------------------------------------------------------
* * unscramble_attrnum: Fix up attribute numbers from foreign muds
*/
static int unscramble_attrnum(int attrnum)
{
char anam[4];
switch (g_format) {
case F_MUSE:
switch (attrnum) {
case 39:
return A_IDLE;
case 40:
return A_AWAY;
case 41:
return 0; /*
* mailk
*/
case 42:
return A_ALIAS;
case 43:
return A_EFAIL;
case 44:
return A_OEFAIL;
case 45:
return A_AEFAIL;
case 46:
return 0; /*
* it
*/
case 47:
return A_LEAVE;
case 48:
return A_OLEAVE;
case 49:
return A_ALEAVE;
case 50:
return 0; /*
* channel
*/
case 51:
return A_QUOTA;
case 52:
return A_TEMP; /*
* temp for pennies
*/
case 53:
return 0; /*
* huhto
*/
case 54:
return 0; /*
* haven
*/
case 57:
return mkattr((char *)"TZ");
case 58:
return 0; /*
* doomsday
*/
case 59:
return mkattr((char *)"Email");
case 98:
return mkattr((char *)"Status");
case 99:
return mkattr((char *)"Race");
default:
return attrnum;
}
case F_MUSH:
/*
* Only need to muck with Pern variants
*/
if (g_version != 2)
return attrnum;
switch (attrnum) {
case 34:
return A_OENTER;
case 41:
return A_LEAVE;
case 42:
return A_ALEAVE;
case 43:
return A_OLEAVE;
case 44:
return A_OXENTER;
case 45:
return A_OXLEAVE;
default:
if ((attrnum >= 126) && (attrnum < 152)) {
anam[0] = 'W';
anam[1] = attrnum - 126 + 'A';
anam[2] = '\0';
return mkattr(anam);
}
if ((attrnum >= 152) && (attrnum < 178)) {
anam[0] = 'X';
anam[1] = attrnum - 152 + 'A';
anam[2] = '\0';
return mkattr(anam);
}
return attrnum;
}
default:
return attrnum;
}
}
#endif
/*
* ---------------------------------------------------------------------------
* * get_list: Read attribute list from flat file.
*/
static int get_list(FILE *f, dbref i, int new_strings)
{
dbref atr;
int c;
char *buff;
#ifdef STANDALONE
dbref aowner;
int xflags, aflags, anum;
char *ownp, *flagp, *buf2, *buf2p;
#endif
buff = alloc_lbuf("get_list");
while (1) {
switch (c = getc(f)) {
case '>': /*
* read # then string
*/
#ifdef STANDALONE
atr = unscramble_attrnum(getref(f));
#else
atr = getref(f);
#endif
if (atr > 0) {
/*
* Store the attr
*/
atr_add_raw(i, atr,
(char *)getstring_noalloc(f, new_strings));
} else {
/*
* Silently discard
*/
getstring_noalloc(f, new_strings);
}
break;
#ifdef STANDALONE
case ']': /*
* Pern 1.13 style text attribute
*/
StringCopy(buff, (char *)getstring_noalloc(f, new_strings));
/*
* Get owner number
*/
ownp = (char *)strchr(buff, '^');
if (!ownp)
{
Log.printf("Bad format in attribute on object %d\n", i);
free_lbuf(buff);
return 0;
}
*ownp++ = '\0';
/*
* Get attribute flags
*/
flagp = (char *)strchr(ownp, '^');
if (!flagp)
{
Log.printf("Bad format in attribute on object %d\n", i);
free_lbuf(buff);
return 0;
}
*flagp++ = '\0';
/*
* Convert Pern-style owner and flags to 2.0 format
*/
aowner = Tiny_atol(ownp);
xflags = Tiny_atol(flagp);
aflags = 0;
if (!aowner)
aowner = NOTHING;
if (xflags & 0x10)
aflags |= AF_LOCK | AF_NOPROG;
if (xflags & 0x20)
aflags |= AF_NOPROG;
if (!strcmp(buff, "XYXXY"))
s_Pass(i, (char *)getstring_noalloc(f, new_strings));
else {
/*
* Look up the attribute name in the
* attribute table. * If the name isn't
* found, create a new * attribute. If the
* create fails, try prefixing * the attr
* name with ATR_ (Pern allows * attributes
* to start with a * non-alphabetic
* character.
*/
anum = mkattr(buff);
if (anum < 0) {
buf2 = alloc_mbuf("get_list.new_attr_name");
buf2p = buf2;
safe_mb_str((char *)"ATR_", buf2, &buf2p);
safe_mb_str(buff, buf2, &buf2p);
*buf2p = '\0';
anum = mkattr(buf2);
free_mbuf(buf2);
}
/*
* MAILFOLDERS under MUX must be owned by the
* player, not GOD
*/
if (!strcmp(buff, "MAILFOLDERS")) {
aowner = Owner(i);
}
if (anum < 0)
{
Log.printf("Bad attribute name '%s' on object %d, ignoring...\n", buff, i);
(void)getstring_noalloc(f, new_strings);
}
else
{
atr_add(i, anum, (char *)getstring_noalloc(f, new_strings), aowner, aflags);
}
}
break;
#endif
case '\n': /*
* ignore newlines. They're due to v(r).
*/
break;
case '<': /*
* end of list
*/
free_lbuf(buff);
c = getc(f);
if (c != '\n')
{
ungetc(c, f);
Log.printf("No line feed on object %d\n", i);
return 1;
}
return 1;
default:
Log.printf("Bad character '%c' when getting attributes on object %d\n", c, i);
/*
* We've found a bad spot. I hope things aren't * *
* * * * * too bad.
*/
(void)getstring_noalloc(f, new_strings);
}
}
}
/*
* ---------------------------------------------------------------------------
* * putbool_subexp: Write a boolean sub-expression to the flat file.
*/
static void putbool_subexp(FILE *f, BOOLEXP *b)
{
ATTR *va;
switch (b->type)
{
case BOOLEXP_IS:
putc('(', f);
putc(IS_TOKEN, f);
putbool_subexp(f, b->sub1);
putc(')', f);
break;
case BOOLEXP_CARRY:
putc('(', f);
putc(CARRY_TOKEN, f);
putbool_subexp(f, b->sub1);
putc(')', f);
break;
case BOOLEXP_INDIR:
putc('(', f);
putc(INDIR_TOKEN, f);
putbool_subexp(f, b->sub1);
putc(')', f);
break;
case BOOLEXP_OWNER:
putc('(', f);
putc(OWNER_TOKEN, f);
putbool_subexp(f, b->sub1);
putc(')', f);
break;
case BOOLEXP_AND:
putc('(', f);
putbool_subexp(f, b->sub1);
putc(AND_TOKEN, f);
putbool_subexp(f, b->sub2);
putc(')', f);
break;
case BOOLEXP_OR:
putc('(', f);
putbool_subexp(f, b->sub1);
putc(OR_TOKEN, f);
putbool_subexp(f, b->sub2);
putc(')', f);
break;
case BOOLEXP_NOT:
putc('(', f);
putc(NOT_TOKEN, f);
putbool_subexp(f, b->sub1);
putc(')', f);
break;
case BOOLEXP_CONST:
putref(f, b->thing);
break;
case BOOLEXP_ATR:
va = atr_num(b->thing);
if (va)
{
fprintf(f, "%s:%s", va->name, (char *)b->sub1);
}
else
{
fprintf(f, "%d:%s\n", b->thing, (char *)b->sub1);
}
break;
case BOOLEXP_EVAL:
va = atr_num(b->thing);
if (va)
{
fprintf(f, "%s/%s\n", va->name, (char *)b->sub1);
}
else
{
fprintf(f, "%d/%s\n", b->thing, (char *)b->sub1);
}
break;
default:
Log.printf("Unknown boolean type in putbool_subexp: %d\n", b->type);
break;
}
}
/*
* ---------------------------------------------------------------------------
* * putboolexp: Write boolean expression to the flat file.
*/
static void putboolexp(FILE *f, BOOLEXP *b)
{
if (b != TRUE_BOOLEXP) {
putbool_subexp(f, b);
}
putc('\n', f);
}
#ifdef STANDALONE
/*
* ---------------------------------------------------------------------------
* * upgrade_flags: Convert foreign flags to MUSH format.
*/
static void upgrade_flags(FLAG *flags1, FLAG *flags2, FLAG *flags3, dbref thing, int db_format, int db_version)
{
FLAG f1, f2, f3, newf1, newf2, newf3;
f1 = *flags1;
f2 = *flags2;
f3 = *flags3;
newf1 = 0;
newf2 = 0;
newf3 = 0;
if (db_format == F_MUD) {
/*
* Old TinyMUD format
*/
newf1 = f1 & (TYPE_MASK | WIZARD | LINK_OK | DARK | STICKY | HAVEN);
if (f1 & MUD_ABODE)
newf2 |= ABODE;
if (f1 & MUD_ROBOT)
newf1 |= ROBOT;
if (f1 & MUD_CHOWN_OK)
newf1 |= CHOWN_OK;
} else if (db_format == F_MUSE) {
if (db_version == 1)
return;
/*
* Convert level-based players to normal
*/
switch (f1 & 0xf) {
case 0: /*
* * room
*/
case 1: /*
* * thing
*/
case 2: /*
* * exit
*/
newf1 = f1 & 0x3;
break;
case 8: /*
* * guest
*/
case 9: /*
* * trial player
*/
case 10: /*
* member
*/
case 11: /*
* junior official
*/
case 12: /*
* official
*/
newf1 = TYPE_PLAYER;
break;
case 13: /*
* honorary wizard
*/
case 14: /*
* administrator
*/
case 15: /*
* director
*/
newf1 = TYPE_PLAYER | WIZARD;
break;
default: /*
* A bad type, mark going
*/
Log.printf("Funny object type for #%d\n", thing);
*flags1 = GOING;
return;
}
/*
* Player #1 is always a wizard
*/
if (thing == (dbref) 1)
newf1 |= WIZARD;
/*
* Set type-specific flags
*/
switch (newf1 & TYPE_MASK) {
case TYPE_PLAYER: /*
* Lose CONNECT TERSE QUITE NOWALLS *
*
* * * * * * * * WARPTEXT
*/
if (f1 & MUSE_BUILD)
s_Powers(thing, Powers(thing) | POW_BUILDER);
if (f1 & MUSE_SLAVE)
newf2 |= SLAVE;
if (f1 & MUSE_UNFIND)
newf2 |= UNFINDABLE;
break;
case TYPE_THING: /*
* lose LIGHT SACR_OK
*/
if (f1 & MUSE_KEY)
newf2 |= KEY;
if (f1 & MUSE_DEST_OK)
newf1 |= DESTROY_OK;
break;
case TYPE_ROOM:
if (f1 & MUSE_ABODE)
newf2 |= ABODE;
break;
case TYPE_EXIT:
if (f1 & MUSE_SEETHRU)
newf1 |= SEETHRU;
default:
break;
}
/*
* Convert common flags
*/
/*
* Lose: MORTAL ACCESSED MARKED SEE_OK UNIVERSAL
*/
if (f1 & MUSE_CHOWN_OK)
newf1 |= CHOWN_OK;
if (f1 & MUSE_DARK)
newf1 |= DARK;
if (f1 & MUSE_STICKY)
newf1 |= STICKY;
if (f1 & MUSE_HAVEN)
newf1 |= HAVEN;
if (f1 & MUSE_INHERIT)
newf1 |= INHERIT;
if (f1 & MUSE_GOING)
newf1 |= GOING;
if (f1 & MUSE_PUPPET)
newf1 |= PUPPET;
if (f1 & MUSE_LINK_OK)
newf1 |= LINK_OK;
if (f1 & MUSE_ENTER_OK)
newf1 |= ENTER_OK;
if (f1 & MUSE_VISUAL)
newf1 |= VISUAL;
if (f1 & MUSE_OPAQUE)
newf1 |= TM_OPAQUE;
if (f1 & MUSE_QUIET)
newf1 |= QUIET;
} else if ((db_format == F_MUSH) && (db_version == 2)) {
/*
* Pern variants
*/
newf1 = (f1 & TYPE_MASK);
newf2 = 0;
newf1 &= ~PENN_COMBAT;
newf1 &= ~PENN_ACCESSED;
newf1 &= ~PENN_MARKED;
newf1 &= ~ROYALTY;
if (f1 & PENN_INHERIT)
newf1 |= INHERIT;
if (f1 & PENN_AUDIBLE)
newf1 |= HEARTHRU;
if (f1 & PENN_ROYALTY)
newf1 |= ROYALTY;
if (f1 & PENN_WIZARD)
newf1 |= WIZARD;
if (f1 & PENN_LINK_OK)
newf1 |= LINK_OK;
if (f1 & PENN_DARK)
newf1 |= DARK;
if (f1 & PENN_VERBOSE)
newf1 |= VERBOSE;
if (f1 & PENN_STICKY)
newf1 |= STICKY;
if (f1 & PENN_TRANSPARENT)
newf1 |= SEETHRU;
if (f1 & PENN_HAVEN)
newf1 |= HAVEN;
if (f1 & PENN_QUIET)
newf1 |= QUIET;
if (f1 & PENN_HALT)
newf1 |= HALT;
if (f1 & PENN_UNFIND)
newf2 |= UNFINDABLE;
if (f1 & PENN_GOING)
newf1 |= GOING;
if (f1 & PENN_CHOWN_OK)
newf1 |= CHOWN_OK;
if (f1 & PENN_ENTER_OK)
newf1 |= ENTER_OK;
if (f1 & PENN_VISUAL)
newf1 |= VISUAL;
if (f1 & PENN_OPAQUE)
newf1 |= TM_OPAQUE;
if (f1 & PENN_DEBUGGING)
newf1 |= TRACE;
if (f1 & PENN_SAFE)
newf1 |= SAFE;
if (f1 & PENN_STARTUP)
newf1 |= HAS_STARTUP;
if (f1 & PENN_NO_COMMAND)
newf2 |= NO_COMMAND;
switch (newf1 & TYPE_MASK) {
case TYPE_PLAYER:
if (f2 & PENN_PLAYER_TERSE)
newf1 |= TERSE;
if (f2 & PENN_PLAYER_MYOPIC)
newf1 |= MYOPIC;
if (f2 & PENN_PLAYER_NOSPOOF)
newf1 |= NOSPOOF;
if (f2 & PENN_PLAYER_SUSPECT)
newf2 |= SUSPECT;
if (f2 & PENN_PLAYER_GAGGED)
newf2 |= SLAVE;
if (f2 & PENN_PLAYER_MONITOR)
newf1 |= MONITOR;
if (f2 & PENN_PLAYER_CONNECT)
newf2 &= ~CONNECTED;
if (f2 & PENN_PLAYER_ANSI)
newf2 |= ANSI;
if (f2 & PENN_PLAYER_HEAD)
newf2 |= HEAD_FLAG;
if (f2 & PENN_PLAYER_FIXED)
newf2 |= FIXED;
if (f2 & PENN_PLAYER_ADMIN)
newf2 |= STAFF;
if (f2 & PENN_PLAYER_SLAVE)
newf2 |= SLAVE;
if (f2 & PENN_PLAYER_COLOR)
newf2 |= ANSI;
if (f2 & PENN_PLAYER_WEIRDANSI)
newf2 |= NOBLEED;
break;
case TYPE_EXIT:
if (f2 & PENN_EXIT_LIGHT)
newf2 |= LIGHT;
break;
case TYPE_THING:
if (f2 & PENN_THING_DEST_OK)
newf1 |= DESTROY_OK;
if (f2 & PENN_THING_PUPPET)
newf1 |= PUPPET;
if (f2 & PENN_THING_LISTEN)
newf1 |= MONITOR;
break;
case TYPE_ROOM:
if (f2 & PENN_ROOM_FLOATING)
newf2 |= FLOATING;
if (f2 & PENN_ROOM_ABODE)
newf2 |= ABODE;
if (f2 & PENN_ROOM_JUMP_OK)
newf1 |= JUMP_OK;
if (f2 & PENN_ROOM_LISTEN)
newf1 |= MONITOR;
if (f2 & PENN_ROOM_UNINSPECT)
newf2 |= UNINSPECTED;
}
} else if ((db_format == F_MUSH) && (db_version >= 3)) {
newf1 = f1;
newf2 = f2;
switch (db_version) {
case 3:
(newf1 &= ~V2_ACCESSED); /*
* Clear ACCESSED
*/
case 4:
(newf1 &= ~V3_MARKED); /*
* Clear MARKED
*/
case 5:
/*
* Merge GAGGED into SLAVE, move SUSPECT
*/
if ((newf1 & TYPE_MASK) == TYPE_PLAYER) {
if (newf1 & V4_GAGGED) {
newf2 |= SLAVE;
newf1 &= ~V4_GAGGED;
}
if (newf1 & V4_SUSPECT) {
newf2 |= SUSPECT;
newf1 &= ~V4_SUSPECT;
}
}
case 6:
switch (newf1 & TYPE_MASK) {
case TYPE_PLAYER:
if (newf1 & V6_BUILDER) {
s_Powers(thing, Powers(thing) | POW_BUILDER);
newf1 &= ~V6_BUILDER;
}
if (newf1 & V6_SUSPECT) {
newf2 |= SUSPECT;
newf1 &= ~V6_SUSPECT;
}
if (newf1 & V6PLYR_UNFIND) {
newf2 |= UNFINDABLE;
newf1 &= ~V6PLYR_UNFIND;
}
if (newf1 & V6_SLAVE) {
newf2 |= SLAVE;
newf1 &= ~V6_SLAVE;
}
break;
case TYPE_ROOM:
if (newf1 & V6_FLOATING) {
newf2 |= FLOATING;
newf1 &= ~V6_FLOATING;
}
if (newf1 & V6_ABODE) {
newf2 |= ABODE;
newf1 &= ~V6_ABODE;
}
if (newf1 & V6ROOM_JUMPOK) {
newf1 |= JUMP_OK;
newf1 &= ~V6ROOM_JUMPOK;
}
if (newf1 & V6ROOM_UNFIND) {
newf2 |= UNFINDABLE;
newf1 &= ~V6ROOM_UNFIND;
}
break;
case TYPE_THING:
if (newf1 & V6OBJ_KEY) {
newf2 |= KEY;
newf1 &= ~V6OBJ_KEY;
}
break;
case TYPE_EXIT:
if (newf1 & V6EXIT_KEY) {
newf2 |= KEY;
newf1 &= ~V6EXIT_KEY;
}
break;
}
case 7:
if (newf1 & ROYALTY) {
newf1 &= ~ROYALTY; /*
* CONTROL_OK
*/
}
break;
}
} else if (db_format == F_MUX) {
newf1 = f1;
newf2 = f2;
newf3 = f3;
}
*flags1 = newf1;
*flags2 = newf2;
*flags3 = newf3;
return;
}
/*
* ---------------------------------------------------------------------------
* * efo_convert: Fix things up for Exits-From-Objects
*/
void NDECL(efo_convert)
{
int i;
dbref link;
DO_WHOLE_DB(i) {
switch (Typeof(i)) {
case TYPE_PLAYER:
case TYPE_THING:
/*
* swap Exits and Link
*/
link = Link(i);
s_Link(i, Exits(i));
s_Exits(i, link);
break;
}
}
}
/*
* ---------------------------------------------------------------------------
* * unscraw_foreign: Fix up strange object linking conventions for other formats
*/
void unscraw_foreign(int db_format, int db_version, int db_flags)
{
dbref tmp, i, aowner;
int aflags;
char *p_str;
switch (db_format)
{
case F_MUSE:
DO_WHOLE_DB(i)
{
if (Typeof(i) == TYPE_EXIT)
{
/*
* MUSE exits are bass-ackwards
*/
tmp = Exits(i);
s_Exits(i, Location(i));
s_Location(i, tmp);
}
if (db_version > 3)
{
/*
* MUSEs with pennies in an attribute have
* it stored in attr 255 (see
* unscramble_attrnum)
*/
p_str = atr_get(i, A_TEMP, &aowner, &aflags);
s_Pennies(i, Tiny_atol(p_str));
free_lbuf(p_str);
atr_clr(i, A_TEMP);
}
}
if (!(db_flags & V_LINK))
{
efo_convert();
}
break;
case F_MUSH:
if ((db_version <= 5) && (db_flags & V_GDBM))
{
/*
* Check for FORWARDLIST attribute
*/
DO_WHOLE_DB(i)
{
if (atr_get_raw(i, A_FORWARDLIST))
{
s_Flags2(i, Flags2(i) | HAS_FWDLIST);
}
}
}
if (db_version <= 6)
{
DO_WHOLE_DB(i)
{
/*
* Make sure A_QUEUEMAX is empty
*/
atr_clr(i, A_QUEUEMAX);
if (db_flags & V_GDBM)
{
/*
* HAS_LISTEN now tracks LISTEN attr
*/
if (atr_get_raw(i, A_LISTEN))
s_Flags2(i, Flags2(i) | HAS_LISTEN);
/*
* Undo V6 overloading of HAS_STARTUP
* * * * * * * with HAS_FWDLIST
*/
if ( (db_version == 6)
&& (Flags2(i) & HAS_STARTUP)
&& atr_get_raw(i, A_FORWARDLIST))
{
/*
* We have FORWARDLIST
*/
s_Flags2(i, Flags2(i) | HAS_FWDLIST);
/*
* Maybe no STARTUP
*/
if (!atr_get_raw(i, A_STARTUP))
s_Flags2(i, Flags2(i) & ~HAS_STARTUP);
}
}
}
}
break;
case F_MUD:
efo_convert();
}
}
/*
* ---------------------------------------------------------------------------
* * getlist_discard, get_atrdefs_discard: Throw away data from MUSE that we
* * don't use.
*/
static void getlist_discard(FILE *f, dbref i, int set)
{
int count;
count = getref(f);
for (count--; count >= 0; count--) {
if (set)
s_Parent(i, getref(f));
else
(void)getref(f);
}
}
static void get_atrdefs_discard(FILE *f)
{
const char *sp;
for (;;) {
sp = getstring_noalloc(f, 0); /*
* flags or endmarker
*/
if (*sp == '\\')
return;
sp = getstring_noalloc(f, 0); /*
* object
*/
sp = getstring_noalloc(f, 0); /*
* name
*/
}
}
static void fix_typed_quotas(dbref i)
{
char *buff, *bp;
dbref aowner;
int aflags, total = 0;
/*
* For 2.2's 'typed quotas'...
*/
/*
* I guess we have to add them up...
*/
if (!(isPlayer(i)))
return;
buff = atr_get(i, A_QUOTA, &aowner, &aflags);
TINY_STRTOK_STATE tts;
Tiny_StrTokString(&tts, buff);
Tiny_StrTokControl(&tts, " ");
for (bp = Tiny_StrTokParse(&tts); bp; bp = Tiny_StrTokParse(&tts))
{
total += Tiny_atol(bp);
}
atr_add_raw(i, A_QUOTA, Tiny_ltoa_t(total));
free_lbuf(buff);
buff = atr_get(i, A_RQUOTA, &aowner, &aflags);
Tiny_StrTokString(&tts, buff);
for (bp = Tiny_StrTokParse(&tts); bp; bp = Tiny_StrTokParse(&tts))
{
total += Tiny_atol(bp);
}
free_lbuf(buff);
atr_add_raw(i, A_RQUOTA, Tiny_ltoa_t(total));
}
static void getpenn_new_locks(FILE *f, int i)
{
char c, *buf, *p;
struct boolexp *tempbool;
buf = alloc_lbuf("getpenn_new_locks");
p = buf;
while (c = getc(f), (c != EOF) && (c != '|'))
*p++ = c;
*p = '\0';
tempbool = getboolexp(f);
if (tempbool == TRUE_BOOLEXP)
return;
if (!strcmp(buf, "Basic"))
atr_add_raw(i, A_LOCK,
unparse_boolexp_quiet(1, tempbool));
else if (!strcmp(buf, "Use"))
atr_add_raw(i, A_LUSE,
unparse_boolexp_quiet(1, tempbool));
else if (!strcmp(buf, "Enter"))
atr_add_raw(i, A_LENTER,
unparse_boolexp_quiet(1, tempbool));
else if (!strcmp(buf, "Page"))
atr_add_raw(i, A_LPAGE,
unparse_boolexp_quiet(1, tempbool));
else if (!strcmp(buf, "Teleport"))
atr_add_raw(i, A_LTPORT,
unparse_boolexp_quiet(1, tempbool));
else if (!strcmp(buf, "Speech"))
atr_add_raw(i, A_LSPEECH,
unparse_boolexp_quiet(1, tempbool));
else if (!strcmp(buf, "Parent"))
atr_add_raw(i, A_LPARENT,
unparse_boolexp_quiet(1, tempbool));
else if (!strcmp(buf, "Link"))
atr_add_raw(i, A_LLINK,
unparse_boolexp_quiet(1, tempbool));
else if (!strcmp(buf, "Leave"))
atr_add_raw(i, A_LLEAVE,
unparse_boolexp_quiet(1, tempbool));
else if (!strcmp(buf, "Drop"))
atr_add_raw(i, A_LDROP,
unparse_boolexp_quiet(1, tempbool));
else if (!strcmp(buf, "Give"))
atr_add_raw(i, A_LGIVE,
unparse_boolexp_quiet(1, tempbool));
free_lbuf(buf);
}
#endif
dbref db_read(FILE *f, int *db_format, int *db_version, int *db_flags)
{
dbref i, anum;
char ch;
const char *tstr;
int header_gotten, size_gotten, nextattr_gotten;
int read_attribs, read_name, read_zone, read_link, read_key, read_parent;
int read_extflags, read_3flags, read_money, read_timestamps, read_new_strings;
#ifdef STANDALONE
int is_penn, read_pern_key, read_pern_comm, read_pern_parent;
int read_pern_warnings, read_pern_creation, read_pern_powers;
int read_pern_new_locks, is_dark;
int read_dark_comm, read_dark_slock, read_dark_mc, read_dark_mpar;
int read_dark_class, read_dark_rank, read_dark_droplock;
int read_dark_givelock, read_dark_getlock;
int read_dark_threepow, penn_version;
int read_muse_parents, read_muse_atrdefs;
int peek;
char *p;
#endif
int read_powers, read_powers_player, read_powers_any;
int deduce_version, deduce_name, deduce_zone, deduce_timestamps;
int aflags, f1, f2, f3;
BOOLEXP *tempbool;
char *buff;
int len;
int nVisualWidth;
header_gotten = 0;
size_gotten = 0;
nextattr_gotten = 0;
g_format = F_UNKNOWN;
g_version = 0;
g_flags = 0;
read_attribs = 1;
read_name = 1;
read_zone = 0;
read_link = 0;
read_key = 1;
read_parent = 0;
read_money = 1;
read_extflags = 0;
read_3flags = 0;
read_timestamps = 0;
read_new_strings = 0;
read_powers = 0;
read_powers_player = 0;
read_powers_any = 0;
deduce_version = 1;
deduce_zone = 1;
deduce_name = 1;
deduce_timestamps = 1;
#ifdef STANDALONE
is_penn = 0;
is_dark = 0;
read_pern_key = 0;
read_pern_comm = 0;
read_pern_parent = 0;
read_pern_warnings = 0;
read_pern_creation = 0;
read_pern_powers = 0;
read_pern_new_locks = 0;
read_dark_comm = 0;
read_dark_slock = 0;
read_dark_mc = 0;
read_dark_mpar = 0;
read_dark_class = 0;
read_dark_rank = 0;
read_dark_droplock = 0;
read_dark_givelock = 0;
read_dark_getlock = 0;
read_dark_threepow = 0;
penn_version = 0;
read_muse_parents = 0;
read_muse_atrdefs = 0;
Log.WriteString("Reading ");
Log.Flush();
#endif
db_free();
#ifdef STANDALONE
int iDotCounter = 0;
#endif
for (i = 0;; i++)
{
#ifdef STANDALONE
if (!iDotCounter)
{
iDotCounter = 100;
fputc('.', stderr);
fflush(stderr);
}
iDotCounter--;
#endif
switch (ch = getc(f))
{
case '-': /* Misc tag */
switch (ch = getc(f))
{
case 'R': /* Record number of players */
mudstate.record_players = getref(f);
break;
default:
(void)getstring_noalloc(f, 0);
}
break;
#ifdef STANDALONE
case '~': /*
* Database size tag
*/
is_penn = 1;
if (!is_dark && penn_version) {
g_format = F_MUSH;
g_version = (((penn_version - 2) / 256) - 5);
/*
* Okay, let's try and unscraw version
* encoding method they use in later Penn
* 1.50.
*/
/*
* Handle Pern veriants specially
*/
if (g_version & 0x20)
read_new_strings = 1;
if (g_version & 0x10)
read_pern_new_locks = 1;
if (!(g_version & 0x08))
read_pern_powers = 1;
if (g_version & 0x04)
read_pern_creation = 1;
if (g_version & 0x02)
read_pern_warnings = 1;
if (!(g_version & 0x01))
read_pern_comm = 1;
g_version = 2;
}
if (size_gotten)
{
Log.printf("\nDuplicate size entry at object %d, ignored.\n", i);
tstr = getstring_noalloc(f, 0); /*
* junk
*/
break;
}
mudstate.min_size = getref(f);
size_gotten = 1;
break;
#endif
case '+': /*
* MUX and MUSH header
*/
switch (ch = getc(f)) { /*
* 2nd char selects
* type
*/
#ifdef STANDALONE
case 'V': /*
* MUSH VERSION
*/
if (header_gotten)
{
Log.printf("\nDuplicate MUSH version header entry at object %d, ignored.\n", i);
tstr = getstring_noalloc(f, 0);
break;
}
header_gotten = 1;
deduce_version = 0;
g_format = F_MUSH;
g_version = getref(f);
penn_version = g_version;
/*
* Otherwise extract feature flags
*/
if (g_version & V_GDBM) {
read_attribs = 0;
read_name = !(g_version & V_ATRNAME);
}
read_zone = (g_version & V_ZONE);
read_link = (g_version & V_LINK);
read_key = !(g_version & V_ATRKEY);
read_parent = (g_version & V_PARENT);
read_money = !(g_version & V_ATRMONEY);
read_extflags = (g_version & V_XFLAGS);
g_flags = g_version & ~V_MASK;
g_version &= V_MASK;
deduce_name = 0;
deduce_version = 0;
deduce_zone = 0;
break;
#endif
case 'X': /*
* MUX VERSION
*/
if (header_gotten)
{
Log.printf("\nDuplicate MUX version header entry at object %d, ignored.\n", i);
tstr = getstring_noalloc(f, 0);
break;
}
header_gotten = 1;
deduce_version = 0;
g_format = F_MUX;
g_version = getref(f);
/*
* Otherwise extract feature flags
*/
if (g_version & V_GDBM) {
read_attribs = 0;
read_name = !(g_version & V_ATRNAME);
}
read_zone = (g_version & V_ZONE);
read_link = (g_version & V_LINK);
read_key = !(g_version & V_ATRKEY);
read_parent = (g_version & V_PARENT);
read_money = !(g_version & V_ATRMONEY);
read_extflags = (g_version & V_XFLAGS);
read_3flags = (g_version & V_3FLAGS);
read_powers = (g_version & V_POWERS);
read_new_strings = (g_version & V_QUOTED);
g_flags = g_version & ~V_MASK;
g_version &= V_MASK;
deduce_name = 0;
deduce_version = 0;
deduce_zone = 0;
break;
#ifdef STANDALONE
case 'K': /*
* Kalkin's DarkZone dist
*/
/*
* Him and his #defines...
*/
if (header_gotten)
{
Log.printf("\nDuplicate MUSH version header entry at object %d, ignored.\n", i);
tstr = getstring_noalloc(f, 0);
break;
}
header_gotten = 1;
deduce_version = 0;
g_format = F_MUSH;
g_version = getref(f);
is_dark = 1;
is_penn = 1;
read_pern_powers = 1;
if (g_version & DB_CHANNELS)
read_dark_comm = 1;
if (g_version & DB_SLOCK)
read_dark_slock = 1;
if (g_version & DB_MC)
read_dark_mc = 1;
if (g_version & DB_MPAR)
read_dark_mpar = 1;
if (g_version & DB_CLASS)
read_dark_class = 1;
if (g_version & DB_RANK)
read_dark_rank = 1;
if (g_version & DB_DROPLOCK)
read_dark_droplock = 1;
if (g_version & DB_GIVELOCK)
read_dark_givelock = 1;
if (g_version & DB_GETLOCK)
read_dark_getlock = 1;
if (g_version & DB_THREEPOW)
read_dark_threepow = 1;
g_version = 2;
break;
#endif
case 'S': /*
* SIZE
*/
if (size_gotten)
{
Log.printf("\nDuplicate size entry at object %d, ignored.\n", i);
tstr = getstring_noalloc(f, 0);
}
else
{
mudstate.min_size = getref(f);
}
size_gotten = 1;
break;
case 'A': /*
* USER-NAMED ATTRIBUTE
*/
anum = getref(f);
tstr = getstring_noalloc(f, read_new_strings);
if (Tiny_IsDigit[(unsigned char)*tstr])
{
aflags = 0;
while (Tiny_IsDigit[(unsigned char)*tstr])
{
aflags = (aflags * 10) + (*tstr++ - '0');
}
tstr++; // skip ':'
}
else
{
aflags = mudconf.vattr_flags;
}
{
int nName;
BOOL bValid;
char *pName = MakeCanonicalAttributeName(tstr, &nName, &bValid);
if (bValid)
{
vattr_define_LEN(pName, nName, anum, aflags);
}
}
break;
case 'F': /*
* OPEN USER ATTRIBUTE SLOT
*/
anum = getref(f);
break;
case 'N': /*
* NEXT ATTR TO ALLOC WHEN NO
* FREELIST
*/
if (nextattr_gotten)
{
Log.printf("\nDuplicate next free vattr entry at object %d, ignored.\n", i);
tstr = getstring_noalloc(f, 0);
}
else
{
mudstate.attr_next = getref(f);
nextattr_gotten = 1;
}
break;
default:
Log.printf("\nUnexpected character '%c' in MUX header near object #%d, ignored.\n", ch, i);
tstr = getstring_noalloc(f, 0);
}
break;
#ifdef STANDALONE
case '@': /*
* MUSE header
*/
if (header_gotten)
{
Log.printf("\nDuplicate MUSE header entry at object #%d.\n", i);
return -1;
}
header_gotten = 1;
deduce_version = 0;
g_format = F_MUSE;
g_version = getref(f);
deduce_name = 0;
deduce_zone = 1;
read_money = (g_version <= 3);
read_link = (g_version >= 5);
read_powers_player = (g_version >= 6);
read_powers_any = (g_version == 6);
read_muse_parents = (g_version >= 8);
read_muse_atrdefs = (g_version >= 8);
if (read_link)
g_flags |= V_LINK;
break;
case '#':
if (deduce_version)
{
g_format = F_MUD;
g_version = 1;
deduce_version = 0;
}
if (g_format != F_MUD)
{
Log.printf("\nMUD-style object found in non-MUD database at object #%d\n", i);
return -1;
}
if (i != getref(f))
{
Log.printf("\nSequence error at object #%d\n", i);
return -1;
}
db_grow(i + 1);
p = getstring_noalloc(f, 0);
buff = alloc_lbuf("dbread.s_Name");
len = ANSI_TruncateToField(p, MBUF_SIZE, buff, MBUF_SIZE, &nVisualWidth, 0);
s_Name(i, buff);
free_lbuf(buff);
atr_add_raw(i, A_DESC, (char *)getstring_noalloc(f, 0));
s_Location(i, getref(f));
s_Contents(i, getref(f));
s_Exits(i, getref(f));
s_Link(i, NOTHING);
s_Next(i, getref(f));
/*
* s_Zone(i, NOTHING);
*/
tempbool = getboolexp(f);
atr_add_raw(i, A_LOCK,
unparse_boolexp_quiet(1, tempbool));
free_boolexp(tempbool);
atr_add_raw(i, A_FAIL, (char *)getstring_noalloc(f, 0));
atr_add_raw(i, A_SUCC, (char *)getstring_noalloc(f, 0));
atr_add_raw(i, A_OFAIL, (char *)getstring_noalloc(f, 0));
atr_add_raw(i, A_OSUCC, (char *)getstring_noalloc(f, 0));
s_Owner(i, getref(f));
s_Parent(i, NOTHING);
s_Pennies(i, getref(f));
f1 = getref(f);
f2 = 0;
f3 = 0;
upgrade_flags(&f1, &f2, &f3, i, g_format, g_version);
s_Flags(i, f1);
s_Flags2(i, f2);
s_Flags3(i, f3);
s_Pass(i, getstring_noalloc(f, 0));
if (deduce_timestamps) {
peek = getc(f);
if ((peek != '#') && (peek != '*')) {
read_timestamps = 1;
}
deduce_timestamps = 0;
ungetc(peek, f);
}
if (read_timestamps) {
aflags = getref(f); /*
* created
*/
aflags = getref(f); /*
* lastused
*/
aflags = getref(f); /*
* usecount
*/
}
break;
case '&': /*
* MUSH 2.0a stub entry/MUSE zoned entry
*/
if (deduce_version) {
deduce_version = 0;
g_format = F_MUSH;
g_version = 1;
deduce_name = 1;
deduce_zone = 0;
read_key = 0;
read_attribs = 0;
} else if (deduce_zone) {
deduce_zone = 0;
read_zone = 1;
g_flags |= V_ZONE;
}
#endif
case '!': /*
* MUX entry/MUSH entry/MUSE non-zoned entry
*/
if (deduce_version) {
g_format = F_MUX;
g_version = 1;
deduce_name = 0;
deduce_zone = 0;
deduce_version = 0;
} else if (deduce_zone) {
deduce_zone = 0;
read_zone = 0;
}
i = getref(f);
db_grow(i + 1);
#ifdef STANDALONE
if (is_penn)
{
tstr = getstring_noalloc(f, read_new_strings);
buff = alloc_lbuf("dbread.s_Name");
len = ANSI_TruncateToField(tstr, MBUF_SIZE, buff, MBUF_SIZE, &nVisualWidth, 0);
s_Name(i, buff);
free_lbuf(buff);
s_Location(i, getref(f));
s_Contents(i, getref(f));
s_Exits(i, getref(f));
s_Next(i, getref(f));
/*
* have no equivalent to multi-parents yet,
* so we have to throw
* them away...
*/
if (read_dark_mpar) {
/*
* Parents
*/
getlist_discard(f, i, 1);
/*
* Children
*/
getlist_discard(f, i, 0);
} else {
s_Parent(i, getref(f));
}
if (read_pern_new_locks) {
while ((ch = getc(f)) == '_')
getpenn_new_locks(f, i);
ungetc(ch, f);
} else {
tempbool = getboolexp(f);
atr_add_raw(i, A_LOCK,
unparse_boolexp_quiet(1, tempbool));
free_boolexp(tempbool);
tempbool = getboolexp(f);
atr_add_raw(i, A_LUSE,
unparse_boolexp_quiet(1, tempbool));
free_boolexp(tempbool);
tempbool = getboolexp(f);
atr_add_raw(i, A_LENTER,
unparse_boolexp_quiet(1, tempbool));
free_boolexp(tempbool);
}
if (read_dark_slock)
(void)getref(f);
if (read_dark_droplock)
(void)getref(f);
if (read_dark_givelock)
(void)getref(f);
if (read_dark_getlock)
(void)getref(f);
s_Owner(i, getref(f));
s_Zone(i, getref(f));
s_Pennies(i, getref(f));
f1 = getref(f);
f2 = getref(f);
f3 = 0;
upgrade_flags(&f1, &f2, &f3, i, F_MUSH, 2);
s_Flags(i, f1);
s_Flags2(i, f2);
s_Flags3(i, f3);
if (read_pern_powers)
(void)getref(f);
/*
* Kalkin's extra two powers words...
*/
if (read_dark_threepow) {
(void)getref(f);
(void)getref(f);
}
/*
* Kalkin's @class
*/
if (read_dark_class)
(void)getref(f);
/*
* Kalkin put his creation times BEFORE * * *
*
* * * * channels * unlike standard Penn...
*/
if (read_dark_mc)
{
(void)getref(f);
(void)getref(f);
}
if (read_pern_comm || read_dark_comm)
(void)getref(f);
if (read_pern_warnings)
(void)getref(f);
if (read_pern_creation)
{
(void)getref(f);
(void)getref(f);
}
/*
* In Penn, clear the player's parent.
*/
if (isPlayer(i))
{
s_Parent(i, NOTHING);
}
if (!get_list(f, i, read_new_strings))
{
Log.printf("\nError reading attrs for object #%d\n", i);
return -1;
}
} else {
#endif
if (read_name)
{
tstr = getstring_noalloc(f, read_new_strings);
if (deduce_name)
{
if (Tiny_IsDigit[(unsigned char)*tstr])
{
read_name = 0;
s_Location(i, Tiny_atol(tstr));
}
else
{
buff = alloc_lbuf("dbread.s_Name");
len = ANSI_TruncateToField(tstr, MBUF_SIZE, buff, MBUF_SIZE, &nVisualWidth, 0);
s_Name(i, buff);
free_lbuf(buff);
s_Location(i, getref(f));
}
deduce_name = 0;
}
else
{
buff = alloc_lbuf("dbread.s_Name");
len = ANSI_TruncateToField(tstr, MBUF_SIZE, buff, MBUF_SIZE, &nVisualWidth, 0);
s_Name(i, buff);
free_lbuf(buff);
s_Location(i, getref(f));
}
}
else
{
s_Location(i, getref(f));
}
/*
* ZONE on MUSE databases and some others
*/
if (read_zone)
s_Zone(i, getref(f));
/*
* else
* * s_Zone(i, NOTHING);
*/
/*
* CONTENTS and EXITS
*/
s_Contents(i, getref(f));
s_Exits(i, getref(f));
/*
* LINK
*/
if (read_link)
s_Link(i, getref(f));
else
s_Link(i, NOTHING);
/*
* NEXT
*/
s_Next(i, getref(f));
/*
* LOCK
*/
if (read_key) {
tempbool = getboolexp(f);
atr_add_raw(i, A_LOCK,
unparse_boolexp_quiet(1, tempbool));
free_boolexp(tempbool);
}
/*
* OWNER
*/
s_Owner(i, getref(f));
/*
* PARENT: PennMUSH uses this field for ZONE
* (which we use as PARENT if we
* didn't already read in a
* non-NOTHING parent.
*/
if (read_parent) {
s_Parent(i, getref(f));
} else {
s_Parent(i, NOTHING);
}
/*
* PENNIES
*/
if (read_money) /*
* if not fix in
* unscraw_foreign
*/
s_Pennies(i, getref(f));
/*
* FLAGS
*/
f1 = getref(f);
if (read_extflags)
f2 = getref(f);
else
f2 = 0;
if (read_3flags)
f3 = getref(f);
else
f3 = 0;
#ifdef STANDALONE
upgrade_flags(&f1, &f2, &f3, i, g_format, g_version);
#endif
s_Flags(i, f1);
s_Flags2(i, f2);
s_Flags3(i, f3);
#ifdef STANDALONE
/*
* POWERS from MUSE. Discard.
*/
if (read_powers_any ||
((Typeof(i) == TYPE_PLAYER) && read_powers_player))
(void)getstring_noalloc(f, 0);
#endif
if (read_powers) {
f1 = getref(f);
f2 = getref(f);
s_Powers(i, f1);
s_Powers2(i, f2);
}
/*
* ATTRIBUTES
*/
if (read_attribs)
{
if (!get_list(f, i, read_new_strings))
{
Log.printf("\nError reading attrs for object #%d\n", i);
return -1;
}
}
#ifdef STANDALONE
/*
* PARENTS from MUSE. Ewwww.
*/
if (read_muse_parents) {
getlist_discard(f, i, 1);
getlist_discard(f, i, 0);
}
/*
* ATTRIBUTE DEFINITIONS from MUSE. Ewwww. *
* Ewwww.
*/
if (read_muse_atrdefs) {
get_atrdefs_discard(f);
}
/*
* Fix up MUSH 2.2's weird quota system
*/
if ((g_format == F_MUSH) && (g_version == 8))
fix_typed_quotas(i);
#endif
/*
* check to see if it's a player
*/
if (Typeof(i) == TYPE_PLAYER) {
c_Connected(i);
}
#ifdef STANDALONE
}
#endif
break;
case '*': /*
* EOF marker
*/
tstr = getstring_noalloc(f, 0);
if (strncmp(tstr, "**END OF DUMP***", 16))
{
Log.printf("\nBad EOF marker at object #%d\n", i);
return -1;
}
else
{
#ifdef STANDALONE
Log.WriteString("\n");
Log.Flush();
#endif
/*
* Fix up bizarro foreign DBs
*/
#ifdef STANDALONE
unscraw_foreign(g_format, g_version, g_flags);
#endif
*db_version = g_version;
*db_format = g_format;
*db_flags = g_flags;
#ifndef STANDALONE
load_player_names();
#endif
return mudstate.db_top;
}
default:
if (Tiny_IsPrint[(unsigned char)ch])
{
Log.printf("\nIllegal character '%c' near object #%d\n", ch, i);
}
else
{
Log.printf("\nIllegal character 0x%02x near object #%d\n", ch, i);
}
return -1;
}
}
}
static int db_write_object(FILE *f, dbref i, int db_format, int flags)
{
#ifndef STANDALONE
ATTR *a;
#endif
char *got, *as;
dbref aowner;
int ca, aflags, j;
BOOLEXP *tempbool;
if (!(flags & V_ATRNAME))
{
putstring(f, Name(i));
}
putref(f, Location(i));
if (flags & V_ZONE)
{
putref(f, Zone(i));
}
putref(f, Contents(i));
putref(f, Exits(i));
if (flags & V_LINK)
{
putref(f, Link(i));
}
putref(f, Next(i));
if (!(flags & V_ATRKEY))
{
got = atr_get(i, A_LOCK, &aowner, &aflags);
tempbool = parse_boolexp(GOD, got, 1);
free_lbuf(got);
putboolexp(f, tempbool);
if (tempbool)
{
free_bool(tempbool);
}
}
putref(f, Owner(i));
if (flags & V_PARENT)
{
putref(f, Parent(i));
}
if (!(flags & V_ATRMONEY))
{
putref(f, Pennies(i));
}
putref(f, Flags(i));
if (flags & V_XFLAGS)
{
putref(f, Flags2(i));
}
if (flags & V_3FLAGS)
{
putref(f, Flags3(i));
}
if (flags & V_POWERS)
{
putref(f, Powers(i));
putref(f, Powers2(i));
}
// Write the attribute list.
//
if ((!(flags & V_GDBM)))
{
char buf[SBUF_SIZE];
buf[0] = '>';
for (ca = atr_head(i, &as); ca; ca = atr_next(&as))
{
#ifndef STANDALONE
a = atr_num(ca);
if (!a)
{
continue;
}
j = a->number;
#else
j = ca;
#endif
if (j < A_USER_START)
{
switch (j)
{
case A_NAME:
if (!(flags & V_ATRNAME))
{
continue;
}
break;
case A_LOCK:
if (!(flags & V_ATRKEY))
{
continue;
}
break;
case A_LIST:
case A_MONEY:
continue;
}
}
// Format is: ">%d\n", j
//
got = atr_get_raw(i, j);
int n = Tiny_ltoa(j, buf+1) + 1;
buf[n++] = '\n';
fwrite(buf, sizeof(char), n, f);
putstring(f, got);
}
fwrite("<\n", sizeof(char), 2, f);
}
return 0;
}
dbref db_write(FILE *f, int format, int version)
{
dbref i;
int flags;
VATTR *vp;
#ifndef MEMORY_BASED
al_store();
#endif // MEMORY_BASED
switch (format)
{
case F_MUX:
flags = version;
break;
default:
Log.WriteString("Can only write MUX format.\n");
return -1;
}
#ifdef STANDALONE
Log.WriteString("Writing ");
Log.Flush();
#endif
i = mudstate.attr_next;
fprintf(f, "+X%d\n+S%d\n+N%d\n", flags, mudstate.db_top, i);
fprintf(f, "-R%d\n", mudstate.record_players);
// Dump user-named attribute info.
//
vp = vattr_first();
char Buffer[LBUF_SIZE];
Buffer[0] = '+';
Buffer[1] = 'A';
while (vp != NULL)
{
if (!(vp->flags & AF_DELETED))
{
// Format is: "+A%d\n\"%d:%s\"\n", vp->number, vp->flags, vp->name
//
char *pBuffer = Buffer+2;
pBuffer += Tiny_ltoa(vp->number, pBuffer);
*pBuffer++ = '\n';
*pBuffer++ = '"';
pBuffer += Tiny_ltoa(vp->flags, pBuffer);
*pBuffer++ = ':';
int nNameLength = strlen(vp->name);
memcpy(pBuffer, vp->name, nNameLength);
pBuffer += nNameLength;
*pBuffer++ = '"';
*pBuffer++ = '\n';
fwrite(Buffer, sizeof(char), pBuffer-Buffer, f);
}
vp = vattr_next(vp);
}
#ifdef STANDALONE
int iDotCounter = 0;
#endif
char buf[SBUF_SIZE];
buf[0] = '!';
DO_WHOLE_DB(i)
{
#ifdef STANDALONE
if (!iDotCounter)
{
iDotCounter = 100;
fputc('.', stderr);
fflush(stderr);
}
iDotCounter--;
#endif // STANDALONE
if (!(Going(i)))
{
// Format is: "!%d\n", i
//
int n = Tiny_ltoa(i, buf+1) + 1;
buf[n++] = '\n';
fwrite(buf, sizeof(char), n, f);
db_write_object(f, i, format, flags);
}
}
fputs("***END OF DUMP***\n", f);
#ifdef STANDALONE
Log.WriteString("\n");
Log.Flush();
#endif
return mudstate.db_top;
}