/*---------------------------------------------------------------------------

	Splitter:  a module to break a line in a list of words,
	therby determinig type and storing results in a List.
	
	Mark Koennecke October 1996
	
	Free for non commercial use, no warranties of any kind taken.
---------------------------------------------------------------------------*/
#include "fortify.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "splitter.h"

typedef enum _CharType {eSpace, eNum,eeText,eQuote} CharType; 


/* ------------------------ local prototypes ------------------------------*/

	static TokenList *CreateToken(TokenList *pN, TokenList *P);
	static CharType     CheckSpecial(char *pWord);
	static int isEnd(char c);
	
/*=========================================================================*/

        static TokenList *CreateToken(TokenList *pN, TokenList *pP)
        {
                TokenList *pRes = NULL;
		
                pRes = (TokenList *) malloc(sizeof(TokenList));
                if(!pRes)return NULL;
		
                pRes->fVal = .0;
                pRes->iVal = 0;
                pRes->Type = eUndefined;
                pRes->text = NULL;
                pRes->pNext = pN;
                if(pN)
                {
                    pN->pPrevious = pRes;
                }
                pRes->pPrevious = pP;
                if(pP)
                {
                    pP->pNext = pRes;
                }
                return pRes;
        }
/*---------------------------------------------------------------------------*/

       static CharType CheckSpecial(char *pWord)
       {
           CharType eRes = eText;
           int iFlag = 0;
		
	   if(isspace(pWord[0]))return(eSpace);
	   if(isdigit(pWord[0]))return(eNum);

	/* simple cases */
           if(pWord[0] == '*') return(eeText);
           if(pWord[0] == '/') return(eeText);
           if(pWord[0] == '\\') return(eeText);
           if(pWord[0] == ']') return(eeText);
           if(pWord[0] == '[') return(eeText);
           if(pWord[0] == '"') return(eQuote);

	/* difficult cases, next characters will be searched for decision*/

           if( pWord[0] == '-') iFlag = 1;
           if( pWord[0] == '+') iFlag = 1;
           if( pWord[0] == '.') iFlag = 1;
	
            if (iFlag == 1)
	    {

                 if( isdigit(pWord[1]) )
                 {
                       return(eNum);
                 }
                 else if( isalpha(pWord[1] ))
                 {
                       return(eeText);
                 }
                 else if (!isspace( pWord[1]) )
		 {
		       pWord++;
                       return(CheckSpecial(pWord));
                 }
            }

            return(eeText);
	} 
/*--------------------------------------------------------------------------*/
        static int isEnd(char c)
        {
        	if( (c == '\0') || (c == '\n') || (c == '\r') )
        	{
        	   return 2;
        	}
        	else if ( c== ' ')
        	{
        		return 1;
        	}
        	else
        	{
        		return 0;
        	}
        }
/*--------------------------------------------------------------------------*/

        TokenList *SplitText(char *pLine)
        {
           TokenList *pList = NULL;
	   TokenList *pCurrent;	
           char pBueffel[132];
           char *pChar;
           CharType eWhat;
           int i;
           
           if(!pLine)return NULL;
           
           pChar = pLine;

        /* loop through line */ 
	   while(isEnd(*pChar) != 2)
	   {
	     
	      eWhat = CheckSpecial(pChar);
	      
	      /* skip spaces */
	      if (eWhat == eSpace)
	      {
	          pChar++;
	          continue;
	      } 
	      
	      /* no space, read word in first place */
	      if(eWhat == eQuote)
	      {
	        i = 0;
	        pChar++;
	        while( (isEnd(*pChar) != 2) && (CheckSpecial(pChar) != eQuote))
	        {
	         pBueffel[i] = *pChar;
	         i++;
	         pChar++;
	        }
	        pBueffel[i] = '\0';
	        pChar++;
                eWhat = eeText;
	      }
	      else
	      {
                i = 0;	
                while(!isEnd(*pChar))
                {
	          pBueffel[i] = *pChar;
	          i++;
	          pChar++;
	        }
	        pBueffel[i] = '\0';
	      }
	      if(pList == NULL)
	      {
	         pList = CreateToken(NULL,NULL);
	         pCurrent = pList;
	      }
	      else
	      {
	      	pCurrent = CreateToken(NULL,pCurrent);
	      }   
	      if(!pCurrent) return NULL;

              /* copyy text always */
              pCurrent->text = strdup(pBueffel);
	      if(eWhat == eeText)
	      {
	         pCurrent->Type = eText;
	      }
	      else if(eWhat == eNum)
	      {
	         /* float ? */
                 if(strchr(pBueffel,'.')== NULL)
                 {
                 	pCurrent->Type = eInt;
                 	sscanf(pBueffel,"%ld",&(pCurrent->iVal));
                 }
                 else
                 {
                 	pCurrent->Type = eFloat;
                 	sscanf(pBueffel,"%f",&(pCurrent->fVal));
                 }
	      }
/*	      pChar++;*/	      if(isEnd(*pChar) == 2)break;
	   } /* eof big while */
	   return pList;
	
        }	
