pdirt/data/
pdirt/data/HELP/
pdirt/data/HELP/0/
pdirt/data/HELP/F/
pdirt/data/HELP/G/
pdirt/data/HELP/H/
pdirt/data/HELP/J/
pdirt/data/HELP/K/
pdirt/data/HELP/O/
pdirt/data/HELP/Q/
pdirt/data/HELP/R/
pdirt/data/HELP/U/
pdirt/data/HELP/V/
pdirt/data/HELP/Y/
pdirt/data/HELP/Z/
pdirt/data/MESSAGES/
pdirt/data/POWERINFO/
pdirt/data/WIZ_ZONES/
pdirt/drv/
pdirt/drv/bin/
pdirt/drv/compiler/converter/
pdirt/drv/compiler/libs/
pdirt/drv/compiler/scripts/
pdirt/drv/include/AberChat/
pdirt/drv/include/InterMud/
pdirt/drv/include/machine/
pdirt/drv/src/InterMud/
pdirt/drv/src/Players/
pdirt/drv/utils/UAFPort/
pdirt/drv/utils/dnsresolv/
pdirt/drv/utils/gdbm/
#define PARSER_C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gen.h"
#include "mflagnames.h"
#include "oflagnames.h"
#include "pflagnames.h"
#include "lflagnames.h"
#include "sflagnames.h"
#include "config.h"
#include "events.h"

/*****************************************************************************
 **                            PROTOTYPE FUNCTIONS
 ****************************************************************************/

stmt_list_record *get_statements(token_record *the_token, FILE *the_file, 
                                 mudcode_record *mudcode, hashTable *the_hash,
                                 int stop_at1, int stop_at2);

stmt_record *get_identifier(token_record *the_token, FILE *the_file, 
                                            mudcode_record *mudcode, 
                                            Boolean Expect_Semicolon);

/*****************************************************************************
 **                            UTILITY FUNCTIONS
 ****************************************************************************/

char thezonenam[MAXNAMLEN]; /* holds current zonename for error report purposes */
char theitem[MAXNAMLEN+15];
char itemname[MAXNAMLEN+1];
int  return_type = 0;       /* holds the return type for passing up functions */
Boolean Valid = True;       /* If no errors have been reported yet */
int  error_counter = 0;	    /* How many errors we have had */

/***************************************************************************
 **
 ** to_neg - states an error, putting filename and line in the error
 **
 ** Parameters: the_err - the string to display
 **             line - the line the error occured on in the zone file
 **
 **
 **
 ***************************************************************************/

void to_neg(char *the_str)
{
   char        nextchar; 
   char        charhold;  
   char        *tmp_char;

   tmp_char = the_str;
   nextchar = *tmp_char;
   *tmp_char = '-';
   tmp_char++;
   while (nextchar != '\0')
   {
      charhold = *tmp_char;
      *tmp_char = nextchar;
      nextchar = charhold;
      tmp_char++;
   }
}
 
/***************************************************************************
 **
 ** state_error - states an error, putting filename and line in the error
 **
 ** Parameters: the_err - the string to display
 **             line - the line the error occured on in the zone file
 **
 **
 **
 ***************************************************************************/

void state_error(char *the_err, int line)
{
   if (line == 0)
      printf("%s%s - %s\n", error_counter == 0 ? "\n" : "",thezonenam, the_err);
   else
      printf("%s%s - %s - %s\n", error_counter == 0 ? "\n" : "",
             thezonenam, the_err, theitem);

   Valid = False;
   error_counter++;
}

/***************************************************************************
 **
 ** state_error - states an error, putting filename and line in the error
 **
 ** Parameters: the_err - the string to display
 **             line - the line the error occured on in the zone file
 **
 **
 **
 ***************************************************************************/

void state_warning(char *the_err)
{
   printf("%s%s - WARNING: %s - %s\n", error_counter == 0 ? "\n" : "",
          thezonenam, the_err, theitem);

}


/*****************************************************************************
 **
 ** table_lookup - looks in a table for a certain string, or flag
 **
 ** Parameters: elem - the element to check
 **             table - the table to check
 **
 ** ret - -1 if not in table, otherwise table number
 **
 ** remarks - old code taken from the old generator, not all my work :)
 **
 *****************************************************************************/

int table_lookup(char *elem, char *table[])
{  int i;
   int r;

   /* Since this function is only used to check flags, i made it so it will
    * not stumble over a flag that has been abbreviated. For example:
    * CanFire is allowed as is CanFireBall
    */
   for (i=0; table[i] != TABLE_END; i++)
   {  if (table[i] == NULL)
         continue;
      if ((r = strncasecmp(elem,table[i],strlen(elem)) == 0))
         return i;
      /*else if (r < 0)
        return -1;*/
   }
   return -1;
}


/****************************************************************************
 **
 ** find_mudfunct - finds the mudfunction record that matches the token string
 **
 ** Parameters: the_token - t
 **             mudcode -
 **
 ** ret - returns a token, NULL if end of file, 
 **
 ****************************************************************************/

mudcode_record *find_mudfunct(token_record *the_token, mudcode_record *mudcode)
{
   mudcode_record *tmp_ptr;

   tmp_ptr = mudcode;
   while (tmp_ptr != NULL)
   {  
      if (!strcasecmp(tmp_ptr->code_name, the_token->the_string))
         return tmp_ptr;
      tmp_ptr = tmp_ptr->next_mudcode;
   }
   return NULL;
}


/*****************************************************************************
 **
 ** xget_token - much like get_token, but with error messages displayed and 
 **              freeing of the last token
 **
 ** Parameters: the_token - the last token gotten
 **             the_file - the file to get tokens from
 **
 ** ret - returns a token, NULL if end of file, 
 **
 ****************************************************************************/

token_record *xget_token(FILE *the_file)
{
   token_record *temp_token;  /* holds the token record to pass back */   
   char         error[80];


   /* get the next token and check for errors */
   temp_token = get_token(the_file, '\n', False);

   /* if we find the end of file */
   if (temp_token->token_type == -1)
   {
      return NULL;
   }
   /* if we find an invalid token, go to next line and start from there */
   else if (temp_token->token_type == -3)
   {
      sprintf(error, "Invalid token %s found", temp_token->the_string);
      state_error(error, temp_token->line);
      if (next_line(the_file) == -1)
      {
         return NULL;
      }
      return xget_token(the_file);
   }

/* printf("token: %s, line: %d\n", temp_token->the_string, temp_token->line);  */
   return temp_token;
}

/*********************************************************************************
 **                       LINE PARSING FUNCTIONS
 *********************************************************************************/

/********************************************************************************
 **
 ** get_str_list_assn - gets a string or list of strings
 **
 ** Parameters: the_token - the token passed in, usually to clear it
 **             the_file - the file to get tokens from
 **
 ** ret - returns a pointer to a list of string records, or
 **       returns NULL for an error
 **
 ********************************************************************************/

string_record *get_str_list_assn(token_record *the_token, FILE *the_file, Boolean Expect_Eq)
{

   char          until_char;   /* the character to get until */
   token_record  *temp_token;  /* used to hold teh token strings */
   token_record  *next_token;  /* used to move through token string */
   string_record *temp_string; /* holds a temp string list to pass back */
   string_record *next_string; /* used to move through string list */
   char          the_assn[MAXNAMLEN];
   char          error[80];

   /* get next token, expect '=' */
   if (Expect_Eq)
   {
      strcpy(the_assn, the_token->the_string);

      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      if (the_token->token_type != T_EQUALS)
      {
         state_error("Missing '=' on assignment", the_token->line);
         if (next_line(the_file) == -1)
         {
            state_error("Unexpected end of file reached", 0);
            return NULL;
         }
         return NULL;
      }
    
       
      /* get next token, expect a '"' or '^' */
      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      if (the_token->token_type == T_APOST)
      {
         until_char = '\'';
      }   
      else if (the_token->token_type == T_RIGHTAPOST)
      {
         until_char = '`';
      }   
      else if (the_token->token_type == T_QUOTE)
      {
         until_char = '\"';
      }
      else if (the_token->token_type == T_CARROT)
      {
         until_char = '^';
      }
      else
      {
         sprintf(error, "Missing '\"', '^', or ''' after '=' on %s assignment\n"
                        "         found1 %s", the_assn, the_token->the_string);
         state_error(error, the_token->line);
         if (next_line(the_file) == -1)
         {
            state_error("Unexpected end of file reached", 0);
         }
         return NULL;
      }
   }
   else
      until_char = '\"';

   /* get all strings and put into the string_record */
   temp_token = get_token(the_file, until_char, False);
   if (temp_token->token_type == -1)
      state_error("End of file reached before closing string character", 
                                                         temp_token->line);   
   else if (temp_token->token_type == -2)
      state_error("Too many lines in string (limit 100), "
                  "possible missing closing char", temp_token->line);
   else if (temp_token->token_type == -4)
   {
      state_error("String too long!", temp_token->line);
      return NULL;
   }
   else
   {   
      next_token = temp_token;
      temp_string = (string_record *) memAlloc(string_record,1,REC_STRING);
      temp_string->the_string = (char *) memAlloc(char,strlen(next_token->the_string) + 1,REC_CHAR);
      next_string = temp_string;
      
      /* move along token list, assigning strings to a string record list instead */
      while (next_token != NULL)
      {
         next_string->the_string = (char *) memAlloc(char,strlen(next_token->the_string) + 1,REC_CHAR);
         strcpy(next_string->the_string, next_token->the_string);
         next_token = next_token->more;
         if (next_token != NULL)
         {
            next_string->nextstr = (string_record *) memAlloc(string_record,1,REC_STRING);
            next_string = next_string->nextstr;       
         }
      }
      return temp_string;
   }

   return NULL;
}

/*******************************************************************************
 **
 ** get_str_assn - gets a string from an assignment, checking for proper format
 **
 ** Parameters: the_token - the token gotten, to free it
 **             the_file - the file to pull tokens from
 **             length - the max length of the strings
 **
 ** ret - returns a zone record with all zone data stored in it or attached to 
 **       it or return \0 for an error
 **
 *******************************************************************************/

char *get_str_assn(token_record *the_token, FILE *the_file, int length)
{

   char get_for[MAXNAMLEN];  /* holds what we are getting the string for */
   char error[80];           /* holds an error message string */
   char *ret_string;

   strcpy(get_for, the_token->the_string);
/*   printf("checking: %s\n", the_token->the_string); */

   /* get next token, expect '=' */
   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if (the_token->token_type != T_EQUALS)
   {
      sprintf(error, "Missing '=' on %s assignment", get_for);
      state_error(error, the_token->line);
      if (next_line(the_file) == -1);
      {
         state_error("Unexpected end of file reached", 0);
         return NULL;
      }
      return NULL;
   }
            
   /* get next token, expect an identifier */
   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if (the_token->token_type == T_APOST)
   {
      the_token = get_token(the_file, '\'', False);
   }
   else if (the_token->token_type == T_QUOTE)
   {
      the_token = get_token(the_file, '\"', False);
   }

   if ((the_token->token_type != T_IDENTIFIER) && (the_token->token_type != T_STRING))
   {
      sprintf(error, "Missing identifier after '=' on %s assignment, found %s.", 
                                             get_for, the_token->the_string);
      state_error(error, the_token->line);
      if (next_line(the_file) == -1)
      {
         state_error("Unexpected end of file reached", 0);
         return NULL;
      }
      ret_string = (char *) memAlloc(char, length,REC_CHAR);
      strcpy(ret_string, the_token->the_string);
      return ret_string;
   }
   if (strlen(the_token->the_string) >= length)
   {
      state_error("String too long", the_token->line);
      return NULL;
   }
   else
   {
      ret_string = (char *) memAlloc(char, length,REC_CHAR);
      strcpy(ret_string, the_token->the_string);
      return ret_string;
   }
}

/*********************************************************************************
 **
 ** get_loc_str_assn - gets a string from an assignment, checking for proper format
 **
 ** Parameters: the_token - the token gotten, to free it
 **             the_file - the file to pull tokens from
 **             length - the max length of the strings
 **
 ** ret - returns a zone record with all zone data stored in it or attached to it or
 **       return \0 for an error
 **
 ********************************************************************************/

