#include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include <time.h> #if defined(macintosh) #include <types.h> #else #include <sys/types.h> #include <sys/time.h> #include <sys/resource.h> #endif #include "merc.h" #include "db.h" #include "recycle.h" #include "music.h" #include "tables.h" #include "lookup.h" #include "olc.h" #include "gdl.h" #include "bounty.h" #include "balance.h" #include "world.h" /* Generic LinkedList loader: an easy way to make linked lists persistant * Copyright 1997 Erwin S. Andreasen <erwin@andreasen.org> * See README and License for further details. */ /* This expands to the first field of what the void* ptr points at, which * is assumed to be a structure whose first field is the pointer to the * next in the list. This is just to make the source more readable - the * purpose of the cast may seem unclear */ #define NEXT(ptr) (*(void**)(ptr)) #define EOF_MARKER "EOF" /* Load a list with size-sized elements from file fname, using translation * table gdl */ void *generic_list_load (const char *fname, const GDL * gdl, int size) { FILE *fp; char *word; void *list, *last, *cur; int i; fp = fopen (fname, "r"); /* perhaps it could be an option, to abort */ if (!fp) /* with error if file doesn't exist? */ return NULL; last = NULL; /* pointer to the last added element */ list = cur = calloc_mem (size); /* allocate cleared memory for one element */ for (;;) { word = fread_word (fp); if (!str_cmp (word, EOF_MARKER)) /* End of file */ break; if (!str_cmp (word, END_MARKER)) /* End of this structure */ { /* Post-Initialize all fields */ for (i = 0; gdl[i].name; i++) (*gdl[i].type) (action_postinit, cur, (char *) cur + gdl[i].offset, gdl[i].extra, fp); last = cur; /* Save cur as our last read element */ cur = calloc_mem (size); /* allocate a new one */ add_mchunk (size); NEXT (last) = cur; /* set the next-ptr of last to this one */ continue; /* Keep reading */ } for (i = 0; gdl[i].name; i++) /* find keyword in list */ if (!str_cmp (word, gdl[i].name)) break; if (!gdl[i].name) /* Hmm, couldn't find keyword */ { bugf ("Unknown keyword %s when reading file %s", word, fname); do_abort (); } (*gdl[i].type) (action_read, cur, (char *) cur + gdl[i].offset, gdl[i].extra, fp); } fclose (fp); if (last == NULL) /* last added == NULL, nothing was read */ list = NULL; else NEXT (last) = NULL; /* Make sure we are not pointing at cur */ /* cur is our current work item, free it */ free_mem (cur, size); del_mchunk (size); return list; } /* Save list starting in list under filename fname, using translation table gdl */ void generic_list_save (const char *fname, const GDL * gdl, void *list) { FILE *fp; int i; fp = fopen (fname, "w"); if (!fp) { bugf ("Could not open %s", fname); do_abort (); } /* here we use assume that the first element is the next* */ for (; list; list = NEXT (list)) { for (i = 0; gdl[i].name; i++) { fprintf (fp, "%s ", gdl[i].name); (*gdl[i].type) (action_write, list, (char *) list + gdl[i].offset, gdl[i].extra, fp); } fprintf (fp, END_MARKER "\n"); } fprintf (fp, EOF_MARKER "\n"); fclose (fp); } /* Functions to read/write/initialize data types */ /* Read/write an integer to this file */ void RWInteger (gdl_action action, void *struct_ptr, void *member_ptr, const void *extra, FILE * fp) { int *p = (int*) member_ptr; if (action == action_read) *p = fread_number (fp); else if (action == action_write) fprintf (fp, "%d\n", *p); } /* Read/write a short integer to this file */ void RWShortInt (gdl_action action, void *struct_ptr, void *member_ptr, const void *extra, FILE * fp) { short int *p = (short int*) member_ptr; if (action == action_read) *p = fread_number (fp); else if (action == action_write) fprintf (fp, "%d\n", *p); } /* Read/write a string (in fread_string format, allocate memory dynamically) */ void RWString (gdl_action action, void *struct_ptr, void *member_ptr, const void *extra, FILE * fp) { char **p = (char**) member_ptr; if (action == action_read) *p = fread_string (fp); else if (action == action_write) fprintf (fp, "%s~\n", *p); else if (action == action_postinit) { /* If string was not read, initialize to a copy of "" */ if (*p == NULL) *p = str_dup (""); } } /* Read/write a flag, converting to a string using the table extra */ void RWFlag (gdl_action action, void *struct_ptr, void *member_ptr, const void *extra, FILE * fp) { int *p = (int*) member_ptr; if (action == action_read) { char *s = fread_string (fp); *p = flag_value (extra, s); free_string (s); } else if (action == action_write) fprintf (fp, "%s~\n", flag_string (extra, *p)); } void * calloc_mem(int size) { void *p = alloc_mem(size); memset(p, 0, size); return p; } void do_abort() { abort(); }