#include "gcomm.h"
#include "cmdargs.h"

#define FILREV "$Revision: 1 $"

CmdArgs::CmdArgs(VOID)         //  Constructor
{
     m_stgarg=NULL;
     m_chars=NULL;
     argv=NULL;
     argc=0;
     m_CharCount=0;
     m_Inited=Setup();
}

CmdArgs::~CmdArgs(VOID)        //  Destructor
{
     if (m_stgarg != NULL) {
          free(m_stgarg);
          m_stgarg=NULL;
     }
     Freeargs();
}

GBOOL
CmdArgs::Setup(VOID)             //  Initialize variables
{
     for (UINT count=0; count < _argc; count ++) {
          if (_argv[count][0] == '@') {
               if (!AddArgFile(_argv[count]+1)) {
                    return(FALSE);
               }
          }
          else {
               AddArg(_argv[count]);
          }
     }
     return(TRUE);
}

GBOOL
CmdArgs::Initialized(VOID)         //  everything initialized?
{
     return(m_Inited);
}

GBOOL
CmdArgs::AddArgFile(             //  Add an argument file
const CHAR *FileName)              //  Filename to add
{
     FILE *fdat;
     CHAR *data;
     struct ffblk fb;

     if (!fnd1st(&fb,FileName,0)) {
          return(FALSE);
     }
     if ((fdat=fopen(FileName,FOPRA)) == NULL) {
          return(FALSE);
     }
     data=(CHAR*)alczer(fb.ff_fsize+1);
     fread(data,fb.ff_fsize,1,fdat);
     fclose(fdat);
     AddArg(data);
     free(data);
     return(TRUE);
}

VOID
CmdArgs::Parse(VOID)             //  Parse the m_stgarg string
{
     Freeargs();
     ParseInput(m_stgarg,NULL,NULL,&argc,&m_CharCount);

     argv=(CHAR**)alczer(argc*sizeof(CHAR *));
     m_chars=(CHAR*)alczer(m_CharCount);

     ParseInput(m_stgarg,argv,m_chars,&argc,&m_CharCount);
}

VOID
CmdArgs::Freeargs(VOID)          //  Free up argv && m_chars
{
     argc=0;
     m_CharCount=0;

     if (argv != NULL) {
          free(argv);
          argv=NULL;
     }
     if (m_chars != NULL) {
          free(m_chars);
          m_chars=NULL;
     }
}

VOID
CmdArgs::AddArg(                 //  Add an argument
const CHAR *arg)                   //  Argument to add
{
     size_t oldsize=0;

     if (m_stgarg != NULL) {
          oldsize=strlen(m_stgarg)+1;
     }

     ASSERT(arg != NULL);
     m_stgarg=(CHAR*)alcrsz(m_stgarg,oldsize,oldsize+strlen(arg)+1);
     if (oldsize == 0) {
          setmem(m_stgarg,oldsize+strlen(arg)+1,0);
     }
     strcat(m_stgarg," ");
     strcat(m_stgarg,arg);
     Parse();
}

VOID
CmdArgs::ParseInput(     //   Parse input buffer for arguments
const CHAR *pszInput,    // Input buffer to parse
CHAR **argv,             // Argument vector which points to args
CHAR *args,              // Pointer to argument input string
INT *iArgCount,          // Pointer to argument counter
INT *iCharCount)         // Pointer to character counter
{
     const CHAR *pszIterator;
     bool bInQuotes;
     bool bCopyChars;
     UINT uiSlashCount;

     *iCharCount=0;
     *iArgCount=0;

     pszIterator=pszInput;
     bInQuotes=false;
     for(;;) {
          if (*pszIterator) {
               while (isspace(*pszIterator)) {
                    ++pszIterator;
               }
          }
          if (*pszIterator == '\0') {
               break;
          }
          if (argv) {
               *argv++=args;
          }
          ++*iArgCount;
          for (;;) {
               bCopyChars=true;
               uiSlashCount=0;
               while (*pszIterator == '\\') {
                    ++uiSlashCount;
                    ++pszIterator;
               }
               if (*pszIterator == '\"') {
                    if ((uiSlashCount%2) == 0) {
                         if (bInQuotes) {
                              if (*(pszIterator+1) == '\"') {
                                   pszIterator++;
                              }
                              else {
                                   bCopyChars=false;
                              }
                         }
                         else {
                              bCopyChars=false;
                         }
                         bInQuotes=!bInQuotes;
                    }
                    uiSlashCount/=2;
               }
               while (uiSlashCount--) {
                    if (args) {
                         *args++='\\';
                    }
                    ++*iCharCount;
               }
               if ((*pszIterator == '\0') || (!bInQuotes && isspace(*pszIterator))) {
                    break;
               }
               if (bCopyChars) {
                    if (args) {
                         *args++=*pszIterator;
                    }
                    ++*iCharCount;
               }
               ++pszIterator;
          }
          if (args) {
               *args++='\0';
          }    
          ++*iCharCount;
     }
}

