#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>

#include <clib/utility_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>

#include <FidoNet.h>

jbNewList(struct jbList *list);
jbAddNode(struct jbList *list, struct jbNode *node);
jbFreeList(struct jbList *list,struct jbNode *firstnode,ULONG sizenode);

ULONG jbcpos;

jbstrcpy(UBYTE *dest,UBYTE *src,ULONG maxlen)
{
   ULONG d=0;
   UBYTE stopchar1,stopchar2;

   while(src[jbcpos]==32 || src[jbcpos]==9) jbcpos++;

   if(src[jbcpos]=='"')
   {
      jbcpos++;
      stopchar1='"';
      stopchar2=0;
   }
   else
   {
   	stopchar1=' ';
   	stopchar2=9;
   }

   while(src[jbcpos]!=stopchar1 && src[jbcpos]!=stopchar2 && src[jbcpos]!=10 && src[jbcpos]!=0 && d<maxlen-1)
   {
      if(src[jbcpos]=='\\' && src[jbcpos+1]!=0 && src[jbcpos+1]!=10)
      {
         jbcpos++;
         dest[d++]=src[jbcpos++];
      }

      else
         dest[d++]=src[jbcpos++];
   }
   dest[d]=0;
   if(src[jbcpos]==9 || src[jbcpos]==' ' || src[jbcpos]=='"') jbcpos++;

   if(d!=0 || stopchar1=='"') return(TRUE);

   return(FALSE);
}

struct jbList
{
   struct jbNode *First;
   struct jbNode *Last;
};

struct jbNode
{
   struct jbNode *Next;
};

#define VERSION "1.1"

UBYTE *ver="$VER: CrashForward "VERSION" ("__COMMODORE_DATE__")";

struct Area
{
   struct Area *Next;
    UBYTE Tagname[80];
   UBYTE Description[80];
   UBYTE Group;
};

struct jbList AreaList;

#define OUTFILE   0
#define GROUP     1
#define NODESC    2
#define SETTINGS  3

ULONG argarray[]={NULL,NULL,NULL,NULL};
UBYTE argstr[]="OUTFILE/A,GROUP,NODESC/S,SETTINGS/K";

struct RDArgs *rdargs;

CleanUp(int err)
{
   if(rdargs) FreeArgs(rdargs);
   jbFreeList(&AreaList,AreaList.First,sizeof(struct Area));
   _exit(err);
}

BOOL CorrectFlags(UBYTE *flags)
{
   ULONG c;

   for(c=0;c<strlen(flags);c++)
   {
      flags[c]=ToUpper(flags[c]);

      if(flags[c]<'A' || flags[c]>'Z')
         return(FALSE);
   }

   return(TRUE);
}

UBYTE cfgbuf[4000];

BOOL ReadConfig(UBYTE *file)
{
   BPTR fh;
   UBYTE cfgword[20];
   UBYTE tag[80];
   UBYTE buf[20];
   struct Area *tmparea,*LastArea;

   if(!(fh=Open(file,MODE_OLDFILE)))
      return(FALSE);

   while(FGets(fh,cfgbuf,4000))
   {
      jbcpos=0;
      jbstrcpy(cfgword,cfgbuf,20);

      if(stricmp(cfgword,"AREA")==0)
      {
         jbstrcpy(tag,cfgbuf,80);

         if(stricmp(tag,"DEFAULT")!=0 && stricmp(tag,"BAD")!=0)
         {
            if(!(tmparea=(struct Area *)AllocMem(sizeof(struct Area),MEMF_CLEAR)))
            {
               Printf("Out of memory\n");
               Close(fh);
               CleanUp(10);
            }

            jbAddNode(&AreaList,(struct jbNode *)tmparea);
            LastArea=tmparea;

            strcpy(tmparea->Tagname,tag);
         }
      }
      else if(stricmp(cfgword,"GROUP")==0 && LastArea)
      {
         if(jbstrcpy(buf,cfgbuf,20) && CorrectFlags(buf))
         {
            LastArea->Group=buf[0];
         }
      }
      else if(stricmp(cfgword,"DESCRIPTION")==0 && LastArea)
      {
         jbstrcpy(LastArea->Description,cfgbuf,80);
      }
    }
   Close(fh);

   return(TRUE);
}

BOOL CheckFlags(UBYTE group,UBYTE *node)
{
   UBYTE c;

   for(c=0;c<strlen(node);c++)
   {
      if(group==ToUpper(node[c]))
         return(TRUE);
    }

   return(FALSE);
}

_main()
{
   struct Area *area;
   BPTR fh;
   BOOL config;

   jbNewList(&AreaList);

   if(!(rdargs=(struct RDArgs *)ReadArgs(argstr,argarray,NULL)))
   {
      PrintFault(IoErr(),NULL);
      CleanUp(10);
   }

   config=FALSE;

   if(argarray[SETTINGS]==NULL)
   {
      if(ReadConfig("PROGDIR:CrashMail.prefs"))
         config=TRUE;

      else if(ReadConfig("MAIL:CrashMail.prefs"))
         config=TRUE;

      if(!config)
      {
         Printf("Couldn't read config file PROGDIR:CrashMail.prefs or MAIL:CrashMail.prefs\n");
         CleanUp(10);
      }
   }
   else
   {
      if(!ReadConfig((UBYTE *)argarray[SETTINGS]))
      {
         Printf("Couldn't read config file %s\n",(long)argarray[SETTINGS]);
         CleanUp(10);
      }
   }

   if(!(fh=Open((UBYTE *)argarray[OUTFILE],MODE_NEWFILE)))
   {
      PrintFault(IoErr(),(UBYTE *)argarray[OUTFILE]);
      CleanUp(10);
   }

   for(area=AreaList.First;area;area=area->Next)
   {
      if(!argarray[GROUP] || CheckFlags(area->Group,(UBYTE *)argarray[GROUP]))
      {
         if(argarray[NODESC]) FPrintf(fh,"%s\n",area->Tagname);
         else                 FPrintf(fh,"%-30s %s\n",area->Tagname,area->Description);
      }
   }

   Close(fh);

   CleanUp(0);
}


