/* extract.c */ #include "os.h" #include "copyright.h" #include "config.h" #include "db.h" #include "externs.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 (void) { return NOTHING; } void fix_free_list (void) { } void report (void) { } void parse_que (dbref player, char *command, dbref cause) { } int eval_boolexp (dbref player, struct boolexp *b, dbref privs, int nrecurs, int locktype) { return 1; } int wild_match (char *s, char *d) { return 1; } int controls (dbref a, dbref b) { return 1; } void notify (dbref player, const char *msg) { } void init_match (dbref player, const char *arg, int type) { } void match_everything (void) { } dbref noisy_match_result (void) { return 1; } char *tprintf (char *format, ...) { return (char *) ""; } void panic (const char *message) { fprintf (stderr, "PANIC: %s\n", message); exit (-1); } /*****************************************************************************/ static int include_all = 0; /* include everything unless specified */ static dbref included[MAXCMDLEN + 1]; static dbref excluded[MAXCMDLEN + 1]; static dbref *trans; /* translation vector */ #define DEFAULT_LOCATION (0) #define DEFAULT_OWNER (1) static int isok (dbref); /* returns 1 if it is not excluded */ static int not_excluded (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 (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 (void) { 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 (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 (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 (dbref x) { if (x == NOTHING || x == HOME) { return 1; } else { return trans[x] != NOTHING; } } static void check_bad_exits (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 (dbref x) { if (ok (x) && !ok (db[x].owner)) { db[x].owner = DEFAULT_OWNER; } } static void check_location (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 (dbref x) { dbref next; if (ok (x)) { while (!ok (next = db[x].next)) db[x].next = db[next].next; } } static void check_contents (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 (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 (void) { 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***"); } int main (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); return (0); }