/*--------------------------------------------------------------------------*/
        void DeleteTokenList(TokenList *pToken)
        {
           TokenList *pCurrent;
           TokenList *pTemp;
           
           pCurrent = pToken;
           while(pCurrent != NULL)
           {
             pTemp = pCurrent->pNext;
             if(pCurrent->text)
             {
                free(pCurrent->text);
             }
             free(pCurrent);
             pCurrent = pTemp;
           }
        }
/*--------------------------------------------------------------------------*/
   TokenList *SplitArguments(int argc, char *argv[])
   {
      int i, ii;
      TokenList *pList = NULL;
      TokenList *pCurrent;
      CharType eWhat;
      
      /* loop through arguments */
      for( i = 0; i < argc; i++)
      {
        /* figure out what we have */
        for(ii = 0; ii < strlen(argv[i]); ii++)
        {
            eWhat = CheckSpecial(argv[i]);
          
            /* skip whitespace */
            if(eWhat == eSpace)
            {
	        continue;
            }
          
            /* Create Token */
            if(pList == NULL)
            {
               pList = CreateToken(NULL, pList);
               pCurrent = pList;
            }
            else
            {
          	  pCurrent = CreateToken(NULL,pCurrent);
            }
            if(!pCurrent)
                 return NULL;

	    /* copy text always */
	    pCurrent->text = strdup(argv[i]);		                

            /* text */
            if(eWhat == eeText)
            {
         	  pCurrent->Type = eText;
         	  break;
            } 
         
            /* numbers */
            if(eWhat == eNum)
            {
                   /*  float ? */
                   if(strchr(argv[i],'.')== NULL)
                   {
                 	pCurrent->Type = eInt;
/*                 	sscanf(argv[i],"%d",&(pCurrent->iVal));
*/                      pCurrent->iVal = atoi(argv[i]); 
                   }
                   else
                   {
                 	pCurrent->Type = eFloat;
                 	sscanf(argv[i],"%f",&(pCurrent->fVal));
                   }
                   break;
            }
        }
      }
      return pList;
   }
/*--------------------------------------------------------------------------*/
   int Text2Arg(char *pLine, int *argc, char **argv[])
   {
      TokenList *pList = NULL;
      TokenList *pCurrent = NULL;
      char **margv = NULL;
      int margc = 0;
      int i = 0;
      
      /* split to a TokenList */
      pList = SplitText(pLine);
      if(!pList)
      {
        return 0;
      }       
      
      /* figure out how many args */
      pCurrent = pList;
      while(pCurrent)
      {
        margc++;
        pCurrent = pCurrent->pNext;
      }
      
      /* allocate memory */
      margv = (char **)malloc((margc + 2) * sizeof(char *));
      if(!margv)
      {
      	DeleteTokenList(pList);
      	return 0;
      }
      
      /* copy to argc, argv */
      *argc = margc;
      pCurrent = pList;
      i = 0;
      while(pCurrent)
      {
        margv[i] = strdup(pCurrent->text);
        i++;
        pCurrent = pCurrent->pNext;
      }
      
      /* done, clean up etc */
      margv[i] = NULL;
      *argv = margv;
      DeleteTokenList(pList);
      return 1;
      
   }
/*---------------------------------------------------------------------------*/
  int Arg2Text(int argc, char *argv[], char *buf, int iBufLen)
  {
     int i, iBufCount = 0;
     
     if(argc < 1)
     {
       strcpy(buf,"\0");
       return 1;
     }
     if(strlen(argv[0]) < iBufLen)
     {
         strcpy(buf, argv[0]);
         iBufCount += strlen(argv[0]);
     }
     else 
     {
       return 0;
     }
     
     for(i = 1; i < argc; i++)
     {
       strcat(buf," ");
       iBufCount += strlen(argv[i]) + 1;
       if(iBufCount >= iBufLen)
       {
         return 0;
       }
       else
       {
         strcat(buf,argv[i]);
         /* strcat(buf," "); */
       }
     }
     return 1;
  }
/*--------------------------------------------------------------------------*/
  int GetShellLine(FILE *fd, char *Buffer, int iBufLen)
  {
     char *pChar = NULL;
     
     while(fgets(Buffer,iBufLen-1,fd) != NULL)
     {
       if(Buffer[0] != '#')
       {
         return 1;
       }
     }
     return EOF;
  }   
/*============================================================================

	Testprogram, can be activated by defining MAIN
*/

#ifdef MAIN
	int main(int argc, char *argv[])
	{
	    TokenList *pList = NULL;
	    TokenList *pCurrent;
	    
	    pList = SplitText("Hallo 22 mal 0.8 Furz");
	    pCurrent = pList;
	    while(pCurrent)
	    {
	       if(pCurrent->Type == eText)
	       {
	       	 printf("TextToken = %s\n",pCurrent->text);
	       }
	       else if(pCurrent->Type == eFloat)
	       {
	       	 printf("FloatToken = %f\n",pCurrent->fVal);
	       }
	       else if(pCurrent->Type == eInt)
	       {
	         printf("IntToken = %d\n",pCurrent->iVal);
	       }
	       else
	       {
	       			puts("ERRRRRRRRRROOOOOOOOOOOORRRRRRR!!!!!!!!");
	       }
	       pCurrent = pCurrent->pNext;
	        
	    }
	    DeleteTokenList(pList);
	    
	}
#endif
 
