00001
00002
00003
00004
00005
00006 #include "copyright.h"
00007 #include "autoconf.h"
00008 #include "config.h"
00009 #include "externs.h"
00010
00011 #include "attrs.h"
00012 #include "vattr.h"
00013
00014 static int g_version;
00015 static int g_format;
00016 static int g_flags;
00017
00018
00019
00020
00021
00022 static BOOLEXP *getboolexp1(FILE *f)
00023 {
00024 BOOLEXP *b;
00025 char *buff, *s;
00026 int d, anum;
00027
00028 int c = getc(f);
00029 switch (c)
00030 {
00031 case '\n':
00032 ungetc(c, f);
00033 return TRUE_BOOLEXP;
00034
00035 case EOF:
00036
00037
00038
00039 mux_assert(0);
00040 break;
00041
00042 case '(':
00043 b = alloc_bool("getboolexp1.openparen");
00044 switch (c = getc(f))
00045 {
00046 case NOT_TOKEN:
00047 b->type = BOOLEXP_NOT;
00048 b->sub1 = getboolexp1(f);
00049 if ((d = getc(f)) == '\n')
00050 {
00051 d = getc(f);
00052 }
00053 if (d != ')')
00054 {
00055 goto error;
00056 }
00057 return b;
00058
00059 case INDIR_TOKEN:
00060 b->type = BOOLEXP_INDIR;
00061 b->sub1 = getboolexp1(f);
00062 if ((d = getc(f)) == '\n')
00063 {
00064 d = getc(f);
00065 }
00066 if (d != ')')
00067 {
00068 goto error;
00069 }
00070 return b;
00071
00072 case IS_TOKEN:
00073 b->type = BOOLEXP_IS;
00074 b->sub1 = getboolexp1(f);
00075 if ((d = getc(f)) == '\n')
00076 {
00077 d = getc(f);
00078 }
00079 if (d != ')')
00080 {
00081 goto error;
00082 }
00083 return b;
00084
00085 case CARRY_TOKEN:
00086 b->type = BOOLEXP_CARRY;
00087 b->sub1 = getboolexp1(f);
00088 if ((d = getc(f)) == '\n')
00089 {
00090 d = getc(f);
00091 }
00092 if (d != ')')
00093 {
00094 goto error;
00095 }
00096 return b;
00097
00098 case OWNER_TOKEN:
00099 b->type = BOOLEXP_OWNER;
00100 b->sub1 = getboolexp1(f);
00101 if ((d = getc(f)) == '\n')
00102 {
00103 d = getc(f);
00104 }
00105 if (d != ')')
00106 {
00107 goto error;
00108 }
00109 return b;
00110
00111 default:
00112 ungetc(c, f);
00113 b->sub1 = getboolexp1(f);
00114 if ((c = getc(f)) == '\n')
00115 {
00116 c = getc(f);
00117 }
00118 switch (c)
00119 {
00120 case AND_TOKEN:
00121 b->type = BOOLEXP_AND;
00122 break;
00123
00124 case OR_TOKEN:
00125 b->type = BOOLEXP_OR;
00126 break;
00127
00128 default:
00129 goto error;
00130 }
00131 b->sub2 = getboolexp1(f);
00132 if ((d = getc(f)) == '\n')
00133 {
00134 d = getc(f);
00135 }
00136 if (d != ')')
00137 {
00138 goto error;
00139 }
00140 return b;
00141 }
00142
00143 case '-':
00144
00145
00146
00147 while ((c = getc(f)) != '\n')
00148 {
00149 mux_assert(c != EOF);
00150 }
00151 ungetc(c, f);
00152 return TRUE_BOOLEXP;
00153
00154 case '"':
00155 ungetc(c, f);
00156 buff = alloc_lbuf("getboolexp_quoted");
00157 strcpy(buff, getstring_noalloc(f, 1));
00158 c = fgetc(f);
00159 if (c == EOF)
00160 {
00161 free_lbuf(buff);
00162 return TRUE_BOOLEXP;
00163 }
00164
00165 b = alloc_bool("getboolexp1_quoted");
00166 anum = mkattr(GOD, buff);
00167 if (anum <= 0)
00168 {
00169 free_bool(b);
00170 free_lbuf(buff);
00171 goto error;
00172 }
00173 free_lbuf(buff);
00174 b->thing = anum;
00175
00176
00177
00178
00179 if ( c == ':'
00180 || c == '/')
00181 {
00182 if (c == '/')
00183 {
00184 b->type = BOOLEXP_EVAL;
00185 }
00186 else
00187 {
00188 b->type = BOOLEXP_ATR;
00189 }
00190 buff = alloc_lbuf("getboolexp1.attr_lock");
00191 strcpy(buff, getstring_noalloc(f, 1));
00192 b->sub1 = (BOOLEXP *)StringClone(buff);
00193 free_lbuf(buff);
00194 }
00195 return b;
00196
00197 default:
00198
00199 ungetc(c, f);
00200 b = alloc_bool("getboolexp1.default");
00201 b->type = BOOLEXP_CONST;
00202 b->thing = 0;
00203
00204
00205
00206
00207
00208
00209 if (mux_isdigit(c))
00210 {
00211 while (mux_isdigit(c = getc(f)))
00212 {
00213 b->thing = b->thing * 10 + c - '0';
00214 }
00215 }
00216 else if (mux_AttrNameInitialSet(c))
00217 {
00218 buff = alloc_lbuf("getboolexp1.atr_name");
00219
00220 for ( s = buff;
00221
00222 (c = getc(f)) != EOF
00223 && c != '\n'
00224 && c != ':'
00225 && c != '/'
00226 && s < buff + LBUF_SIZE;
00227
00228 *s++ = (char)c)
00229 {
00230 ;
00231 }
00232
00233 if (c == EOF)
00234 {
00235 free_lbuf(buff);
00236 free_bool(b);
00237 goto error;
00238 }
00239 *s = '\0';
00240
00241
00242
00243
00244 anum = mkattr(GOD, buff);
00245 if (anum <= 0)
00246 {
00247 free_bool(b);
00248 free_lbuf(buff);
00249 goto error;
00250 }
00251 free_lbuf(buff);
00252 b->thing = anum;
00253 }
00254 else
00255 {
00256 free_bool(b);
00257 goto error;
00258 }
00259
00260
00261
00262
00263 if ( c == ':'
00264 || c == '/')
00265 {
00266 if (c == '/')
00267 {
00268 b->type = BOOLEXP_EVAL;
00269 }
00270 else
00271 {
00272 b->type = BOOLEXP_ATR;
00273 }
00274 buff = alloc_lbuf("getboolexp1.attr_lock");
00275 for ( s = buff;
00276
00277 (c = getc(f)) != EOF
00278 && c != '\n'
00279 && c != ')'
00280 && c != OR_TOKEN
00281 && c != AND_TOKEN
00282 && s < buff + LBUF_SIZE;
00283
00284 *s++ = (char)c)
00285 {
00286 ;
00287 }
00288 if (c == EOF)
00289 {
00290 goto error;
00291 }
00292 *s++ = 0;
00293 b->sub1 = (BOOLEXP *)StringClone(buff);
00294 free_lbuf(buff);
00295 }
00296 ungetc(c, f);
00297 return b;
00298 }
00299
00300 error:
00301
00302
00303
00304 mux_assert(0);
00305 return TRUE_BOOLEXP;
00306 }
00307
00308
00309
00310
00311
00312 static BOOLEXP *getboolexp(FILE *f)
00313 {
00314 BOOLEXP *b = getboolexp1(f);
00315 int c = getc(f);
00316 mux_assert(c == '\n');
00317
00318 if (g_format == F_MUX)
00319 {
00320 if ((c = getc(f)) != '\n')
00321 {
00322 ungetc(c, f);
00323 }
00324 }
00325 return b;
00326 }
00327
00328
00329
00330
00331
00332 static bool get_list(FILE *f, dbref i)
00333 {
00334 char *buff = alloc_lbuf("get_list");
00335 for (;;)
00336 {
00337 dbref atr;
00338 int c;
00339 switch (c = getc(f))
00340 {
00341 case '>':
00342 atr = getref(f);
00343 if (atr > 0)
00344 {
00345
00346
00347 atr_add_raw(i, atr, getstring_noalloc(f, true));
00348 }
00349 else
00350 {
00351
00352
00353 getstring_noalloc(f, true);
00354 }
00355 break;
00356
00357 case '\n':
00358
00359 break;
00360
00361 case '<':
00362
00363 free_lbuf(buff);
00364 c = getc(f);
00365 if (c != '\n')
00366 {
00367 ungetc(c, f);
00368 Log.tinyprintf("No line feed on object %d" ENDLINE, i);
00369 return true;
00370 }
00371 return true;
00372
00373 default:
00374 Log.tinyprintf("Bad character '%c' when getting attributes on object %d" ENDLINE, c, i);
00375
00376
00377
00378 getstring_noalloc(f, true);
00379 }
00380 }
00381 }
00382
00383
00384
00385
00386 static void putbool_subexp(FILE *f, BOOLEXP *b)
00387 {
00388 ATTR *va;
00389
00390 switch (b->type)
00391 {
00392 case BOOLEXP_IS:
00393
00394 putc('(', f);
00395 putc(IS_TOKEN, f);
00396 putbool_subexp(f, b->sub1);
00397 putc(')', f);
00398 break;
00399
00400 case BOOLEXP_CARRY:
00401
00402 putc('(', f);
00403 putc(CARRY_TOKEN, f);
00404 putbool_subexp(f, b->sub1);
00405 putc(')', f);
00406 break;
00407
00408 case BOOLEXP_INDIR:
00409
00410 putc('(', f);
00411 putc(INDIR_TOKEN, f);
00412 putbool_subexp(f, b->sub1);
00413 putc(')', f);
00414 break;
00415
00416 case BOOLEXP_OWNER:
00417
00418 putc('(', f);
00419 putc(OWNER_TOKEN, f);
00420 putbool_subexp(f, b->sub1);
00421 putc(')', f);
00422 break;
00423
00424 case BOOLEXP_AND:
00425
00426 putc('(', f);
00427 putbool_subexp(f, b->sub1);
00428 putc(AND_TOKEN, f);
00429 putbool_subexp(f, b->sub2);
00430 putc(')', f);
00431 break;
00432
00433 case BOOLEXP_OR:
00434
00435 putc('(', f);
00436 putbool_subexp(f, b->sub1);
00437 putc(OR_TOKEN, f);
00438 putbool_subexp(f, b->sub2);
00439 putc(')', f);
00440 break;
00441
00442 case BOOLEXP_NOT:
00443
00444 putc('(', f);
00445 putc(NOT_TOKEN, f);
00446 putbool_subexp(f, b->sub1);
00447 putc(')', f);
00448 break;
00449
00450 case BOOLEXP_CONST:
00451
00452 putref(f, b->thing);
00453 break;
00454
00455 case BOOLEXP_ATR:
00456
00457 va = atr_num(b->thing);
00458 if (va)
00459 {
00460 fprintf(f, "%s:%s", va->name, (char *)b->sub1);
00461 }
00462 else
00463 {
00464 fprintf(f, "%d:%s\n", b->thing, (char *)b->sub1);
00465 }
00466 break;
00467
00468 case BOOLEXP_EVAL:
00469
00470 va = atr_num(b->thing);
00471 if (va)
00472 {
00473 fprintf(f, "%s/%s\n", va->name, (char *)b->sub1);
00474 }
00475 else
00476 {
00477 fprintf(f, "%d/%s\n", b->thing, (char *)b->sub1);
00478 }
00479 break;
00480
00481 default:
00482
00483 Log.tinyprintf("Unknown boolean type in putbool_subexp: %d" ENDLINE, b->type);
00484 break;
00485 }
00486 }
00487
00488
00489
00490
00491
00492 static void putboolexp(FILE *f, BOOLEXP *b)
00493 {
00494 if (b != TRUE_BOOLEXP)
00495 {
00496 putbool_subexp(f, b);
00497 }
00498 putc('\n', f);
00499 }
00500
00501 dbref db_read(FILE *f, int *db_format, int *db_version, int *db_flags)
00502 {
00503 dbref i, anum;
00504 int ch;
00505 const char *tstr;
00506 int aflags;
00507 BOOLEXP *tempbool;
00508 char *buff;
00509 int nVisualWidth;
00510
00511 g_format = F_UNKNOWN;
00512 g_version = 0;
00513 g_flags = 0;
00514
00515 bool header_gotten = false;
00516 bool size_gotten = false;
00517 bool nextattr_gotten = false;
00518
00519 bool read_attribs = true;
00520 bool read_name = true;
00521 bool read_key = true;
00522 bool read_money = true;
00523
00524 int nName;
00525 bool bValid;
00526 char *pName;
00527
00528 int iDotCounter = 0;
00529 if (mudstate.bStandAlone)
00530 {
00531 Log.WriteString("Reading ");
00532 Log.Flush();
00533 }
00534 db_free();
00535 for (i = 0;; i++)
00536 {
00537 if (mudstate.bStandAlone)
00538 {
00539 if (!iDotCounter)
00540 {
00541 iDotCounter = 100;
00542 fputc('.', stderr);
00543 fflush(stderr);
00544 }
00545 iDotCounter--;
00546 }
00547
00548 ch = getc(f);
00549 switch (ch)
00550 {
00551 case '-':
00552 ch = getc(f);
00553 if (ch == 'R')
00554 {
00555
00556
00557 mudstate.record_players = getref(f);
00558 if (mudconf.reset_players)
00559 {
00560 mudstate.record_players = 0;
00561 }
00562 }
00563 break;
00564
00565 case '+':
00566
00567
00568
00569 ch = getc(f);
00570 if (ch == 'A')
00571 {
00572
00573
00574 anum = getref(f);
00575 tstr = getstring_noalloc(f, true);
00576 if (mux_isdigit(*tstr))
00577 {
00578 aflags = 0;
00579 while (mux_isdigit(*tstr))
00580 {
00581 aflags = (aflags * 10) + (*tstr++ - '0');
00582 }
00583 tstr++;
00584 }
00585 else
00586 {
00587 aflags = mudconf.vattr_flags;
00588 }
00589 pName = MakeCanonicalAttributeName(tstr, &nName, &bValid);
00590 if (bValid)
00591 {
00592 vattr_define_LEN(pName, nName, anum, aflags);
00593 }
00594 }
00595 else if (ch == 'X')
00596 {
00597
00598
00599 if (header_gotten)
00600 {
00601 Log.tinyprintf(ENDLINE "Duplicate MUX version header entry at object %d, ignored." ENDLINE, i);
00602 tstr = getstring_noalloc(f, 0);
00603 }
00604 else
00605 {
00606 header_gotten = true;
00607 g_format = F_MUX;
00608 g_version = getref(f);
00609 mux_assert((g_version & MANDFLAGS) == MANDFLAGS);
00610
00611
00612
00613 if (g_version & V_DATABASE)
00614 {
00615 read_attribs = false;
00616 read_name = !(g_version & V_ATRNAME);
00617 }
00618 read_key = !(g_version & V_ATRKEY);
00619 read_money = !(g_version & V_ATRMONEY);
00620 g_flags = g_version & ~V_MASK;
00621
00622 g_version &= V_MASK;
00623 if ( g_version < MIN_SUPPORTED_VERSION
00624 || MAX_SUPPORTED_VERSION < g_version)
00625 {
00626 Log.tinyprintf(ENDLINE "Unsupported flatfile version: %d." ENDLINE, g_version);
00627 return -1;
00628 }
00629 }
00630 }
00631 else if (ch == 'S')
00632 {
00633
00634
00635 if (size_gotten)
00636 {
00637 Log.tinyprintf(ENDLINE "Duplicate size entry at object %d, ignored." ENDLINE, i);
00638 tstr = getstring_noalloc(f, 0);
00639 }
00640 else
00641 {
00642 mudstate.min_size = getref(f);
00643 size_gotten = true;
00644 }
00645 }
00646 else if (ch == 'N')
00647 {
00648
00649
00650 if (nextattr_gotten)
00651 {
00652 Log.tinyprintf(ENDLINE "Duplicate next free vattr entry at object %d, ignored." ENDLINE, i);
00653 tstr = getstring_noalloc(f, 0);
00654 }
00655 else
00656 {
00657 mudstate.attr_next = getref(f);
00658 nextattr_gotten = true;
00659 }
00660 }
00661 else
00662 {
00663 Log.tinyprintf(ENDLINE "Unexpected character '%c' in MUX header near object #%d, ignored." ENDLINE, ch, i);
00664 tstr = getstring_noalloc(f, 0);
00665 }
00666 break;
00667
00668 case '!':
00669 i = getref(f);
00670 db_grow(i + 1);
00671
00672 if (read_name)
00673 {
00674 tstr = getstring_noalloc(f, true);
00675 buff = alloc_lbuf("dbread.s_Name");
00676 (void)ANSI_TruncateToField(tstr, MBUF_SIZE, buff, MBUF_SIZE,
00677 &nVisualWidth, ANSI_ENDGOAL_NORMAL);
00678 s_Name(i, buff);
00679 free_lbuf(buff);
00680
00681 s_Location(i, getref(f));
00682 }
00683 else
00684 {
00685 s_Location(i, getref(f));
00686 }
00687
00688
00689
00690 int zone;
00691 zone = getref(f);
00692 if (zone < NOTHING)
00693 {
00694 zone = NOTHING;
00695 }
00696 s_Zone(i, zone);
00697
00698
00699
00700 s_Contents(i, getref(f));
00701 s_Exits(i, getref(f));
00702
00703
00704
00705 s_Link(i, getref(f));
00706
00707
00708
00709 s_Next(i, getref(f));
00710
00711
00712
00713 if (read_key)
00714 {
00715 tempbool = getboolexp(f);
00716 atr_add_raw(i, A_LOCK,
00717 unparse_boolexp_quiet(1, tempbool));
00718 free_boolexp(tempbool);
00719 }
00720
00721
00722
00723 s_Owner(i, getref(f));
00724
00725
00726
00727 s_Parent(i, getref(f));
00728
00729
00730
00731 if (read_money)
00732 {
00733 s_PenniesDirect(i, getref(f));
00734 }
00735
00736
00737
00738 s_Flags(i, FLAG_WORD1, getref(f));
00739 s_Flags(i, FLAG_WORD2, getref(f));
00740 s_Flags(i, FLAG_WORD3, getref(f));
00741
00742
00743
00744 s_Powers(i, getref(f));
00745 s_Powers2(i, getref(f));
00746
00747
00748
00749 if (read_attribs)
00750 {
00751 if (!get_list(f, i))
00752 {
00753 Log.tinyprintf(ENDLINE "Error reading attrs for object #%d" ENDLINE, i);
00754 return -1;
00755 }
00756 }
00757
00758
00759
00760 if (isPlayer(i))
00761 {
00762 c_Connected(i);
00763 }
00764 break;
00765
00766 case '*':
00767 tstr = getstring_noalloc(f, 0);
00768 if (strncmp(tstr, "**END OF DUMP***", 16))
00769 {
00770 Log.tinyprintf(ENDLINE "Bad EOF marker at object #%d" ENDLINE, i);
00771 return -1;
00772 }
00773 else
00774 {
00775 *db_version = g_version;
00776 *db_format = g_format;
00777 *db_flags = g_flags;
00778 if (mudstate.bStandAlone)
00779 {
00780 Log.WriteString(ENDLINE);
00781 Log.Flush();
00782 }
00783 else
00784 {
00785 load_player_names();
00786 }
00787 return mudstate.db_top;
00788 }
00789
00790 case EOF:
00791 Log.tinyprintf(ENDLINE "Unexpected end of file near object #%d" ENDLINE, i);
00792 return -1;
00793
00794 default:
00795 if (mux_isprint(ch))
00796 {
00797 Log.tinyprintf(ENDLINE "Illegal character '%c' near object #%d" ENDLINE, ch, i);
00798 }
00799 else
00800 {
00801 Log.tinyprintf(ENDLINE "Illegal character 0x%02x near object #%d" ENDLINE, ch, i);
00802 }
00803 return -1;
00804 }
00805 }
00806 }
00807
00808 static bool db_write_object(FILE *f, dbref i, int db_format, int flags)
00809 {
00810 UNUSED_PARAMETER(db_format);
00811
00812 ATTR *a;
00813 char *got, *as;
00814 dbref aowner;
00815 int ca, aflags, j;
00816 BOOLEXP *tempbool;
00817
00818 if (!(flags & V_ATRNAME))
00819 {
00820 putstring(f, Name(i));
00821 }
00822 putref(f, Location(i));
00823 putref(f, Zone(i));
00824 putref(f, Contents(i));
00825 putref(f, Exits(i));
00826 putref(f, Link(i));
00827 putref(f, Next(i));
00828 if (!(flags & V_ATRKEY))
00829 {
00830 got = atr_get(i, A_LOCK, &aowner, &aflags);
00831 tempbool = parse_boolexp(GOD, got, true);
00832 free_lbuf(got);
00833 putboolexp(f, tempbool);
00834 if (tempbool)
00835 {
00836 free_boolexp(tempbool);
00837 }
00838 }
00839 putref(f, Owner(i));
00840 putref(f, Parent(i));
00841 if (!(flags & V_ATRMONEY))
00842 {
00843 putref(f, Pennies(i));
00844 }
00845 putref(f, Flags(i));
00846 putref(f, Flags2(i));
00847 putref(f, Flags3(i));
00848 putref(f, Powers(i));
00849 putref(f, Powers2(i));
00850
00851
00852
00853 if (!(flags & V_DATABASE))
00854 {
00855 char buf[SBUF_SIZE];
00856 buf[0] = '>';
00857 for (ca = atr_head(i, &as); ca; ca = atr_next(&as))
00858 {
00859 if (mudstate.bStandAlone)
00860 {
00861 j = ca;
00862 }
00863 else
00864 {
00865 a = atr_num(ca);
00866 if (!a)
00867 {
00868 continue;
00869 }
00870 j = a->number;
00871 }
00872
00873 if (j < A_USER_START)
00874 {
00875 switch (j)
00876 {
00877 case A_NAME:
00878 if (!(flags & V_ATRNAME))
00879 {
00880 continue;
00881 }
00882 break;
00883
00884 case A_LOCK:
00885 if (!(flags & V_ATRKEY))
00886 {
00887 continue;
00888 }
00889 break;
00890
00891 case A_LIST:
00892 case A_MONEY:
00893 continue;
00894 }
00895 }
00896
00897
00898
00899 const char *p = atr_get_raw(i, j);
00900 int n = mux_ltoa(j, buf+1) + 1;
00901 buf[n++] = '\n';
00902 fwrite(buf, sizeof(char), n, f);
00903 putstring(f, p);
00904 }
00905 fwrite("<\n", sizeof(char), 2, f);
00906 }
00907 return false;
00908 }
00909
00910 dbref db_write(FILE *f, int format, int version)
00911 {
00912 dbref i;
00913 int flags;
00914 ATTR *vp;
00915
00916 switch (format)
00917 {
00918 case F_MUX:
00919 flags = version;
00920 break;
00921
00922 default:
00923 Log.WriteString("Can only write MUX format." ENDLINE);
00924 return -1;
00925 }
00926 if (mudstate.bStandAlone)
00927 {
00928 Log.WriteString("Writing ");
00929 Log.Flush();
00930 }
00931 i = mudstate.attr_next;
00932 fprintf(f, "+X%d\n+S%d\n+N%d\n", flags, mudstate.db_top, i);
00933 fprintf(f, "-R%d\n", mudstate.record_players);
00934
00935
00936
00937 char Buffer[LBUF_SIZE];
00938 Buffer[0] = '+';
00939 Buffer[1] = 'A';
00940 int iAttr;
00941 for (iAttr = A_USER_START; iAttr <= anum_alc_top; iAttr++)
00942 {
00943 vp = (ATTR *) anum_get(iAttr);
00944 if ( vp != NULL
00945 && !(vp->flags & AF_DELETED))
00946 {
00947
00948
00949 char *pBuffer = Buffer+2;
00950 pBuffer += mux_ltoa(vp->number, pBuffer);
00951 *pBuffer++ = '\n';
00952 *pBuffer++ = '"';
00953 pBuffer += mux_ltoa(vp->flags, pBuffer);
00954 *pBuffer++ = ':';
00955 int nNameLength = strlen(vp->name);
00956 memcpy(pBuffer, vp->name, nNameLength);
00957 pBuffer += nNameLength;
00958 *pBuffer++ = '"';
00959 *pBuffer++ = '\n';
00960 fwrite(Buffer, sizeof(char), pBuffer-Buffer, f);
00961 }
00962 }
00963
00964 int iDotCounter = 0;
00965 char buf[SBUF_SIZE];
00966 buf[0] = '!';
00967 DO_WHOLE_DB(i)
00968 {
00969 if (mudstate.bStandAlone)
00970 {
00971 if (!iDotCounter)
00972 {
00973 iDotCounter = 100;
00974 fputc('.', stderr);
00975 fflush(stderr);
00976 }
00977 iDotCounter--;
00978 }
00979
00980 if (!isGarbage(i))
00981 {
00982
00983
00984 int n = mux_ltoa(i, buf+1) + 1;
00985 buf[n++] = '\n';
00986 fwrite(buf, sizeof(char), n, f);
00987 db_write_object(f, i, format, flags);
00988 }
00989 }
00990 fputs("***END OF DUMP***\n", f);
00991 if (mudstate.bStandAlone)
00992 {
00993 Log.WriteString(ENDLINE);
00994 Log.Flush();
00995 }
00996 return mudstate.db_top;
00997 }