/*
 * CDE - Common Desktop Environment
 *
 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
 *
 * These libraries and programs are free software; you can
 * redistribute them and/or modify them under the terms of the GNU
 * Lesser General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * These libraries and programs are distributed in the hope that
 * they will be useful, but WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE. See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with these libraries and programs; if not, write
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 * Floor, Boston, MA 02110-1301 USA
 */
/* $XConsortium: parser.c /main/8 1996/03/25 09:14:08 rswiston $ */
/***************************************************************************/
/*                                                                         */
/*  parser.c                                                               */
/*                                                                         */
/***************************************************************************/
#ifdef _AIX
#define _ILS_MACRO
#endif /* _AIX */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

#include "dtcreate.h"
#include "parser.h"
#include <ctype.h>

/***************************************************************************
 *
 *  Local procedure declarations
 *
 ***************************************************************************/


char ** GetKeywordValuePairs(char *, int *, int);
FiletypeData ** GetFiletypeData(FILE *, char *, short *);
char ** ProcessExecString(char *);
int ProcessContents(FiletypeData *);
Boolean IsLastSingle(char *);


/***************************************************************************
 *
 *  Extern variable declarations
 *
 ***************************************************************************/


/***************************************************************************
 *
 *  Global variable declarations
 *
 ***************************************************************************/

/* Action Keyword Table */
char keywordDB[][30] = { "ACTION"         ,
                          "ICON"          ,
                          "EXEC_STRING"   ,
                          "DESCRIPTION"   ,
                          "TYPE"          ,
                          "WINDOW_TYPE"   ,
                          "ARG_TYPE"      ,
                          "LABEL"         ,
                          '\0'            ,
                     };

/* Max Number of fields in Action Keyword Table */
#define MAX_NUM_ACTION_FIELDS     8

/* Filetype Keyword Table */
char FiletypekeywordDB[][30] = { "DATA_ATTRIBUTES"       ,
                                  "ICON"                 ,
                                  "DESCRIPTION"          ,
                                  "EXEC_STRING"          ,
                                  "NAME_PATTERN"         ,
                                  "PATH_PATTERN"         ,
                                  "MODE"                 ,
                                  "CONTENT"              ,
                                  "ACTIONS"              ,
                                  "DATA_ATTRIBUTES_NAME" ,
                                  "DATA_CRITERIA"        ,
                                  "WINDOW_TYPE"          ,
                                  "ACTION"               ,
                                  "ARG_TYPE"             ,
                                  "MAP_ACTION"           ,
                                  "TYPE"                 ,
                                  "LABEL"                ,
                                   '\0'                  ,
                     };

/* Max Number of fields in Filetype Keyword Table */
#define MAX_NUM_FILETYPE_FIELDS     17


char *args[3],*fline;
int flinesize=0;
static int state = 0;


/*****************************************************************
**                                                              **
** GetActionData(FILE *fp, ActionData *)                        **
**                                                              **
** Description: Parses the action file and fills the data in the**
**              pointer pointing to the ActionData structure    **
**              passed as input.                                **
**                                                              **
** Input      : Filepointer that points to the ActionFile and,  **
**              a pointer to the ActionData structure.          **
**                                                              **
** Output     : 0 (No error).                                   **
**              1 (error).                                      **
**                                                              **
** references : dtcreate.h, parser.h, and dtcreate spec.        **
**                                                              **
******************************************************************/


