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 SEMANTIC_C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gen.h"
#include "semantic.h"

char          thetype[15];
string_record *var_list; 

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

Boolean check_statements(hashTable *the_hash, stmt_list_record *stmts, 
                        char *in_name, zone_record *thezone);

Boolean check_defined(hashTable *the_hash, stmt_record *stmt, char *in_name, 
                                                   zone_record *thezone);

Boolean check_stmt(hashTable *the_hash, stmt_record *stmt, 
                   char *in_name, zone_record *thezone);

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

void sem_error(char *the_err, char *thezone, char *theitem, Boolean is_warning)
{  extern Boolean supress_warnings;
 
   if ((!supress_warnings) || (!is_warning))
      printf("[%-12s] %s - in %s %s@%s\n", thezone, the_err, thetype, theitem,thezone);

   return;
}

/******************************************************************************
 **
 ** has_amperstand
 ** 
 ** Parameters:
 **      str : a object name that needs to be checked for validity
 **
 ** ret - True if name is valid, False if name is invalid
 *****************************************************************************/

Boolean has_amperstand(char *str)
{  int i;
   for (i=0; i<strlen(str); i++)
   {
      if (*str == '@')
         return True;
      str++;
   }
   return False;
}

/******************************************************************************
 **
 ** verify_gamename
 ** 
 ** Parameters:
 **      str : a object name that needs to be checked for validity
 **
 ** ret - True if name is valid, False if name is invalid
 *****************************************************************************/
Boolean verify_gamename(char *str)
{  int i;

   for (i = 0; i < strlen(str); i++)
   {   if (!isalpha(str[i]) && str[i] != '-')
          return False;
   }
   return True;
}

/********************************************************************************
 **
 ** verify_item
 **
 ** Parameters: 
 **     the_hash: Hashtable with all names in it
 **     the_loc : the item to verify.
 **     zone    : the zone that is the owner of the item.
 **     type    : the type of item to look up (either "mob","loc","obj"
 **
 ** ret - True if found, False if not found
 **
 ********************************************************************************/

Boolean verify_item(hashTable *the_hash, char *the_loc, char *zone, char *type)
{
   char    fullloc[(MAXNAMLEN*2)+5]; /* holds location string */
   Boolean has_amper = False;        /* if it has an amperstand in it */ 
   char    *check_ptr;               /* used to move along the string */
   char    *tempstr;
   char    *s;
 
   if (*the_loc == '#')
      return True;

   /* The way it was done first was wrong because the entries in the hashtable
    * are of the format <type>@<zone>@<name>
    */
   s=tempstr=xlowercase(the_loc,strlen(the_loc) + 1);

   if ((check_ptr = index(tempstr,'@')) != NULL)
   {   *check_ptr = '\0';
       check_ptr++;
       has_amper = True;
   }

   if (*tempstr == '^')
   {  tempstr++;
      type = "obj";
   }

#if 0
   has_amper = has_amperstand(check_ptr);

   if (*the_loc == '^')
   {
      the_loc++;
      type = "obj";
   }

   tempstr=xlowercase(the_loc,strlen(the_loc) + 1);
#endif

   if (has_amper)
      sprintf(fullloc, "%s@%s@%s", type, check_ptr, tempstr);
   else
      sprintf(fullloc, "%s@%s@%s", type, zone, tempstr);
   xfree(s,REC_CHAR);
 
   /*printf("Checking for \"%s\"\n",fullloc);  */
   if (findHashRecord(fullloc, the_hash) == NULL)
      return False;
   else
      return True;
}


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

Boolean verify_location(hashTable *the_hash, loc_str_record *the_loc, zone_record *thezone)
{
 
   if ((the_loc->loc_type == T_WIELDEDBY) || (the_loc->loc_type == T_WORNBY) ||
       (the_loc->loc_type == T_BOTHBY) || (the_loc->loc_type == T_CARRIEDBY))
      return verify_item(the_hash, the_loc->the_loc, thezone->zonename, "mob");
   if (the_loc->loc_type == T_INROOM)
      return verify_item(the_hash, the_loc->the_loc, thezone->zonename, "loc");
   if (the_loc->loc_type == T_INCONTAINER)  
      return verify_item(the_hash, the_loc->the_loc, thezone->zonename, "obj");
   else
      return False;
}


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