char *get_loc_str_assn(token_record *the_token, FILE *the_file, int length)
{

   char get_for[MAXNAMLEN];  /* holds what we are getting the string for */
   char error[80];           /* holds an error message string */
   char *ret_string;

/*    printf("checking: %s\n", the_token->the_string); */

   strcpy(get_for, the_token->the_string);

   /* get next token, expect '=' */
   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if (the_token->token_type != T_EQUALS)
   {
      state_error("Missing '=' on assignment", the_token->line);
      if (next_line(the_file) == -1);
      {
         state_error("Unexpected end of file reached", 0);
         return NULL;
      }
      return NULL;
   }
            
   /* get next token, expect an identifier */
   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;


   if (the_token->token_type == T_APOST)
   {
      the_token = get_token(the_file, '\'', False);
   }
   else if (the_token->token_type == T_QUOTE)
   {
      the_token = get_token(the_file, '\"', False);
   }
   else if (the_token->token_type == T_POUND)
   {
      /* get next token, expect a number */
      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      if ((the_token->token_type != T_NUMERICAL))
      {
         state_error("Missing number after '#' on location assignment", 
                                                             the_token->line);
         if (next_line(the_file) == -1)
         {
            state_error("Unexpected end of file reached", 0);
            return NULL;
         }
         return NULL;
      }
 
      ret_string = (char *) memAlloc(char, (MAXNAMLEN*2)+5,REC_CHAR);
      strcpy(ret_string, "#");
      strcat(ret_string, the_token->the_string);
     
      /*return the_token->the_string;*/
      return ret_string;      
   }
   else if ((the_token->token_type != T_IDENTIFIER) && 
                                  (the_token->token_type != T_CARROT))
   {
      sprintf(error, "Missing identifier after '=' on %s assignment, found %s.",
                                        get_for, the_token->the_string);
      state_error(error, the_token->line);
      if (next_line(the_file) == -1)
      {
         state_error("Unexpected end of file reached", 0);
         return NULL;
      }
      ret_string = (char *) memAlloc(char, (MAXNAMLEN*2)+5,REC_CHAR);
      strcpy(ret_string, the_token->the_string);
      return ret_string;
   }
   if (the_token->token_type == T_CARROT)
   {
      /* get next token, expect an identifier */
      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      if (the_token->token_type == T_APOST)
      {
         the_token = get_token(the_file, '\'', False);
      }
      else if (the_token->token_type == T_QUOTE)
      {
         the_token = get_token(the_file, '\"', False);
      }

      else if ((the_token->token_type != T_IDENTIFIER))
      {
         state_error("Missing identifer after '^' on location assignment", the_token->line);
         if (next_line(the_file) == -1)
         {
            state_error("Unexpected end of file reached", 0);
            return NULL;
         }
         return NULL;
      }

      ret_string = (char *) memAlloc(char,(MAXNAMLEN*2)+5,REC_CHAR);
      sprintf(ret_string, "^%s", the_token->the_string);
      return ret_string;
   }

   if (strlen(the_token->the_string) >= length)
   {
      state_error("String too long", the_token->line);
      return NULL;
   }
   else
   {
      ret_string = (char *) memAlloc(char,(MAXNAMLEN*2)+5,REC_CHAR);
      strcpy(ret_string, the_token->the_string);
      return ret_string;            
   }
}


/*********************************************************************************
 **
 ** get_int_assn - gets an integer from an assignment, checking for proper format
 **
 ** Parameters: the_token - the token passed in, for freeing it
 **             the_file - the file to pull tokens from
 **
 ** ret - an integer, or -1 if an error is found
 **
 ********************************************************************************/

int get_int_assn(token_record *the_token, FILE *the_file)
{

   int returnint;  /* holds the integer value for returning */
   Boolean is_negative = False;

   /* get next token, expect '=' */
   if ((the_token = xget_token(the_file)) == NULL)
      return -1;
   if (the_token->token_type != T_EQUALS)
   {
      state_error("Missing '=' on assignment", the_token->line);
      if (next_line(the_file) == -1)
      {
         state_error("Unexpected end of file reached", 0);
         return -1;
      }
      return -1;
   }
            
   /* get next token, expect a numeral */
   if ((the_token = xget_token(the_file)) == NULL)
      return -1;
   if (the_token->token_type == T_MINUS)
   {
      if ((the_token = xget_token(the_file)) == NULL)
         return -1;

      is_negative = True;
   }

   if (the_token->token_type != T_NUMERICAL)
   {
      state_error("Missing number after '=' on assignment", the_token->line);
      if (next_line(the_file) == -1)
      {
         state_error("Unexpected end of file reached", 0);
         return -1;
      }
      return -1;
   }
   returnint = atoi(the_token->the_string);
   if (is_negative)
      returnint = -returnint;

   return returnint;
}

/*********************************************************************************
 **
 ** xget_location - gets all locations, returning a pointer to a string list
 **
 ** Parameters: the_token - the token passed in, it is freed first
 **             the_file - the file pointer
 **
 ** ret - -1 if encountered an error, otherwise the location
 **
 ********************************************************************************/

loc_str_record *xget_location(token_record *the_token, FILE *the_file, Boolean allow_type)
{

   loc_str_record *temp_loc_str;
   char           error[80];

   temp_loc_str = (loc_str_record *) memAlloc(loc_str_record,1,REC_LOCSTR);

   if (allow_type)
   {
      if ((the_token->token_type == T_INROOM) || 
          (the_token->token_type == T_INCONTAINER) || 
          (the_token->token_type == T_WORNBY) || 
          (the_token->token_type == T_WIELDEDBY) ||
          (the_token->token_type == T_BOTHBY) ||  
          (the_token->token_type == T_CARRIEDBY))
          {
             temp_loc_str->loc_type = the_token->token_type;
                        
             /* get next token, expect ':' */
             if ((the_token = xget_token(the_file)) == NULL)
                return NULL;
      
             if (the_token->token_type != T_COLON)
             {
                state_error("Missing required : after location type.", the_token->line);
             }
 
             /* get next token, expect identifer */
             if ((the_token = xget_token(the_file)) == NULL)
                return NULL;                       

          }
          else
             temp_loc_str->loc_type = T_INROOM;
   }
   else
      temp_loc_str->loc_type = T_INROOM;

   if ((the_token->token_type != T_IDENTIFIER))
   {
      sprintf(error, "Missing identifier on location, found %s,", the_token->the_string);
      state_error(error, the_token->line);
      if (next_line(the_file) == -1)
      {
         state_error("Unexpected end of file reached", 0);
         return NULL;
      }
   }

   if (strlen(the_token->the_string) >= ((MAXNAMLEN*2)+1))
   {
      state_error("String too long", the_token->line);
      return NULL;
   }

   strcpy(temp_loc_str->the_loc, the_token->the_string);
   lowercase(temp_loc_str->the_loc);

   if (check_next_char(the_file) == ',')
   {
      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      temp_loc_str->nextloc = xget_location(the_token, the_file, allow_type);
   }
   return temp_loc_str;

}


/*************************************************************************************
 **
 ** get_location - gets all locations, returning a pointer to a string list
 **
 ** Parameters: elem - the element to check
 **             table - the 
 **
 ** ret - -1 if encountered an error, otherwise the location
 **
 *************************************************************************************/

loc_str_record *get_location(token_record *the_token, FILE *the_file, Boolean allow_type)
{

   /* get next token, expect '=' */
   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;
 
   if (the_token->token_type != T_EQUALS)
   {
      state_error("Missing '=' on assignment", the_token->line);
      if (next_line(the_file) == -1);
      {
         state_error("Unexpected end of file reached", 0);
         return NULL;
      }
      return NULL;
   }

   /* get next token, expect a location type or identifier */
   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;
 
   return xget_location(the_token, the_file, allow_type);
}

/*************************************************************************************
 **
 ** xget_flags - gets all flags, returning an integer value
 **
 ** Parameters: elem - the element to check
 **             table - the table to check
 **
 ** ret - -1 if encountered an error, otherwise the number of flags gotten
 **
 *************************************************************************************/

int xget_flags(token_record *the_token, DoubleLongInt *FLAGS, char *table[], FILE *the_file)
{
   token_record *temp_token;
   int flagnum;
   char error[120];
   int count = 0;

   if ((temp_token = xget_token(the_file)) == NULL)
      return -1;

   if ((flagnum = table_lookup(temp_token->the_string, table)) == -1)
   {
      sprintf(error, "Unknown flag %s", temp_token->the_string);
      state_error(error, temp_token->line);
   }
   else
   {
      if (flagnum < 32)
         XSETBIT(FLAGS->b3,flagnum);
      else if (flagnum >= 32 && flagnum < 64)
         XSETBIT(FLAGS->b2,flagnum);
      else if (flagnum >= 64 && flagnum < 96)
         XSETBIT(FLAGS->b1,flagnum);
      count++;
   }
   if (check_next_char(the_file) == ',')
   {
      if ((temp_token = xget_token(the_file)) == NULL)
         return -1;

      return (count + xget_flags(temp_token, FLAGS, table, the_file));
   }
   return count;

}

/*************************************************************************************
 **
 ** xget_mflags - gets all flags, returning an integer value
 **
 ** Parameters: elem - the element to check
 **             table - the table to check
 **
 ** ret - -1 if encountered an error, otherwise the number of flags gotten
 **
 *************************************************************************************/

int xget_mflags(token_record *the_token, MFLAGS *FLAGS, FILE *the_file)
{
   token_record *temp_token;
   int flagnum;
   char error[120];
   int count = 0;

   if ((temp_token = xget_token(the_file)) == NULL)
      return -1;

   if ((flagnum = table_lookup(temp_token->the_string, Mflags)) == -1)
   {
      sprintf(error, "Unknown flag %s", temp_token->the_string);
      state_error(error, temp_token->line);
   }
   else
   {
      if (flagnum < 32)
         XSETBIT(FLAGS->l,flagnum);
      else if (flagnum >= 32)
         XSETBIT(FLAGS->h,flagnum);
      count++;
   }
   if (check_next_char(the_file) == ',')
   {
      if ((temp_token = xget_token(the_file)) == NULL)
         return -1;

      return (count + xget_mflags(temp_token, FLAGS, the_file));
   }
   return count;

}


/*************************************************************************************
 **
 ** get_mflags - gets all flags, returning an integer value
 **
 ** Parameters: elem - the element to check
 **             table - the table to check
 **
 ** ret - -1 if encountered an error, otherwise the number of flags gotten
 **
 *************************************************************************************/

int get_mflags(token_record *the_token, MFLAGS *FLAGS, FILE *the_file)
{
   token_record *temp_token;

   /* get next token, expect '=' */
   if ((temp_token = xget_token(the_file)) == NULL)
      return -1;


   if (temp_token->token_type != T_EQUALS)
   {
      state_error("Missing '=' for flags", temp_token->line);
      if (next_line(the_file) == -1)
      {
         state_error("Unexpected end of file reached", 0);
         return -1;
      }
      return -1;
   }
   
   return xget_mflags(temp_token, FLAGS, the_file);
}

/*************************************************************************************
 **
 ** get_flags - gets all flags, returning an integer value
 **
 ** Parameters: elem - the element to check
 **             table - the table to check
 **
 ** ret - -1 if encountered an error, otherwise the number of flags gotten
 **
 *************************************************************************************/

int get_flags(token_record *the_token, DoubleLongInt *FLAGS, char *table[], FILE *the_file)
{
   token_record *temp_token;

   /* get next token, expect '=' */
   if ((temp_token = xget_token(the_file)) == NULL)
      return -1;


   if (temp_token->token_type != T_EQUALS)
   {
      state_error("Missing '=' for flags", temp_token->line);
      if (next_line(the_file) == -1)
      {
         state_error("Unexpected end of file reached", 0);
         return -1;
      }
      return -1;
   }
   
   return xget_flags(temp_token, FLAGS, table, the_file);
}