int
GetActionData(FILE *fp, ActionData *ActionDataptr)
{
int         rc,manflds=0,len,first=TRUE,lastfld=0,fldid=-1;
char        linebuf[1024],**wordPairs,**execstr;


        /* reset the read pointer to zero byte for fp */
        rewind(fp);
        /* Initialize the ActionData structure passed */
        if(ActionDataptr)
           memset(ActionDataptr,
                       0,sizeof(ActionData));
        else {
#ifdef DEBUG
           printf("ActionDataptr is NULL\n");
#endif
           return 1;
        }

        /* initialize the linebuf with NULL's  */
        bzero(linebuf,sizeof(linebuf));
        while (fgets (linebuf, sizeof (linebuf)-1, fp))
        {
           /* skip the complete line if it starts with a '{' or a comment ('#')  */
           if(linebuf[0] == '{' || linebuf[0] == '#') continue;
           /* If the first character is '}' reached the end of Action Stanza so quit */
           if(linebuf[0] == '}')
              break;
           len = strlen (linebuf);
           if (linebuf[len-1] == '\n')
              linebuf[len-1] = '\0';
           /* Get the keyword and value pair from the string linebuf */
           /* On return, wordPairs[0] = keyword like ICON
              and        wordPairs[1] = value for the keyword
           */
           if( (wordPairs = GetKeywordValuePairs(linebuf,&fldid,ACTION_TABLE)) != NULL)
           {
              if( first && strcmp(wordPairs[0],"ACTION") )
              {
#ifdef DEBUG
                  printf("first && strcmp(wordPairs[0],ACTION)\n");
#endif
                  return 1;
              }
              else
                  first = FALSE;
              /* Update the mandatory fields counter */
              if( !strcmp(wordPairs[0],"TYPE") ||
                  !strcmp(wordPairs[0],"EXEC_STRING") ||
                  !strcmp(wordPairs[0],"WINDOW_TYPE") )
                     manflds++;
              if( !strcmp(wordPairs[0],"WINDOW_TYPE") )
              {
                 if( !strcmp(wordPairs[1],"PERM_TERMINAL") )
                    ActionDataptr->fsFlags |= CA_WT_PERMTERM;
                 if( !strcmp(wordPairs[1],"TERMINAL") )
                    ActionDataptr->fsFlags |= CA_WT_TERM;
                 if( !strcmp(wordPairs[1],"NO_STDIO") )
                    ActionDataptr->fsFlags |= CA_WT_XWINDOWS;
              }
              if( !strcmp(wordPairs[0],"ARG_TYPE") )
                 ActionDataptr->fsFlags |= CA_DF_ONLYFTFILES;

              /* if linebuf does not contain the keyword then everything
              in wordPairs[0],else, wordPairs[0] contains the keyword
              and wordpairs[1] contains the value.
              */
              if( wordPairs && wordPairs[0] && !wordPairs[1])
              {
                 /* fldid is returned by the GetKeywordValuePairs function.
                 This id determines which field of the ActionDataptr will
                 have the value. Please see KeywordDB array in parser.h
                 for more details.
                 */
                 switch(fldid)
                 {
                     case 7:   /* next line for action_name */
                               ActionDataptr->pszName=wordPairs[0];
                               break;

                     case 1:   /* next line for action_icon_name */
                               ActionDataptr->pszIcon=wordPairs[0];
                               break;

                     case 2 :  /* next line for exec_string */
                               ActionDataptr->pszCmd=wordPairs[0];
                               break;

                     case 3:   /* next line for action_help_text */
                               ActionDataptr->pszHelp=wordPairs[0];
                               break;

                    default:   break;
                 }
             }
             else if(wordPairs && wordPairs[1])
             {
                 if(fldid >= 0 && fldid <=2)
                        state = 0;
                 /* for fldid see the comments above */
                 switch(fldid)
                 {
                     case 7:   /* first line for action_name */
                               ActionDataptr->pszName=wordPairs[1];
                               break;

                     case 1:   /* first line for action_icon_name */
                               ActionDataptr->pszIcon=wordPairs[1];
                               break;

                     case 2 :  /* first line for exec_string */
                               ActionDataptr->pszCmd=wordPairs[1];
                               break;

                     case 3:   /* first line for action_help_text */
                               state = HELP_TEXT;
                               ActionDataptr->pszHelp=wordPairs[1];
                               break;

                    default:   state=0;break;
                 }

              }
              /* reset the linebuf to NULL's */
              bzero(linebuf,sizeof(linebuf));
          }
        }

        state=0;
        /* Done with retrieving Action Data */
        /* Check if we got all the mandatory fields data */
        if(manflds != 3) {
#ifdef DEBUG
            printf("if(manflds != 3)\n");
#endif
            return 1;
        } else
        {
            /* Everything looks right so process the exec_string */
            if( !(execstr = ProcessExecString(ActionDataptr->pszCmd)) )
            {
                ActionDataptr->pszCmd = NULL;
                ActionDataptr->pszPrompt = 0;
            }
            else
            {
                ActionDataptr->pszCmd = execstr[0];
                ActionDataptr->pszPrompt = execstr[1];
                free(execstr);
            }
            /* Got the ActionData,so, go get the FiletypeData */
            ActionDataptr->papFiletypes =
                        (FiletypeData **) GetFiletypeData(fp,(char *)(ActionDataptr->pszCmd),
                                                         (short *)&(ActionDataptr->cFiletypes) );
            if( !ActionDataptr->papFiletypes && ActionDataptr->cFiletypes > 0) {
#ifdef DEBUG
                 printf("!ActionDataptr->papFiletypes && ActionDataptr->cFiletypes > 0)\n");
#endif
                 return(1);  /* return 1 if error */
            } else
                 return(0);  /* return 0 if no error */
        }


}