Boolean check_boolean(hashTable *the_hash, bool_stmt *bool_exp, char *in_name, 
                                                   zone_record *thezone)
{
   Boolean      still_valid = True;

   if (bool_exp->next_bool != NULL)
   {
      still_valid = still_valid && check_boolean(the_hash, bool_exp->next_bool,
                                                 in_name, thezone);
   }

   if (bool_exp->the_stmt != NULL)
   {
      still_valid = still_valid && check_stmt(the_hash, bool_exp->the_stmt,
                                            in_name, thezone);
   }

   return still_valid;
}

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

Boolean check_arith_str(hashTable *the_hash, arith_string *stmt, char *in_name, 
                                                   zone_record *thezone)
{
   Boolean still_good;
   
   if (stmt->stringfunct1 != NULL)
   {
      still_good = check_defined(the_hash, 
               stmt->stringfunct1, in_name, thezone);
   }

   if (stmt->string2 != NULL)
      still_good = still_good && check_arith_str(the_hash, 
                            stmt->string2->stmt.arith_str_d, in_name, thezone);
   return still_good;
}


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

Boolean check_arith_num(hashTable *the_hash, arith_number *stmt, char *in_name, 
                                                   zone_record *thezone)
{
   Boolean still_good;
   
   if (stmt->numberfunct != NULL)
   {
      still_good = check_defined(the_hash, 
               stmt->numberfunct, in_name, thezone);
   }

   if (stmt->next_number != NULL)
      still_good = still_good && check_arith_num(the_hash, 
                            stmt->next_number, in_name, thezone);
   return still_good;
}

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

Boolean check_assignmt(hashTable *the_hash, stmt_record *stmt, char *in_name, 
                                                      zone_record *thezone)
{
   hashRecord  *tmp_hash;
   char        hashnam [(MAXNAMLEN*3)+5]; 
   char        error[80];

   sprintf(hashnam, "dec@%s@%s@%s", thezone->zonename, in_name, stmt->stmt.assignmt_d->var_name);
   lowercase(hashnam);

   if (stmt->stmt.assignmt_d->the_stmt->stmt_type == STMT_ARITH_NUM)
   {
      if ((tmp_hash = findHashRecord(hashnam, the_hash)) == NULL)
      {
         sprintf(error, "Variable %s not defined",  
                                        stmt->stmt.assignmt_d->var_name);
         sem_error(error, thezone->zonefile, in_name, False);
         return False;
      }

      if (tmp_hash->idnumber != T_NUMBER)
      {
         sprintf(error, "Error with variable %s, must assign a number to a number type",  
                                        stmt->stmt.assignmt_d->var_name);
         sem_error(error, thezone->zonefile, in_name, False);
         return False;
      }
     
   }
   else if (stmt->stmt.assignmt_d->the_stmt->stmt_type == STMT_ARITH_STR)
   {
      if ((tmp_hash = findHashRecord(hashnam, the_hash)) == NULL)
      {
         sprintf(error, "Variable %s not defined",  
                                        stmt->stmt.assignmt_d->var_name);
         sem_error(error, thezone->zonefile, in_name, False);
         return False;
      }

      if (tmp_hash->idnumber != T_STR)
      {
         sprintf(error, "Error with variable %s, must assign an arithmetic string to a string type",  
                                        stmt->stmt.assignmt_d->var_name);
         sem_error(error, thezone->zonefile, in_name, False);
         return False;
      }


   }
   else
   {
      printf("BAD ERROR! Unexpected function type in assignment found!\n");
      return False;
   }
   return True;
}


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