/*****************************************************************************
 **                            MUDCODE PARSING FUNCTIONS
 ****************************************************************************/


/******************************************************************************
 **
 ** get_const - gets the code in a for loop
 **
 ** Parameters: the_file - 
 **
 ** ret - returns the first token on the next line
 **
 *********************************************************************************/

stmt_record *get_const(token_record *the_token, FILE *the_file, 
                                         mudcode_record *mudcode, hashTable *the_hash)
{
   const_decl  *const_ptr;
   stmt_record *ret_union;
   Boolean     is_neg = False;
   char       error[80];
   char       the_zone[MAXNAMLEN];
   char       holder[(MAXNAMLEN*3)+5];
   hashRecord *next_hash; 
   int        i;


   ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT);
   ret_union->stmt_type = STMT_CONST_DECL;

/*   printf("status - beginning check on constant declaration\n"); */
   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if (the_token->token_type != T_IDENTIFIER)
   {
      state_error("Identifier expected in constant declaration.", 
                                                        the_token->line);
      return NULL;
   }


   const_ptr = (const_decl * ) memAlloc(const_decl,1,REC_CONSTDECL);

   strcpy(const_ptr->const_name, the_token->the_string);


   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if (the_token->token_type != T_EQUALS)
   {
      state_error("Missing '=' in constant declaration.", the_token->line);
      return NULL;
   }

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if ((the_token->token_type != T_APOST) && 
       (the_token->token_type != T_QUOTE) && 
       (the_token->token_type != T_NUMERICAL) &&
       (the_token->token_type != T_TRUE) &&
       (the_token->token_type != T_FALSE) &&
       (the_token->token_type != T_MINUS))
   {
      state_error("Missing value after '='.", the_token->line);
      return NULL;
   }

   if ((the_token->token_type == T_TRUE) || (the_token->token_type == T_FALSE))
   {
      const_ptr->const_type = T_BOOLEAN;
      const_ptr->assign = (char * ) memAlloc(char,strlen(the_token->the_string) + 1,
                                                                            REC_CHAR);
      strcpy(const_ptr->assign, the_token->the_string);
   }
   else if (the_token->token_type == T_QUOTE)
   {
      const_ptr->const_type = T_STR;
      ungetc('"', the_file);
      ungetc('=', the_file);
      const_ptr->assign = get_str_assn(the_token, the_file, MAXNAMLEN);
   }
   else if (the_token->token_type == T_APOST)
   {
      const_ptr->const_type = T_STR;
      ungetc('\'', the_file);
      ungetc('=', the_file);
      const_ptr->assign = get_str_assn(the_token, the_file, MAXNAMLEN);
   }
   else if (the_token->token_type == T_MINUS)
   {
      is_neg = True;

      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

   }
   /* This cant be an else if you just set is_neg and want to use it here.
   else
   */

   if (the_token->token_type == T_NUMERICAL)
   {
      const_ptr->const_type = T_NUMBER;

      const_ptr->assign = (char * ) memAlloc(char,strlen(the_token->the_string) + 1,
                                                                            REC_CHAR);

      strcpy(const_ptr->assign, the_token->the_string);

      if (is_neg)
      {
         to_neg(const_ptr->assign);
      }
   }


   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if (the_token->token_type != T_SEMICOLON)
   {
      state_error("Missing ';' at end of constant declaration.", the_token->line);
      return NULL;
   }

   strcpy(the_zone, thezonenam);
   for (i=0; i< strlen(the_zone); i++)
      if (the_zone[i] == '.')
         the_zone[i] = '\0'; 

   sprintf(holder, "dec@%s@%s@%s", the_zone, itemname, const_ptr->const_name);

   lowercase(holder);

   /* printf("storing const: %s\n", holder);  */
   next_hash = createHashRecord(holder, const_ptr->const_type);

   if (addHashRecord(next_hash, the_hash) == 0)
   {
      sprintf(error, "Redefinition of variable %s", the_token->the_string);
      state_error(error, the_token->line);
   }

/*   printf("status - finishing check on constant declaration\n"); */
   ret_union->stmt.const_d = const_ptr;
   return ret_union;  
}


/******************************************************************************
 **
 ** xget_decl - gets the code in a for loop
 **
 ** Parameters: the_file - 
 **
 ** ret - returns the first token on the next line
 **
 *********************************************************************************/

var_decl *xget_decl(token_record *the_token, FILE *the_file, 
                      mudcode_record *mudcode, int the_type, hashTable *the_hash)
{
   var_decl   *var_ptr;
   char       holder[(MAXNAMLEN*3)+5];
   hashRecord *next_hash; 
   char       error[80];
   char       the_zone[MAXNAMLEN];
   int        i;

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if (the_token->token_type != T_IDENTIFIER)
   {
      state_error("Identifier expected in type declaration.", the_token->line);
      return NULL;
   }

   strcpy(the_zone, thezonenam);
   for (i=0; i< strlen(the_zone); i++)
      if (the_zone[i] == '.')
         the_zone[i] = '\0'; 

   sprintf(holder, "dec@%s@%s@%s", the_zone, itemname, the_token->the_string);

   lowercase(holder);

   /*   printf("storing: %s\n", holder); */
   next_hash = createHashRecord(holder, the_type);

   if (addHashRecord(next_hash, the_hash) == 0)
   {
      sprintf(error, "Redefinition of variable %s", the_token->the_string);
      state_error(error, the_token->line);
   }

   var_ptr = (var_decl * ) memAlloc(var_decl,1,REC_VARDECL);
   var_ptr->var_type = the_type;
   strcpy(var_ptr->var_name, the_token->the_string);

   if (the_type == T_STR)
   {
      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      if (the_token->token_type != T_LPAREN)
      {
         state_error("Missing required length for string declaration.", the_token->line);
         return NULL;
      }

      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      if (the_token->token_type != T_NUMERICAL)
      {
         state_error("Missing number after '(' in string length declaration.", the_token->line);
         return NULL;
      }
      var_ptr->str_len = atoi(the_token->the_string);

      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      if (the_token->token_type != T_RPAREN)
      {
         state_error("Missing ')' after string length.", the_token->line);
         return NULL;
      }

   }

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if (the_token->token_type == T_COMMA)
   {
      var_ptr->more_var = xget_decl(the_token, the_file, mudcode, the_type, the_hash);
   }
   else if (the_token->token_type == T_SEMICOLON)
   {
      var_ptr->more_var = NULL;
 /*     printf("status - finishing check on declaration\n"); */
   }
   else
   {
      state_error("Missing ';' after variable declaration.", the_token->line);
      return NULL;
   }
   return var_ptr;
}

/******************************************************************************
 **
 ** get_decl - 
 **
 ** Parameters: the_file - 
 **
 ** ret - returns the first token on the next line
 **
 *********************************************************************************/

stmt_record *get_decl(token_record *the_token, FILE *the_file, 
                                    mudcode_record *mudcode, hashTable *the_hash)
{
   int      var_type;
   stmt_record *ret_union;

   ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT);
   ret_union->stmt_type = STMT_VAR_DECL;

/*    printf("status - beginning check on declaration\n"); */
   var_type = the_token->token_type;
   ret_union->stmt.var_d = xget_decl(the_token, the_file, mudcode, var_type, the_hash);
   return ret_union;
}

/******************************************************************************
 **
 ** get_for - gets the code in a for loop
 **
 ** Parameters: the_file - 
 **
 ** ret - returns the first token on the next line
 **
 *********************************************************************************/

stmt_record *get_for(token_record *the_token, FILE *the_file, 
                                      mudcode_record *mudcode, hashTable *the_hash)
{
   for_decl *for_ptr;
   stmt_record *ret_union;
   Boolean is_neg = False;

   ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT);
   ret_union->stmt_type = STMT_FOR_LOOP;


/*   printf("status - beginning check on for statement\n"); */

   for_ptr = (for_decl * ) memAlloc(for_decl,1,REC_FORDECL);

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if (the_token->token_type == T_MINUS)
   {
      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      is_neg = True;
   }

   if (the_token->token_type != T_NUMERICAL)
   {
      state_error("Missing initial number expected after 'for'.", the_token->line);
      return NULL;
   }

   for_ptr->from = atoi(the_token->the_string);

   if (is_neg)
   {
      for_ptr->from = -(for_ptr->from);
      is_neg = False;
   }

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if (the_token->token_type != T_TO)
   {
      state_error("Missing 'to' in for statement.", the_token->line);
      return NULL;
   }

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if (the_token->token_type == T_MINUS)
   {
      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      is_neg = True;
   }

   if (the_token->token_type != T_NUMERICAL)
   {
      state_error("Missing to number after 'to' in for statement.",
                                                       the_token->line);
      return NULL;
   }

   for_ptr->to = atoi(the_token->the_string);
   if (is_neg)
   {
      for_ptr->to = -(for_ptr->to);
   }

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if (the_token->token_type != T_LOOP)
   {
      state_error("Missing 'loop' in for statement.",
                                                       the_token->line);
      return NULL;
   }

   for_ptr->for_statements = get_statements(the_token, the_file, mudcode, the_hash,
                                                                     T_END, 0);

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if (the_token->token_type != T_LOOP)
   {
      state_error("Missing 'loop' after 'end' in while loop.", the_token->line);
      return NULL;
   }

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if (the_token->token_type != T_SEMICOLON)
   {
      state_error("Missing ';' after 'end loop' in while loop.", the_token->line);
      return NULL;
   }

 /*  printf("status - check finished on for statement\n"); */
   ret_union->stmt.for_d = for_ptr;
   return ret_union;
}


/******************************************************************************
 **
 ** get_boolean - gets the code for a repeat type
 **
 ** Parameters: the_file - 
 **
 ** ret - returns the first token on the next line
 **
 *********************************************************************************/

bool_stmt *get_boolean(token_record *the_token, FILE *the_file, 
                                                 mudcode_record *mudcode, int until)
{
   bool_stmt    *the_bool;


   the_bool = (bool_stmt *) memAlloc(bool_stmt, 1,REC_BOOLSTMT);
   
   while (the_token->token_type != until)
   {
      if (the_token->token_type == T_AND)
      {
         strcat(the_bool->bool_string, "&&"); 

      }
      else if (the_token->token_type == T_OR)
      {
         strcat(the_bool->bool_string, "||"); 
      }
      else if (the_token->token_type == T_IDENTIFIER)
      {
         if ((the_bool->the_stmt = 
                 get_identifier(the_token, the_file, mudcode, False)) == NULL)
         {
            state_error("Error in boolean expression.", 1);
            return False;
         }

         if ((the_token = xget_token(the_file)) == NULL)
            return NULL;

         the_bool->next_bool = get_boolean(the_token, the_file, mudcode, until);
         return the_bool;
      }
      else
      {
         strcat(the_bool->bool_string, the_token->the_string);
      }
      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;
   }
   the_bool->the_stmt = NULL;
   the_bool->next_bool = NULL;
   return the_bool;
}


/******************************************************************************
 **
 ** get_while - gets the code for a repeat type
 **
 ** Parameters: the_file - 
 **
 ** ret - returns the first token on the next line
 **
 *********************************************************************************/

stmt_record *get_while(token_record *the_token, FILE *the_file, 
                                  mudcode_record *mudcode, hashTable *the_hash)
{
   while_decl *while_ptr;
   stmt_record *ret_union;

   ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT);
   ret_union->stmt_type = STMT_WHILE_LOOP;

   /* printf("status - beginning check on while statement\n"); */

   while_ptr = (while_decl * ) memAlloc(while_decl,1,REC_WHILEDECL);

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   /* printf("status - beginning check on boolean statement\n"); */
   while_ptr->bool_exp = get_boolean(the_token, the_file, mudcode, T_LOOP);

   while_ptr->while_statements = get_statements(the_token, the_file, mudcode, 
                                                         the_hash, T_END, 0);

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if (the_token->token_type != T_LOOP)
   {
      state_error("Missing 'loop' after 'end' in while loop.", the_token->line);
      return NULL;
   }

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if (the_token->token_type != T_SEMICOLON)
   {
      state_error("Missing ';' after 'end loop' in while loop.", the_token->line);
      return NULL;
   }

 /*  printf("status - check finished on while statement\n"); */
   ret_union->stmt.while_d = while_ptr;
   return ret_union;
}