/*****************************************************************
**                                                              **
** GetFiletypeData(FILE *fp, char *pszOpenCmd)                  **
**                                                              **
** Description: Parses the action file and returns a pointer    **
**              that points to the data in the form of          **
**              FiletypeData structure (defined in dtcreate.h). **
**                                                              **
** Input      : Filepointer that points to the ActionFile, and, **
**              a char pointer to the exec_string of the        **
**              ActionData structure as obtained in the GetAc-  **
**              -tionData function call.                        **
**                                                              **
** Output     : Pointer to an array of FiletypeData structures  **
**              containing data for all the Filetypes,and,no of **
**              file types.                                     **
**                                                              **
** references : dtcreate.h, parser.h, and dtcreate spec.        **
**                                                              **
******************************************************************/

FiletypeData **
GetFiletypeData(FILE  *fp, char *pszOpenCmd, short *nftypes)
{
int         manflds=0,len,nfiletypes,previous=0,lastfld=0,fldid;
char        linebuf[1024],**wordPairs,**execstr;
FiletypeData  **ppFiletypeData,**ppnewFiletypeData;

        wordPairs=0;
        ppFiletypeData=0;
        nfiletypes=0;

        /* Initialize the linebuf */
        bzero(linebuf,sizeof(linebuf));
        while (fgets (linebuf, sizeof (linebuf)-1, fp))
        {
           /* If begin of a stanza skip and continue */
           if(linebuf[0] == '{')
           {
               continue;
           }

           /* skip the rest of the line if a comment found */
           if(linebuf[0] == '#') continue;

           /* If end of a stanza check if all the mandatory fields are there */
           if( linebuf[0] == '}' )
           {
               /* Check for atleast one field in DATA_ATTRIBUTES stanza */
               if( previous == DATA_ATTRIBUTES && manflds != 1 )
               {
                   printf("Error in DATA_ATTR stanza of the FiletypeData\n");
                   return NULL;
               }
               /* Check for atleast one field in DATA_CRITERIA stanza */
               else if( previous == DATA_CRITERIA && manflds != 1 )
               {
                   printf("Error in DATA_CRITERIA stanza of the FiletypeData\n");
                   return NULL;
               }
               /* Check for atleast two fields in ACTION_OPEN or ACTION_PRINT stanza */
               else if( (previous == ACTION_OPEN || previous == ACTION_PRINT) )
               {
                   if( manflds != 4)
                   {
                      printf("Error in ACTION_OPEN/PRINT stanza of the FiletypeData\n");
                      return NULL;
                   }
               }
               /* Check for atleast three fields in ACTION_PRINT_FTYPE stanza */
               else if( previous == ACTION_PRINT_FTYPE && manflds != 3 )
               {
                   printf("Error in ACTION_PRINT_FTYPE stanza of the FiletypeData\n");
                   return NULL;
               }
               continue;
           }
           len = strlen (linebuf);
           if (linebuf[len-1] == '\n')
              linebuf[len-1] = '\0';

           if( (wordPairs = GetKeywordValuePairs(linebuf,&fldid,FILETYPE_TABLE)) != NULL)
           {
              if( !strcmp(wordPairs[0],"DATA_ATTRIBUTES") )
              {
                /* first filetype */
                if( previous == 0 )
                {
                     /* Allocate a filetypedata pointer to an array of filetypedata records   */
                     if( !ppFiletypeData)
                     {
                         if( (ppFiletypeData = (FiletypeData **)calloc(1,sizeof(FiletypeData *)))
                                                  == NULL )
                         {
                                 printf("\n Cannot allocate memory\n");
                                 return NULL;
                         }
                         /* Allocate a filetypedata record   */
                         else
                         {
                                 if( (ppFiletypeData[nfiletypes] =
                                 (FiletypeData *)calloc(1,sizeof(FiletypeData)) )
                                                   == NULL )
                                 {
                                       printf("\n Cannot allocate memory\n");
                                       return NULL;
                                 }
                          }
                     }

                     ppFiletypeData[nfiletypes]->pszOpenCmd = pszOpenCmd;
                     previous = DATA_ATTRIBUTES;
                     manflds=0;
                }
                else if(previous == ACTION_OPEN || previous == ACTION_PRINT)
                {
                     /* New filetypedata started so allocate a new filetypedata ptr */
                     if( (ppnewFiletypeData =
                        (FiletypeData **)realloc((FiletypeData *)ppFiletypeData,
                        nfiletypes+2 * sizeof(FiletypeData *)))
                                              == NULL )
                     {
                          printf("\n Cannot allocate memory\n");
                          return NULL;
                     }
                     else if(ppFiletypeData)
                     {
                          ppFiletypeData=ppnewFiletypeData;
                          /* Process the contents field if any  */
                          if(ProcessContents((FiletypeData *)ppFiletypeData[nfiletypes]) < 0 )
                          {
                                printf("\n Error in Contents Data\n");
                                return NULL;
                          }
                         /* Everything looks right so process the exec_string */
                          if( !(execstr = ProcessExecString((char *)ppFiletypeData[nfiletypes]->pszPrintCmd)) )
                              ppFiletypeData[nfiletypes]->pszPrintCmd=NULL;
                          else {
                              ppFiletypeData[nfiletypes]->pszPrintCmd=execstr[0];
                              free(execstr);
			  }
                          nfiletypes++;
                          /* Allocate a new filetypedata record */
                          if( (ppFiletypeData[nfiletypes] =
                                (FiletypeData *)calloc(1,sizeof(FiletypeData)) )
                                                  == NULL )
                          {
                              printf("\n Cannot allocate memory\n");
                              return NULL;
                          }
                          ppFiletypeData[nfiletypes]->pszOpenCmd = pszOpenCmd;
                          previous = DATA_ATTRIBUTES;
                          manflds=0;
                     }

                }
                else
                {
                     printf("Error in filetypedata \n");
                     return NULL;
                }
           }
           else if( !strcmp(wordPairs[0],"DATA_CRITERIA") )
           {
                  if( previous == DATA_ATTRIBUTES )
                  {
                      previous = DATA_CRITERIA;
                      manflds=0;
                  }
                  else
                  {
                      printf("Error in filetypedata \n");
                      return NULL;
                  }
              }
              else if( !strcmp(wordPairs[0],"ACTION") && !strcmp(wordPairs[1],"Open") )
              {
                  if( previous == DATA_CRITERIA )
                  {
                      previous = ACTION_OPEN;
                      manflds=0;
                  }
                  else
                  {
                      printf("Error in filetypedata \n");
                      return NULL;
                  }
              }
           else if( !strcmp(wordPairs[0],"ACTION") && strcmp(wordPairs[1],"Open") &&
                  strcmp(wordPairs[1], "Print")  )
           {
                  if( previous == ACTION_OPEN )
                  {
                      previous = ACTION_PRINT_FTYPE;
                      manflds=0;
                  }
                  else
                  {
                      printf("Error in filetypedata \n");
                      return NULL;
                  }
           }
           else if( !strcmp(wordPairs[0],"ACTION") && !strcmp(wordPairs[1],"Print") )
           {
                  if( previous == ACTION_PRINT_FTYPE )
                  {
                      previous = ACTION_PRINT;
                      manflds=0;
                  }
                  else
                  {
                      printf("Error in filetypedata \n");
                      return NULL;
                  }
           }


           /* update mandatory fields counter */
           if( previous == DATA_ATTRIBUTES && strcmp(wordPairs[0],"DATA_ATTRIBUTES") )
           {
                  if( !strcmp(wordPairs[0],"ACTIONS") )
                      manflds++;
           }
           else if( previous == DATA_CRITERIA )
           {
                  if( !strcmp(wordPairs[0],"DATA_ATTRIBUTES_NAME") )
                      manflds++;
           }
           else if( previous == ACTION_OPEN || previous == ACTION_PRINT )
           {
                  if( !strcmp(wordPairs[0],"ARG_TYPE")   ||
                      !strcmp(wordPairs[0],"TYPE")       ||
                      !strcmp(wordPairs[0],"MAP_ACTION") ||
                      !strcmp(wordPairs[0],"LABEL") )
                      manflds++;
           }
           else if( previous == ACTION_PRINT_FTYPE )
           {
                  if( !strcmp(wordPairs[0],"TYPE") ||
                      !strcmp(wordPairs[0],"WINDOW_TYPE") )
                      manflds++;
           }

       }



   if( wordPairs && !wordPairs[1] && wordPairs[0])
           {
              switch(fldid)
              {
                  case 0:    /* next line for filetype_name */
                             ppFiletypeData[nfiletypes]->pszName=wordPairs[0];
                             break;

                  case 1:    /* next line for icon_name */
                             ppFiletypeData[nfiletypes]->pszIcon=wordPairs[0];
                             break;

                  case 2 :   /* next line for help_text */
                             ppFiletypeData[nfiletypes]->pszHelp=wordPairs[0];
                             break;

                  case 3:    /* next line for print_cmd */
                             ppFiletypeData[nfiletypes]->pszPrintCmd=wordPairs[0];
                             manflds++;
                             break;
                  case 4:    /* next line for name_pattern or path_pattern */
                             ppFiletypeData[nfiletypes]->pszPattern=wordPairs[0];
                             break;
                  case 5:    /* next line for name_pattern or path_pattern */
                             ppFiletypeData[nfiletypes]->pszPattern=wordPairs[0];
                             break;
                  case 6:    /* next line for mode */
                             ppFiletypeData[nfiletypes]->pszPermissions=wordPairs[0];
                             break;
                  case 7:    /* next line for contents */
                             ppFiletypeData[nfiletypes]->pszContents=wordPairs[0];
                             break;

                 default:    break;
              }
           }
           else if(wordPairs && wordPairs[1])
           {
              switch(fldid)
              {
                  case 0:   /* first line for filetype_name */
                            ppFiletypeData[nfiletypes]->pszName = wordPairs[1];
                            break;

                  case 1:   /* first line for icon_name */
                            ppFiletypeData[nfiletypes]->pszIcon=wordPairs[1];
                            break;

                  case 2 :  /* first line for help_text */
                            ppFiletypeData[nfiletypes]->pszHelp=wordPairs[1];
                            break;

                  case 3:   /* first line for print_cmd */
                            ppFiletypeData[nfiletypes]->pszPrintCmd=wordPairs[1];
                            manflds++;
                            break;

                  case 4:   /* first line for name_pattern or path_pattern */
                            ppFiletypeData[nfiletypes]->pszPattern=wordPairs[1];
                            break;

                  case 5:   /* first line for name_pattern or path_pattern */
                            ppFiletypeData[nfiletypes]->pszPattern=wordPairs[1];
                            break;

                  case 6:   /* first line for mode */
                            ppFiletypeData[nfiletypes]->pszPermissions=wordPairs[1];
                            break;

                  case 7:   /* first line for contents */
                            ppFiletypeData[nfiletypes]->pszContents=wordPairs[1];
                            break;

                 default:   break;
              }

           }

              bzero(linebuf,sizeof(linebuf));
        } /* end of while fgets */

        /* Done with retrieving FiletypeData */
        /* Check if we got all the mandatory fields data */
        if( (previous == ACTION_OPEN  && manflds != 4) ||
            (previous == ACTION_PRINT  && manflds != 4)   )
            return NULL;
        else if(ppFiletypeData)
        {
            /* Process Contents for the last file filetype if any */
            if(ProcessContents((FiletypeData *)ppFiletypeData[nfiletypes]) < 0)
                          {
                                printf("\n Error in Contents Data\n");
                                return NULL;
                          }
            /* Everything looks right so process the exec_string */
            if(!(execstr =
                    ProcessExecString((char *)ppFiletypeData[nfiletypes]->pszPrintCmd)) )
                ppFiletypeData[nfiletypes]->pszPrintCmd=NULL;
            else
                ppFiletypeData[nfiletypes]->pszPrintCmd=execstr[0];
            if( !ppFiletypeData[nfiletypes])
                ppFiletypeData[nfiletypes] = 0;
            /* return number of filetypes */
            *nftypes = nfiletypes+1;
            free(execstr);
            return ppFiletypeData;

        }
        else
            return NULL;

}