Boolean check_defined(hashTable *the_hash, stmt_record *stmt, char *in_name, 
                                                      zone_record *thezone)
{
   mudfunct_param  *tmp_param;
   Boolean         still_valid = True;
   char            error[80];
   char            holder[(MAXNAMLEN*3)+5];

   if (stmt->stmt_type == STMT_IDENT)
   {
      if (has_amperstand(stmt->stmt.ident_d->the_ident))
            strcpy(holder, stmt->stmt.ident_d->the_ident);
      else
      {
         sprintf(holder, "dec@%s@%s@%s", thezone->zonename, in_name, 
                                                       stmt->stmt.ident_d->the_ident);
         lowercase(holder);
      }

      if ((findHashRecord(holder, the_hash) == NULL) &&
             (isalpha(stmt->stmt.ident_d->the_ident[0])))
      {
         sprintf(error, "Identifier %s not defined",  
                                     stmt->stmt.ident_d->the_ident);
         sem_error(error, thezone->zonefile, in_name, False);
         return False;
      }
      else
         return True;
   }

   tmp_param = stmt->stmt.mudfunct_d->parameters;

   while (tmp_param != NULL)
   {

      if (tmp_param->the_param != NULL)
      {
         if (has_amperstand(tmp_param->the_param->the_string))
            strcpy(holder, tmp_param->the_param->the_string);
         else
         {
            sprintf(holder, "dec@%s@%s@%s", thezone->zonename, in_name, 
                                                       tmp_param->the_param->the_string);
            lowercase(holder);
         }

         if ((!tmp_param->has_quotes) &&
             (findHashRecord(holder, the_hash) == NULL) &&
             (isalpha(tmp_param->the_param->the_string[0])))
         {
            sprintf(error, "Identifier %s not defined", tmp_param->the_param->the_string);
            sem_error(error, thezone->zonefile, in_name, False);
            still_valid = False;
         }
      }
      else
      {
         if (tmp_param->funct_param == NULL)
            return still_valid;

         if (tmp_param->funct_param->stmt_type == STMT_IDENT) 
         {
            if (has_amperstand(tmp_param->funct_param->stmt.ident_d->the_ident))
               strcpy(holder, tmp_param->funct_param->stmt.ident_d->the_ident);
            else
            {
               sprintf(holder, "dec@%s@%s@%s", thezone->zonename, in_name, 
                               tmp_param->funct_param->stmt.ident_d->the_ident);
               lowercase(holder);
            }

            if ((findHashRecord(holder, the_hash) == NULL) &&
                  (isalpha(tmp_param->funct_param->stmt.ident_d->the_ident[0])))
            {
               sprintf(error, "Identifier %s not defined", 
                      tmp_param->funct_param->stmt.ident_d->the_ident);
               sem_error(error, thezone->zonefile, in_name, False);
               still_valid = False;
            }
            /* printf("found: %s\n", tmp_param->funct_param->stmt.ident_d->the_ident); */
         }     
         else if (tmp_param->funct_param->stmt_type == STMT_MUD_DEFINED) 
         {
            still_valid = still_valid && check_defined(the_hash, 
                                              tmp_param->funct_param, in_name, thezone);
         } 
         else if (tmp_param->funct_param->stmt_type == STMT_ARITH_STR) 
         {
            still_valid = still_valid &&  check_arith_str(the_hash, 
                       tmp_param->funct_param->stmt.arith_str_d, in_name, thezone); 
         }       
         else if (tmp_param->funct_param->stmt_type == STMT_ARITH_NUM) 
         {
            still_valid = still_valid &&  check_arith_num(the_hash, 
                       tmp_param->funct_param->stmt.arith_num_d, in_name, thezone); 
         }        
         else
         {
            printf("HHHHHHHOOOOOOOOOOOOOLYYYYYYYYYYY MOLYYYYYYYYYY!!! A BUG A BUG!!!!\n");
            return False;
         }
      }

      /* for some reason I need this here, not sure why, but it made it work right */
      fflush(stdout);

      tmp_param = tmp_param->more_param;      
   }

   return still_valid;
}


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

Boolean check_if(hashTable *the_hash, if_decl *stmt, char *in_name, 
                                                   zone_record *thezone)
{
   Boolean still_good;

/*   printf("checking if statement\n");  */
   still_good = check_boolean(the_hash, stmt->bool_exp, in_name, thezone);  
   still_good = still_good && check_statements(the_hash, stmt->if_statements,
                                               in_name, thezone) &&
                check_statements(the_hash, stmt->else_statements,
                                               in_name, thezone); 

   return still_good;
}


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

Boolean check_repeat(hashTable *the_hash, while_decl *stmt, char *in_name, 
                                                   zone_record *thezone)
{
   Boolean still_good = True;
 
   still_good = check_statements(the_hash, stmt->while_statements,
                                               in_name, thezone); 
   still_good = still_good && check_boolean(the_hash, stmt->bool_exp, 
                                                      in_name, thezone);  

   return still_good;
}


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

Boolean check_while(hashTable *the_hash, while_decl *stmt, char *in_name, 
                                                   zone_record *thezone)
{
   Boolean still_good = True;
 
   still_good = check_boolean(the_hash, stmt->bool_exp, in_name, thezone);  
   still_good = still_good && check_statements(the_hash, stmt->while_statements,
                                               in_name, thezone); 
   return still_good;
}


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

