home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / games / tinymud2.zip / DB.C < prev    next >
C/C++ Source or Header  |  1990-09-02  |  9KB  |  471 lines

  1. #include "copyright.h"
  2.  
  3. #include <stdio.h>
  4. #include <ctype.h>
  5.  
  6. #include "db.h"
  7. #include "config.h"
  8.  
  9. struct object *db = 0;
  10. dbref db_top = 0;
  11.  
  12. #ifdef TEST_MALLOC
  13. int malloc_count = 0;
  14. #endif /* TEST_MALLOC */
  15.  
  16. #ifndef DB_INITIAL_SIZE
  17. #define DB_INITIAL_SIZE 10000
  18. #endif /* DB_INITIAL_SIZE */
  19.  
  20. #ifdef DB_DOUBLING
  21.  
  22. dbref db_size = DB_INITIAL_SIZE;
  23. #endif /* DB_DOUBLING */
  24.  
  25. const char *alloc_string(const char *string)
  26. {
  27.     char *s;
  28.  
  29.     /* NULL, "" -> NULL */
  30.     if(string == 0 || *string == '\0') return 0;
  31.  
  32.     if((s = (char *) malloc(strlen(string)+1)) == 0) {
  33.     abort();
  34.     }
  35.     strcpy(s, string);
  36.     return s;
  37. }
  38.  
  39. #ifdef DB_DOUBLING
  40.  
  41. static void db_grow(dbref newtop)
  42. {
  43.     struct object *newdb;
  44.  
  45.     if(newtop > db_top) {
  46.     db_top = newtop;
  47.     if(!db) {
  48.         /* make the initial one */
  49.         db_size = DB_INITIAL_SIZE;
  50.         if((db = (struct object *)
  51.         malloc(db_size * sizeof(struct object))) == 0) {
  52.         abort();
  53.         }
  54.     }
  55.     
  56.     /* maybe grow it */
  57.     if(db_top > db_size) {
  58.         /* make sure it's big enough */
  59.         while(db_top > db_size) db_size *= 2;
  60.         if((newdb = (struct object *)
  61.         realloc((void *) db,
  62.             db_size * sizeof(struct object))) == 0) {
  63.         abort();
  64.         } 
  65.         db = newdb;
  66.     }
  67.     }
  68. }
  69.  
  70. #else /* DB_DOUBLING */
  71.  
  72. static void db_grow(dbref newtop)
  73. {
  74.     struct object *newdb;
  75.  
  76.     if(newtop > db_top) {
  77.     db_top = newtop;
  78.     if(db) {
  79.         if((newdb = (struct object *)
  80.         realloc((void *) db,
  81.             db_top * sizeof(struct object))) == 0) {
  82.         abort();
  83.         } 
  84.         db = newdb;
  85.     } else {
  86.         /* make the initial one */
  87.         if((db = (struct object *)
  88.         malloc(DB_INITIAL_SIZE * sizeof(struct object))) == 0) {
  89.         abort();
  90.         }
  91.     }
  92.     }
  93. }
  94. #endif /* DB_DOUBLING */
  95.  
  96. dbref new_object(void)
  97. {
  98.     dbref newobj;
  99.     struct object *o;
  100.  
  101.     newobj = db_top;
  102.     db_grow(db_top + 1);
  103.  
  104.     /* clear it out */
  105.     o = db+newobj;
  106.     o->name = 0;
  107.     o->description = 0;
  108.     o->location = NOTHING;
  109.     o->contents = NOTHING;
  110.     o->exits = NOTHING;
  111.     o->next = NOTHING;
  112.     o->key = TRUE_BOOLEXP;
  113.     o->fail_message = 0;
  114.     o->succ_message = 0;
  115.     o->ofail = 0;
  116.     o->osuccess = 0;
  117.     o->owner = NOTHING;
  118.     o->pennies = 0;
  119.     /* flags you must initialize yourself */
  120.     o->password = 0;
  121.  
  122.     return newobj;
  123. }
  124.     
  125. #define DB_MSGLEN 512
  126.  
  127. void putref(FILE *f, dbref ref)
  128. {
  129.     fprintf(f, "%d\n", ref);
  130. }
  131.  
  132. static void putstring(FILE *f, const char *s)
  133. {
  134.     if(s) {
  135.     fputs(s, f);
  136.     } 
  137.     putc('\n', f);
  138. }
  139.     
  140. static void putbool_subexp(FILE *f, struct boolexp *b)
  141. {
  142.     switch(b->type) {
  143.       case BOOLEXP_AND:
  144.     putc('(', f);
  145.     putbool_subexp(f, b->sub1);
  146.     putc(AND_TOKEN, f);
  147.     putbool_subexp(f, b->sub2);
  148.     putc(')', f);
  149.     break;
  150.       case BOOLEXP_OR:
  151.     putc('(', f);
  152.     putbool_subexp(f, b->sub1);
  153.     putc(OR_TOKEN, f);
  154.     putbool_subexp(f, b->sub2);
  155.     putc(')', f);
  156.     break;
  157.       case BOOLEXP_NOT:
  158.     putc('(', f);
  159.     putc(NOT_TOKEN, f);
  160.     putbool_subexp(f, b->sub1);
  161.     putc(')', f);
  162.     break;
  163.       case BOOLEXP_CONST:
  164.     fprintf(f, "%d", b->thing);
  165.     break;
  166.       default:
  167.     break;
  168.     }
  169. }
  170.  
  171. void putboolexp(FILE *f, struct boolexp *b)
  172. {
  173.     if(b != TRUE_BOOLEXP) {
  174.     putbool_subexp(f, b);
  175.     }
  176.     putc('\n', f);
  177. }
  178.     
  179. int db_write_object(FILE *f, dbref i)
  180. {
  181.     struct object *o;
  182.  
  183.     o = db + i;
  184.     putstring(f, o->name);
  185.     putstring(f, o->description);
  186.     putref(f, o->location);
  187.     putref(f, o->contents);
  188.     putref(f, o->exits);
  189.     putref(f, o->next);
  190.     putboolexp(f, o->key);
  191.     putstring(f, o->fail_message);
  192.     putstring(f, o->succ_message);
  193.     putstring(f, o->ofail);
  194.     putstring(f, o->osuccess);
  195.     putref(f, o->owner);
  196.     putref(f, o->pennies);
  197.     putref(f, o->flags);
  198.     putstring(f, o->password);
  199.  
  200.     return 0;
  201. }
  202.  
  203. dbref db_write(FILE *f)
  204. {
  205.     dbref i;
  206.  
  207.     for(i = 0; i < db_top; i++) {
  208.     fprintf(f, "#%d\n", i);
  209.     db_write_object(f, i);
  210.     }
  211.     fputs("***END OF DUMP***\n", f);
  212.     fflush(f);
  213.     return(db_top);
  214. }
  215.  
  216. dbref parse_dbref(const char *s)
  217. {
  218.     const char *p;
  219.     long x;
  220.  
  221.     x = atol(s);
  222.     if(x > 0) {
  223.     return x;
  224.     } else if(x == 0) {
  225.     /* check for 0 */
  226.     for(p = s; *p; p++) {
  227.         if(*p == '0') return 0;
  228.         if(!isspace(*p)) break;
  229.     }
  230.     }
  231.  
  232.     /* else x < 0 or s != 0 */
  233.     return NOTHING;
  234. }
  235.         
  236. dbref getref(FILE *f)
  237. {
  238.     static char buf[DB_MSGLEN];
  239.  
  240.     fgets(buf, sizeof(buf), f);
  241.     return(atol(buf));
  242. }
  243.  
  244. static const char *getstring_noalloc(FILE *f)
  245. {
  246.     static char buf[DB_MSGLEN];
  247.     char *p;
  248.  
  249.     fgets(buf, sizeof(buf), f);
  250.     for(p = buf; *p; p++) {
  251.     if(*p == '\n') {
  252.         *p = '\0';
  253.         break;
  254.     }
  255.     }
  256.  
  257.     return buf;
  258. }
  259.  
  260. #define getstring(x) alloc_string(getstring_noalloc(x))
  261.  
  262. #ifdef COMPRESS
  263. extern const char *compress(const char *);
  264. #define getstring_compress(x) alloc_string(compress(getstring_noalloc(x)));
  265. #else
  266. #define getstring_compress(x) getstring(x)
  267. #endif /* COMPRESS */
  268.  
  269. static struct boolexp *negate_boolexp(struct boolexp *b)
  270. {
  271.     struct boolexp *n;
  272.  
  273.     /* Obscure fact: !NOTHING == NOTHING in old-format databases! */
  274.     if(b == TRUE_BOOLEXP) return TRUE_BOOLEXP;
  275.  
  276.     n = (struct boolexp *) malloc(sizeof(struct boolexp));
  277.     n->type = BOOLEXP_NOT;
  278.     n->sub1 = b;
  279.  
  280.     return n;
  281. }
  282.  
  283. static struct boolexp *getboolexp1(FILE *f)
  284. {
  285.     struct boolexp *b;
  286.     int c;
  287.  
  288.     c = getc(f);
  289.     switch(c) {
  290.       case '\n':
  291.     ungetc(c, f);
  292.     return TRUE_BOOLEXP;
  293.     /* break; */
  294.       case EOF:
  295.     abort();        /* unexpected EOF in boolexp */
  296.     break;
  297.       case '(':
  298.     b = (struct boolexp *) malloc(sizeof(struct boolexp));
  299.     if((c = getc(f)) == '!') {
  300.         b->type = BOOLEXP_NOT;
  301.         b->sub1 = getboolexp1(f);
  302.         if(getc(f) != ')') goto error;
  303.         return b;
  304.     } else {
  305.         ungetc(c, f);
  306.         b->sub1 = getboolexp1(f);
  307.         switch(c = getc(f)) {
  308.           case AND_TOKEN:
  309.         b->type = BOOLEXP_AND;
  310.         break;
  311.           case OR_TOKEN:
  312.         b->type = BOOLEXP_OR;
  313.         break;
  314.           default:
  315.         goto error;
  316.         /* break */
  317.         }
  318.         b->sub2 = getboolexp1(f);
  319.         if(getc(f) != ')') goto error;
  320.         return b;
  321.     }
  322.     /* break; */
  323.       case '-':
  324.     /* obsolete NOTHING key */
  325.     /* eat it */
  326.     while((c = getc(f)) != '\n') if(c == EOF) abort(); /* unexp EOF */
  327.     ungetc(c, f);
  328.     return TRUE_BOOLEXP;
  329.     /* break */
  330.       default:
  331.     /* better be a dbref */
  332.     ungetc(c, f);
  333.     b = (struct boolexp *) malloc(sizeof(struct boolexp));
  334.     b->type = BOOLEXP_CONST;
  335.     b->thing = 0;
  336.         
  337.     /* NOTE possibly non-portable code */
  338.     /* Will need to be changed if putref/getref change */
  339.     while(isdigit(c = getc(f))) {
  340.         b->thing = b->thing * 10 + c - '0';
  341.     }
  342.     ungetc(c, f);
  343.     return b;
  344.     }
  345.  
  346.   error:
  347.     abort();            /* bomb out */
  348.     return TRUE_BOOLEXP;
  349. }
  350.  
  351. struct boolexp *getboolexp(FILE *f)
  352. {
  353.     struct boolexp *b;
  354.  
  355.     b = getboolexp1(f);
  356.     if(getc(f) != '\n') abort(); /* parse error, we lose */
  357.     return b;
  358. }
  359.  
  360. void free_boolexp(struct boolexp *b)
  361. {
  362.     if(b != TRUE_BOOLEXP) {
  363.     switch(b->type) {
  364.       case BOOLEXP_AND:
  365.       case BOOLEXP_OR:
  366.         free_boolexp(b->sub1);
  367.         free_boolexp(b->sub2);
  368.         free((void *) b);
  369.         break;
  370.       case BOOLEXP_NOT:
  371.         free_boolexp(b->sub1);
  372.         free((void *) b);
  373.         break;
  374.       case BOOLEXP_CONST:
  375.         free((void *) b);
  376.         break;
  377.     }
  378.     }
  379. }
  380.  
  381. void db_free(void)
  382. {
  383.     dbref i;
  384.     struct object *o;
  385.  
  386.     if(db) {
  387.     for(i = 0; i < db_top; i++) {
  388.         o = &db[i];
  389.         if(o->name) free((void *) o->name);
  390.         if(o->description) free((void *) o->description);
  391.         if(o->succ_message) free((void *) o->succ_message);
  392.         if(o->fail_message) free((void *) o->fail_message);
  393.         if(o->ofail) free((void *) o->ofail);
  394.         if(o->osuccess) free((void *) o->osuccess);
  395.         if(o->password) free((void *) o->password);
  396.         if(o->key) free_boolexp(o->key);
  397.     }
  398.     free((void *) db);
  399.     db = 0;
  400.     db_top = 0;
  401.     }
  402. }
  403.  
  404. dbref db_read(FILE *f)
  405. {
  406.     dbref i;
  407.     struct object *o;
  408.     const char *end;
  409.  
  410. #ifdef PLAYER_LIST
  411.     clear_players();
  412. #endif
  413.     
  414.     db_free();
  415.     for(i = 0;; i++) {
  416.     switch(getc(f)) {
  417.       case '#':
  418.         /* another entry, yawn */
  419.         if(i != getref(f)) {
  420.         /* we blew it */
  421.         return -1;
  422.         }
  423.         /* make space */
  424.         db_grow(i+1);
  425.         
  426.         /* read it in */
  427.         o = db+i;
  428.         o->name = getstring(f);
  429.         o->description = getstring_compress(f);
  430.         o->location = getref(f);
  431.         o->contents = getref(f);
  432.         o->exits = getref(f);
  433.         o->next = getref(f);
  434.         o->key = getboolexp(f);
  435.         o->fail_message = getstring_compress(f);
  436.         o->succ_message = getstring_compress(f);
  437.         o->ofail = getstring_compress(f);
  438.         o->osuccess = getstring_compress(f);
  439.         o->owner = getref(f);
  440.         o->pennies = getref(f);
  441.         o->flags = getref(f);
  442.         o->password = getstring(f);
  443.         /* For downward compatibility with databases using the */
  444.         /* obsolete ANTILOCK flag. */ 
  445.         if(o->flags & ANTILOCK) {
  446.           o->key = negate_boolexp(o->key);
  447.           o->flags &= ~ANTILOCK;
  448.         }
  449. #ifdef PLAYER_LIST        
  450.         if(Typeof(i) == TYPE_PLAYER) {
  451.         add_player(i);
  452.         }
  453. #endif PLAYER_LIST        
  454.         break;
  455.       case '*':
  456.         end = getstring(f);
  457.         if(strcmp(end, "**END OF DUMP***")) {
  458.         free((void *) end);
  459.         return -1;
  460.         } else {
  461.         free((void *) end);
  462.         return db_top;
  463.         }
  464.       default:
  465.         return -1;
  466.         /* break; */
  467.     }
  468.     }
  469. }
  470.         
  471.