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