Boolean add_const(hashTable *the_hash, const_decl *stmt, char *in_name, 
                                                 zone_record *thezone)
{
   Boolean       still_valid = True;
   const_decl      *tmp_decl;
   string_record *new_str;
   hashRecord    *new_hash;
   char          error[80];

   tmp_decl = stmt;

   while (tmp_decl != NULL)
   {
      if (new_str == NULL)
         new_str = (string_record *) memAlloc(string_record, 1,REC_STRING);

      new_str = var_list;
      while (new_str->nextstr != NULL)
         new_str = new_str->nextstr;
 
      new_str->nextstr = (string_record *) memAlloc(string_record, 1,REC_STRING);
      new_str->nextstr->the_string = (char *) memAlloc(char, strlen(tmp_decl->const_name) + 1, REC_CHAR);
      new_str = new_str->nextstr;
      strcpy(new_str->the_string, tmp_decl->const_name);
      new_hash = createHashRecord(tmp_decl->const_name, -1);
      if (!addHashRecord(new_hash, the_hash))
      {
         sprintf(error, "Variable %s previously declared.", tmp_decl->const_name);
         sem_error(error, thezone->zonefile, in_name, False);
         still_valid = False;
      }
   }
   return still_valid;

}


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


Boolean add_decl(hashTable *the_hash, var_decl *stmt, char *in_name, 
                                                 zone_record *thezone)
{
   Boolean       still_valid = True;
   var_decl      *tmp_decl;
   string_record *new_str;
   hashRecord    *new_hash;
   char          error[80];

   tmp_decl = stmt;

   while (tmp_decl != NULL)
   {
      if (new_str == NULL)
         new_str = (string_record *) memAlloc(string_record, 1,REC_STRING);

      new_str = var_list;
      while (new_str->nextstr != NULL)
         new_str = new_str->nextstr;
 
      new_str->nextstr = (string_record *) memAlloc(string_record, 1,REC_STRING);
      new_str->nextstr->the_string = (char *) memAlloc(char, strlen(tmp_decl->var_name) + 1, REC_CHAR);
      new_str = new_str->nextstr;
      strcpy(new_str->the_string, tmp_decl->var_name);
      new_hash = createHashRecord(tmp_decl->var_name, -1);
      if (!addHashRecord(new_hash, the_hash))
      {
         sprintf(error, "Variable %s previously declared.", tmp_decl->var_name);
         sem_error(error, thezone->zonefile, in_name, False);
         still_valid = False;
      }
   }
   return still_valid;
}

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


Boolean check_stmt(hashTable *the_hash, stmt_record *stmt, 
                   char *in_name, zone_record *thezone)
{
/*   printf("checking statement\n");  */
   switch(stmt->stmt_type)
   {
      case STMT_VAR_DECL:  /* a variable declaration */
         break;
   /*      return add_decl(the_hash, stmt->stmt.var_d, in_name, thezone); */

      case STMT_CONST_DECL:  /* a constant declaration */
   /*      return add_const(the_hash, stmt->stmt.const_d, in_name, thezone); */
         break;
      case STMT_FOR_LOOP:    /* a for loop */
         return check_statements(the_hash, stmt->stmt.for_d->for_statements,
                                                       in_name, thezone); 
         break;
      case STMT_WHILE_LOOP:      /* a while loop */
         return check_while(the_hash, stmt->stmt.while_d, in_name, thezone);
         break;
      case STMT_REPEAT_UNTIL:    /* a repeat until loop */
         return check_repeat(the_hash, stmt->stmt.while_d, in_name, thezone);
         break;
      case STMT_IF_THEN:         /* an if then segment */
         return check_if(the_hash, stmt->stmt.if_d, in_name, thezone);
         break;
      case STMT_BLOCK:           /* a begin end block */
         return check_statements(the_hash, stmt->stmt.block_d->block_statements,
                                                       in_name, thezone); 
         break;
      case STMT_RAW_CODE:        /* actual raw C code */ 
         break;
      case STMT_IDENT:
      case STMT_MUD_DEFINED:     /* mudcode defined in the mudcode.lib file */
         return check_defined(the_hash, stmt, in_name, thezone);
         break;
      case STMT_ASSIGNMT:
         return check_assignmt(the_hash, stmt, in_name, thezone);
         break;
      default:
         printf("BAD ERROR ENCOUNTERED!!! ARGH!!! SAVE YOURSELVES!!!\n");
         return False;
   }
   return True;
}
/********************************************************************************
 **
 ** check_statements
 **
 ** Parameters: filename - the filename string to open
 **
 ** ret - returns a zone record with all zone data stored in it or attached to it
 **
 ********************************************************************************/