/******************************************************************************
 **
 ** get_repeat - gets the code for a repeat type
 **
 ** Parameters: the_file - 
 **
 ** ret - returns the first token on the next line
 **
 *********************************************************************************/

stmt_record *get_repeat(token_record *the_token, FILE *the_file, 
                                      mudcode_record *mudcode, hashTable *the_hash)
{
   while_decl *repeat_ptr;
   stmt_record *ret_union;

   ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT);
   ret_union->stmt_type = STMT_REPEAT_UNTIL;

   /* printf("status - beginning check on repeat statement\n");  */

   repeat_ptr = (while_decl * ) memAlloc(while_decl,1,REC_WHILEDECL);

   repeat_ptr->while_statements = get_statements(the_token, the_file, mudcode, 
                                                         the_hash, T_UNTIL, 0);
 
   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;
   repeat_ptr->bool_exp = get_boolean(the_token, the_file, mudcode, T_SEMICOLON);

   /* printf("status - check finished on repeat statement\n"); */
   ret_union->stmt.while_d = repeat_ptr;
   return ret_union;

}


/******************************************************************************
 **
 ** get_block - gets a block statement
 **
 ** Parameters: the_file - 
 **
 ** ret - returns the first token on the next line
 **
 *********************************************************************************/

stmt_record *get_block(token_record *the_token, FILE *the_file, 
                                              mudcode_record *mudcode, hashTable *the_hash)
{
   block_decl *block_ptr;
   stmt_record *ret_union;

   ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT);
   ret_union->stmt_type = STMT_BLOCK;

/*   printf("Status - beginning check on block statements\n"); */

   block_ptr = (block_decl * ) memAlloc(block_decl,1,REC_BLOCKDECL);

   block_ptr->block_statements = get_statements(the_token, the_file, mudcode, 
                                                                  the_hash, T_END, 0);

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;
   if (the_token->token_type != T_SEMICOLON)
   {
      state_error("Missing expected ';' after end for block statements.", 
                                                               the_token->line);
      return NULL;    
   }
 /*  printf("Status - finishing check on block statements\n"); */

   ret_union->stmt.block_d = block_ptr;
   return ret_union;
}

/*************************************************************************************
 **
 ** xget_arith_number - 
 **
 ** Parameters: the_file - 
 **
 ** ret - returns the first token on the next line
 **
 *************************************************************************************/

arith_number *xget_arith_number(token_record *the_token, FILE *the_file, 
                               mudcode_record *mudcode)
{

   arith_number *tmp_arith;

   tmp_arith = (arith_number *) memAlloc(arith_number, 1,REC_ARITHNR);
   
   while (the_token->token_type != T_SEMICOLON)
   {
      if (the_token->token_type == T_IDENTIFIER)
      {
         if ((tmp_arith->numberfunct = 
                 get_identifier(the_token, the_file, mudcode, False)) == NULL)
         {
            state_error("Error in arithmetic expression.", 1);
            return False;
         }

         if ((the_token = xget_token(the_file)) == NULL)
            return NULL;

         tmp_arith->next_number = xget_arith_number(the_token, the_file, mudcode);
         return tmp_arith;
      }
      else
      {
         strcat(tmp_arith->arith_str, the_token->the_string);
      }
      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;
   }
   tmp_arith->numberfunct = NULL;
   tmp_arith->next_number = NULL;

   return tmp_arith;
}

/*************************************************************************************
 **
 ** get_arith_number - 
 **
 ** Parameters: the_file - 
 **
 ** ret - returns the first token on the next line
 **
 *************************************************************************************/

stmt_record *get_arith_number(token_record *the_token, FILE *the_file, 
                               mudcode_record *mudcode)
{
   stmt_record *ret_union;

   ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT);
   ret_union->stmt_type = STMT_ARITH_NUM;
   ret_union->stmt.arith_num_d = xget_arith_number(the_token, the_file, mudcode);

   return ret_union;
}


/*************************************************************************************
 **
 ** get_arith_string - 
 **
 ** Parameters: the_file - 
 **
 ** ret - returns the first token on the next line
 **
 *************************************************************************************/

stmt_record *get_arith_string(token_record *the_token, FILE *the_file, 
                              mudcode_record *mudcode)
{
   arith_string *str_ptr;
   char         error[80];
   stmt_record *ret_union;

   ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT);
   ret_union->stmt_type = STMT_ARITH_STR;

 /*  printf("Status - beginning check on an arithmetic string\n"); */

   str_ptr = (arith_string * ) memAlloc(arith_string,1,REC_ARITHSTR);
   
   str_ptr->stringfunct1 = NULL;

   if ((the_token->token_type == T_QUOTE) || (the_token->token_type == T_APOST))
   {  
      str_ptr->string1 = get_str_list_assn(the_token, the_file, False);
   }
   else if (the_token->token_type == T_IDENTIFIER)
   { 
      str_ptr->stringfunct1 = get_identifier(the_token, the_file, mudcode, False);
   }
   else
   {
      sprintf(error, "Unknown identifier %s for arithmetic string.", 
                                                          the_token->the_string);
      state_error(error, the_token->line);
      return NULL;
   }

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if ((the_token->token_type == T_QUOTE) || (the_token->token_type == T_APOST))
      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

   if (the_token->token_type != T_SEMICOLON)
   {
      if (the_token->token_type == T_PLUS)
      {
        str_ptr->the_op = T_PLUS;
      }
      else
      {
         sprintf(error, "Unknown string operand %s.", the_token->the_string);
         state_error(error, the_token->line);
         return NULL;
      }

      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      str_ptr->string2 = get_arith_string(the_token, the_file, mudcode);

 /*     printf("Status - finishing check on an arithmetic string\n"); */
   }

   ret_union->stmt.arith_str_d = str_ptr;
   return ret_union;
}

/*********************************************************************************
 **
 ** get_identifier - get mudcode code
 **
 ** Parameters: the_file - 
 **
 ** ret - returns the first token on the next line
 **
 ********************************************************************************/

stmt_record *get_identifier(token_record *the_token, FILE *the_file, 
                                mudcode_record *mudcode, Boolean Expect_Semicolon)
{
   mudfunct_decl  *funct_ptr;  /* the function call record created */
   mudcode_record *templ_ptr;  /* points to the correct stored mudfunction template */
   param_record   *param_ptr;  /* used to move along parameters */
   mudfunct_param *functp_ptr; /* used to store the user entered parameter values */
   ident_decl     *ident_ptr;   /* if it is an identifier */
   char           error[80];
   stmt_record    *ret_union;
   string_record  *temp_str;
   assignmt       *assn_ptr;
   char           *name_ptr;

   ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT);
   ret_union->stmt_type = STMT_MUD_DEFINED;

   /* printf("Status - beginning check on an identifier %s (a function probably)\n", 
                                                         the_token->the_string); */

      templ_ptr = NULL;
      if ((templ_ptr = find_mudfunct(the_token, mudcode)) == NULL)
      {
         if (check_next_char(the_file) == '(')
         {
            sprintf(error, "Unknown function %s.", the_token->the_string);
            state_error(error, the_token->line);
            return NULL;
         }
         else if (Expect_Semicolon)
         {
            name_ptr = the_token->the_string;

            if (check_next_char(the_file) == '=')
            {
  
               if ((the_token = xget_token(the_file)) == NULL)
                  return NULL;

               if ((the_token = xget_token(the_file)) == NULL)
                  return NULL;

               assn_ptr = (assignmt * ) memAlloc(assignmt,1,REC_ASSIGNMT);
               strcpy(assn_ptr->var_name, name_ptr);
               assn_ptr->the_stmt = get_arith_number(the_token, the_file, mudcode);
               ret_union->stmt_type = STMT_ASSIGNMT;
               ret_union->stmt.assignmt_d = assn_ptr;
               return ret_union;

            }
            else if (check_next_char(the_file) == ':')
            {
  
               if ((the_token = xget_token(the_file)) == NULL)
                  return NULL;

               if ((the_token = xget_token(the_file)) == NULL)
                  return NULL;

               if (the_token->token_type != T_EQUALS)
               {
                  state_error("Missing expected '=' after ':' on "
                              "string arithmetic assignment.", the_token->line);
                  return NULL;    
               }

               if ((the_token = xget_token(the_file)) == NULL)
                  return NULL;

               assn_ptr = (assignmt * ) memAlloc(assignmt,1,REC_ASSIGNMT);
               strcpy(assn_ptr->var_name, name_ptr);
               assn_ptr->the_stmt = get_arith_string(the_token, the_file, mudcode);
               ret_union->stmt_type = STMT_ASSIGNMT;
               ret_union->stmt.assignmt_d = assn_ptr;
               return ret_union;

            }

            else
            {
               ident_ptr = (ident_decl * ) memAlloc(ident_decl,1,REC_IDENTDECL);
               strcpy(ident_ptr->the_ident, the_token->the_string);
               /* printf("Status - finishing check on an identifier, not a function\n"); */
               ret_union->stmt_type = STMT_IDENT;
               ret_union->stmt.ident_d = ident_ptr;
               return ret_union;
            }
         }
         else
         {
            ident_ptr = (ident_decl * ) memAlloc(ident_decl,1,REC_IDENTDECL);
            strcpy(ident_ptr->the_ident, the_token->the_string);
            /* printf("Status - finishing check on an identifier, not a function\n"); */
            ret_union->stmt_type = STMT_IDENT;
            ret_union->stmt.ident_d = ident_ptr;
            return ret_union;
         }
      }
      
      if (templ_ptr == NULL)
         printf("ARGH!! I escaped the unescapeable if statement!!!! error!!\n");
 
   /* printf("found function %s\n", templ_ptr->code_name); */
   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;
   if (the_token->token_type != T_LPAREN)
   {
      sprintf(error, "Missing expected '(' after %s.", the_token->the_string);
      state_error(error, the_token->line);
      return NULL;    
   }

   param_ptr = templ_ptr->parameters;
   
   funct_ptr = (mudfunct_decl * ) memAlloc(mudfunct_decl,1,REC_MFDECL);
   funct_ptr->parameters = (mudfunct_param * ) memAlloc(mudfunct_param,1,REC_MFPARAM);
   funct_ptr->parameters->has_quotes = False;
   funct_ptr->the_funct = templ_ptr;

   functp_ptr = funct_ptr->parameters;
   functp_ptr->funct_param = NULL;
 
   while (param_ptr != NULL)
   {
      switch(param_ptr->param_type)
      {
         case T_STR:
            if ((the_token = xget_token(the_file)) == NULL)
               return NULL;

            switch(the_token->token_type)
            {  
	         case T_APOST:
               case T_QUOTE:
                  functp_ptr->has_quotes = True;
                  functp_ptr->the_param = 
                                     get_str_list_assn(the_token, the_file, False);
                  

                  /* allow "blah" "blah" to be seen as one string here */
                  while (check_next_char(the_file) == '\"' || 
                         check_next_char(the_file) == '\'')
                  {
                     temp_str = functp_ptr->the_param;
                     while (temp_str->nextstr != NULL)
                        temp_str = temp_str->nextstr;
                     if ((the_token = xget_token(the_file)) == NULL)
                        return NULL;
                     temp_str->nextstr =
                                     get_str_list_assn(the_token, the_file, False);                       
                  }

                  break;


               case T_IDENTIFIER:
            
                  if ((functp_ptr->funct_param = 
                              get_identifier(the_token, the_file, mudcode, False)) 
                                                                            == NULL)
                  {
                     sprintf(error, "Unknown identifier %s.", the_token->the_string);
                     state_error(error, the_token->line);
                     return NULL;
                  } 
                  break;

               default:
                  state_error("Missing expected '\"' for defined string parameter", 
                                                                  the_token->line);
                  return NULL;
                  break;   
            }
            break;

         case T_NUMBER:
            if ((the_token = xget_token(the_file)) == NULL)
               return NULL;
            if (the_token->token_type == T_MINUS)
            {
               if ((the_token = xget_token(the_file)) == NULL)
                  return NULL;

               if (the_token->token_type != T_NUMERICAL)
               {
                  sprintf(error, "Expected number after '-', found %s.", 
                                                        the_token->the_string);
                  state_error(error, the_token->line);
                  return NULL;
               }

               functp_ptr->the_param = (string_record * ) memAlloc(string_record,1,REC_STRING);
               functp_ptr->the_param->the_string = (char *) memAlloc(char,strlen(the_token->the_string) + 1,REC_CHAR);
               strcpy(functp_ptr->the_param->the_string, the_token->the_string);
               to_neg(functp_ptr->the_param->the_string);
            }
            if (the_token->token_type == T_NUMERICAL)
            {
               functp_ptr->the_param = (string_record * ) memAlloc(string_record,1,REC_STRING);
               functp_ptr->the_param->the_string = (char *) memAlloc(char,strlen(the_token->the_string) + 1,REC_CHAR);
               strcpy(functp_ptr->the_param->the_string, the_token->the_string);
            }
            else if (the_token->token_type == T_IDENTIFIER)
            { 
               if ((functp_ptr->funct_param = 
                       get_identifier(the_token, the_file, mudcode, False)) == NULL)
               {
                  sprintf(error, "Unknown identifier %s.", the_token->the_string);
                  state_error(error, the_token->line);
                  return NULL;
               } 
               /* printf("got ident: %s\n", functp_ptr->funct_param->stmt.ident_d->the_ident); */
            }
            else
            {
               state_error("Missing expected number for defined numerical parameter", 
                                                                  the_token->line);
               return NULL;    
            }
            break;

         case T_BOOL:
            if ((the_token = xget_token(the_file)) == NULL)
                return NULL;
            if (the_token->token_type == T_BOOL)
            {
               functp_ptr->the_param = (string_record * ) memAlloc(string_record,1,REC_STRING);
            functp_ptr->the_param->the_string = (char *) memAlloc(char,strlen(the_token->the_string) + 1,REC_CHAR);
               strcpy(functp_ptr->the_param->the_string, the_token->the_string);
            }
            else if (the_token->token_type == T_IDENTIFIER)
            { 
               if ((functp_ptr->funct_param = 
                           get_identifier(the_token, the_file, mudcode, False)) == NULL)
               {
                  sprintf(error, "Unknown identifier %s.", the_token->the_string);
                  state_error(error, the_token->line);
                  return NULL;
               } 
            }
            else 
            {
               state_error("Missing expected boolean type for defined boolean parameter", 
                                                                  the_token->line);
               return NULL;    
            }
            functp_ptr->the_param = (string_record * ) memAlloc(string_record,1,REC_STRING);
            functp_ptr->the_param->the_string = (char *) memAlloc(char,strlen(the_token->the_string) + 1,REC_CHAR);
            strcpy(functp_ptr->the_param->the_string, the_token->the_string);
            break;

         case T_IDENT:
               if ((the_token = xget_token(the_file)) == NULL)
                   return NULL;
               functp_ptr->the_param = 
                                  (string_record * ) memAlloc(string_record,1,REC_STRING);
               functp_ptr->the_param->the_string = (char *) memAlloc(char,strlen(the_token->the_string) + 1,REC_CHAR);
               strcpy(functp_ptr->the_param->the_string, the_token->the_string);
               functp_ptr->funct_param = get_identifier(the_token, the_file, 
                                                                   mudcode, False);
               break;

         default:
            printf("default return: type: %d\n", param_ptr->param_type );
            return NULL;
      }

      if (param_ptr->next_param != NULL)
      {
         if ((the_token = xget_token(the_file)) == NULL)
            return NULL;
         if (the_token->token_type != T_COMMA)
         {
            sprintf(error, "Missing expected ',' after parameter in %s function.", 
                                                              templ_ptr->code_name);
            state_error(error, the_token->line);
            return NULL;    
         }
         functp_ptr->more_param = (mudfunct_param * ) memAlloc(mudfunct_param,1,REC_MFPARAM);
         functp_ptr->more_param->has_quotes = False;
         functp_ptr = functp_ptr->more_param;
         functp_ptr->funct_param = NULL;
      }
      param_ptr = param_ptr->next_param;
   }
   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;
   if (the_token->token_type != T_RPAREN)
   {
      sprintf(error, "Missing expected ')' at the end of %s function, found %s.", 
                                          templ_ptr->code_name, the_token->the_string);
      state_error(error, the_token->line);
      return NULL;    
   }

   if (Expect_Semicolon)
   {
      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;
      if (the_token->token_type != T_SEMICOLON)
      {
         sprintf(error, "Missing expected ';' at the end of %s function.", 
                                                                 templ_ptr->code_name);
         state_error(error, the_token->line);
         return NULL;    
      }
   }
   /* printf("Status - finishing check on an identifier (a function probably)\n"); */
   ret_union->stmt.mudfunct_d = funct_ptr;
   return ret_union;
}

