// 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; }