Boolean check_statements(hashTable *the_hash, stmt_list_record *stmts, 
                        char *in_name, zone_record *thezone)
{
   stmt_list_record *tmp_stmt;
   stmt_list_record *last_stmt;
   Boolean          still_good = True;
   string_record    *tmp_str;
   string_record    *prev_str;  

   tmp_stmt = stmts;   
   
   last_stmt = NULL;
   while (tmp_stmt != NULL)
   {
      if (tmp_stmt->the_statement == NULL)
      {
         xfree(tmp_stmt,REC_STMTLIST);
         if (last_stmt != NULL)
            last_stmt->more_statements = NULL;
         return still_good;
      }

      still_good = still_good && check_stmt(the_hash, tmp_stmt->the_statement,
                                            in_name, thezone);

      last_stmt = tmp_stmt;
      tmp_stmt = tmp_stmt->more_statements;
   }
   tmp_str = var_list;

   /* remove declarations from the hash table */
   while (tmp_str != NULL)
   {
      deleteHashRecord(tmp_str->the_string, the_hash);
      prev_str = tmp_str;
      tmp_str = tmp_str->nextstr;
      xfree(prev_str,REC_STRING);
   }

   return still_good;
}

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

Boolean check_code(hashTable *the_hash, trap_record *the_traps,
                                        char *in_name, zone_record *thezone)
{
   trap_record    *tmp_trap;
   Boolean        still_good = True;
   char          errstr[80];

   tmp_trap = the_traps;

   if ((the_traps != NULL) && (the_traps->trap_verb->trap_location[0] != '\0'))
   {
      if (!verify_item(the_hash, the_traps->trap_verb->trap_location, 
                                                 thezone->zonename, "trap"))
      {
         sprintf(errstr, "Unknown extern pointer, trap %s does not exist",
                                  the_traps->trap_verb->trap_location);
         sem_error(errstr, thezone->zonename, in_name, False);
         still_good = False;
      }
   }

   while (tmp_trap != NULL)
   {

      still_good = still_good && check_statements(the_hash, 
                                  the_traps->the_statements, in_name, thezone);
      tmp_trap = tmp_trap->more_traps;
   }

   if (!still_good)
   { 
       sem_error("Error in code",thezone->zonename,in_name, False);
   }
   return still_good;
}


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

