/* This software is Copyright 1989, 1990, 1992, 1993 by various individuals. Please see the accompanying file COPYRIGHT for details. */ #include #include #include #include "db.h" #include "defs.h" #include "ctype.h" #include "params.h" #include "config.h" #include "random.h" #include "externs.h" #include "strings.h" #include "property.h" #include "interface.h" #include "pw-crypt.h" #include "pw-a.h" #include "pw-b.h" /* Support for old db formats */ #define ANTILOCK CFLAG #define GENDER_MASK 0x00003000 #define GENDER_SHIFT 12 #define MOUSEFLAGS (CFLAG|EFLAG|KFLAG|PFLAG|RFLAG|XFLAG|YFLAG|ZFLAG) struct object *db = 0; dbref db_top = 0; dbref rec_min; dbref rec_mid; dbref rec_max; int rec_n = 0; int rec_mid_low; #ifdef REC_DEBUG static int rec_debug = 1; #endif #ifndef DB_INITIAL_SIZE #define DB_INITIAL_SIZE 10000 #endif /* DB_INITIAL_SIZE */ dbref db_size; struct macrotable *macrotop; struct plist *new_prop(void); int number(const char *); void putproperties(FILE *, struct plist *); static char *got_dbref = 0; static struct dbref_list *drl_free = 0; static struct dbref_list *drl_block = 0; static int liststrings; static struct dbref_list *alloc_drl(void) { struct dbref_list *d; if (! drl_free) { int n; d = malloc_roundup(8000,&n); d->object = 0xdead0001; d->next = drl_block; drl_block = d; d ++; for (n/=sizeof(struct dbref_list);n>1;n--) { d->object = 0xdead0003; d->next = drl_free; drl_free = d; d ++; } } d = drl_free; drl_free = d->next; d->object = 0xdead0005; return(d); } static void free_drl(struct dbref_list *d) { d->object = 0xdead0007; d->next = drl_free; drl_free = d; } void free_drl_blocks(void) { while (drl_block) { struct dbref_list *d; d = drl_block; drl_block = d->next; d->object = 0xdead0009; free(d); } } /* return true if password is wrong */ int check_password(const char *plaintext, dbref player) { int value; if (strlen(DBFETCH(player)->sp.player.password) == 13) { value = pw_crypt_check(DBFETCH(player)->sp.player.password,plaintext); } else { switch (DBFETCH(player)->sp.player.password[0]) { case 'a': value = pw_a_check(DBFETCH(player)->sp.player.password+1,plaintext); break; case 'b': value = pw_b_check(DBFETCH(player)->sp.player.password+1,plaintext); break; default: value = 1; break; } } return(value); } char *make_password(const char *plaintext) { char *t; char *p; t = pw_b_make(plaintext); cfree(plaintext); p = malloc(1+strlen(t)+1); sprintf(p,"b%s",t); free(t); return(p); } void free_line(struct line *l) { if (l->this_line) free(l->this_line); free(l); } void free_prog_text(struct line *l) { struct line *next; while (l) { next = l->next; free_line(l); l = next; } } void db_clear_object(dbref i) { struct object *o; o = DBFETCH(i); NAME(i) = 0; o->description = NOSTR; o->fail_message = NOSTR; o->succ_message = NOSTR; o->drop_message = NOSTR; o->ofail = NOSTR; o->osuccess = NOSTR; o->odrop = NOSTR; o->location = NOTHING; o->contents = NOTHING; o->next = NOTHING; o->backlinks = 0; o->backlocks = 0; o->backprops = 0; o->sleepers = 0; o->key = TRUE_BOOLEXP; o->properties = 0; #ifdef TIMESTAMPS o->time_created = curtm(); o->time_modified = o->time_created; o->time_used = o->time_created; #endif DBDIRTY(i); /* flags you must initialize yourself */ /* type-specific fields you must also initialize */ } static void db_grow(dbref newtop) { dbref oldtop; struct object *newdb; int i; oldtop = db_top; if (newtop > db_top) { if (! db) { /* make the initial one */ db_size = DB_INITIAL_SIZE; db = (struct object *) malloc(db_size*sizeof(struct object)); if (db == 0) abort(); db_top = 0; #ifdef LOG_DB_GROWTH if (! liststrings) log_status("Created initial db, size %d [%d]",db_size,db_size*sizeof(struct object)); #endif } /* maybe grow it */ if (newtop > db_size) { /* make sure it's big enough */ #ifdef DB_DOUBLING while (newtop > db_size) db_size *= 2; #else db_size = newtop; #endif newdb = (struct object *) realloc((void *)db,db_size*sizeof(struct object)); if (newdb == 0) abort(); db = newdb; #ifdef LOG_DB_GROWTH log_status("Grew db, new size %d [%d]",db_size,db_size*sizeof(struct object)); #endif } db_top = newtop; got_dbref = realloc(got_dbref,newtop); bzero(got_dbref+oldtop,newtop-oldtop); for (i=oldtop;iflags = TYPE_THING; o->sp.thing.home = NOTHING; o->sp.thing.actions = NOTHING; o->sp.thing.value = 0; DBDIRTY(i); } } } static void clear_recyclable(void) { rec_min = -1; rec_mid = -1; rec_max = -1; rec_n = 0; rec_mid_low = 0; #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"clear_recyclable\n"); #endif } static dbref next_garbage(dbref d, int dir) { do { d += dir; } while (Typeof(d) != TYPE_GARBAGE); return(d); } void add_to_recyclable(dbref thing) { #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"add_to_recyclable, %d: ",(int)thing); #endif if (rec_n == 0) { rec_min = thing; rec_mid = thing; rec_max = thing; rec_n = 1; #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"n=0 -> n=1\n"); #endif } else { if (thing < rec_min) { rec_min = thing; #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"[new min] "); #endif } if (thing > rec_max) { rec_max = thing; #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"[new max] "); #endif } if (rec_n & 1) { rec_mid_low = (thing > rec_mid); #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"[odd, mid_low=%d] ",rec_mid_low); #endif } else { if (rec_mid_low && (thing > rec_mid)) { rec_mid = next_garbage(rec_mid,1); #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"[even, >, mid=%d] ",(int)rec_mid); #endif } else if (!rec_mid_low && (thing < rec_mid)) { rec_mid = next_garbage(rec_mid,-1); #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"[even, <, mid=%d] ",(int)rec_mid); #endif } } rec_n ++; #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"[n=%d]\n",rec_n); #endif } } static dbref take_from_recyclable(int fortype) { dbref newobj; #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"take_from_recyclable n=%d: ",rec_n); #endif if (rec_n < 1) { #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"NOTHING\n"); #endif return(NOTHING); } if (rec_n < 2) { if ((rec_min != rec_mid) || (rec_min != rec_max)) { #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"abort\n"); #endif abort(); } newobj = rec_min; #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"%d (cleanout)\n",(int)newobj); #endif clear_recyclable(); return(newobj); } switch (fortype) { case TYPE_EXIT: newobj = rec_mid; #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"EXIT %d ",(int)newobj); #endif if (rec_n & 1) { rec_mid_low = rnd(2); rec_mid = next_garbage(rec_mid,rec_mid_low?-1:1); #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"[odd, mid_low=%d, mid=%d] ",rec_mid_low,(int)rec_mid); #endif } else { rec_mid = next_garbage(rec_mid,rec_mid_low?1:-1); #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"[even, mid_low=%d, mid=%d] ",rec_mid_low,(int)rec_mid); #endif } if (newobj == rec_min) { rec_min = rec_mid; #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"[took min, min=%d] ",(int)rec_min); #endif } if (newobj == rec_max) { rec_max = rec_mid; #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"[took max, max=%d] ",(int)rec_max); #endif } break; case TYPE_DAEMON: newobj = rec_max; #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"DAEMON %d ",(int)newobj); #endif if (rec_n & 1) { rec_mid_low = 0; #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"[odd, mid_low=0] "); #endif } else { if (! rec_mid_low) { rec_mid = next_garbage(rec_mid,-1); #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"[even, mid_low=0, mid=%d] ",(int)rec_mid); #endif } else { #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"[even, mid_low=1] "); #endif } } rec_max = next_garbage(rec_max,-1); #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"[max=%d] ",(int)rec_max); #endif break; default: newobj = rec_min; #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"other %d ",(int)newobj); #endif if (rec_n & 1) { rec_mid_low = 1; #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"[odd, mid_low=1] "); #endif } else { if (rec_mid_low) { rec_mid = next_garbage(rec_mid,1); #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"[even, mid_low=1, mid=%d] ",(int)rec_mid); #endif } else { #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"[even, mid_low=0] "); #endif } } rec_min = next_garbage(rec_min,1); #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"[min=%d] ",(int)rec_min); #endif break; } rec_n --; #ifdef REC_DEBUG if (rec_debug) fprintf(stderr,"[n=%d]\n",rec_n); #endif remove_ownerlist(newobj); return(newobj); } dbref new_object(int fortype) { dbref newobj; newobj = take_from_recyclable(fortype); if (newobj == NOTHING) { newobj = db_top; db_grow(db_top+1); } db_free_object(newobj); db_clear_object(newobj); return(newobj); } #define DB_MSGLEN 16384 void putref(FILE *f, dbref ref) { fprintf(f,"%d\n",ref); } static void putstring(FILE *f, const char *s) { if (s) fputs(s,f); putc('\n',f); } static void putstring_str(FILE *f, STR s) { fputs_str(s,f); putc('\n',f); } static void putbool_subexp(FILE *f, struct boolexp *b) { switch(b->type) { case BOOLEXP_AND: putc('(',f); putbool_subexp(f,b->u.dyad.sub1); putc(AND_TOKEN,f); putbool_subexp(f,b->u.dyad.sub2); putc(')',f); break; case BOOLEXP_OR: putc('(',f); putbool_subexp(f,b->u.dyad.sub1); putc(OR_TOKEN,f); putbool_subexp(f,b->u.dyad.sub2); putc(')',f); break; case BOOLEXP_NOT: putc('(',f); putc(NOT_TOKEN,f); putbool_subexp(f,b->u.monad); putc(')',f); break; case BOOLEXP_OBJ: fprintf(f,"%d",(int)b->u.obj.thing); if (b->u.obj.param && *b->u.obj.param) { fprintf(f,"'"); write_boolexp_param(f,b->u.obj.param); } break; case BOOLEXP_PROP: putc('[',f); put_lockprop(f,b->u.prop); putc(']',f); break; default: break; } } void putboolexp(FILE *f, struct boolexp *b) { if (b != TRUE_BOOLEXP) putbool_subexp(f,b); putc('\n',f); } static void skip_backlists(FILE *f) { char buf[BUFFER_LEN]; if (fgets(&buf[0],BUFFER_LEN-1,f) != &buf[0]) return; if (buf[0] == '-') return; if (!strcmp(&buf[0],"*no backlists*\n")) return; do { if (fgets(&buf[0],BUFFER_LEN-1,f) != &buf[0]) return; } while (!strncmp(&buf[0],"*end",4)); if (fgets(&buf[0],BUFFER_LEN-1,f) != &buf[0]) return; do { if (fgets(&buf[0],BUFFER_LEN-1,f) != &buf[0]) return; } while (!strncmp(&buf[0],"*end",4)); } void macrodump(struct macrotable *node, FILE *f) { if (!node) return; macrodump(node->left,f); putstring(f,node->name); putstring(f,node->definition); putref(f,node->implementor); macrodump(node->right,f); } static char *file_line(FILE *f) { int l; char buf[BUFFER_LEN]; if (! fgets(buf,BUFFER_LEN,f)) return(0); l = strlen(buf); seed_random(&buf[0],l); if (l > 0) buf[l-1] = '\0'; return(dup_string(buf)); } static void foldtree (struct macrotable *center) { int count; struct macrotable *nextcent; count = 0; nextcent = center; for (;nextcent;nextcent=nextcent->left) count++; if (count > 1) { for (nextcent=center,count/=2;count--;nextcent=nextcent->left); if (center->left) center->left->right = 0; center->left = nextcent; foldtree(center->left); } for (count = 0,nextcent=center;nextcent;nextcent=nextcent->right) count ++; if (count > 1) { for (nextcent=center,count/=2;count--;nextcent=nextcent->right); if (center->right) center->right->left = 0; foldtree(center->right); } } static int macrochain(struct macrotable *lastnode, FILE *f) { int count; char *line; char *line2; struct macrotable *newmacro; count = 0; while (1) { line = file_line(f); if (! line) break; line2 = file_line(f); if (! line2) { free(line); break; } newmacro = (struct macrotable *) new_macro(line,line2,getref(f)); free(line); free(line2); if (! macrotop) { macrotop = (struct macrotable *) newmacro; } else { newmacro->left = lastnode; lastnode->right = newmacro; } lastnode = newmacro; count ++; } return(count); } void macroload(FILE *f) { int count; macrotop = 0; count = macrochain(macrotop,f); for (count/=2;count--;macrotop=macrotop->right) ; foldtree(macrotop); } void write_program(struct line *first, dbref i) { FILE *f; char fname[BUFFER_LEN]; sprintf(fname,"muf/%d.m",(int)i); f = fopen(fname,"w"); if (! f) { log_status("Couldn't open file %s!",fname); return; } for (;first;first=first->next) { fputs(first->this_line?first->this_line:"",f); fputc('\n',f); } fclose(f); } int db_write_object(FILE *f, dbref i) { struct object *o; int j; o = DBFETCH(i); putstring(f,NAME(i)); putstring_str(f,o->description); putref(f,o->location); putref(f,o->contents); putref(f,o->next); putref(f,o->nextowned); putref(f,o->owner); putboolexp(f,o->key); putstring_str(f,o->fail_message); putstring_str(f,o->succ_message); putstring_str(f,o->drop_message); putstring_str(f,o->ofail); putstring_str(f,o->osuccess); putstring_str(f,o->odrop); switch (Typeof(i)) { case TYPE_ROOM: case TYPE_EXIT: putref(f,FLAGS(i)); break; default: putref(f,FLAGS(i)&~IFLAG); break; } #ifdef TIMESTAMPS putref(f,o->time_created); putref(f,o->time_modified); putref(f,o->time_used); #else putref(f,0); putref(f,0); putref(f,0); #endif putplist(f,o->properties); switch (Typeof(i)) { case TYPE_THING: putref(f,o->sp.thing.home); putref(f,o->sp.thing.actions); putref(f,o->sp.thing.value); break; case TYPE_ROOM: putref(f,o->sp.room.dropto); putref(f,o->sp.room.exits); fprintf(f,"%g\n",o->sp.room.useval); putref(f,o->sp.room.stamp); break; case TYPE_EXIT: putref(f, o->sp.exit.ndest); for (j=0;jsp.exit.ndest;j++) putref(f,o->sp.exit.dest[j]); break; case TYPE_PLAYER: putref(f,o->sp.player.home); putref(f,o->sp.player.actions); putref(f,o->sp.player.pennies); putstring(f,o->sp.player.password); break; case TYPE_PROGRAM: if (! DBFETCH(i)->sp.program.proglocks) free_prog(i); break; } return(0); } dbref db_write(FILE *f, FILE *sf) { dbref i; #ifdef DB_SIZE_FILE long int preoff; long int postoff; #endif newdb_str_write(); fputs("***MouseMUCK dump format 1***\n",f); for (i=db_top-1;i>=0;i--) { switch (Typeof(i)) { case TYPE_GARBAGE: case TYPE_DAEMON: break; default: #ifdef DB_SIZE_FILE if (sf) preoff = ftell(f); #endif fprintf(f,"#%d\n",i); db_write_object(f,i); #ifdef DB_SIZE_FILE if (sf) { postoff = ftell(f); fprintf(sf,"%7d %8ld\n",(int)i,postoff-preoff); fflush(sf); } #endif break; } if ((i%1000) == 0) { newcon_check(); } } fputs("***END OF DUMP***\n",f); fflush(f); return(db_top); } dbref parse_dbref(const char *s) { const char *p; long int x; x = atol(s); if (x > 0) { return(x); } else if (x == 0) { /* check for 0 */ for (p=s;*p;p++) { if (*p == '0') return(0); if (! Cisspace(*p)) break; } } /* else x < 0 or s != 0 */ return(NOTHING); } dbref getref(FILE *f) { static char buf[DB_MSGLEN]; fgets(&buf[0],sizeof(buf),f); return(atol(&buf[0])); } static char *getstring_noalloc(FILE *f) { static char buf[DB_MSGLEN]; char c; int l; fgets(&buf[0],sizeof(buf),f); l = strlen(&buf[0]); if (l > 0) { if (buf[l-1] != '\n') { /* ignore whatever comes after */ fprintf(stderr,"warning: ignoring trailing part of too-long line\n"); while ((c = fgetc(f)) != '\n') ; } else { buf[l-1] = '\0'; } } seed_random(&buf[0],l); return(&buf[0]); } #define getstring(x) dup_string(getstring_noalloc(x)) #define getstring_str(x) unfputs_str(getstring_noalloc(x)) static struct boolexp *negate_boolexp(struct boolexp *b) { struct boolexp *n; /* Obscure fact: !NOTHING == NOTHING in old-format databases! */ if (b == TRUE_BOOLEXP) return(TRUE_BOOLEXP); /* could perhaps optimize if b->type == BOOLEXP_NOT...but why bother */ n = malloc(sizeof(struct boolexp)); n->type = BOOLEXP_NOT; n->u.monad = b; return(n); } /* returns true for numbers of form [ + | - ] */ int number(const char *s) { if (!s) return(0); while (Cisspace(*s)) s++; if ((*s == '+') || (*s == '-')) s++; for (;*s;s++) if (!Cisdigit(*s)) return(0); return(1); } static jmp_buf bxerr_jmp; static dbref bxerr_objno; static struct boolexp *getboolexp1(FILE *f) { struct boolexp *b; int c; c = getc(f); switch(c) { case '\n': ungetc(c,f); return(TRUE_BOOLEXP); break; case EOF: abort(); /* unexpected EOF in boolexp */ break; case '(': b = malloc(sizeof(struct boolexp)); c = getc(f); if (c == '!') { b->type = BOOLEXP_NOT; b->u.monad = getboolexp1(f); if (getc(f) != ')') goto error; return(b); } else { ungetc(c,f); b->u.dyad.sub1 = getboolexp1(f); c = getc(f); switch (c) { case AND_TOKEN: b->type = BOOLEXP_AND; break; case OR_TOKEN: b->type = BOOLEXP_OR; break; default: goto error; break; } b->u.dyad.sub2 = getboolexp1(f); if (getc(f) != ')') goto error; return(b); } break; case '-': /* obsolete NOTHING key */ /* eat it */ while (1) { c = getc(f); if (c == EOF) abort(); /* unexpected EOF */ if (c == '\n') break; } ungetc(c,f); return(TRUE_BOOLEXP); break; case '[': b = malloc(sizeof(struct boolexp)); b->type = BOOLEXP_PROP; if (get_lockprop(f,&b->u.prop)) goto error; c = getc(f); if (c != ']') goto error; return(b); break; default: /* better be a dbref */ ungetc(c,f); b = malloc(sizeof(struct boolexp)); b->type = BOOLEXP_OBJ; b->u.obj.thing = 0; /* NOTE code assumes digits are consecutive */ /* Will need to be changed if putref/getref change */ while (1) { c = getc(f); if (c == EOF) abort(); if (! isdigit(c)) break; b->u.obj.thing = (b->u.obj.thing * 10) + (c - '0'); } if (c == '\'') { b->u.obj.param = read_boolexp_param(f); } else { ungetc(c,f); b->u.obj.param = 0; } return(b); } error:; longjmp(bxerr_jmp,1); abort(); /* bomb out */ return(TRUE_BOOLEXP); } struct boolexp *getboolexp(FILE *f) { struct boolexp *b; if (setjmp(bxerr_jmp)) { while ((getc(f) != '\n') && !ferror(f) && !feof(f)) ; log_status("Error reading key for #%d",(int)bxerr_objno); fprintf(stderr,"Error reading key for #%d\n",(int)bxerr_objno); return(TRUE_BOOLEXP); } b = getboolexp1(f); if (getc(f) != '\n') abort(); /* parse error, we lose */ return(b); } void db_free_object(dbref i) { struct object *o; o = DBFETCH(i); if (NAME(i)) free(NAME(i)); free_str(o->description); free_str(o->succ_message); free_str(o->fail_message); free_str(o->drop_message); free_str(o->ofail); free_str(o->osuccess); free_str(o->odrop); if (o->key) free_boolexp(o->key); burn_dbref_list(o->backlinks); burn_dbref_list(o->backlocks); burn_dbref_list(o->backprops); free_plist(o->properties); o->properties = 0; switch (Typeof(i)) { case TYPE_EXIT: if (o->sp.exit.dest) free(o->sp.exit.dest); break; case TYPE_PLAYER: if (o->sp.player.password) free(o->sp.player.password); burn_proglocks(i); break; case TYPE_DAEMON: burn_proglocks(i); break; case TYPE_PROGRAM: burn_proglocks(i); free_code(o->sp.program.codevec,o->sp.program.codesiz); free_stab(o->sp.program.stabvec,o->sp.program.stabsiz); break; } DBDIRTY(i); } void db_free(void) { dbref i; if (db) { for (i=0;ithis_line = 0; new->next = 0; new->prev = 0; return(new); } struct line *read_program(dbref i) { char buf[BUFFER_LEN]; struct line *first; struct line *prev; struct line *new; FILE *f; int l; first = 0; sprintf(buf,"muf/%d.m",(int)i); f = fopen(buf,"r"); if (!f) return(0); while (fgets(buf,BUFFER_LEN,f)) { new = get_new_line(); l = strlen(buf); if ((l > 0) && (buf[l-1] == '\n')) buf[--l] = '\0'; new->this_line = dup_string(buf); if (! first) { first = prev = new; } else { prev->next = new; new->prev = prev; prev = new; } } fclose(f); return(first); } static void setgarbage(dbref objno) { OWNER(objno) = NOTHING; free((void *)NAME(objno)); free_str(DBFETCH(objno)->description); NAME(objno) = dup_string(""); DBFETCH(objno)->description = store_str(""); FLAGS(objno) = TYPE_GARBAGE; add_to_recyclable(objno); DBDIRTY(objno); } static void gendercvt(dbref objno) { if ((FLAGS(objno) & TYPE_MASK) == TYPE_PLAYER) { const char *s; switch((FLAGS(objno) & GENDER_MASK) >> GENDER_SHIFT) { case GENDER_NEUTER: s = "neuter"; break; case GENDER_FEMALE: s = "female"; break; case GENDER_MALE: s = "male"; break; default: s = 0; break; } if (s) { struct propref *pr; pr = create_property_compat(objno,"_sex"); propref_set_type_and_value(pr,PTYPE_STRING,s); } FLAGS(objno) &= ~GENDER_MASK; } } static void db_read_object_old(FILE *f, struct object *o, dbref objno) { dbref exits; int pennies; const char *password; bxerr_objno = objno; NAME(objno) = getstring(f); o->description = getstring_str(f); o->location = getref(f); o->contents = getref(f); exits = getref(f); o->backlinks = 0; o->backlocks = 0; o->backprops = 0; o->next = getref(f); o->nextowned = NOTHING; o->key = getboolexp(f); o->fail_message = getstring_str(f); o->succ_message = getstring_str(f); o->ofail = getstring_str(f); o->osuccess = getstring_str(f); OWNER(objno) = getref(f); pennies = getref(f); FLAGS(objno) = getref(f); /* flags have to be checked for conflict --- the bits that are now OWNABLE and JUMP_OK should be mapped to HAVEN and ABODE */ if (FLAGS(objno) & OWNABLE) { FLAGS(objno) &= ~OWNABLE; FLAGS(objno) |= HAVEN; } if (FLAGS(objno) & JUMP_OK) { FLAGS(objno) &= ~JUMP_OK; FLAGS(objno) |= ABODE; } password = getstring(f); o->properties = 0; /* For downward compatibility with databases using the */ /* obsolete ANTILOCK flag. */ if (FLAGS(objno) & ANTILOCK) { o->key = negate_boolexp(o->key); FLAGS(objno) &= ~ANTILOCK; } switch (FLAGS(objno) & TYPE_MASK) { case TYPE_THING: o->sp.thing.home = exits; o->sp.thing.actions = NOTHING; o->sp.thing.value = pennies; break; case TYPE_ROOM: o->sp.room.dropto = o->location; o->location = NOTHING; o->sp.room.exits = exits; o->sp.room.useval = 0; o->sp.room.stamp = curtm(); break; case TYPE_EXIT: if (o->location == NOTHING) { o->sp.exit.ndest = 0; o->sp.exit.dest = 0; } else { o->sp.exit.ndest = 1; o->sp.exit.dest = (dbref *) malloc(sizeof(dbref)); o->sp.exit.dest[0] = o->location; } o->location = NOTHING; break; case TYPE_PLAYER: o->sp.player.home = exits; o->sp.player.actions = NOTHING; o->sp.player.pennies = pennies; o->sp.player.password = make_password(password); o->sp.player.proglocks = 0; o->sp.player.proglock_type = 0; o->sp.player.daemons = 0; o->sp.player.dbrefs_owned = 1; OWNER(objno) = objno; add_player(objno); break; case TYPE_PROGRAM: o->sp.program.proglocks = 0; break; case TYPE_GARBAGE: setgarbage(objno); break; } gendercvt(objno); FLAGS(objno) &= ~MOUSEFLAGS; } static void db_read_object_new(FILE *f, struct object *o, dbref objno) { int j; bxerr_objno = objno; NAME(objno) = getstring(f); o->description = getstring_str(f); o->location = getref(f); o->contents = getref(f); o->backlinks = 0; o->backlocks = 0; o->backprops = 0; o->next = getref(f); o->nextowned = NOTHING; o->key = getboolexp(f); o->fail_message = getstring_str(f); o->succ_message = getstring_str(f); o->ofail = getstring_str(f); o->osuccess = getstring_str(f); FLAGS(objno) = getref(f); /* flags have to be checked for conflict --- the bits that are now OWNABLE and JUMP_OK should be mapped to HAVEN and ABODE */ if (FLAGS(objno) & OWNABLE) { FLAGS(objno) &= ~OWNABLE; FLAGS(objno) |= HAVEN; } if (FLAGS(objno) & JUMP_OK) { FLAGS(objno) &= ~JUMP_OK; FLAGS(objno) |= ABODE; } o->properties = 0; /* o->password = getstring(f); */ /* For downward compatibility with databases using the */ /* obsolete ANTILOCK flag. */ if (FLAGS(objno) & ANTILOCK) { o->key = negate_boolexp(o->key); FLAGS(objno) &= ~ANTILOCK; } switch (FLAGS(objno) & TYPE_MASK) { case TYPE_THING: o->sp.thing.home = getref(f); o->sp.thing.actions = getref(f); OWNER(objno) = getref(f); o->sp.thing.value = getref(f); break; case TYPE_ROOM: o->sp.room.dropto = getref(f); o->sp.room.exits = getref(f); OWNER(objno) = getref(f); o->sp.room.useval = 0; o->sp.room.stamp = curtm(); break; case TYPE_EXIT: o->sp.exit.ndest = getref(f); o->sp.exit.dest = (dbref *) malloc(o->sp.exit.ndest*sizeof(dbref)); for (j=0;jsp.exit.ndest;j++) { o->sp.exit.dest[j] = getref(f); } OWNER(objno) = getref(f); break; case TYPE_PLAYER: o->sp.player.home = getref(f); o->sp.player.actions = getref(f); o->sp.player.pennies = getref(f); o->sp.player.password = getstring(f); o->sp.player.password = make_password(o->sp.player.password); o->sp.player.proglocks = 0; o->sp.player.proglock_type = 0; o->sp.player.daemons = 0; o->sp.player.dbrefs_owned = 1; OWNER(objno) = objno; add_player(objno); break; case TYPE_PROGRAM: o->sp.program.proglocks = 0; break; } gendercvt(objno); FLAGS(objno) &= ~MOUSEFLAGS; } static void db_read_object_lachesis(FILE *f, struct object *o, dbref objno) { int j; int c; int prop_flag; prop_flag = 0; bxerr_objno = objno; NAME(objno) = getstring(f); o->description = getstring_str(f); o->location = getref(f); o->contents = getref(f); o->backlinks = 0; o->backlocks = 0; o->backprops = 0; o->next = getref(f); o->nextowned = NOTHING; o->key = getboolexp(f); o->fail_message = getstring_str(f); o->succ_message = getstring_str(f); o->drop_message = getstring_str(f); o->ofail = getstring_str(f); o->osuccess = getstring_str(f); o->odrop = getstring_str(f); /* OWNER(objno) = getref(f); */ /* o->pennies = getref(f); */ FLAGS(objno) = getref(f); c = getc(f); if (c == '*') { compat_getplist(f,objno); prop_flag ++; } else { /* do our own getref */ int sign; char buf[BUFFER_LEN]; int i; sign = 0; i = 0; if (c == '-') { sign = 1; } else if (c != '+') { buf[i] = c; i ++; } while ((c = getc(f)) != '\n') { buf[i] = c; i ++; } buf[i] = '\0'; j = atol(buf); if (sign) j = -j; o->properties = 0; gendercvt(objno); } /* o->password = getstring(f); */ /* For downward compatibility with databases using the */ /* obsolete ANTILOCK flag. */ if (FLAGS(objno) & ANTILOCK) { o->key = negate_boolexp(o->key); FLAGS(objno) &= ~ANTILOCK; } switch (FLAGS(objno) & TYPE_MASK) { case TYPE_THING: o->sp.thing.home = prop_flag ? getref(f) : j; o->sp.thing.actions = getref(f); OWNER(objno) = getref(f); o->sp.thing.value = getref(f); break; case TYPE_ROOM: o->sp.room.dropto = prop_flag ? getref(f) : j; o->sp.room.exits = getref(f); OWNER(objno) = getref(f); o->sp.room.useval = 0; o->sp.room.stamp = curtm(); break; case TYPE_EXIT: o->sp.exit.ndest = prop_flag ? getref(f) : j; o->sp.exit.dest = (dbref *) malloc(o->sp.exit.ndest * sizeof(dbref)); for (j=0;jsp.exit.ndest;j++) o->sp.exit.dest[j] = getref(f); OWNER(objno) = getref(f); break; case TYPE_PLAYER: o->sp.player.home = prop_flag ? getref(f) : j; o->sp.player.actions = getref(f); o->sp.player.pennies = getref(f); o->sp.player.password = getstring(f); o->sp.player.curr_prog = NOTHING; o->sp.player.insert_mode = 0; o->sp.player.run = 0; o->sp.player.password = make_password(o->sp.player.password); o->sp.player.proglocks = 0; o->sp.player.proglock_type = 0; o->sp.player.daemons = 0; o->sp.player.dbrefs_owned = 1; OWNER(objno) = objno; add_player(objno); break; case TYPE_PROGRAM: OWNER(objno) = getref(f); FLAGS(objno) &= ~INTERNAL; o->sp.program.curr_line = 0; o->sp.program.first = read_program(objno); o->sp.program.codesiz = 0; o->sp.program.codevec = 0; o->sp.program.stabsiz = 0; o->sp.program.stabvec = 0; o->sp.program.start = 0; o->sp.program.proglocks = 0; #ifdef COMPILE_ON_LOAD o->sp.program.first = read_program(objno); do_compile(NOTHING,objno,NOTHING); free_prog_text(o->sp.program.first); #endif free_prog_text(o->sp.program.first); break; case TYPE_GARBAGE: setgarbage(objno); break; } FLAGS(objno) &= ~MOUSEFLAGS; } static void db_read_object_doran(FILE *f, struct object *o, dbref objno) { int j; int c; int prop_flag; prop_flag = 0; bxerr_objno = objno; NAME(objno) = getstring(f); o->description = getstring_str(f); o->location = getref(f); o->contents = getref(f); o->backlinks = 0; o->backlocks = 0; o->backprops = 0; o->next = getref(f); o->nextowned = NOTHING; o->key = getboolexp(f); o->fail_message = getstring_str(f); o->succ_message = getstring_str(f); o->drop_message = getstring_str(f); o->ofail = getstring_str(f); o->osuccess = getstring_str(f); o->odrop = getstring_str(f); FLAGS(objno) = getref(f); o->time_created = getref(f); o->time_modified = getref(f); o->time_used = getref(f); c = getc(f); if (c == '*') { compat_getplist(f,objno); prop_flag ++; } else { /* do our own getref */ int sign; char buf[BUFFER_LEN]; int i; sign = 0; i = 0; if (c == '-') { sign = 1; } else if (c != '+') { buf[i] = c; i ++; } while ((c = getc(f)) != '\n') { buf[i] = c; i ++; } buf[i] = '\0'; j = atol(buf); if (sign) j = -j; o->properties = 0; gendercvt(objno); } /* Blast the gender flags (Doran) */ FLAGS(objno) &= ~GENDER_MASK; /* o->password = getstring(f); */ /* For downward compatibility with databases using the */ /* obsolete ANTILOCK flag. */ if (FLAGS(objno) & ANTILOCK) { o->key = negate_boolexp(o->key); FLAGS(objno) &= ~ANTILOCK; } switch (FLAGS(objno) & TYPE_MASK) { case TYPE_THING: o->sp.thing.home = prop_flag ? getref(f) : j; o->sp.thing.actions = getref(f); OWNER(objno) = getref(f); o->sp.thing.value = getref(f); break; case TYPE_ROOM: o->sp.room.dropto = prop_flag ? getref(f) : j; o->sp.room.exits = getref(f); OWNER(objno) = getref(f); o->sp.room.useval = 0; o->sp.room.stamp = curtm(); break; case TYPE_EXIT: o->sp.exit.ndest = prop_flag ? getref(f) : j; o->sp.exit.dest = (dbref *) malloc(o->sp.exit.ndest * sizeof(dbref)); for (j=0;jsp.exit.ndest;j++) o->sp.exit.dest[j] = getref(f); OWNER(objno) = getref(f); break; case TYPE_PLAYER: o->sp.player.home = prop_flag ? getref(f) : j; o->sp.player.actions = getref(f); o->sp.player.pennies = getref(f); o->sp.player.password = getstring(f); o->sp.player.curr_prog = NOTHING; o->sp.player.insert_mode = 0; o->sp.player.run = 0; o->sp.player.daemons = 0; o->sp.player.proglocks = 0; o->sp.player.proglock_type = 0; o->sp.player.dbrefs_owned = 1; OWNER(objno) = objno; add_player(objno); break; case TYPE_DAEMON: if (prop_flag) getref(f); /* just throw away the data */ getref(f); getref(f); free(getstring(f)); recycle((dbref)1,objno,1); break; case TYPE_PROGRAM: OWNER(objno) = getref(f); FLAGS(objno) &= ~INTERNAL; o->sp.program.curr_line = 0; o->sp.program.codesiz = 0; o->sp.program.codevec = 0; o->sp.program.stabsiz = 0; o->sp.program.stabvec = 0; o->sp.program.start = 0; o->sp.program.proglocks = 0; #ifdef COMPILE_ON_LOAD o->sp.program.first = read_program(objno); do_compile(NOTHING,objno,NOTHING); free_prog_text(o->sp.program.first); #endif o->sp.program.first = 0; break; case TYPE_GARBAGE: setgarbage(objno); break; } FLAGS(objno) &= ~MOUSEFLAGS; } void burn_dbref_list(struct dbref_list *drl) { while (drl) { struct dbref_list *nx; nx = drl->next; free_drl(drl); drl = nx; } } struct dbref_list *sort_dbref_list(struct dbref_list *drl) { struct dbref_list *l1; struct dbref_list *l2; struct dbref_list *ln; struct dbref_list *rv; struct dbref_list **lt; if (!drl || !drl->next) return(drl); while (drl) { ln = drl->next; drl->next = l1; l1 = l2; l2 = drl; drl = ln; } l1 = sort_dbref_list(l1); l2 = sort_dbref_list(l2); lt = &rv; while (l1 || l2) { if (l1 && (!l2 || (l1->object < l2->object))) { ln = l1; l1 = ln->next; } else { ln = l2; l2 = ln->next; } *lt = ln; lt = &ln->next; } *lt = 0; return(rv); } static void db_read_object_daemon(FILE *f, struct object *o, dbref objno) { int j; int c; int prop_flag; prop_flag = 0; bxerr_objno = objno; NAME(objno) = getstring(f); o->description = getstring_str(f); o->location = getref(f); o->contents = getref(f); o->backlinks = 0; o->backlocks = 0; o->backprops = 0; o->next = getref(f); o->nextowned = getref(f); o->nextowned = NOTHING; o->owner = getref(f); o->key = getboolexp(f); o->fail_message = getstring_str(f); o->succ_message = getstring_str(f); o->drop_message = getstring_str(f); o->ofail = getstring_str(f); o->osuccess = getstring_str(f); o->odrop = getstring_str(f); FLAGS(objno) = getref(f) & ~MOUSEFLAGS; o->time_created = getref(f); o->time_modified = getref(f); o->time_used = getref(f); skip_backlists(f); c = getc(f); if (c == '*') { compat_getplist(f,objno); prop_flag ++; } else { /* do our own getref */ int sign; char buf[BUFFER_LEN]; int i; sign = 0; i = 0; if (c == '-') { sign = 1; } else if (c != '+') { buf[i] = c; i ++; } while ((c = getc(f)) != '\n') { buf[i] = c; i ++; } buf[i] = '\0'; j = atol(buf); if (sign) j = -j; o->properties = 0; } switch (FLAGS(objno) & TYPE_MASK) { case TYPE_THING: o->sp.thing.home = prop_flag ? getref(f) : j; o->sp.thing.actions = getref(f); o->sp.thing.value = getref(f); break; case TYPE_ROOM: o->sp.room.dropto = prop_flag ? getref(f) : j; o->sp.room.exits = getref(f); o->sp.room.useval = 0; o->sp.room.stamp = curtm(); break; case TYPE_EXIT: o->sp.exit.ndest = prop_flag ? getref(f) : j; o->sp.exit.dest = (dbref *) malloc(o->sp.exit.ndest * sizeof(dbref)); for (j=0;jsp.exit.ndest;j++) o->sp.exit.dest[j] = getref(f); break; case TYPE_PLAYER: o->sp.player.home = prop_flag ? getref(f) : j; o->sp.player.actions = getref(f); o->sp.player.pennies = getref(f); o->sp.player.password = getstring(f); o->sp.player.curr_prog = NOTHING; o->sp.player.insert_mode = 0; o->sp.player.run = 0; o->sp.player.daemons = 0; o->sp.player.proglocks = 0; o->sp.player.proglock_type = 0; o->sp.player.dbrefs_owned = 1; add_player(objno); break; case TYPE_DAEMON: o->sp.daemon.first = 0; o->sp.daemon.cycles = 0; o->sp.daemon.run = 0; o->sp.daemon.proglocks = 0; o->sp.daemon.proglock_type = 0; o->sp.daemon.sleepobj = NOTHING; recycle((dbref)1,objno,1); break; case TYPE_PROGRAM: FLAGS(objno) &= ~INTERNAL; o->sp.program.curr_line = 0; o->sp.program.codesiz = 0; o->sp.program.codevec = 0; o->sp.program.stabsiz = 0; o->sp.program.stabvec = 0; o->sp.program.start = 0; o->sp.program.proglocks = 0; #ifdef COMPILE_ON_LOAD o->sp.program.first = read_program(objno); do_compile(NOTHING,objno,NOTHING); free_prog_text(o->sp.program.first); #endif /* COMPILE_ON_LOAD */ o->sp.program.first = 0; break; case TYPE_GARBAGE: setgarbage(objno); break; } FLAGS(objno) &= ~MOUSEFLAGS; } static void print_boolexp_strings(struct boolexp *b) { if (b == TRUE_BOOLEXP) return; switch (b->type) { case BOOLEXP_AND: case BOOLEXP_OR: print_boolexp_strings(b->u.dyad.sub1); print_boolexp_strings(b->u.dyad.sub2); break; case BOOLEXP_NOT: print_boolexp_strings(b->u.monad); break; case BOOLEXP_OBJ: break; case BOOLEXP_PROP: { char *s; s = lockprop_value(b->u.prop); record_string(s); free(s); } break; } } static void db_read_object_oldmouse(FILE *f, struct object *o, dbref objno) { int j; bxerr_objno = objno; NAME(objno) = getstring(f); o->description = getstring_str(f); o->location = getref(f); o->contents = getref(f); o->backlinks = 0; o->backlocks = 0; o->backprops = 0; o->next = getref(f); o->nextowned = getref(f); o->nextowned = NOTHING; o->owner = getref(f); o->key = getboolexp(f); o->fail_message = getstring_str(f); o->succ_message = getstring_str(f); o->drop_message = getstring_str(f); o->ofail = getstring_str(f); o->osuccess = getstring_str(f); o->odrop = getstring_str(f); FLAGS(objno) = getref(f); o->time_created = getref(f); o->time_modified = getref(f); o->time_used = getref(f); skip_backlists(f); compat_getplist(f,objno); switch (FLAGS(objno) & TYPE_MASK) { case TYPE_THING: o->sp.thing.home = getref(f); o->sp.thing.actions = getref(f); o->sp.thing.value = getref(f); break; case TYPE_ROOM: o->sp.room.dropto = getref(f); o->sp.room.exits = getref(f); { int c; c = getc(f); ungetc(c,f); if (isdigit(c)) { char *s; double d; s = getstring_noalloc(f); sscanf(s,"%lg",&d); o->sp.room.useval = d; o->sp.room.stamp = getref(f); } else { o->sp.room.useval = 0; o->sp.room.stamp = curtm(); } } break; case TYPE_EXIT: o->sp.exit.ndest = getref(f); o->sp.exit.dest = (dbref *) malloc(o->sp.exit.ndest*sizeof(dbref)); for (j=0;jsp.exit.ndest;j++) o->sp.exit.dest[j] = getref(f); break; case TYPE_PLAYER: o->sp.player.home = getref(f); o->sp.player.actions = getref(f); o->sp.player.pennies = getref(f); o->sp.player.password = getstring(f); o->sp.player.curr_prog = NOTHING; o->sp.player.insert_mode = 0; o->sp.player.run = 0; o->sp.player.daemons = 0; o->sp.player.proglocks = 0; o->sp.player.proglock_type = 0; o->sp.player.dbrefs_owned = 1; add_player(objno); break; case TYPE_DAEMON: o->sp.daemon.first = 0; o->sp.daemon.cycles = 0; o->sp.daemon.run = 0; o->sp.daemon.proglocks = 0; o->sp.daemon.proglock_type = 0; o->sp.daemon.sleepobj = NOTHING; recycle((dbref)1,objno,1); break; case TYPE_PROGRAM: FLAGS(objno) &= ~INTERNAL; o->sp.program.curr_line = 0; o->sp.program.codesiz = 0; o->sp.program.codevec = 0; o->sp.program.stabsiz = 0; o->sp.program.stabvec = 0; o->sp.program.start = 0; o->sp.program.proglocks = 0; #ifdef COMPILE_ON_LOAD o->sp.program.first = read_program(objno); do_compile(NOTHING,objno,NOTHING); free_prog_text(o->sp.program.first); #endif /* COMPILE_ON_LOAD */ o->sp.program.first = 0; break; case TYPE_GARBAGE: setgarbage(objno); break; } } static void db_read_object_mouse1(FILE *f, struct object *o, dbref objno) { int j; bxerr_objno = objno; if (liststrings) { struct boolexp *lock; unsigned int flg; getstring_noalloc(f); /* name */ str_print(getstring_noalloc(f)); /* desc */ getstring_noalloc(f); /* location */ getstring_noalloc(f); /* contents */ getstring_noalloc(f); /* next */ getstring_noalloc(f); /* nextowned */ getstring_noalloc(f); /* owner */ lock = getboolexp(f); /* lock */ print_boolexp_strings(lock); free_boolexp(lock); str_print(getstring_noalloc(f)); /* fail */ str_print(getstring_noalloc(f)); /* succ */ str_print(getstring_noalloc(f)); /* drop */ str_print(getstring_noalloc(f)); /* ofail */ str_print(getstring_noalloc(f)); /* osucc */ str_print(getstring_noalloc(f)); /* odrop */ flg = getref(f); /* flags */ getstring_noalloc(f); /* ctime */ getstring_noalloc(f); /* mtime */ getstring_noalloc(f); /* utime */ get_plist_strings(f,record_string); switch (flg & TYPE_MASK) { case TYPE_THING: getstring_noalloc(f); /* home */ getstring_noalloc(f); /* actions */ getstring_noalloc(f); /* value */ break; case TYPE_ROOM: getstring_noalloc(f); /* dropto */ getstring_noalloc(f); /* exits */ { int c; c = getc(f); ungetc(c,f); if (isdigit(c)) { getstring_noalloc(f); /* useval */ getstring_noalloc(f); /* stamp */ } } break; case TYPE_EXIT: { int n; for (n=getref(f);n>0;n--) getref(f); /* link-tos */ } break; case TYPE_PLAYER: getstring_noalloc(f); /* home */ getstring_noalloc(f); /* actions */ getstring_noalloc(f); /* pennies */ getstring_noalloc(f); /* password */ break; case TYPE_DAEMON: break; case TYPE_PROGRAM: break; case TYPE_GARBAGE: break; } return; } NAME(objno) = getstring(f); o->description = getstring_str(f); o->location = getref(f); o->contents = getref(f); o->backlinks = 0; o->backlocks = 0; o->backprops = 0; o->next = getref(f); o->nextowned = getref(f); o->nextowned = NOTHING; o->owner = getref(f); o->key = getboolexp(f); o->fail_message = getstring_str(f); o->succ_message = getstring_str(f); o->drop_message = getstring_str(f); o->ofail = getstring_str(f); o->osuccess = getstring_str(f); o->odrop = getstring_str(f); FLAGS(objno) = getref(f); o->time_created = getref(f); o->time_modified = getref(f); o->time_used = getref(f); getplist(f,objno); switch (FLAGS(objno) & TYPE_MASK) { case TYPE_THING: o->sp.thing.home = getref(f); o->sp.thing.actions = getref(f); o->sp.thing.value = getref(f); break; case TYPE_ROOM: o->sp.room.dropto = getref(f); o->sp.room.exits = getref(f); { int c; c = getc(f); ungetc(c,f); if (isdigit(c)) { char *s; double d; s = getstring_noalloc(f); sscanf(s,"%lg",&d); o->sp.room.useval = d; o->sp.room.stamp = getref(f); } else { o->sp.room.useval = 0; o->sp.room.stamp = curtm(); } } break; case TYPE_EXIT: o->sp.exit.ndest = getref(f); o->sp.exit.dest = (dbref *) malloc(o->sp.exit.ndest*sizeof(dbref)); for (j=0;jsp.exit.ndest;j++) o->sp.exit.dest[j] = getref(f); break; case TYPE_PLAYER: o->sp.player.home = getref(f); o->sp.player.actions = getref(f); o->sp.player.pennies = getref(f); o->sp.player.password = getstring(f); o->sp.player.curr_prog = NOTHING; o->sp.player.insert_mode = 0; o->sp.player.run = 0; o->sp.player.daemons = 0; o->sp.player.proglocks = 0; o->sp.player.proglock_type = 0; o->sp.player.dbrefs_owned = 1; add_player(objno); break; case TYPE_DAEMON: o->sp.daemon.first = 0; o->sp.daemon.cycles = 0; o->sp.daemon.run = 0; o->sp.daemon.proglocks = 0; o->sp.daemon.proglock_type = 0; o->sp.daemon.sleepobj = NOTHING; recycle((dbref)1,objno,1); break; case TYPE_PROGRAM: FLAGS(objno) &= ~INTERNAL; o->sp.program.curr_line = 0; o->sp.program.codesiz = 0; o->sp.program.codevec = 0; o->sp.program.stabsiz = 0; o->sp.program.stabvec = 0; o->sp.program.start = 0; o->sp.program.proglocks = 0; #ifdef COMPILE_ON_LOAD o->sp.program.first = read_program(objno); do_compile(NOTHING,objno,NOTHING); free_prog_text(o->sp.program.first); #endif /* COMPILE_ON_LOAD */ o->sp.program.first = 0; break; case TYPE_GARBAGE: setgarbage(objno); break; } } static struct dbref_list *dbref_list_remove1(struct dbref_list *drl, dbref object) { struct dbref_list **dlp; dlp = &drl; while (*dlp) { if ((*dlp)->object == object) { struct dbref_list *tmp; tmp = *dlp; *dlp = tmp->next; free_drl(tmp); break; } else { dlp = &(*dlp)->next; } } return(drl); } void remove_backlinks(dbref src, dbref dest) { if (dest < 0) return; DBSTORE(dest,backlinks,dbref_list_remove1(DBFETCH(dest)->backlinks,src)); } void remove_backprop(dbref onobj, dbref toobj) { if (toobj < 0) return; DBSTORE(toobj,backprops,dbref_list_remove1(DBFETCH(toobj)->backprops,onobj)); } void remove_proglock(dbref src, dbref dst) { #ifdef PROGLOCK_DEBUG if ((FLAGS(GOD_DBREF) & (WIZARD|BUILDER)) == (WIZARD|BUILDER)) { char buf[256]; sprintf(&buf[0],"remove_proglock: src %s",unparse_object(GOD_DBREF,src)); sprintf(&buf[strlen(&buf[0])]," dst %s",unparse_object(GOD_DBREF,dst)); notify(GOD_DBREF,&buf[0]); } #endif if ((src == NOTHING) || (dst == NOTHING)) return; switch (Typeof(src)) { case TYPE_PLAYER: DBSTORE(src,sp.player.proglocks,dbref_list_remove1(DBFETCH(src)->sp.player.proglocks,dst)); if (! DBFETCH(src)->sp.player.proglocks) DBSTORE(src,sp.player.proglock_type,0); break; case TYPE_DAEMON: DBSTORE(src,sp.daemon.proglocks,dbref_list_remove1(DBFETCH(src)->sp.daemon.proglocks,dst)); if (! DBFETCH(src)->sp.daemon.proglocks) DBSTORE(src,sp.daemon.proglock_type,0); break; case TYPE_PROGRAM: DBSTORE(src,sp.program.proglocks,dbref_list_remove1(DBFETCH(src)->sp.program.proglocks,dst)); break; } switch (Typeof(dst)) { case TYPE_PLAYER: DBSTORE(dst,sp.player.proglocks,dbref_list_remove1(DBFETCH(dst)->sp.player.proglocks,src)); if (! DBFETCH(dst)->sp.player.proglocks) DBSTORE(dst,sp.player.proglock_type,0); break; case TYPE_DAEMON: DBSTORE(dst,sp.daemon.proglocks,dbref_list_remove1(DBFETCH(dst)->sp.daemon.proglocks,src)); if (! DBFETCH(dst)->sp.daemon.proglocks) DBSTORE(dst,sp.daemon.proglock_type,0); break; case TYPE_PROGRAM: DBSTORE(dst,sp.program.proglocks,dbref_list_remove1(DBFETCH(dst)->sp.program.proglocks,src)); break; } } void burn_proglocks(dbref obj) { struct dbref_list *tmp; struct dbref_list *drl; #ifdef PROGLOCK_DEBUG if ((FLAGS(GOD_DBREF) & (WIZARD|BUILDER)) == (WIZARD|BUILDER)) { char buf[256]; sprintf(&buf[0],"burn_proglocks: %s",unparse_object(GOD_DBREF,obj)); notify(GOD_DBREF,&buf[0]); } #endif switch(Typeof(obj)) { case TYPE_PLAYER: drl = DBFETCH(obj)->sp.player.proglocks; DBSTORE(obj,sp.player.proglocks,0); DBSTORE(obj,sp.player.proglock_type,0); break; case TYPE_DAEMON: drl = DBFETCH(obj)->sp.daemon.proglocks; DBSTORE(obj,sp.daemon.proglocks,0); DBSTORE(obj,sp.daemon.proglock_type,0); break; case TYPE_PROGRAM: drl = DBFETCH(obj)->sp.program.proglocks; DBSTORE(obj,sp.program.proglocks,0); break; } while (drl) { remove_proglock(drl->object,obj); tmp = drl; drl = drl->next; free_drl(tmp); } } void remove_backlocks(dbref src, dbref dest) { if (dest != NOTHING) { DBSTORE(dest,backlocks,dbref_list_remove1(DBFETCH(dest)->backlocks,src)); } } void add_backlink(dbref src, dbref dest) { struct dbref_list *drl; switch (dest) { case HOME: case BUILTIN: return; break; } if ((src < 0) || (dest < 0) || (src >= db_top) || (dest >= db_top)) abort(); drl = alloc_drl(); drl->object = src; drl->next = DBFETCH(dest)->backlinks; DBSTORE(dest,backlinks,drl); } void add_backlock(dbref src, dbref dest) { struct dbref_list *drl; if ((src < 0) || (dest < 0) || (src >= db_top) || (dest >= db_top)) abort(); drl = alloc_drl(); drl->object = src; drl->next = DBFETCH(dest)->backlocks; DBSTORE(dest,backlocks,drl); } void add_backprop(dbref onobj, dbref toobj) { struct dbref_list *drl; if (toobj == NOTHING) return; if ((toobj < 0) || (toobj >= db_top) || (Typeof(toobj) == TYPE_GARBAGE)) abort(); if ((onobj < 0) || (onobj >= db_top) || (Typeof(onobj) == TYPE_GARBAGE)) abort(); drl = alloc_drl(); drl->object = onobj; drl->next = DBFETCH(toobj)->backprops; DBSTORE(toobj,backprops,drl); } void add_proglock(dbref program, dbref player, int type) { struct dbref_list *drl; #ifdef PROGLOCK_DEBUG if ((FLAGS(GOD_DBREF) & (WIZARD|BUILDER)) == (WIZARD|BUILDER)) { char buf[256]; sprintf(&buf[0],"add_proglock: prog %s",unparse_object(GOD_DBREF,program)); sprintf(&buf[strlen(&buf[0])]," player %s",unparse_object(GOD_DBREF,player)); sprintf(&buf[strlen(&buf[0])]," type %d",type); notify(GOD_DBREF,&buf[0]); } #endif switch(Typeof(player)) { case TYPE_PLAYER: drl = alloc_drl(); drl->object = program; drl->next = DBFETCH(player)->sp.player.proglocks; DBSTORE(player,sp.player.proglocks,drl); DBSTORE(player,sp.player.proglock_type,type); break; case TYPE_DAEMON: drl = alloc_drl(); drl->object = program; drl->next = DBFETCH(player)->sp.daemon.proglocks; DBSTORE(player,sp.daemon.proglocks,drl); DBSTORE(player,sp.daemon.proglock_type,type); } drl = alloc_drl(); drl->object = player; drl->next = DBFETCH(program)->sp.program.proglocks; DBSTORE(program,sp.program.proglocks,drl); } static int check_proglock_(dbref program, int flag) { struct dbref_list *drl; for (drl=DBFETCH(program)->sp.program.proglocks;drl;drl=drl->next) { switch (Typeof(drl->object)) { case TYPE_PLAYER: if (DBFETCH(drl->object)->sp.player.proglock_type == flag) return(1); break; case TYPE_DAEMON: if (DBFETCH(drl->object)->sp.daemon.proglock_type == flag) return(1); break; } } return(0); } int check_proglock(dbref program, int flag) { #ifdef PROGLOCK_DEBUG if ((FLAGS(GOD_DBREF) & (WIZARD|BUILDER)) == (WIZARD|BUILDER)) { int rv; char buf[256]; rv = check_proglock_(program,flag); sprintf(&buf[0],"check_proglock: prog %s flag %d -> %d", unparse_object(GOD_DBREF,program),flag,rv); notify(GOD_DBREF,&buf[0]); return(rv); } else #endif { return(check_proglock_(program,flag)); } } void add_ownerlist(dbref d) { dbref player; player = DBFETCH(d)->owner; if (player != NOTHING) { if (Typeof(player) == TYPE_PLAYER) { DBSTORE(d,nextowned,DBFETCH(player)->nextowned); if (Typeof(d) != TYPE_GARBAGE) DBFETCH(player)->sp.player.dbrefs_owned ++; DBFETCH(player)->nextowned = d; DBDIRTY(player); } else { fprintf(stderr,"Error, illegal owner value for #%d.\n",(int)d); } } } void remove_ownerlist(dbref d) { dbref step; dbref temp; dbref player; player = DBFETCH(d)->owner; step = player; while (step != NOTHING) { temp = DBFETCH(step)->nextowned; if (temp == d) { DBSTORE(step,nextowned,DBFETCH(temp)->nextowned); if (Typeof(d) != TYPE_GARBAGE) DBFETCH(player)->sp.player.dbrefs_owned --; DBDIRTY(player); break; } step = temp; } } void add_backlocks_parse(dbref src, struct boolexp *b) { if (b) { switch (b->type) { case BOOLEXP_AND: case BOOLEXP_OR: add_backlocks_parse(src,b->u.dyad.sub1); add_backlocks_parse(src,b->u.dyad.sub2); break; case BOOLEXP_NOT: add_backlocks_parse(src,b->u.monad); break; case BOOLEXP_OBJ: add_backlock(src,b->u.obj.thing); break; case BOOLEXP_PROP: break; } } } void remove_backlocks_parse(dbref src, struct boolexp *b) { if (b) { switch (b->type) { case BOOLEXP_AND: case BOOLEXP_OR: remove_backlocks_parse(src,b->u.dyad.sub1); remove_backlocks_parse(src,b->u.dyad.sub2); break; case BOOLEXP_NOT: remove_backlocks_parse(src,b->u.monad); break; case BOOLEXP_OBJ: remove_backlocks(src,b->u.obj.thing); break; case BOOLEXP_PROP: break; } } } static void establish_lists(void) { dbref d; int i; for (d=0;dkey); switch (Typeof(d)) { case TYPE_ROOM: if (DBFETCH(d)->sp.room.dropto != NOTHING) { add_backlink(d,DBFETCH(d)->sp.room.dropto); } add_ownerlist(d); break; case TYPE_THING: add_backlink(d,DBFETCH(d)->sp.thing.home); add_ownerlist(d); break; case TYPE_PLAYER: add_backlink(d,DBFETCH(d)->sp.player.home); break; case TYPE_EXIT: for (i=0;isp.exit.ndest;i++) { add_backlink(d,DBFETCH(d)->sp.exit.dest[i]); } add_ownerlist(d); break; default: add_ownerlist(d); break; } } } void reset_lists(void) { dbref d; fputs("Resetting lists...\n",stderr); for (d=0;dbacklinks); DBSTORE(d,backlinks,0); burn_dbref_list(DBFETCH(d)->backlocks); DBSTORE(d,backlocks,0); DBSTORE(d,nextowned,NOTHING); switch (Typeof(d)) { case TYPE_PLAYER: DBSTORE(d,sp.player.dbrefs_owned,1); break; } } establish_lists(); } dbref db_read(FILE *f, int liststrings_arg) { dbref i; struct object *o; const char *special; enum { F_OLD, F_NEW, F_LACHESIS, F_DORAN, F_DAEMON, F_OLDMOUSE, F_MOUSE1 } fmt; char c; liststrings = liststrings_arg; fmt = F_OLD; c = getc(f); if (c == '*') { special = getstring_noalloc(f); if (!strcmp(special,"**TinyMUCK DUMP Format***")) fmt = F_NEW; else if (!strcmp(special,"**Lachesis TinyMUCK DUMP Format***")) fmt = F_LACHESIS; else if (!strcmp(special,"**Doran TinyMUCK DUMP Format***")) fmt = F_DORAN; else if (!strcmp(special,"**DaemonMUCK DUMP Format***")) fmt = F_DAEMON; else if (!strcmp(special,"**Mouse DaemonMUCK DUMP Format***")) fmt = F_OLDMOUSE; else if (!strcmp(special,"**MouseMUCK dump format 1***")) fmt = F_MOUSE1; c = getc(f); } newdb_str_read(); db_free(); init_primitives(); while (1) { switch (c) { case '#': i = getref(f); if (liststrings) { db_grow(1); o = DBFETCH(0); } else { db_grow(i+1); got_dbref[i] = 1; o = DBFETCH(i); } switch (fmt) { case F_OLD: db_read_object_old(f,o,i); break; case F_NEW: db_read_object_new(f,o,i); break; case F_LACHESIS: db_read_object_lachesis(f,o,i); break; case F_DORAN: db_read_object_doran(f,o,i); break; case F_DAEMON: db_read_object_daemon(f,o,i); break; case F_OLDMOUSE: db_read_object_oldmouse(f,o,i); break; case F_MOUSE1: db_read_object_mouse1(f,o,i); break; } seed_random(o,sizeof(o)); break; case '*': special = getstring_noalloc(f); if (strcmp(special,"**END OF DUMP***")) { return(NOTHING); } else { if (! liststrings) { for (i=db_top;i>0;i--) { if (! got_dbref[i-1]) setgarbage(i-1); } switch (fmt) { case F_DAEMON: case F_OLDMOUSE: case F_MOUSE1: break; default: establish_lists(); break; } reset_lists(); } return(db_top); } break; default: return(-1); } c = getc(f); } } int special_typeof(dbref x) { switch (x) { case HOME: return(TYPE_ROOM); break; case BUILTIN: return(NOTYPE); break; } abort(); }