/*****************************************************************
**                                                              **
** GetKeywordValuePairs(char *s, int *id, int table)            **
**                                                              **
** Description: Parses the text string in *s and returns a      **
**              pointer to two strings that are Keyword and     **
**              values.However, it returns the complete string  **
**              in the first pointer if keyword not found.      **
**                                                              **
** Input      : A character pointer pointing to text string.    **
**              An integer pointer to return the field id.      **
**              An integer value that determines which table to **
**              use (either ACTION_TABLE of FILETYPE_TABLE).    **
**              see definitions in parser.h                     **
**                                                              **
** Output     : pointer to two pointers pointing to text strings**
**              fieldid in the id parameter.                    **
**                                                              **
** references : dtcreate.h, parser.h, and dtcreate spec.        **
**                                                              **
******************************************************************/

char **
GetKeywordValuePairs(char *s, int *id, int table)
{
    char    *wordStart;
    static int fldid=-1;
    int        idx;

        args[0] = args[1] = args[2] = NULL;
        /* Skip all leading spaces */
        while (*s && isspace (*s))
            ++s;
        /* Skip the complete line if a '#' character is found (comments)  */
        if (!*s || *s == '#')
            return NULL;
        wordStart = s;
        while (*s && *s != '#' && !isspace (*s))
            ++s;
        if (!args[0])
        {
            int szArgs0 = s - wordStart + 1;
            args[0] = (char *)malloc (szArgs0);
            if (!args[0])
                return NULL;
            memset(args[0],0,szArgs0);
        }
        strncpy (args[0], wordStart, s - wordStart);
        args[0][s-wordStart] = '\0';
        if (!args[1])
        {
	    int szArgs1 = strlen(s) + 1;
            args[1] = (char *)malloc (szArgs1);
            if (!args[1])
            {
                if(args[0])
                free(args[0]);
                return NULL;
            }
            memset(args[1],0,szArgs1);
        }
        /* Skip all leading spaces */
        while (*s && isspace (*s))
            ++s;
        strcpy (args[1], s);
        args[2]=NULL;
        /* Check for whether args[0] is a keyword or not */
        idx=0;
        if( table == ACTION_TABLE )
        {
           /* Check for keyword in keywordDB defined in parser.h */
           while((strcmp(keywordDB[idx],"")) && (strcmp(args[0],keywordDB[idx])) ) idx++;
           if(idx >= 0 && idx < MAX_NUM_ACTION_FIELDS)
              fldid = idx;
        }
        else if( table == FILETYPE_TABLE )
        {
           /* Check for keyword in FiletypekeywordDB defined in parser.h */
           while((strcmp(FiletypekeywordDB[idx],"")) && (strcmp(args[0],FiletypekeywordDB[idx])) ) idx++;
           if(idx >= 0 && idx < MAX_NUM_FILETYPE_FIELDS)
              fldid = idx;
        }
        /* If no keyword found then keep the complete string
           in the first array
        */
        if( (idx == MAX_NUM_ACTION_FIELDS && table == ACTION_TABLE)  ||
            (idx == MAX_NUM_FILETYPE_FIELDS && table == FILETYPE_TABLE) )
        {
           char *temp4;

           if( (temp4 = (char *)realloc(args[0],strlen(args[0])+strlen(args[1])+2) ) == NULL )
           {
                printf("Cannot Allocate memory\n");
                return NULL;
           }
           args[0] = temp4;
           strcat(args[0]," ");
           strcat(args[0],args[1]);

           if(args[1])
           {
              free(args[1]);
              args[1]=NULL;
           }
           if( IsLastSingle(args[0]) && args[0][strlen(args[0])-1] == '\\' )
               args[0][strlen(args[0])-1] = '\0';
           if( (temp4 = (char *)realloc(fline,flinesize+strlen(args[0])+1)) == NULL)
           {
                printf("Cannot Allocate memory\n");
                return NULL;
           }
          strcat(temp4,args[0]);
          free(args[0]);
          args[0]=temp4;
        }

    *id = fldid;  /* return field id   */
    if(args[1] && IsLastSingle(args[1]) && args[1][strlen(args[1])-1] == '\\')
       args[1][strlen(args[1])-1] = '\0';
    if(args[0])
        args[0][strlen(args[0])] = '\0';
    if(args[1])
        args[1][strlen(args[1])] = '\0';
    if(args[0] && args[1])
    {
        fline = args[1];
        flinesize=strlen(fline);
    }
    if(!args[1] && args[0])
    {
        fline = args[0];
        flinesize=strlen(fline);
    }
    return args;
}