Boolean check_locations(hashTable *the_hash, location_record *theloc, zone_record *thezone)
{
   Boolean         still_valid = True;  /* if the location is still valid */
   location_record *loc_ptr;
   char            error[80];

   loc_ptr = theloc;

   strcpy(thetype, "location");

   while (loc_ptr != NULL)
   {
      if (loc_ptr->north != NULL)
      {
         if (!verify_item(the_hash, loc_ptr->north, thezone->zonename, "loc"))
         {
            sprintf(error, "Location %s not defined, located in north decl.", loc_ptr->north);
            sem_error(error, thezone->zonefile, loc_ptr->name, False);
            still_valid = False;
         }
      }

      if (loc_ptr->south != NULL)
      {
         if (!verify_item(the_hash, loc_ptr->south, thezone->zonename, "loc"))
         {
            sprintf(error, "Location %s not defined, located in south decl.", 
                                                                          loc_ptr->south);
            sem_error(error, thezone->zonefile, loc_ptr->name, False);
            still_valid = False;
         }
      }
 
      if (loc_ptr->east != NULL)
      {
         if (!verify_item(the_hash, loc_ptr->east, thezone->zonename, "loc"))
         {
            sprintf(error, "Location %s not defined, located in east decl", 
                                                                    loc_ptr->east);
            sem_error(error, thezone->zonefile, loc_ptr->name, False);
            still_valid = False;
         }
      }
      if (loc_ptr->west != NULL)
      {
         if (!verify_item(the_hash, loc_ptr->west, thezone->zonename, "loc"))
         {
            sprintf(error, "Location %s not defined, located in west decl.", 
                                                                     loc_ptr->west);
            sem_error(error, thezone->zonefile, loc_ptr->name, False);
            still_valid = False;
         }
      }
      if (loc_ptr->up != NULL)
      {
         if (!verify_item(the_hash, loc_ptr->up, thezone->zonename, "loc"))
         {
            sprintf(error, "Location %s not defined, located in up decl.", 
                                                                    loc_ptr->up);
            sem_error(error, thezone->zonefile, loc_ptr->name, False);
            still_valid = False;
         }
      }
      if (loc_ptr->down != NULL)
      {
         if (!verify_item(the_hash, loc_ptr->down, thezone->zonename, "loc"))
         {
            sprintf(error, "Location %s not defined, located in down decl.", 
                                                                 loc_ptr->down);
            sem_error(error, thezone->zonefile, loc_ptr->name, False);
            still_valid = False;
         }
      }
      if (loc_ptr->northeast != NULL)
      {
         if (!verify_item(the_hash, loc_ptr->northeast, thezone->zonename, "loc"))
         {
            sprintf(error, "Location %s not defined, located in northeast decl.", 
                                                                        loc_ptr->northeast);
            sem_error(error, thezone->zonefile, loc_ptr->name, False);
            still_valid = False;
         }
      }
      if (loc_ptr->northwest != NULL)
      {
         if (!verify_item(the_hash, loc_ptr->northwest, thezone->zonename, "loc"))
         {
            sprintf(error, "Location %s not defined, located in northwest decl.", 
                                                                loc_ptr->northwest);
            sem_error(error, thezone->zonefile, loc_ptr->name, False);
            still_valid = False;
         }
      }
      if (loc_ptr->southeast != NULL)
      {
         if (!verify_item(the_hash, loc_ptr->southeast, thezone->zonename, "loc"))
         {
            sprintf(error, "Location %s not defined, located in southeast decl.", 
                                                           loc_ptr->southeast);
            sem_error(error, thezone->zonefile, loc_ptr->name, False);
            still_valid = False;
         }
      }
      if (loc_ptr->southwest != NULL)
      {
         if (!verify_item(the_hash, loc_ptr->southwest, thezone->zonename, "loc"))
         {
            sprintf(error, "Location %s not defined, located in southwest.", 
                                                                loc_ptr->southwest);
            sem_error(error, thezone->zonefile, loc_ptr->name, False);
            still_valid = False;
         }
      }

      still_valid = still_valid && check_code(the_hash, loc_ptr->loc_code, 
                                             loc_ptr->name, thezone); 

      loc_ptr = loc_ptr->next_loc;
   }
   return still_valid;   
}

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

Boolean check_objects(hashTable *the_hash, object_record *theobj, zone_record *thezone)
{
   Boolean         still_valid = True;  /* if the location is still valid */
   object_record   *obj_ptr;
   char            error[80];
   loc_str_record  *locptr;

   obj_ptr = theobj;

   strcpy(thetype, "object");

   while (obj_ptr != NULL)
   {
      locptr = obj_ptr->location;
      while (locptr != NULL)
      {
         if (!verify_location(the_hash, locptr, thezone))
         {
            sprintf(error, "Location %s not defined.", locptr->the_loc);
            sem_error(error, thezone->zonefile, obj_ptr->oname, False);
            still_valid = False;
         }
         locptr = locptr->nextloc;
      }
  
      if (obj_ptr->name == NULL)
      {   if (!verify_gamename(obj_ptr->oname)) 
          {   sprintf(error,"Object has an invalid gamename: %s.",obj_ptr->oname);
              sem_error(error,thezone->zonefile, obj_ptr->oname, False);
              still_valid = False;
          }
      }
      else if (!verify_gamename(obj_ptr->name))
      {   sprintf(error,"Object has an invalid gamename: %s.",obj_ptr->name);
          sem_error(error,thezone->zonefile, obj_ptr->oname, False);
          still_valid = False;
      }
     
      if (obj_ptr->altname != NULL)
      {   if (!verify_gamename(obj_ptr->altname))
          {   sprintf(error,"Object has an invalid gamename: %s.",obj_ptr->altname);
              sem_error(error,thezone->zonefile, obj_ptr->oname, False);
              still_valid = False;
          }
      }
 
      if (obj_ptr->linked != NULL)
      {
         if (!verify_item(the_hash, obj_ptr->linked, thezone->zonename, "obj"))
         {
            sprintf(error, "object %s not defined, located in linked.", 
                                                                obj_ptr->linked);
            sem_error(error, thezone->zonefile, obj_ptr->oname, False);
            still_valid = False;
         }
      }

#if 0
      /* Check to see if the current state is allowed considering the maxstate.
       * For very strict checking yes, for the mud.. no ;)
       */
      if (obj_ptr->state > obj_ptr->maxstate)
      {
         sprintf(error, "object state %d greater than maxstate %d", 
                                            obj_ptr->state, obj_ptr->maxstate);
         sem_error(error, thezone->zonefile, obj_ptr->oname, False);
         still_valid = False;
      }
#endif

      if (obj_ptr->basevalue > MAX_OBJ_BASEVALUE)
      {
         sprintf(error, "Warning: basevalue is %d", obj_ptr->basevalue);
         sem_error(error, thezone->zonefile, obj_ptr->oname, True);
      }

      if (obj_ptr->maxstate > MAX_OBJ_MAXSTATE)
      {
         sprintf(error, "Warning: maxstate is %d", obj_ptr->maxstate);
         sem_error(error, thezone->zonefile, obj_ptr->oname, True);
      }

      if (obj_ptr->armor > MAX_OBJ_ARMOR)
      {
         sprintf(error, "Warning: armor is %d", obj_ptr->armor);
         sem_error(error, thezone->zonefile, obj_ptr->oname, True);
      }

      if (obj_ptr->damage > MAX_OBJ_DAMAGE)
      {
         sprintf(error, "Warning: damage is %d", obj_ptr->damage);
         sem_error(error, thezone->zonefile, obj_ptr->oname, True);
      }

      if (obj_ptr->weight > MAX_OBJ_WEIGHT)
      {
         sprintf(error, "Warning: weight is %d", obj_ptr->basevalue);
         sem_error(error, thezone->zonefile, obj_ptr->oname, True);
      }


      still_valid = still_valid && check_code(the_hash, obj_ptr->obj_code, 
                                             obj_ptr->oname, thezone); 
      
      obj_ptr = obj_ptr->next_obj;
   }
   return still_valid;
}

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

