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/
/*************************************************************************************
 **
 ** pDirt World/Verb/Spell Generation utility
 **
 ** This program was made came about due to great efforts on the part of Slate
 ** (George Noel) and some help by Marty (Peter Eussen). Please be so kind to
 ** give us some credit for this!
 **
 ** Functions provided:
 **            main - the main procedure for the generate program
 **
 **
 *************************************************************************************/
#define GENMAIN_C

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <unistd.h>
#include "gen.h"
#include "semantic.h"
#include "codegen.h"
#include "config.h"
#include "events.h"

#ifdef NOSTRSIGNAL_DEV
char *strsignal(int sig);
#endif

void error_trap(int signal);
void abort_trap(int signal);
void add_zone(zone_record **root, zone_record *addition);
void set_signals();
int  read_area_listfile(char *fn);
void show_usage(char *executable);

static hashTable         *the_hash;
static zone_record       *world = NULL;
static mudcode_record    *mudcode;

Boolean supress_warnings = False;

/*************************************************************************************
 **
 ** main - the main procedure for the generate function
 **
 ** Parameters: argc - the number of arguments
 **             argv - the array of arguments
 **
 *************************************************************************************/

int main(int argc, char *argv[])
{  int            argcount;
   Boolean	  in_error = False;
   Boolean        memstat = False;
   Boolean        worldgen = False;
   Boolean        verbgen = False;
   Boolean        spellgen = False;
   char           *arealist = NULL;
   char           *verbfile = NULL;

   /* Show who made it.. We should be proud of our work ;) */
   printf("\033[1;37mpDirt Area Compiler - (c) 1997/1998 George Noel, Peter Eussen ("GEN_VERSION")\033[40m\033[0m\n");

   /* Initialise global data structures */
   initializeMemStat();
   the_hash = createHashTable(HASHTABLESIZE);

   if (read_configuration("../compiler/mudc.config") < 0)
   {   return 1;
   }
   
   arealist = request_char_value("AREALIST");
   verbfile = request_char_value("VERBFILE");

   /* Check Parameters  */
   if (argc == 1)
   {  show_usage(argv[0]);
      return 0;
   }

   if (request_char_value("AREAS_DIR") != NULL)
   {    if (chdir(request_char_value("AREAS_DIR")) < 0)
        {  perror("Unable to switch to areas directory");
           return 1;
        }
   }

   mudcode = load_mudcode();
   if (mudcode == NULL)
      return 1;

   if (load_events(request_char_value("EVENTS_LIBRARY")) < 0)
   {   return 1;
   }
   set_signals();

   /*printf("%ld memory used by global data structures.\n",mem_usage);*/

   for (argcount = 1; argcount < argc && !in_error; argcount++)
   {   if (strncasecmp(argv[argcount],"-world",strlen(argv[argcount])) == 0)
           worldgen = True;
       else if (strncasecmp(argv[argcount],"-verbs",strlen(argv[argcount])) == 0)
           verbgen = True;
       else if (strncasecmp(argv[argcount],"-spells",strlen(argv[argcount])) == 0)
           spellgen = True;
       else if (strncasecmp(argv[argcount],"-memstat",strlen(argv[argcount])) == 0)
           memstat = True;
       else if (strncasecmp(argv[argcount],"-help",strlen(argv[argcount])) == 0)
       {   show_usage(argv[0]);
           return 0;
       }
       else if (strncasecmp(argv[argcount],"-file",strlen(argv[argcount])) == 0)
       {   zone_record *zon;

           if (++argcount >= argc)
           {   printf("Missing zone file name.\n");
               return 1;
           }
           printf(" [F] Checking file %s\n",argv[argcount]);
           zon = get_zone(argv[argcount],the_hash,mudcode);
           if (zon != NULL)
           {   if (!semantic_check(the_hash,zon))
               {   printf("     File didnt pass semantic checking.\n");
                   return 0; 
               }
               printf("     Done, file passed semantic checking.\n");
               return 0;
           }
           else
              printf("     The file didnt pass the first phase.\n");
           return 0;
       }
       else if (strncasecmp(argv[argcount],"-ignore",strlen(argv[argcount])) == 0)
           supress_warnings = True;
       else
       {   show_usage(argv[0]);
           return 1;
       }
   }

   
   /* Read Process */
   if (worldgen && arealist != NULL)
   {   printf(" [W] Starting World Generation...\n"); 
       if (read_area_listfile(arealist) == 0)
       {   printf("\n     Checking semantics of the zones.\n");

           /* semantically check zone data trees */
           if (!(semantic_check(the_hash,world)))
           {   printf("Error in semantic check, no code will be generated.\n");
               return 1;
           }
           else
           {   printf("     Generating Database, Include and Code files.\n");
               if (gen_code(the_hash, world) == -1)
               {
                   printf("Eek! Unexpected error generating code. Code may be corrupted.\n");
                   return 1;
               }
            }
       }
       printf("\n");
   }

   if (verbgen)
   {   /* Verb generation */
      printf(" [V] Starting Verbs generation...");
      if (verbfile == NULL)
      {   printf("Verb file not defined in configuration file.\n");
          return 1;
      }
      if (generate_verb_files(verbfile,request_char_value("DATA_DIR")) < 0)
         in_error = True;
   }
   if (spellgen)
   {   /* get spell data and generate code */
       printf(" [S] Starting Spell Table generation...");
       printf("Done.\n");
   }


   /* generate spell code */

   if (in_error)
      printf("Error occured during the read process, aborting compilation.\n");

   /* cleanup */
   if (memstat)
   {   printMemStat();
       printHashTableStatistics(the_hash);
   }
   deleteHashTable(the_hash);
   printf("\nDone.\n");
   return 0;   
}

