#ifndef _DB_H_077adb40_ #define _DB_H_077adb40_ #if defined(__GCC__) && defined(__GCC_MINOR__) &&\ ((__GCC__ > 2) || ((__GCC__ == 2) && (__GCC_MINOR__ >= 5))) #define attribute(x) __attribute__(x) #else #define attribute(x) /* nothing */ #endif /* This software is Copyright 1989, 1990, 1992, 1993 by various individuals. Please see the accompanying file COPYRIGHT for details. */ #include #include "str.h" #include "params.h" #include "regexp.h" typedef int dbref; /* offset into db */ #ifdef GDBM_DATABASE #define DBFETCH(x) dbfetch(x) #define DBDIRTY(x) dbdirty(x) #else /* !GDBM_DATABASE */ #define DBFETCH(x) dbfetch(x) extern struct object *dbfetch(int); #define DBDIRTY(x) /* nothing */ #endif #define DBSTORE(x, y, z) {DBFETCH(x)->y = z; DBDIRTY(x);} #define NAME(x) (db[x].name) #define FLAGS(x) (db[x].flags) #define OWNER(x) (db[x].owner) /* The order of the bits is historical and is preserved for the sake of db file compatability... */ #define TYPE_ROOM 0x00000000 #define TYPE_THING 0x00000001 #define TYPE_EXIT 0x00000002 #define TYPE_PLAYER 0x00000003 #define TYPE_PROGRAM 0x00000004 #define TYPE_DAEMON 0x00000005 #define TYPE_GARBAGE 0x00000006 #define NOTYPE 0x00000007 #define TYPE_MASK 0x00000007 #define CFLAG 0x00000008 #define WFLAG 0x00000010 #define LFLAG 0x00000020 #define DFLAG 0x00000040 #define INTERNAL 0x00000080 #define SFLAG 0x00000100 #define BFLAG 0x00000200 #define OFLAG 0x00000400 #define JFLAG 0x00000800 #define EFLAG 0x00001000 #define KFLAG 0x00002000 #define NFLAG 0x00004000 #define FFLAG 0x00008000 #define HFLAG 0x00010000 #define AFLAG 0x00020000 #define MFLAG 0x00040000 #define UFLAG 0x00080000 /*#define SWAPOUT 0x00100000*/ #define IFLAG 0x00200000 #define TFLAG 0x00400000 #define PFLAG 0x00800000 #define GFLAG 0x01000000 #define QFLAG 0x02000000 #define VFLAG 0x04000000 #define RFLAG 0x08000000 #define XFLAG 0x10000000 #define YFLAG 0x20000000 #define ZFLAG 0x40000000 /* never used 0x80000000 */ #define ABODE AFLAG #define AUTHOR AFLAG #define AUTOSTART AFLAG #define BUILDER BFLAG #define BUSY BFLAG #define DARK DFLAG #define DEBUG DFLAG #define EXACT EFLAG #define FINALSTACK FFLAG #define FOLLOWSTATUS FFLAG #define FULLNAME FFLAG #define GOD GFLAG #define HAVEN HFLAG #define HEAR HFLAG #define INCONTENTS IFLAG #define INDIVIDUAL IFLAG #define INTERACTIVE IFLAG #define JUMP_OK JFLAG #define KEEP KFLAG #define LINK_OK LFLAG #define MONITOR MFLAG #define MUCKER MFLAG #define NOINVENTORY NFLAG #define NOISY NFLAG #define OBSERVE OFLAG #define OWNABLE OFLAG #define PREFIX PFLAG #define QUELL QFLAG #define ROYALTY RFLAG #define SETUID SFLAG #define SILENT SFLAG #define STICKY SFLAG #define TAP TFLAG #define TRIGGERUID TFLAG #define UNCONNECTED UFLAG #define UNKILLABLE UFLAG #define UNLISTABLE UFLAG #define UNSEEN UFLAG #define VISUAL VFLAG #define WIZARD WFLAG #define GENDER_UNASSIGNED 0x0 #define GENDER_NEUTER 0x1 #define GENDER_FEMALE 0x2 #define GENDER_MALE 0x3 typedef int object_flag_type; #define GOD_DBREF ((dbref)1) #define TrueGod(x) (((x)==GOD_DBREF) || (FLAGS(x) & GOD)) #define TrueWizard(x) (((x)==GOD_DBREF) || (FLAGS(x) & (WIZARD|GOD))) #define TrueRoyalty(x) (((x)==GOD_DBREF) || (FLAGS(x) & (ROYALTY|WIZARD|GOD))) #define Quelled(x) (FLAGS(x) & QUELL) #define God(x) (TrueGod(x) && !Quelled(x)) #define Wizard(x) (TrueWizard(x) && !Quelled(x)) #define Royalty(x) (TrueRoyalty(x) && !Quelled(x)) #define ProgGod(program) (God(program) && TrueGod(OWNER(program))) #define ProgWizard(program) (Wizard(program) && TrueWizard(OWNER(program))) #define ProgRoyalty(program) (Royalty(program) && TrueRoyalty(OWNER(program))) #define DoNull(s) ((s) ? (s) : "") #define Typeof(x) (((x < 0) || (x >= db_top)) ? special_typeof(x) : (FLAGS(x) & TYPE_MASK)) extern int special_typeof(dbref); #define Dark(x) ((FLAGS(x) & DARK) != 0) #ifdef MUCKER_ALL #define Mucker(x) ((Typeof(x) == TYPE_PLAYER)) #else /* !MUCKER_ALL */ #define Mucker(x) ((FLAGS(x) & (WIZARD|MUCKER)) != 0) /* note: not GOD */ #endif /* MUCKER_ALL */ #ifndef RESTRICTED_BUILDING #define Builder(x) ((Typeof(x) == TYPE_PLAYER)) #else /* RESTRICTED_BUILDING */ #define Builder(x) ((FLAGS(x) & (ROYALTY|WIZARD|BUILDER)) != 0) /* note: not GOD */ #endif /* RESTRICTED_BUILDING */ #define Linkable(x) ( ((x) == HOME) || \ ( FLAGS(x) & \ ( (Typeof(x) == TYPE_ROOM) ? ABODE : LINK_OK ) ) ) typedef enum { BOOLEXP_AND = 1, BOOLEXP_OR, BOOLEXP_NOT, BOOLEXP_OBJ, BOOLEXP_PROP } boolexp_type; struct boolexp { boolexp_type type; union { struct { struct boolexp *sub1; struct boolexp *sub2; } dyad; struct boolexp *monad; struct { dbref thing; char *param; } obj; struct lockprop *prop; } u; } ; #define TRUE_BOOLEXP ((struct boolexp *) 0) /* special dbrefs */ #define NOTHING ((dbref) -1) /* null dbref */ #define AMBIGUOUS ((dbref) -2) /* multiple possibilities, for matchers */ #define HOME ((dbref) -3) /* virtual room, represents mover's home */ #define INVALID ((dbref) -4) /* returned for invalid things */ #define BUILTIN ((dbref) -5) /* link to this for builtins */ /* editor data structures */ /* Line data structure */ struct line { char *this_line; /* the line itself */ struct line *next, *prev; /* the next line and the previous line */ }; /* A dbref serial number */ typedef unsigned long int SERIAL; /* A MUF "quad" */ typedef unsigned long long int MUFQUAD; /* An open file */ typedef struct ofile OFILE; /* stack and object declarations */ /* When adding a new type here, - add it to inst.c:insttotext() - if it's a PROG__CLEAR type, add it to interp.c:interp_clear() - if it's a PROG__CLEAR type, add it to interp.c:copyinst() - if it has constants, make the compiler (compile.c) recognize it - if it has constants, add it to interp.c:interp_loop() - probably add it to interp.c:push() - probably add a test to p_tests.[ch] - add it to any primitives that are supposed to understand it */ #define PROG__CLEAR 0x10 /* needs interp_clear call */ #define PROG_NONE (0) #define PROG_PRIMITIVE (1) /* forth primitives and hard-coded C routines */ #define PROG_STRING (2|PROG__CLEAR) /* string */ #define PROG_INTEGER (3) /* integer */ #define PROG_ADD (4) /* program address --- used in calls and jumps */ #define PROG_OBJECT (5) /* database objects */ #define PROG_VAR (6) /* variables */ #define PROG_PTR (7|PROG__CLEAR) /* pair */ #define PROG_RE (8|PROG__CLEAR) /* compiled regexp */ #define PROG_PLT (9|PROG__CLEAR) /* plist traversal object */ #define PROG_FLOAT (10|PROG__CLEAR) /* floating-point number */ #define PROG_ARRAY (11|PROG__CLEAR) /* heterogenous array */ #define PROG_QUAD (12|PROG__CLEAR) /* 64-bit unsigned integer */ #define PROG_OFILE (13|PROG__CLEAR) /* open file */ #define PROGLOCK_READ 1 /* program locked for read access */ #define PROGLOCK_WRITE 2 /* program locked for write access */ #define MAX_VAR 53 /* maximum number of variables including the built-in ones */ #define STACK_SIZE 512 /* maximum size of stack */ #define ILIMIT_DEFAULT 1000000 /* maximum iterations of interp_loop */ #define ILIMIT_MIN 10 /* minimum settable ilimit */ #define QUANTUM 10000 /* iterations before player is swapped out */ #define NOPLAYER_QUANTUM 100000 /* QUANTUM when interpreting for nobody */ struct progptr { dbref prog; struct inst *ptr; } ; struct plt_prop { struct plt_prop *link; char *name; } ; struct plt { int refcnt; dbref dbr; SERIAL serial; struct plt_prop *props; } ; struct mufarray { int refcnt; int ndims; int size; int *dims; struct inst *data; } ; struct ofile { int refcnt; dbref who; int how; FILE *f; char *path; } ; struct cre { int refcnt; regexp *re; } ; struct inst { /* instruction */ unsigned int type : 8; unsigned int prog : 24; union { char *string; int number; /* used for both primitives and integers */ dbref objref; struct inst *call; /* use in IF and JMPs */ struct progptr *ptr; struct cre *re; struct plt *plt; double *flt; struct mufarray *arr; MUFQUAD *quad; OFILE *ofile; } data; } ; struct stab { int off; char *name; } ; struct stack { int top; struct inst st[STACK_SIZE]; } ; struct dbref_list { dbref object; struct dbref_list *next; } ; struct for_struct { int current; int target; int stepsize; struct for_struct *next; } ; struct frame { /* frame data structure for executing programs */ signed int systop; /* return stack depth */ struct inst *sysst[STACK_SIZE]; /* return stack elements */ struct stack argument; /* data stack */ struct inst variables[MAX_VAR]; /* variables */ struct inst *pc; /* next instruction to execute */ unsigned int writeonly : 1; /* this program can't do reads */ unsigned int reading : 1; /* blocked waiting for input */ int iterations; /* the number of iterations done */ int timeslice; /* iterations done in the slice */ struct dbref_list *caller; dbref trigger; dbref startcaller; dbref daemon; dbref prog; struct for_struct *for_loop; struct frame *next; struct frame *flink; struct frame *blink; MUFQUAD serial; } ; /* union of type-specific fields */ union specific { struct { /* ROOM-specific fields */ dbref dropto; dbref exits; double useval; unsigned long int stamp; } room; struct { /* THING-specific fields */ dbref home; dbref actions; int value; } thing; struct { /* EXIT-specific fields */ int ndest; dbref *dest; } exit; struct { /* PLAYER-specific fields */ dbref home; dbref actions; dbref curr_prog; int dbrefs_owned; int daemons; int pennies; char *password; struct frame *run; struct dbref_list *proglocks; unsigned int proglock_type : 2; unsigned int insert_mode : 1; #ifdef TRAILSIZE dbref trail[TRAILSIZE]; int trailh; #endif } player; struct { /* PROGRAM-specific fields */ struct dbref_list *proglocks; struct line *first; int curr_line; int codesiz; struct inst *codevec; int stabsiz; struct stab *stabvec; struct inst *start; } program; struct { /* DAEMON-specific fields */ struct line *first; unsigned long int cycles; struct frame *run; struct dbref_list *proglocks; int proglock_type; dbref sleepobj; } daemon; } ; struct object { char *name; STR description; STR fail_message; STR succ_message; STR drop_message; STR ofail; STR osuccess; STR odrop; dbref location; dbref owner; dbref contents; dbref next; dbref nextowned; struct dbref_list *backlinks; struct dbref_list *backlocks; struct dbref_list *backprops; struct dbref_list *sleepers; struct boolexp *key; struct plist *properties; object_flag_type flags; #ifdef TIMESTAMPS long int time_created; long int time_modified; long int time_used; #endif SERIAL serial; union specific sp; } ; struct flagname { object_flag_type flag; object_flag_type othermask; object_flag_type otherval; const char *name; } ; struct flagname1 { object_flag_type flag; char name; } ; struct macrotable { char *name; char *definition; dbref implementor; struct macrotable *left; struct macrotable *right; }; /* Possible data types that may be stored in a hash table */ union u_hash_data { int ival; /* Store compiler tokens here */ dbref dbval; /* Player hashing will want this */ void *pval; /* Can't hurt, we might need it someday */ }; /* The actual hash entry for each item */ struct t_hash_entry { struct t_hash_entry *next; /* Pointer for conflict resolution */ const char *name; /* The name of the item */ union u_hash_data dat; /* Data value for item */ }; typedef union u_hash_data hash_data; typedef struct t_hash_entry hash_entry; typedef hash_entry *hash_tab; #define PLAYER_HASH_SIZE (1 << 12) /* Table for player lookups */ #define COMP_HASH_SIZE (1 << 6) /* Table for compiler keywords */ extern struct object *db; extern struct macrotable *macrotop; extern dbref db_top; extern dbref new_object(int); extern void add_to_recyclable(dbref); extern dbref getref (FILE *); /* Read a database reference from a file. */ extern void putref (FILE *, dbref); /* Write one ref to the file */ extern struct boolexp *getboolexp(FILE *); /* get a boolexp */ extern void putboolexp(FILE *, struct boolexp *); /* put a boolexp */ extern int db_write_object(FILE *, dbref); /* write one object to file */ extern dbref db_write(FILE *, FILE *); /* write db to file, return # of objects */ /* read db from file, return # of objects */ /* Warning: destroys existing db contents! */ extern dbref db_read(FILE *, int); extern void free_boolexp(struct boolexp *); extern void db_free(void); extern dbref parse_dbref(const char *); /* parse a dbref */ #define DOLIST(var, first) \ for((var) = (first); (var) != NOTHING; (var) = DBFETCH(var)->next) #define PUSH(thing, locative) \ {DBSTORE((thing), next, (locative)); (locative) = (thing);} #define getloc(thing) (DBFETCH(thing)->location) /* Usage guidelines: To obtain an object pointer use DBFETCH(i). Pointers returned by DBFETCH may become invalid after a call to new_object(). To update an object, use DBSTORE(i, f, v), where i is the object number, f is the field (after ->), and v is the new value. If you have updated an object without using DBSTORE, use DBDIRTY(i) before leaving the routine that did the update. When using PUSH, be sure to call DBDIRTY on the object which contains the locative (see PUSH definition above). Some fields are now handled in a unique way, since they are always memory resident, even in the GDBM_DATABASE disk-based muck. These are: name, flags and owner. Refer to these by NAME(i), FLAGS(i) and OWNER(i). Always call DBDIRTY(i) after updating one of these fields. The programmer is responsible for managing storage for string components of entries; db_read will produce malloc'd strings. The alloc_string routine is provided for generating malloc'd strings duplicates of other strings. Note that db_free and db_read will attempt to free any non-NULL string that exists in db when they are invoked. */ #endif