/******************************************************************************
 **
 ** get_if - get if/then/else code
 **
 ** Parameters: the_file - 
 **
 ** ret - returns the first token on the next line
 **
 *********************************************************************************/

stmt_record *get_if(token_record *the_token, FILE *the_file, mudcode_record *mudcode, 
                                                              hashTable *the_hash)
{
   if_decl *if_ptr;
   stmt_record *ret_union;

   ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT);
   ret_union->stmt_type = STMT_IF_THEN;

/*   printf("status - beginning check on if statement\n"); */
   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if_ptr = (if_decl * ) memAlloc(if_decl,1,REC_IFDECL);

   if_ptr->bool_exp = get_boolean(the_token, the_file, mudcode, T_THEN);

   if_ptr->if_statements = get_statements(the_token, the_file, mudcode, 
                                                            the_hash, T_ELSE, T_END);

   if (return_type == T_ELSE)
   {
/*      printf("status - beginning check on else statement\n"); */
      if_ptr->else_statements = get_statements(the_token, the_file, mudcode, the_hash, 
                                                                            T_END, 0);
   }
   else if (return_type == T_END)
   {
      if_ptr->else_statements = NULL;
   }
   else
      printf(
          "WARNING -- Wierd error encountered in get_if procedure, unexpected return_type!\n"); 
   
   return_type = 0;

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;
   if (the_token->token_type != T_IF)
   {
      state_error("Missing if after end for if statement.", the_token->line);
      return NULL;    
   }

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;
   if (the_token->token_type != T_SEMICOLON)
   {
      state_error("Missing ';' after end if.", the_token->line);
      return NULL;    
   }
/*   printf("status - check finished on if statement\n"); */
   ret_union->stmt.if_d = if_ptr;
   return ret_union;

}

/*************************************************************************************
 **
 ** get_raw - get raw code in a linked list format
 **
 ** Parameters: the_file - 
 **
 ** ret - returns the first token on the next line
 **
 *************************************************************************************/

stmt_record *get_raw(FILE *the_file)
{
   raw_decl *raw_ptr;
   stmt_record *ret_union;

   ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT);
   ret_union->stmt_type = STMT_RAW_CODE;

   /* printf("status - beginning check on raw code\n");*/

   raw_ptr = (raw_decl * ) memAlloc(raw_decl,1,REC_RAWDECL);
   raw_ptr->the_code = get_str_until(the_file, '@', '\0');
   
   /* printf("status - check finished on raw code\n");*/

   ret_union->stmt.raw_d = raw_ptr;
   return ret_union;
}

/*************************************************************************************
 **
 ** get_statements - gets a list of statements
 **
 ** Parameters: the_token - 
 **             the_file -
 **             stop_at - 
 **
 ** ret - returns the first token on the next line
 **
 *************************************************************************************/

stmt_list_record *get_statements(token_record *the_token, FILE *the_file, 
                              mudcode_record *mudcode, hashTable *the_hash, 
                              int stop_at1, int stop_at2)
{
   stmt_list_record *temp_stmt; /* holds the main statement list record */
   stmt_list_record *stmt_ptr;  /* used to move along statement records */
   stmt_list_record *last_stmt = NULL; /* holds the last record for removing a record */
   char error[80];

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   /* printf("Starting parse of a statement.\n");  */
   temp_stmt = (stmt_list_record * ) memAlloc(stmt_list_record,1,REC_STMTLIST);
   stmt_ptr = temp_stmt;

   while ((the_token->token_type != stop_at1) && 
          (the_token->token_type != stop_at2))
   {
       if (error_counter >= MAX_ERRORS)
          return NULL;

       switch(the_token->token_type)
      {
         case T_CONSTANT:
            stmt_ptr->the_statement = get_const(the_token, the_file, mudcode, the_hash);
            break;
         case T_STR:
         case T_NUMBER:
         case T_BOOL:
            stmt_ptr->the_statement = get_decl(the_token, the_file, mudcode, the_hash);  
            break;
         case T_FOR:
            stmt_ptr->the_statement = get_for(the_token, the_file, mudcode, the_hash);
            break;
         case T_WHILE:
            stmt_ptr->the_statement = get_while(the_token, the_file, mudcode, the_hash);
            break;
         case T_REPEAT:
            stmt_ptr->the_statement = get_repeat(the_token, the_file, mudcode, the_hash);
            break;
         case T_BEGIN:
            stmt_ptr->the_statement = get_block(the_token, the_file, mudcode, the_hash);
            break;
         case T_IDENTIFIER:
            stmt_ptr->the_statement = get_identifier(the_token, the_file, 
                                                                    mudcode, True);
            break;
         case T_IF:
            stmt_ptr->the_statement = get_if(the_token, the_file, mudcode, the_hash);
            break;
         case T_AMPER:
            stmt_ptr->the_statement = get_raw(the_file);
            if ((the_token = xget_token(the_file)) == NULL)
               return NULL;

            break;
         default: 
            sprintf(error, "Unknown token %s in statement lists.", the_token->the_string);
            state_error(error, the_token->line);
            if (next_line(the_file) == -1)
            {
               state_error("Unexpected end of file reached", 0);
               return NULL;
            }
            break;
      }
 
      stmt_ptr->more_statements = (stmt_list_record * ) memAlloc(stmt_list_record,1,REC_STMTLIST);
      last_stmt = stmt_ptr;
      stmt_ptr = stmt_ptr->more_statements;
     
      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;
   }
  
   return_type = the_token->token_type;

   /* remove the empty last one */
   if (last_stmt != NULL)
   {
      xfree(last_stmt->more_statements,REC_STMTLIST);
      last_stmt->more_statements = NULL;

      return temp_stmt; 
   }
   return NULL;

}   


/*********************************************************************************
 **
 ** xget_code - gets all locations, returning a pointer to a string list
 **
 ** Parameters: the_token - the token passed in, it is freed first
 **             the_file - the file pointer
 **
 ** ret - -1 if encountered an error, otherwise the location
 **
 ********************************************************************************/