Boolean check_mobiles(hashTable *the_hash, mobile_record *themob, zone_record *thezone)
{
   Boolean         still_valid = True;  /* if the location is still valid */
   mobile_record   *mob_ptr;
   char            error[80];
   loc_str_record  *locptr;

   mob_ptr = themob;

   strcpy(thetype, "mobile");

   while (mob_ptr != NULL)
   {
      locptr = mob_ptr->location;
      while (locptr != NULL)
      {
         if (!verify_location(the_hash, locptr, thezone))
         {
            sprintf(error, "Location %s not defined.", locptr->the_loc);
            sem_error(error, thezone->zonefile, mob_ptr->mname, False);
            still_valid = False;
         }
         locptr = locptr->nextloc;
      }



      if (mob_ptr->strength > MAX_MOB_STRENGTH)
      {
         sprintf(error, "Warning: strength is %d", mob_ptr->strength);
         sem_error(error, thezone->zonefile, mob_ptr->mname, True);
      }

      if (mob_ptr->damage > MAX_MOB_DAMAGE)
      {
         sprintf(error, "Warning: damage is %d", mob_ptr->damage);
         sem_error(error, thezone->zonefile, mob_ptr->mname, True);
      }

      if (mob_ptr->armor > MAX_MOB_ARMOR)
      {
         sprintf(error, "Warning: armor is %d", mob_ptr->armor);
         sem_error(error, thezone->zonefile, mob_ptr->mname ,True);
      }

      still_valid = still_valid && check_code(the_hash, mob_ptr->mob_code, 
                                             mob_ptr->mname, thezone); 
      
      mob_ptr = mob_ptr->next_mob;
   }
   return still_valid;
}



/*********************************************************************************
 **                          MAIN SEMANTIC CHECK FUNCTION
 ********************************************************************************/

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

Boolean semantic_check(hashTable *the_hash, zone_record *thezone)
{
   Boolean     is_good = True; /* stores if the zones are still good */
   zone_record *zone_ptr;      /* used to move along zones */
   
   zone_ptr = thezone;
   while (zone_ptr != NULL)
   {
      if (!(check_locations(the_hash, zone_ptr->location_data, zone_ptr) &&
            check_objects(the_hash, zone_ptr->object_data, zone_ptr) &&
            check_mobiles(the_hash, zone_ptr->mobile_data, zone_ptr)))
      {  printf("Error occured in zone %s\n",zone_ptr->zonename);
         is_good = False;
      }
      zone_ptr = zone_ptr->next_zone;
   }
   return is_good;
}