/*****************************************************************
**                                                              **
** ProcessExecString(char *)                                    **
**                                                              **
** Description: Parses the text string and returns two pointers,**
**              the first pointing to cmd part (if any)         **
**              the second pointing to prompt part (if any)     **
**              of either the ActionData structure type or      **
**              FiletypeData structure type. Please see         **
**              dtcreate.h for the above mentioned datastructure**
**              definitions and for the cmd and prompt fields   **
**                                                              **
** Input      : A character pointer that points to the complete **
**              text string comprising the command and arguments**
**              and prompt (if any).                            **
**                                                              **
** Limitation : Supports only ONE prompt.                       **
**                                                              **
** Output     : Pointer to 3-element result array from malloc,  **
**              or NULL on error                                **
**                                                              **
** Assumptions: a) Arg fields start with a '%' character.       **
**              b) Prompt string start and end with '"' chara-  **
**                 cter. Also, the prompt string comes after    **
**                 the Arg strings if any.                      **
**                                                              **
** references : dtcreate.h, parser.h, and dtcreate spec.        **
**                                                              **
******************************************************************/

char **
ProcessExecString(char *cmd)
{

char *s1, *s2,*s3,*s4,*argbuf,**exec_args;
int  done=FALSE, argfound=FALSE,promptfound=FALSE;

        if (!cmd) {
           return((char **)NULL);
        }
        s1=s2=s3=s4=argbuf=NULL;
        exec_args = calloc(3, sizeof(char*));
        if (!exec_args) return NULL;
        /* Allocate buffer for the cmd string */
        exec_args[0] = (char *)calloc(1,strlen(cmd)+1);
        exec_args[1] = exec_args[2] = NULL;
        /* check if any Args present */
        s1=cmd;
        while( !done )
        {
                char *tmp;
                tmp=NULL;
                s4 = strstr(s1,"%Arg");
                if(s4)
                {
                      if ( (s4-s1) > 0 )
                      {
                          strncat(exec_args[0],s1,(s4-s1));
                          exec_args[0][strlen(exec_args[0])] = '\0';
                      }
                      s1 = s4;
                      s2 = strchr(s1+1,'%');  /* at this point we got s1 to s2
                                             covers the complete string
                                             between %'s
                                            */
                      if(argbuf) { free(argbuf); argbuf = NULL; }
                      if(s2)
                      {
                         argbuf = (char *)calloc(1,(s2-s1)+2);
                         strncpy(argbuf,s1,(s2-s1)+1);
                      }
                      else
                      {
                         strcat(exec_args[0],s1);
                         done=TRUE;
                         continue;
                      }
                      argbuf[strlen(argbuf)]='\0';
                      if( strncmp(argbuf,"%Arg_",5) &&
                               strncmp(argbuf,"%Args%",6) &&
                               strncmp(argbuf,"%Args\"",6)   )
                      {
                           strncat(exec_args[0],argbuf,strlen(argbuf)-1);
                           exec_args[0][strlen(exec_args[0])] = '\0';
                           s1=s2;
                           continue;
                      }
                }
                else if (*s1)
                {
                     strcat(exec_args[0],s1);
                     if(argbuf)   { free(argbuf); argbuf = NULL; }
                     done = TRUE;
                     continue;
                }
                else
                {
                     done = TRUE;
                     continue;
                }

                  /* move s1 until a '_' or 's' */
                  tmp = strchr(argbuf,'_');
                  if(!tmp)
                      tmp= strchr(argbuf,'s');
                  strcat(exec_args[0],"$");
                  argfound=TRUE;
                  /* start of Arg processing */
                  while (*tmp != '%' && *tmp != '"' )
                  {
                      if(*tmp == 's')
                      {
                         strcat(exec_args[0],"*");
                         break;
                      }
                      if( *tmp > '0' && *tmp <= '9')
                      {
                         strncat(exec_args[0],tmp,1);
                         exec_args[0][strlen(exec_args[0])] = '\0';
                      }
                      tmp++;
                  }
                /* end of Arg processing */

                /* Get Prompt string if any */
                s3 = strchr(argbuf,'"');
                if(s3 && *(s3+1) != '"')
                {
                      s3++;
                      if(!promptfound)
                      {
                          if( (tmp = strchr(s3,'"')) )
                          {
                               promptfound=TRUE;
                               exec_args[1] = (char *)calloc(1,(tmp-s3)+1);
                               strncpy(exec_args[1],s3,(tmp-s3));
                               exec_args[1][strlen(exec_args[1])] = '\0';
                          }
                      }
                }

                /* see if there is some stuff between the last '%'
                   and the next first '%' of another Arg
                */
                if( argfound) s2++;
                argfound = FALSE;
                s1=s2;
         }
         if(argbuf) { free(argbuf); argbuf = NULL; }
   return exec_args;
}