void show_usage(char *executable)
{    printf("\nUsage: %s [-world] [-verbs] [-spells] [-memstat] [-file <filename>]\n\n"
            "       -world  : Generate new world database & code files.\n"
            "       -verbs  : Generate new verbs file and include file.\n"
            "       -spells : Generate a new spell table file.\n"
            "       -memstat: Create a memory statistic overview.\n"
            "       -file   : Do a check of the specified file only.\n"
            "       -ignore : Ignore semantic check warnings.\n",
            executable);
}

void set_signals()
{   signal(SIGSEGV,error_trap);
    signal(SIGPIPE,error_trap);
    signal(SIGFPE,error_trap);
    signal(SIGBUS,error_trap);
    signal(SIGILL,error_trap);
    signal(SIGTERM,abort_trap);
    signal(SIGINT,abort_trap);
    signal(SIGABRT,abort_trap);
    signal(SIGTRAP,SIG_DFL);
    signal(SIGCHLD,SIG_IGN);
}

void error_trap(int sig)
{    extern int theline;
     extern char thezonenam[MAXNAMLEN];

     printf("\n\bAn unrecoverable error occured while compiling, causing the following error\n"
            "to occur: the compiler received the signal[%d] - %s\n",sig,(char *)strsignal(sig));

     printf("\n\nDumping debugging information.\n"
            "Zone file name         : %s\n" 
            "Zone file line number  : %d\n\n"
            "Current Location number: %d\n"
            "Current Mobile number  : %d\n"
            "Current Object number  : %d\n\n"
            "Total Memory usage     : %ld\n",
	    thezonenam,theline,cur_loc,cur_mob,cur_obj,mem_usage);
     exit(sig);
}

void abort_trap(int sig)
{    printf("\nCompiler aborted by user (signal[%d]: %s).\n",sig,(char *)strsignal(sig));
     exit(sig);
}

void add_zone(zone_record **root, zone_record *addition)
{   if (*root == NULL)
    {   *root = addition;
        addition->next_zone = NULL;
    }
    else
    {   zone_record *tmp_ptr = *root;

        while (tmp_ptr->next_zone != NULL)
             tmp_ptr = tmp_ptr->next_zone;

        tmp_ptr->next_zone = addition;
        addition->next_zone = NULL;
    }
}

int  read_area_listfile(char *fn)
{   char           argbuffer[120],*p;
    FILE           *fp;
    Boolean        in_error = False;
    zone_record    *the_zone = NULL;

    if ((fp = fopen(fn,"r")) == NULL)
    {   printf("Unable to open listfile %s\n",fn);
        return -1;
    }
         
    printf("     Reading zones from file: %s\n",fn);
 
    fgets(argbuffer,100,fp);
         
    while (!feof(fp) && !in_error)
    {   
         if ((p = strstr(argbuffer,fn_extension)) != NULL)
             *p = '\0'; 

         printf("\r     Reading zone %-16.16s",argbuffer);              
         fflush(stdout); 
         the_zone = get_zone(argbuffer, the_hash, mudcode);

         if (the_zone != NULL)
         {
              add_zone(&world,the_zone);
              num_zones++;
         } 
         else
         {   printf("Nothing found for this zone, or error(s) occured while reading.\n");
             in_error = True;
         } 
  
         fgets(argbuffer,100,fp);
    } 
    fclose(fp);

    if (in_error)
       printf("\nError(s) occured during reading.\n");    
    return in_error ? -1 : 0;
}