/
area/city/
area/crypts/
area/guilds/
area/psuedowild/
area/religion/
data/documents/MPDocs/
data/html/
data/mobprogs/
data/quest/
data/world/
data/world/_utilities/
data/world/images/
design/html/
notes/
player/
#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(); }