/*****************************************************************
**                                                              **
** ProcessContents(FiletypeData *)                              **
**                                                              **
** Description: Parses the text string in pszContents field and **
**              fills the sStart,fsFlags and pszContents fields **
**              of the filetypeData datastructure that is passed**
**              as input.                                       **
**                                                              **
** Input      : A pointer of type FiletypeData defined in       **
**              dtcreate.h                                      **
**                                                              **
** Output     : Fills the sStart, fsFlags and pszContents fields**
**              of the FiletypeData pointer and returns 0 (No   **
**              error or >0 (error) values.                     **
**                                                              **
** Assumptions: Fields are separated by atleast one blank       **
**              character.                                      **
**                                                              **
** references : dtcreate.h, parser.h, and dtcreate spec.        **
**                                                              **
******************************************************************/

int
ProcessContents(FiletypeData *pFtD)
{

char    *s1,*tmp,*s2,buf[10],*cts;

        s1=s2=tmp=cts=NULL;
        bzero(buf,sizeof(buf));
        /* simply return if there is no data in contents field */
        if(!pFtD->pszContents)
           return (0);
        cts = (char *)calloc(1,strlen(pFtD->pszContents)+1);
        strcpy(cts,pFtD->pszContents);
        s1=cts;
        free(pFtD->pszContents);
        pFtD->pszContents=NULL;
        /* Skip all leading spaces */
        while( *s1 && isspace(*s1) )  s1++;
        /* Get the sStart value if any */
/*
        if( (s1 = strchr(cts,' ')) )
*/
        while( *s1 && !isspace(*s1) && *s1 != '\n') s1++;
        if((s1-cts) > 0)
        {
           strncpy(buf,cts,(s1-cts));
           buf[s1-cts]='\0';
           pFtD->sStart=atoi(buf);
        }
        while( *s1 && isspace(*s1) )  s1++;

        /* Get the fsFlags value if any */
        tmp=s1;
        bzero(buf,sizeof(buf));
/*
        if ( (tmp = strchr(s1,' ')) )
*/
        while( *tmp && !isspace(*tmp) && *tmp != '\n') tmp++;
        if((tmp-s1) > 0)
        {
           strncpy(buf,s1,(tmp-s1));
           buf[tmp-s1]='\0';
           if ( !strcmp(buf,"byte") )
               pFtD->fsFlags|=CA_FT_CNTBYTE;
           else if ( !strcmp(buf,"string") )
               pFtD->fsFlags|=CA_FT_CNTSTRING;
           else if ( !strcmp(buf,"long") )
               pFtD->fsFlags|=CA_FT_CNTLONG;
           else if ( !strcmp(buf,"short") )
               pFtD->fsFlags|=CA_FT_CNTSHORT;
           else {
               free(cts);
               return (-1);
           }
        }
        while( *tmp && isspace(*tmp) )  tmp++;
        s2=tmp;
        /* Get the contents if any */
        if (*s2)
        {
              pFtD->pszContents =  (char *)calloc(1,strlen(s2)+1);
              strcpy(pFtD->pszContents,s2);
              free(cts);

        }


 return 0;
}

/*****************************************************************
**                                                              **
** IsLastSingle(char *str)                                      **
**                                                              **
** Description: returns TRUE if the last character of the       **
**              string str is a single-byte character, returns  **
**              FALSE if it is a multi-byte character.          **
**                                                              **
******************************************************************/

Boolean
IsLastSingle(char *str)
{
    int n = 0;

    if(MB_CUR_MAX == 1)
        return(TRUE);

    while(*str) {
        n = mblen(str, MB_CUR_MAX);
        str += n;
    }
    if(n > 1)
        return(FALSE);
    else
        return(TRUE);
}
