/* $Header: /belch_a/users/rearl/tinymuck/include/RCS/db.h,v 1.10 90/09/28 12:15:15 rearl Exp $ * * $Log: db.h,v $ * Revision 1.10 90/09/28 12:15:15 rearl * Added shared string structures to interp.c. * * Revision 1.9 90/09/18 08:05:45 rearl * Took out FILTER, added INTERNAL. Moved stuff to params.h * * Revision 1.8 90/09/16 13:59:03 rearl * Disk based preparation code added. * * Revision 1.7 90/09/13 06:33:20 rearl * MAX_VAR increased to 53 == 50 user variables. * * Revision 1.6 90/09/01 06:03:46 rearl * Took out TEST_MALLOC references. * * Revision 1.5 90/08/27 14:06:31 rearl * Disk-based MUF source code and added necessary locks. * * Revision 1.4 90/08/15 03:50:57 rearl * Added some new macros and made others more useful... * * Revision 1.3 90/07/29 17:16:43 rearl * Moved some things to config.h, minor change in programs to allow * locks to rooms, @# in rooms, etc. * * Revision 1.2 90/07/19 23:06:07 casie * Removed comment log at top. * * */ #include "copyright.h" #ifndef __DB_H #define __DB_H #include <stdio.h> extern void *malloc(unsigned long); extern void *realloc(void *, unsigned long); extern void free(void *); extern char match_args[BUFSIZ]; typedef int dbref; /* offset into db */ #define getstring(x) alloc_string(getstring_noalloc(x)) #ifdef COMPRESS #define alloc_compressed(x) alloc_string(compress(x)) #define getstring_compress(x) alloc_string(compress(getstring_noalloc(x))) #define get_compress(x) compress(x) #define get_uncompress(x) uncompress(x) #else #define alloc_compressed(x) alloc_string(x) #define getstring_compress(x) getstring(x) #define get_compress(x) (x) #define get_uncompress(x) (x) #endif /* COMPRESS */ #ifdef GDBM_DATABASE #define DBFETCH(x) dbfetch(x) #define DBDIRTY(x) dbdirty(x) #else /* !GDBM_DATABASE */ #define DBFETCH(x) (db + (x)) #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) #define TYPE_ROOM 0x0 #define TYPE_THING 0x1 #define TYPE_EXIT 0x2 #define TYPE_PLAYER 0x3 #define TYPE_PROGRAM 0x4 /* related structures */ #define TYPE_DAEMON 0x5 /* but not the same thing */ #define TYPE_GARBAGE 0x6 #define NOTYPE 0x7 /* no particular type */ #define TYPE_MASK 0x7 /* room for expansion */ #define ANTILOCK 0x8 /* negates key (*OBSOLETE*) */ #define WIZARD 0x10 /* gets automatic control */ #define LINK_OK 0x20 /* anybody can link to this room */ #define DARK 0x40 /* contents of room are not printed */ #define INTERNAL 0x80 /* internal-use-only flag */ #define STICKY 0x100 /* this object goes home when dropped */ #define BUILDER 0x200 /* this player can use construction commands */ #ifdef PLAYER_CHOWN #define CHOWN_OK 0x400 /* this player can be @chowned to */ #endif /* PLAYER_CHOWN */ #define JUMP_OK 0x800 /* A room which can be Trumped from, or */ /* a player who can be Trumped to */ #define GENDER_MASK 0x3000 /* 2 bits of gender */ #define GENDER_SHIFT 12 /* 0x1000 is 12 bits over (for shifting) */ #define GENDER_UNASSIGNED 0x0 /* unassigned - the default */ #define GENDER_NEUTER 0x1 /* neuter */ #define GENDER_FEMALE 0x2 /* for women */ #define GENDER_MALE 0x3 /* for men */ #define BUSY_MACHINE 0x4000 /* Machine busy... commands are delayed */ #define PUPPET 0x8000 /* Owner hears everything. */ #define HALTED 0x10000 #ifdef HAVEN #undef HAVEN #define HAVEN HALTED #endif /* HAVEN */ #define ARCHITECT 0x20000 /* super builder */ #ifdef ABODE #undef ABODE #define ABODE ARCHITECT #endif /* ABODE */ #define MAGE 0x40000 /* programmer */ #define QUELL 0x80000 #define ENTER_OK 0x100000 /* Things can be given to it, and you can 'enter' it. */ #define INTERACTIVE 0x200000 /* when this is set, player is either * editing a program or in a READ. */ #define OPAQUE 0x400000 /* can't see into this player/room's /object's contents */ #define VISIBLE 0x800000 /* can be ex'd by other people */ typedef long object_flag_type; #define GOD ((dbref) 1) #define is_god(x) ((x) == (GOD)) #define DoNull(s) ((s) ? (s) : "") #define Typeof(x) (x == HOME ? TYPE_ROOM : \ ((x >= db_top || x < 0) ? TYPE_GARBAGE : \ (FLAGS(x) & TYPE_MASK))) #ifndef ABODE #define Linkable(x) ((x) == HOME || ((FLAGS(x) & LINK_OK) != 0)) #else /* ABODE */ #define Linkable(x) ((x) == HOME || ((Typeof(x) == TYPE_ROOM ? \ (FLAGS(x) & ABODE) : \ (FLAGS(x) & LINK_OK)) != 0)) #endif /* ABODE */ /* Properties lists */ struct plist { const char *type; /* kind of property -- e.g. "sex" */ const char *class; /* value of this property -- e.g. "male" */ struct plist *next; /* next item on property list */ /* struct plist *child; */ /* propdirs not implemented */ }; /* property lists are used thus: @set me=property:class As of right now, the value field is not used, but it is there for later expansion. SEX is no longer going to be a flag, it's going to be a property, so that locks can lock against the sex of the character. */ /* Boolean expressions, for locks */ typedef char boolexp_type; #define BOOLEXP_AND 0 #define BOOLEXP_OR 1 #define BOOLEXP_NOT 2 #define BOOLEXP_CONST 3 #define BOOLEXP_PROP 4 struct boolexp { boolexp_type type; struct boolexp *sub1; struct boolexp *sub2; dbref thing; struct plist *prop_check; }; #define TRUE_BOOLEXP ((struct boolexp *) 0) /* special dbref's */ #define NOTHING ((dbref) -1) /* null dbref */ #define AMBIGUOUS ((dbref) -2) /* multiple possibilities, for matchers */ #define HOME ((dbref) -3) /* virtual room, represents mover's home */ /* editor data structures */ /* Line data structure */ struct line { const char *this_line; /* the line itself */ struct line *next, *prev; /* the next line and the previous line */ }; /* stack and object declarations */ #define PROG_PRIMITIVE 1 /* forth primitives and hard-coded C routines */ #define PROG_STRING 2 /* string types */ #define PROG_INTEGER 3 /* integer types */ #define PROG_ADD 4 /* program address --- used in calls and jumps */ #define PROG_OBJECT 5 /* database objects */ #define PROG_VAR 6 /* variables */ #define PROG_CON 7 /* descriptors */ #define PROG_BOOLEXP 8 /* Boolexp... */ #define MAX_VAR 53 /* maximum number of variables including the basic ME and LOC */ #define RES_VAR 3 /* no of reserved variables */ #define STACK_SIZE 512 /* maximum size of stack */ struct shared_string /* for sharing strings in programs */ { int links; /* number of pointers to this struct */ int length; /* length of string data */ char data[1]; /* shared string data */ }; #define CLEAR(C) { if ((C)->type == PROG_STRING && (C)->data.string && \ --(C)->data.string->links == 0) \ free((void *) (C)->data.string);} struct inst /* instruction */ { short type; union { struct shared_string *string; int number; /* used for both primitives and integers */ dbref objref; /* object reference */ struct descriptor_data *con; struct inst *call; /* use in IF and JMPs */ struct boolexp *boolexp; /* for boolexp. (obvious) */ } data; }; struct stack { int top; struct inst st[STACK_SIZE]; }; struct frame /* frame data structure necessary for executing programs */ { struct stack system; /* system stack */ struct stack argument; /* argument stack */ struct inst variables[MAX_VAR];/* variables */ struct inst *pc; /* next executing instruction */ int writeonly; /* This program should not do reads */ }; /* union of type-specific fields */ union specific { struct { dbref *dest; int ndest; } exit; struct { /* THING-specific fields */ int value; } thing; struct { /* PLAYER-specific fields */ int pennies; const char *password; } player; struct { /* PROGRAM-specific fields */ struct line *first; /* first line */ int siz; /* size of code */ int curr_line; /* current-line */ struct inst *code; /* byte-compiled code */ struct inst *start; /* place to start executing */ } program; struct { /* DAEMON-specific fields */ struct line *first; int curr_line; int siz; /* size of code */ struct inst *code; struct inst *start; /* place to start executing */ int cycles; /* execute per n cycles */ struct frame *run; } daemon; }; struct object { const char *name; dbref link,exits; /* link and exits */ dbref location; /* pointer to container */ dbref owner; dbref contents; dbref next; /* pointer to next in contents/exits chain */ /* Program junk. */ dbref curr_prog; /* program I'm currently editing */ int insert_mode; /* in insert mode? */ struct frame *run; struct boolexp *key; /* if not NOTHING, must have this to do op */ struct plist *attributes; struct plist *properties; object_flag_type flags; union specific sp; }; 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 recyclable; extern struct shared_string *alloc_prog_string(const char *); extern dbref new_object(); /* return a new object */ 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 *f); /* write db to file, return # of objects */ extern dbref db_read(FILE *f); /* read db from file, return # of objects */ /* Warning: destroys existing db contents! */ 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 /* __DB_H */ #define MUCKER MAGE extern char buf[8192]; /* change this if BUFFER_LEN is changed. */