trap_desc *xget_code(token_record *the_token, FILE *the_file, 
                     hashTable *the_hash, char *zonename, Boolean allow_loc)
{

   trap_desc     *temp_trap_desc;
   char           error[80];
   hashRecord   *next_hash;
   char          hashnam[(MAXNAMLEN*2)+5];
   

   temp_trap_desc = (trap_desc *) memAlloc(trap_desc,1,REC_TRAPDESC);
   temp_trap_desc->next_desc = NULL;

   if (!((the_token->token_type >= 0) && (the_token->token_type <= last_event())))
   {
      /* printf("type: %d\n", the_token->token_type);*/
      sprintf(error, "Expected trap action(s) after '=', found token %s.", 
                                                          the_token->the_string);
      state_error(error, the_token->line);
      return NULL;    
   }

   temp_trap_desc->trap_verb = the_token->token_type;

   if (allow_loc)
   {
      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;
      if (the_token->token_type != T_COLON)
      {
         state_error("Missing ':' after UseTrap statement action.", the_token->line);
         return NULL;
      }

      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      if (the_token->token_type != T_IDENTIFIER)
      {
         state_error("Missing identifier after ':' for Trap location.", the_token->line);
         return NULL;    
      }

      if (!strcasecmp(itemname, the_token->the_string))
      {
         state_warning("Extern location name is same as this location; could result in a stack overflow");
      }

      strcpy(temp_trap_desc->trap_location, the_token->the_string);
   }
   else
      temp_trap_desc->trap_location[0] = '\0';

   if (check_next_char(the_file) == ',')
   {  if (allow_loc)
      {   state_error("Only one external event allowed after UseTrap statement.",the_token->line);
          return NULL;
      }

      if ((the_token = xget_token(the_file)) == NULL)
      {  state_error("Expected a trap after a ',', but found nothing.\n",the_token->line);
         return NULL;
      }

      the_token = get_token(the_file, '\n', True);

      temp_trap_desc->next_desc = xget_code(the_token, the_file, the_hash, 
                                                        zonename, allow_loc);
   }

   /* put this event into the hash table */

   sprintf(hashnam, "trap@%s@%s", zonename, itemname);

   next_hash = createHashRecord(hashnam, 0);
   addHashRecord(next_hash, the_hash);
       
   return temp_trap_desc;
}

/*******************************************************************************
 **
 ** get_extern - gets a string of code or data
 **
 ** Parameters: the_file -
 **             stop_at - 
 **
 ** ret - returns the first token on the next line
 **
 *******************************************************************************/

trap_record *get_extern(token_record *the_token, FILE *the_file, 
                        hashTable *the_hash, char *zonename, 
                        mudcode_record *mudcode)
{
   trap_record  *the_trap;  /* Holds a trap record for passing back */

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;
   if (the_token->token_type != T_EQUALS)
   {
      state_error("Expected '=' after UseTrap token.", the_token->line);
      return NULL;    
   }

   the_trap = (trap_record * ) memAlloc(trap_record,1,REC_TRAP);

   the_token = get_token(the_file, '\n', True);

   the_trap->trap_verb = xget_code(the_token, the_file, the_hash, zonename, True);
   
   the_trap->the_statements = NULL;

   return the_trap;
}

/*******************************************************************************
 **
 ** get_code - gets a string of code or data
 **
 ** Parameters: the_file -
 **             stop_at - 
 **
 ** ret - returns the first token on the next line
 **
 *******************************************************************************/

trap_record *get_code(token_record *the_token, FILE *the_file, 
                mudcode_record *mudcode, hashTable *the_hash, 
                char *zonename, int stop_at)
{
   trap_record  *the_trap;  /* Holds a trap record for passing back */
   trap_desc    *temp_ptr;

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;
   if (the_token->token_type != T_EQUALS)
   {
      state_error("Expected '=' after trap token.", the_token->line);
      return NULL;    
   }

   the_trap = (trap_record * ) memAlloc(trap_record,1,REC_TRAP);

   the_token = get_token(the_file, '\n', True);

   the_trap->trap_verb = xget_code(the_token, the_file, the_hash, zonename, False);
   temp_ptr = the_trap->trap_verb;   

   the_trap->the_statements = get_statements(the_token, the_file, mudcode, 
                                                           the_hash, stop_at, 0);

   return the_trap;
}

/*********************************************************************************
 **                      MUDCODE TEMPLATE LOADING FUNCTIONS
 ********************************************************************************/

/*********************************************************************************
 **
 ** xload_mudcode - reads in mudcode from the file mudcode.lib and loads it all into a
 **                linked list
 **
 ** ret - returns a linked list of mudcode records containing all mudcode information
 **
 ********************************************************************************/

mudcode_record *xload_mudcode(token_record *the_token, FILE *the_file)
{
   mudcode_record *temp_code;
   param_record   *temp_param;
   thecode_record *temp_thecode;
   char           error[80];

   /* check for an identifier, name of mudcode function */
   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if ((the_token->token_type != T_IDENTIFIER) && (the_token->token_type != T_STRENGTH))
   {
      sprintf(error, "Identifier for name of function expected, found %s.", 
                                                             the_token->the_string);
      state_error(error, the_token->line);
      return NULL;    
   }

   /* create a place to store the template */
   temp_code = (mudcode_record *) memAlloc(mudcode_record,1,REC_MUDCODE);

   /* copy name into template */
   strcpy(temp_code->code_name, the_token->the_string);

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   /* start getting mudcode parameters */
   if (the_token->token_type != T_LPAREN)
   {
      state_error("Missing required '('.", the_token->line);
      return NULL;
   }

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;
   
   if (the_token->token_type != T_RPAREN)
   {
      temp_code->parameters = (param_record *) memAlloc(param_record,1,REC_PARAM);
      temp_param = temp_code->parameters;
   }

   /* while we dont find a closing right parenthesis, get parameters */
   while (the_token->token_type != T_RPAREN)
   {
      temp_param->next_param = NULL;

      if ((the_token->token_type != T_STR) && (the_token->token_type != T_NUMBER) &&
          (the_token->token_type != T_BOOL) && (the_token->token_type != T_IDENT))
      {
         sprintf(error, "Missing required variable type, found %s.", the_token->the_string);
         state_error(error, the_token->line);
         return NULL;
      } 

      temp_param->param_type = the_token->token_type;

      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      if (the_token->token_type != T_LPAREN)
      {
         state_error("Missing required '('.", the_token->line);
         return NULL;
      } 

      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      if (the_token->token_type != T_NUMERICAL)
      {
         state_error("Missing required number for variable.", the_token->line);
         return NULL;
      }  
      
      temp_param->param_num = atoi(the_token->the_string);
 
      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      if (the_token->token_type != T_RPAREN)
      {
         state_error("Missing required ')'.", the_token->line);
         return NULL;
      }

      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      if (the_token->token_type == T_COMMA)
      {
         temp_param->next_param = (param_record * ) memAlloc(param_record,1,REC_PARAM);
         temp_param = temp_param->next_param;
         if ((the_token = xget_token(the_file)) == NULL)
            return NULL;
      }
   }
   /* done getting parameters, expect a semicolon to close it off */

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if (the_token->token_type != T_SEMICOLON)
   {
      state_error("Missing required ';' at end of function declaration.", the_token->line);
      return NULL;
   }
   
   /* go to the next char, which should be the start of the conversion code */
   if (goto_next_char(the_file) < 0)
      return NULL;
   
   temp_code->the_code = (thecode_record * ) memAlloc(thecode_record,1,REC_THECODE);
   temp_thecode = temp_code->the_code;

   /* get until we hit a parameter or the end, and store it */
   temp_thecode->code_str = get_str_until(the_file, '@', '{');
 
   while (check_next_char(the_file) != '@')
   {      
      /* get the squiggly */
      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      /* get the type and check it */
      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      if ((the_token->token_type != T_STR) && (the_token->token_type != T_NUMBER) &&
          (the_token->token_type != T_BOOL) && (the_token->token_type != T_IDENT))
      {
         state_error("Missing variable type after '{'.", the_token->line);
         return NULL;
      }

      temp_thecode->param_type = the_token->token_type;

      /* expect a left paren */
      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      if (the_token->token_type != T_LPAREN)
      {
         state_error("Missing '(' after variable type.", the_token->line);
         return NULL;
      }

      /* get the number of the parameter */
      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      if (the_token->token_type != T_NUMERICAL)
      {
         state_error("Missing variable number after '('.", the_token->line);
         return NULL;
      }

      temp_thecode->param_num = atoi(the_token->the_string);

      /* get right paren and squiggly and finish off this param */
      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      if (the_token->token_type != T_RPAREN)
      {
         state_error("Missing ')' after variable number.", the_token->line);
         return NULL;
      }

      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;

      if (the_token->token_type != T_RSQUIG)
      {
         state_error("Missing '}' after ')'.", the_token->line);
         return NULL;
      }

      temp_thecode->next_code = (thecode_record * ) memAlloc(thecode_record,1,REC_THECODE);
      temp_thecode = temp_thecode->next_code;

      temp_thecode->code_str = get_str_until(the_file, '@', '{');

   }

   temp_thecode->param_type = -1;
   temp_thecode->param_num = -1;

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   while (the_token->token_type == T_POUND)
   {
      if (next_line(the_file) == -1)
      {
         state_error("Unexpected end of file reached", 0);
         return NULL;
      }
      if ((the_token = xget_token(the_file)) == NULL)
         return NULL;         
   }

   if (the_token->token_type != T_PERCENT)
   {
      sprintf(error, "Unknown token %s in mudcode.lib file", the_token->the_string);
      state_error(error, the_token->line);
      return NULL;
   }

   if ((the_token = xget_token(the_file)) == NULL)
      return NULL;

   if (the_token->token_type == T_START)
   {
      temp_code->next_mudcode = xload_mudcode(the_token, the_file);
   }
   else if (the_token->token_type != T_END)
   {
      state_error("Unknown token in mudcode.lib file", the_token->line);
      return NULL;      
   }
   return temp_code;
}

/*********************************************************************************
 **
 ** load_mudcode - reads in mudcode from the file mudcode.lib and loads it all into a
 **                linked list
 **
 ** ret - returns a linked list of mudcode records containing all mudcode information
 **
 ********************************************************************************/

mudcode_record *load_mudcode(void)
{
   FILE *codefile;
   token_record *the_token;
   mudcode_record *the_code; 
   char *mudcode_fn = request_char_value("MUDCODE_LIBRARY");

   if (mudcode_fn == NULL)
      mudcode_fn = "mudcode.lib"; 

   if ((codefile = xfopen(mudcode_fn)) == NULL)
   {
      state_error("Error opening mudcode file 'mudcode.lib'.", 0);
      return NULL;
   }

   printf(" [1] Loading Mud Code Library... ");
   strcpy(thezonenam, "mudcode");
 
   if ((the_token = xget_token(codefile)) == NULL)
      return NULL;

   while (the_token->token_type != T_PERCENT)
   {
/*      printf("num: %d\n", the_token->line); */
      if (the_token->token_type == T_POUND)
      {
         if (next_line(codefile) == -1)
         {
            state_error("Unexpected end of file reached", 0);
            return NULL;
         }         
      }
      else
      {
         state_error("Unexpected token", the_token->line);
      }
      if ((the_token = xget_token(codefile)) == NULL)
         return NULL;
   }

   if ((the_token = xget_token(codefile)) == NULL)
      return NULL;

   if (the_token->token_type != T_START)
   {
      state_error("Token start expected.", the_token->line);
      return NULL;        
   }
   the_code = xload_mudcode(the_token, codefile);
   if (the_code != NULL)
      printf(" Succesful.\n");
   return the_code;
}


/*********************************************************************************
 **                          MAIN PARSE FUNCTION
 ********************************************************************************/

/********************************************************************************
 **
 ** get_zone
 **
 ** Parameters: filename - the filename string to open
 **
 ** ret - returns a zone record with all zone data stored in it or attached to it
 **
 ********************************************************************************/

