/* extract.c */ #include "copyright.h" #include <stdio.h> #include <sys/param.h> #include "config.h" #include "db.h" /* The following routines are ONLY here to allow linking with a few needed * files. It is okay that they do nothing. */ /*****************************************************************************/ dbref free_get() { return NOTHING; } void fix_free_list() { } void report() { } void parse_que(player, command, cause) dbref player, cause; char *command; { } int eval_boolexp(player, b, privs, nrecurs, locktype) dbref player; struct boolexp *b; dbref privs; int nrecurs; int locktype; { return 1; } int wild_match(s, d) char *s, *d; { return 1; } int controls(a, b) dbref a,b; { return 1; } void notify(player, msg) dbref player; const char *msg; { } void init_match(player, arg, type) dbref player; const char *arg; int type; { } void match_everything() { } dbref noisy_match_result() { return 1; } char *tprintf(format, a, b, c, d, e, f) char *format; int a, b, c, d, e, f; { return (char *)""; } void panic(message) const char *message; { fprintf(stderr, "PANIC: %s\n", message); exit(-1); } /*****************************************************************************/ static int include_all = 0; /* include everything unless specified */ static dbref included[NCARGS + 1]; static dbref excluded[NCARGS + 1]; static dbref *trans; /* translation vector */ #define DEFAULT_LOCATION (0) #define DEFAULT_OWNER (1) static int isok(); /* returns 1 if it is not excluded */ static int not_excluded(x) dbref x; { int i; /* check that it isn't excluded */ for (i = 0; excluded[i] != NOTHING; i++) { if (excluded[i] == x || excluded[i] == db[x].owner) /* exclude specifics, but also exclude something that is owned by * a direct exclusion to prevent conflicts. */ return 0; } /* if it's an exit, check that its destination is ok */ if (Typeof(x) == TYPE_EXIT && db[x].location != x) { return isok(db[x].location); } else { return 1; } } /* returns 1 if it should be included in translation vector */ static int isok(x) dbref x; { int i; if (x == DEFAULT_OWNER || x == DEFAULT_LOCATION) return 1; for (i = 0; included[i] != NOTHING; i++) { if (included[i] == x) return 1; /* always get specific ones */ if (included[i] == db[x].owner) { return not_excluded(x); } } /* not in the list, can only get it if include_all is on */ /* or it's owned by DEFAULT_OWNER */ return (include_all && not_excluded(x)); } static void build_trans() { dbref i; dbref val; if ((trans = (dbref *) malloc(sizeof(dbref) * db_top)) == 0) { abort(); } val = 0; for (i = 0; i < db_top; i++) { if (isok(i)) { trans[i] = val++; } else { trans[i] = NOTHING; } } } static dbref translate(x) dbref x; { if (x == NOTHING || x == HOME) { return (x); } else { return (trans[x]); } } /* TRUE_BOOLEXP means throw this argument out */ /* even on OR; it's effectively a null boolexp */ /* NOTE: this doesn't free anything, it just munges it up */ static struct boolexp *translate_boolexp(exp) struct boolexp *exp; { struct boolexp *s1; struct boolexp *s2; if (exp == TRUE_BOOLEXP) { return TRUE_BOOLEXP; } else { switch (exp->type) { case BOOLEXP_NOT: case BOOLEXP_IND: case BOOLEXP_IS: case BOOLEXP_CARRY: s1 = translate_boolexp(exp->sub1); if (s1 == TRUE_BOOLEXP) { return TRUE_BOOLEXP; } else { exp->sub1 = s1; return exp; } /* break; */ case BOOLEXP_AND: case BOOLEXP_OR: s1 = translate_boolexp(exp->sub1); s2 = translate_boolexp(exp->sub2); if (s1 == TRUE_BOOLEXP && s2 == TRUE_BOOLEXP) { /* nothing left */ return TRUE_BOOLEXP; } else if (s1 == TRUE_BOOLEXP && s2 != TRUE_BOOLEXP) { /* s2 is all that is left */ return s2; } else if (s1 != TRUE_BOOLEXP && s2 == TRUE_BOOLEXP) { /* s1 is all that is left */ return s1; } else { exp->sub1 = s1; exp->sub2 = s2; return exp; } /* break; */ case BOOLEXP_ATR: return exp; case BOOLEXP_CONST: exp->thing = translate(exp->thing); if (exp->thing == NOTHING) { return TRUE_BOOLEXP; } else { return exp; } /* break; */ default: abort(); /* bad boolexp type, we lose */ return TRUE_BOOLEXP; } } } static int ok(x) dbref x; { if (x == NOTHING || x == HOME) { return 1; } else { return trans[x] != NOTHING; } } static void check_bad_exits(x) dbref x; { dbref e; if (Typeof(x) == TYPE_ROOM && !isok(x)) { /* mark all exits as excluded */ DOLIST(e, db[x].exits) { trans[e] = NOTHING; } } } static void check_owner(x) dbref x; { if (ok(x) && !ok(db[x].owner)) { db[x].owner = DEFAULT_OWNER; } } static void check_location(x) dbref x; { dbref loc; dbref newloc; if (ok(x) && (Typeof(x) == TYPE_THING || Typeof(x) == TYPE_PLAYER) && !ok(loc = db[x].location)) { /* move it to home or DEFAULT_LOCATION */ if (ok(db[x].exits)) { newloc = db[x].exits; /* home */ } else { newloc = DEFAULT_LOCATION; } db[loc].contents = remove_first(db[loc].contents, x); PUSH(x, db[newloc].contents); db[x].location = newloc; } } static void check_next(x) dbref x; { dbref next; if (ok(x)) { while (!ok(next = db[x].next)) db[x].next = db[next].next; } } static void check_contents(x) dbref x; { dbref c; if (ok(x)) { while (!ok(c = db[x].contents)) db[x].contents = db[c].next; } } /* also updates home */ /* MUST BE CALLED AFTER check_owner! */ static void check_exits(x) dbref x; { dbref e; if (ok(x) && !ok(e = db[x].exits)) { switch (Typeof(x)) { case TYPE_ROOM: while (!ok(e = db[x].exits)) db[x].exits = db[e].next; break; case TYPE_PLAYER: case TYPE_THING: if (ok(db[db[x].owner].exits)) { /* set it to owner's home */ db[x].exits = db[db[x].owner].exits; /* home */ } else { /* set it to DEFAULT_LOCATION */ db[x].exits = DEFAULT_LOCATION; /* home */ } break; } } } static void do_write() { dbref i; dbref kludge; /* this is braindamaged */ /* we have to rebuild the translation map */ /* because part of it may have gotten nuked in check_bad_exits */ for (i = 0, kludge = 0; i < db_top; i++) { if (trans[i] != NOTHING) trans[i] = kludge++; } /* more of a kludge. newer db's need an object count at top */ kludge = 0; for (i = 0; i < db_top; i++) { if(ok(i)) kludge++; } printf("~%d\n", kludge); for (i = 0; i < db_top; i++) { if (ok(i)) { /* translate all object pointers */ db[i].location = translate(db[i].location); db[i].contents = translate(db[i].contents); db[i].exits = translate(db[i].exits); db[i].next = translate(db[i].next); db[i].key = translate_boolexp(db[i].key); db[i].owner = translate(db[i].owner); /* write it out */ printf("!%d\n", translate(i)); /* make it right out the current db * type otherwise we cannot read it * back in! */ db_write_object(stdout, i); } } puts("***END OF DUMP***"); } void main(argc, argv) int argc; char **argv; { dbref i; int top_in; int top_ex; char *arg0; top_in = 0; top_ex = 0; /* now parse args */ if(argc < 2) { fprintf(stderr,"Usage: %s [all] [{<include_dbref> } {-<exclude_dbref> }]\n", *argv); fprintf(stderr, "\t all -- assume all objects included unless specified\n"); fprintf(stderr, "\t <include> -- specifically include this object\n"); fprintf(stderr, "\t (and anything it owns)\n"); fprintf(stderr, "\t-<exclude> -- specifically exclude this object\n"); fprintf(stderr, "\t (and anything it owns)\n"); exit(-1); } arg0 = *argv; for (argv++, argc--; argc > 0; argv++, argc--) { i = atol(*argv); if (i == 0) { if (!strcmp(*argv, "all")) { include_all = 1; } else { fprintf(stderr, "%s: bogus argument %s\n", arg0, *argv); } } else if (i < 0) { excluded[top_ex++] = -i; } else { included[top_in++] = i; } } /* Terminate */ included[top_in++] = NOTHING; excluded[top_ex++] = NOTHING; /* Load database */ if (db_read(stdin) < 0) { fputs("Database load failed!\n", stderr); exit(1); } fputs("Done loading database...\n", stderr); /* Build translation table */ build_trans(); fputs("Done building translation table...\n", stderr); /* Scan everything */ for (i = 0; i < db_top; i++) check_bad_exits(i); fputs("Done checking bad exits...\n", stderr); for (i = 0; i < db_top; i++) check_owner(i); fputs("Done checking owners...\n", stderr); for (i = 0; i < db_top; i++) check_location(i); fputs("Done checking locations...\n", stderr); for (i = 0; i < db_top; i++) check_next(i); fputs("Done checking next pointers...\n", stderr); for (i = 0; i < db_top; i++) check_contents(i); fputs("Done checking contents...\n", stderr); for (i = 0; i < db_top; i++) check_exits(i); fputs("Done checking homes and exits...\n", stderr); do_write(); fputs("Done.\n", stderr); exit(0); }