zone_record *get_zone(char *zonename, hashTable *hasht, mudcode_record *mudcode)
{
   FILE *zonefile;             /* the zone file to parse */
   char error[120];            /* stores an error message */
   token_record *the_token;    /* holds the pointer to a token */
   zone_record  *the_zone;     /* points to the zone */
   location_record *next_loc;  /* points to the next location in the line */
   object_record *next_obj;    /* points to the next object in the line */
   mobile_record *next_mob;    /* points to the next mobile in the line */
   hashRecord    *next_hash;   /* the next hash record to add */
   trap_record   *next_trap;   /* pointer to go to the next trap record in the line */
   char          hashnam[(MAXNAMLEN*2)+5];
   char          filename[MAXNAMLEN];
   char          *tempstr;
   char          *CPP_str;
#ifdef USE_PIPE
   char          pipe[256];
#endif

   Boolean       is_loc_title;
   Boolean       is_loc_desc;
   Boolean       is_mob_loc;
   Boolean       is_mob_str;
   Boolean       is_mob_desc;
   Boolean       is_obj_loc;

   sprintf(filename, "%s%s", zonename,fn_extension);

   /* try to open the file, passing it through the C preprocessor first */

#ifdef USE_PIPE
   CPP_str = request_char_value("CPP");
   sprintf(pipe, CPP_str, filename);
   if ((zonefile = popen(pipe, "r")) == NULL)
   {
      sprintf(error, "Error opening zone file %s, it may not exist.", filename);
      state_error(error, 0);
      return NULL;
   }

#else
   if ((zonefile = xfopen(filename)) == NULL)
   {
      sprintf(error, "Error opening zone file %s, it may not exist.", filename);
      state_error(error, 0);
      return NULL;
   }

#endif

   strcpy(thezonenam, filename); 
  
   the_zone = (zone_record *) memAlloc(zone_record,1,REC_ZONE);
   strcpy(the_zone->zonefile, zonename);
   the_zone->zonename = xlowercase(thezonenam, strlen(thezonenam) + 1);
   /*the_zone->zonename = (char *) memAlloc(char, strlen(thezonenam) + 1,REC_CHAR);*/
   strcpy(the_zone->zonename, zonename);

   /* get all stuff at the head of the zone file, not sure what I should do with includes */
   if ((the_token = xget_token(zonefile)) == NULL)
   {
      state_error("Unexpected error (end of file?). Terminating parse.", 0);
      return NULL;
   }

   while ((the_token->token_type != T_LOCATION) && (the_token->token_type != T_MOBILE) &&
          (the_token->token_type != T_OBJECT) && (the_token->token_type != T_ZONE))
   {
      if (next_line(zonefile) == -1)
      {
         state_error("End of file encountered before any locations, objects, or mobiles.\n", 0);
         return NULL;
      }
      if ((the_token = xget_token(zonefile)) == NULL)
      {
         state_error("Unexpected error (end of file?). Terminating parse.", 0);
         return NULL;
      }

   }
   
   /* get each item */
   while (!(feof(zonefile))) 
   {
      switch(the_token->token_type)
      {
         /* if we get a record for the zone */
         case T_ZONE:
            /***************************getting zone name **********************/
            xfree(the_zone->zonename,REC_CHAR);
            the_zone->zonename = lowercase(get_str_assn(the_token, zonefile, MAXNAMLEN));
            if (the_zone->zonename == NULL)
               break;
            sprintf(theitem, "zone %s", the_zone->zonename);
            strcpy(itemname, the_zone->zonename);

            /***************************getting any other zone data ************/
            if ((the_token = xget_token(zonefile)) == NULL)
            {
               state_error("Unexpected error (end of file?). Terminating parse.", 0);
               return NULL;
            }

            while (the_token->token_type != T_ENDZONE)
            {
               if (error_counter >= MAX_ERRORS)
	       {
                  state_error("Too many errors, terminating compile.", 1);
                  return NULL;
               }

               switch(the_token->token_type)
               {
                  case T_AUTHOR:
                     the_zone->author = get_str_assn(the_token, zonefile, 30);
                     break;

                  case T_QUEST:
                     the_zone->quest = get_str_assn(the_token, zonefile, 
                                                              MAXQUESTNAMLEN);
                     break;

                  case T_DATA:
                     the_zone->code = get_statements(the_token, zonefile, mudcode, 
                                                                    hasht, T_ENDDATA, 0);
                     break;

                  case T_LOCATION:
                  case T_OBJECT:
                  case T_MOBILE:
                     state_error("Missing EndZone for the previous zone record.", 
                                                                    the_token->line);
                     return NULL;
                     break;

                  default:
                     sprintf(error, "%s not a member of the zone data record", 
                                                          the_token->the_string);
                     state_error(error, the_token->line);
                     if (next_line(zonefile) == -1)
                     {
                        state_error("End of file encountered before required EndZone in zone record", 0);
                        return the_zone;
                     }
                     break;
               }
               if ((the_token = xget_token(zonefile)) == NULL)
               {
                  state_error("Unexpected error (end of file?). Terminating parse.", 0);
                  return NULL;
               }


            }
            tempstr = get_str_assn(the_token, zonefile, MAXNAMLEN);
            if (strcasecmp(the_zone->zonename, tempstr))
            {
               sprintf(error, 
                       "Endzone name %s does not match the zone record %s.", 
                                               tempstr, the_zone->zonename); 
               state_error(error, 0);
            }
            break;

         case T_LOCATION:

            if (the_zone->location_data == NULL)
            {
               the_zone->location_data = (location_record *) 
                                           memAlloc(location_record,1,REC_LOCATION);
               next_loc = the_zone->location_data;
            }
            else
            {
               next_loc->next_loc = (location_record *) 
                                           memAlloc(location_record,1,REC_LOCATION);
               next_loc = next_loc->next_loc;
            }

            /******************** initialize location data ********************/
            is_loc_title = False;
            is_loc_desc = False;

            next_loc->north = NULL;
            next_loc->south = NULL;
            next_loc->east  = NULL;
            next_loc->west = NULL;
            next_loc->up = NULL;
            next_loc->down = NULL;
            next_loc->northeast = NULL;
            next_loc->northwest = NULL;
            next_loc->southeast = NULL;
            next_loc->southwest = NULL;
            next_loc->hint = NULL;
            next_loc->lflags.b1 = next_loc->lflags.b2 = next_loc->lflags.b3 = 0;
            next_loc->loc_code = NULL;

            /***************************getting location name ********************/
            next_loc->name = get_str_assn(the_token, zonefile, MAXNAMLEN);
            if (next_loc->name == NULL)
               break;

            /* load it into the globals */
            tempstr = xlowercase(next_loc->name, MAXNAMLEN);
            sprintf(theitem, "location %s", next_loc->name);
            strcpy(itemname, next_loc->name);

            /* put this into the hash table */
            sprintf(hashnam, "loc@%s@%s", zonename, tempstr);

            next_hash = createHashRecord(hashnam, cur_loc--);
            if (addHashRecord(next_hash, hasht) == 0)
            {
               sprintf(error, "Redefinition of location %s", tempstr);
               state_error(error, the_token->line);
            }
            xfree(tempstr,REC_CHAR);


            /***************************getting any other location data *************/
            if ((the_token = xget_token(zonefile)) == NULL)
            {
               state_error("Unexpected error (end of file?). Terminating parse.", 0);
               return NULL;
            }


            while (the_token->token_type != T_ENDLOCATION)
            {
               if (error_counter >= MAX_ERRORS)
	       {
                  state_error("Too many errors, terminating compile.", 1);
                  return NULL;
               }

               switch(the_token->token_type)
               {
                  case T_NORTH:
                     next_loc->north = lowercase(get_loc_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1));
                     break;
                                                           
                  case T_SOUTH:
                     next_loc->south = lowercase(get_loc_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1));
                     break;

                  case T_EAST:
                     next_loc->east = lowercase(get_loc_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1));
                     break;

                  case T_WEST:
                     next_loc->west = lowercase(get_loc_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1));
                     break;

                  case T_UP:
                     next_loc->up = lowercase(get_loc_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1));
                     break;
                 
                  case T_DOWN:
                     next_loc->down = lowercase(get_loc_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1));
                     break;

                  case T_NORTHEAST:
                     next_loc->northeast = lowercase(get_loc_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1));
                     break;

                  case T_NORTHWEST:
                     next_loc->northwest = lowercase(get_loc_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1));
                     break;

                  case T_SOUTHEAST:
                     next_loc->southeast = lowercase(get_loc_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1));
                     break;

                  case T_SOUTHWEST:
                     next_loc->southwest = lowercase(get_loc_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1));
                     break;

                  case T_TITLE:
                     next_loc->title = get_str_assn(the_token, zonefile, MAXTITLLEN);
                     is_loc_title = True;
                     break;

                  case T_DESC:
                     next_loc->desc = get_str_list_assn(the_token, zonefile, True);
                     is_loc_desc = True;
                     break;
       
                  case T_HINT:
                     next_loc->desc = get_str_list_assn(the_token, zonefile, True);
                     break;

                  case T_LFLAGS:
                     get_flags(the_token, &next_loc->lflags, Lflags, zonefile);
                     break;

                  case T_TRAP:

                     if (next_loc->loc_code == NULL)                     
                        next_loc->loc_code = get_code(the_token, zonefile, 
                                            mudcode, hasht, zonename, T_ENDTRAP);
                     else
                     {
                        next_trap = next_loc->loc_code;
                        while (next_trap->more_traps != NULL)
                           next_trap = next_trap->more_traps;
                        next_trap->more_traps = get_code(the_token, zonefile, 
                                            mudcode, hasht, zonename, T_ENDTRAP);
                     }
                     break;
                  case T_USETRAP:

                     next_loc->loc_code = get_extern(the_token, zonefile, 
                                             hasht, zonename, mudcode);
                     break;

                  case T_ZONE:
                  case T_OBJECT:
                  case T_MOBILE:
                     state_error("Missing EndLocation for the previous location record.", the_token->line);
                     return NULL;
                     break;

                  default:
                     sprintf(error, "%s not a member of the location data record", 
                                                                     the_token->the_string);
                     state_error(error, the_token->line);
                     if (next_line(zonefile) == -1)
                     {
                        state_error("End of file encountered before required EndLocation in location record", 0);
                        return the_zone;
                     }
                     break;
               }
               if ((the_token = xget_token(zonefile)) == NULL)
               {
                  state_error("Unexpected error (end of file?). Terminating parse.", 0);
                  return NULL;
               }
      

            } 

            tempstr = get_str_assn(the_token, zonefile, MAXNAMLEN);
            if (strcasecmp(next_loc->name, tempstr))
            {
               sprintf(error, "EndLocation name %s does not match the location record %s.", 
                                                         tempstr, next_loc->name); 
               state_error(error, 0);
            }

            /* make sure we have all location elements */
            if (!is_loc_title)
               state_error("Missing required title element for location record",
                                                                         the_token->line);
            if (!is_loc_desc)
               state_error("Missing required description element for location record",
                                                                         the_token->line);

            break;

         case T_OBJECT:

            /*********************create a new object record ******************/ 
            if (the_zone->object_data == NULL)
            {
               the_zone->object_data = (object_record *) 
                                           memAlloc(object_record,1,REC_OBJECT);
               next_obj = the_zone->object_data;
            }
            else
            {
               next_obj->next_obj = (object_record *) 
                                           memAlloc(object_record,1,REC_OBJECT);
               next_obj = next_obj->next_obj;
            }

            /******************** initialize object data ********************/
            is_obj_loc = False;

            next_obj->name = NULL;
            next_obj->altname = NULL;
            next_obj->linked = NULL;
            next_obj->examine = NULL;
            next_obj->desc[0] = NULL;
            next_obj->desc[1] = NULL;
            next_obj->desc[2] = NULL;
            next_obj->desc[3] = NULL;
            next_obj->basevalue = DEF_OBJ_BVALUE;
            next_obj->state = DEF_OBJ_STATE;
            next_obj->maxstate = DEF_OBJ_STATE;
            next_obj->armor = DEF_OBJ_ARMOR;
            next_obj->damage = DEF_OBJ_DAMAGE;
            next_obj->size = DEF_OBJ_SIZE;
            next_obj->weight = DEF_OBJ_WEIGHT;
            next_obj->hint = NULL;
            next_obj->oflags.b1 = next_obj->oflags.b2 = next_obj->oflags.b3 = 0;
            next_obj->obj_code = NULL;

            /***************************getting object name *******************************/

            next_obj->oname = get_str_assn(the_token, zonefile, MAXNAMLEN);
            if (next_obj->oname == NULL)
               break;
            
            /* store the object in the hash table */
            tempstr = xlowercase(next_obj->oname, MAXNAMLEN);
            sprintf(hashnam, "obj@%s@%s", zonename, tempstr);

            /* load it into the globals */
            sprintf(theitem, "object %s", next_obj->oname);
            strcpy(itemname, next_obj->oname);

	    /*            printf("parsing: %s\n", theitem);
            printf("storing: %s\n", hashnam);*/
            next_hash = createHashRecord(hashnam, cur_obj++);
            if (addHashRecord(next_hash, hasht) == 0)
            {
               sprintf(error, "Redefinition of object %s", tempstr);
               state_error(error, the_token->line);
            }
            xfree(tempstr,REC_CHAR);


            /***************************getting any other object data *********************/
            if ((the_token = xget_token(zonefile)) == NULL)
            {
               state_error("Unexpected error (end of file?). Terminating parse.", 0);
               return NULL;
            }
     
            while (the_token->token_type != T_ENDOBJECT)
            {
               if (error_counter >= MAX_ERRORS)
	       {
                  state_error("Too many errors, terminating compile.", 1);
                  return NULL;
               }

               switch(the_token->token_type)
               {
                  case T_NAME:
                     next_obj->name = get_str_assn(the_token, zonefile, 
                                                              (MAXNAMLEN*2)+1);
                     break;
                              
                  case T_ALTNAME:
                     next_obj->altname = get_str_assn(the_token, zonefile, 
                                                             (MAXNAMLEN*2)+1);
                     break;

                  case T_LOCATION:
 
                     next_obj->location = 
                                        get_location(the_token, zonefile, True); 
                     is_obj_loc = True;
                     break;

                  case T_LINKED:
                     next_obj->linked = get_str_assn(the_token, zonefile, 
                                                         (MAXNAMLEN*2)+1);
                     break;

                  case T_BASEVALUE:
                     next_obj->basevalue = get_int_assn(the_token, zonefile);
                     break;

                  case T_STATE:
                     next_obj->state = get_int_assn(the_token, zonefile);
                     break;

                  case T_MAXSTATE:
                     next_obj->maxstate = get_int_assn(the_token, zonefile);
                     break;

                  case T_ARMOR:
                     next_obj->armor = get_int_assn(the_token, zonefile);
                     break;

                  case T_DAMAGE:
                     next_obj->damage = get_int_assn(the_token, zonefile);
                     break;

                  case T_SIZE:
                     next_obj->size = get_int_assn(the_token, zonefile);
                     break;

                  case T_WEIGHT:
                     next_obj->weight = get_int_assn(the_token, zonefile);
                     break;

                  case T_VISIBILITY:
                     next_obj->vis = get_int_assn(the_token, zonefile);
                     break;

                  case T_EXAMINE:
                     next_obj->examine = get_str_list_assn(the_token, zonefile, True);
                     break;

                  case T_DESC1:
                     next_obj->desc[0] = get_str_list_assn(the_token, zonefile, True);
                     break;

                  case T_DESC2:
                     next_obj->desc[1] = get_str_list_assn(the_token, zonefile, True);
                     break;

                  case T_DESC3:
                     next_obj->desc[2] = get_str_list_assn(the_token, zonefile, True);
                     break;

                  case T_DESC4:
                     next_obj->desc[3] = get_str_list_assn(the_token, zonefile, True);
                     break;
       
                  case T_HINT:
                     next_obj->hint = get_str_list_assn(the_token, zonefile, True);
                     break;

                  case T_OFLAGS:
                     get_flags(the_token, &next_obj->oflags, Oflags, zonefile);
                     break;

                  case T_TRAP:

                     if (next_obj->obj_code == NULL)                     
                        next_obj->obj_code = get_code(the_token, zonefile, 
                                             mudcode, hasht, zonename, T_ENDTRAP);
                     else
                     {
                        next_trap = next_obj->obj_code;
                        while (next_trap->more_traps != NULL)
                           next_trap = next_trap->more_traps;
                        next_trap->more_traps = get_code(the_token, zonefile,
                                            mudcode, hasht, zonename, T_ENDTRAP);
                     }
                     break;

                  case T_USETRAP:

                     next_obj->obj_code = get_extern(the_token, zonefile, 
                                                 hasht, zonename, mudcode);
                     break;

                  case T_ZONE:
                  case T_MOBILE:
                     state_error("Missing EndObject for the previous object record.", the_token->line);
                     return NULL;
                     break;

                  default:
                     sprintf(error, "%s not a member of the object data record", 
                                                                     the_token->the_string);
                     state_error(error, the_token->line);
                     if (next_line(zonefile) == -1)
                     {
                        state_error("End of file encountered before required EndObject in object record", 0);
                        return the_zone;
                     }
                     break;
               }

               if ((the_token = xget_token(zonefile)) == NULL)
               {
                  state_error("Unexpected error (end of file?). Terminating parse.", 0);
                  return NULL;
               }
                   
            } 

            tempstr = get_str_assn(the_token, zonefile, MAXNAMLEN);
            if (strcasecmp(next_obj->oname, tempstr))
            {
               sprintf(error, "EndObject name %s does not match the object record %s.", 
                                                         tempstr, next_obj->oname); 
               state_error(error, 0);
            }

            /* make sure we got the required object element */
            if (!is_obj_loc)
               state_error("Missing required location element for object record",
                                                                         the_token->line); 

            break;

         case T_MOBILE:

            /*********************create a new mobile record ******************/ 
            if (the_zone->mobile_data == NULL)
            {
               the_zone->mobile_data = (mobile_record *) 
                                           memAlloc(mobile_record,1,REC_MOBILE);
               next_mob = the_zone->mobile_data;
            }
            else
            {
               next_mob->next_mob = (mobile_record *) 
                                           memAlloc(mobile_record,1,REC_MOBILE);
               next_mob = next_mob->next_mob;
            }

            /******************** initialize mobile data ********************/
            is_mob_loc = False;
            is_mob_str = False;
            is_mob_desc = False;

            next_mob->name = NULL;
            next_mob->examine = NULL;
            next_mob->armor = DEF_MOB_ARMOR;
            next_mob->damage = DEF_MOB_DAMAGE;
            next_mob->aggr = DEF_MOB_AGGRESSION;
            next_mob->speed = DEF_MOB_SPEED;
            next_mob->wimpy = DEF_MOB_WIMPY;
            next_mob->hint = NULL;
            next_mob->mflags.h = next_mob->mflags.l = 0;
            next_mob->pflags.b1 = next_mob->pflags.b2 = next_mob->pflags.b3 = 0;
            next_mob->sflags.b1 = next_mob->sflags.b2 = next_mob->sflags.b3 = 0;
            next_mob->mob_code = NULL;

            /***************************getting mobile name *******************************/
            next_mob->mname = get_str_assn(the_token, zonefile, MAXNAMLEN);
            if (next_mob->mname == NULL)
               break;
            
            /* load the mobile into the hash table */
            tempstr = xlowercase(next_mob->mname, MAXNAMLEN);
            sprintf(hashnam, "mob@%s@%s", zonename, tempstr);


            /* load it into the globals */
            sprintf(theitem, "mobile %s", next_mob->mname);
            strcpy(itemname, next_mob->mname);

            next_hash = createHashRecord(hashnam, cur_mob++);
            if (addHashRecord(next_hash, hasht) == 0)
            {
               sprintf(error, "Redefinition of mobile %s", tempstr);
               state_error(error, the_token->line);
            }
            xfree(tempstr,REC_CHAR);


            /***************************getting any other mobile data *********************/
            if ((the_token = xget_token(zonefile)) == NULL)
            {
               state_error("Unexpected error (end of file?). Terminating parse.", 0);
               return NULL;
            }
     
            while (the_token->token_type != T_ENDMOBILE)
            {
               if (error_counter >= MAX_ERRORS)
	       {
                  state_error("Too many errors, terminating compile.", 1);
                  return NULL;
               }

               switch(the_token->token_type)
               {
                  case T_NAME:
                     next_mob->name = get_str_assn(the_token, zonefile, 
                                                              (MAXNAMLEN*2)+1);
                     break;
                                                           
                  case T_LOCATION:

                     next_mob->location = get_location(the_token, zonefile, False);
                     is_mob_loc = True;
                     break;

                  case T_STRENGTH:
                     next_mob->strength = get_int_assn(the_token, zonefile);
                     is_mob_str = True;
                     break;

                  case T_DAMAGE:
                     next_mob->damage = get_int_assn(the_token, zonefile);
                     break;

                  case T_ARMOR:
                     next_mob->armor = get_int_assn(the_token, zonefile);
                     break;

                  case T_SPEED:
                     next_mob->speed = get_int_assn(the_token, zonefile);
                     break;

                  case T_AGGRESSION:
                     next_mob->aggr = get_int_assn(the_token, zonefile);
                     break;

                  case T_WIMPY:
                     next_mob->wimpy = get_int_assn(the_token, zonefile);
                     break;

                  case T_VISIBILITY:
                     next_mob->vis = get_int_assn(the_token, zonefile);
                     break;

                  case T_DESC:
                     next_mob->desc = get_str_list_assn(the_token, zonefile, True);
                     is_mob_desc = True;
                     break;

                  case T_EXAMINE:
                     next_mob->examine = get_str_list_assn(the_token, zonefile, True);
                     break;
       
                  case T_HINT:
                     next_mob->hint = get_str_list_assn(the_token, zonefile, True);
                     break;

                  case T_MFLAGS:
                     get_mflags(the_token, &next_mob->mflags, zonefile);
                     break;

                  case T_SFLAGS:
                     get_flags(the_token, &next_mob->sflags, Sflags, zonefile);
                     break;

                  case T_PFLAGS:
                     get_flags(the_token, &next_mob->pflags, Pflags, zonefile);
                     break;

                  case T_TRAP:

                     if (next_mob->mob_code == NULL)                     
                        next_mob->mob_code = get_code(the_token, zonefile, 
                                            mudcode, hasht, zonename, T_ENDTRAP);
                     else
                     {
                        next_trap = next_mob->mob_code;
                        while (next_trap->more_traps != NULL)
                           next_trap = next_trap->more_traps;
                        next_trap->more_traps = get_code(the_token, zonefile,
                                             mudcode, hasht, zonename, T_ENDTRAP);
                     }
                     break;

                  case T_USETRAP:

                     next_mob->mob_code = get_extern(the_token, zonefile, 
                                             hasht, zonename, mudcode);
                     break;

                  case T_ZONE:
                  case T_OBJECT:
                     state_error("Missing EndMobile for the previous mobile record.", the_token->line);
                     return NULL;
                     break;

                  default:
                     sprintf(error, "%s not a member of the mobile data record", 
                                                                     the_token->the_string);
                     state_error(error, the_token->line);
                     if (next_line(zonefile) == -1)
                     {
                        state_error("End of file encountered before required EndMobile in mobile record", 0);
                        return the_zone;
                     }
                     break;

               }

               if ((the_token = xget_token(zonefile)) == NULL)
               {
                  state_error("Unexpected error (end of file?). Terminating parse.", 0);
                  return NULL;
               }
     
            } 

            tempstr = get_str_assn(the_token, zonefile, MAXNAMLEN);
            if (strcasecmp(next_mob->mname, tempstr))
            {
               sprintf(error, "EndMobile name %s does not match the mobile record %s.", 
                                                         tempstr, next_mob->mname); 
               state_error(error, 0);
            }

            /* make sure we got all required elements */
            if (!is_mob_loc)
               state_error("Missing required location element for mobile record",
                                                                         the_token->line);  
            if (!is_mob_str)
               state_error("Missing required strength element for mobile record",
                                                                         the_token->line); 
            if (!is_mob_desc)
               state_error("Missing required description element for mobile record",
                                                                         the_token->line);   
            break;

         default:
            sprintf(error, "Unrecognized element %s in zone file", the_token->the_string);
            state_error(error, the_token->line);
            if (next_line(zonefile) == -1)
            {
               return the_zone;
            }
            break;
      }
      strcpy(theitem, "<none>");
      strcpy(itemname, "<none>");
      if ((the_token = xget_token(zonefile)) == NULL)
         if (Valid == True)
            return the_zone;
         else
         {  printf("Zone not valid\n");
            return NULL;
         }
   }
#ifndef USE_PIPE
   fclose(zonefile);
#else
   pclose(zonefile);
#endif
   if (Valid == True)
      return the_zone;
   else
   {  printf("%d errors occured while reading this zone.\n",error_counter);
      return NULL;
   }
}