dtwm: basic multihead(xinerama only) support
[oweals/cde.git] / cde / programs / dtcreate / parser.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: parser.c /main/8 1996/03/25 09:14:08 rswiston $ */
24 /***************************************************************************/
25 /*                                                                         */
26 /*  parser.c                                                               */
27 /*                                                                         */
28 /***************************************************************************/
29 #ifdef _AIX
30 #define _ILS_MACRO
31 #endif /* _AIX */
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <sys/stat.h>
36
37 #include "dtcreate.h"
38 #include "parser.h"
39 #include <ctype.h>
40
41 /***************************************************************************
42  *
43  *  Local procedure declarations
44  *
45  ***************************************************************************/
46
47
48 char ** GetKeywordValuePairs(char *, int *, int);
49 FiletypeData ** GetFiletypeData(FILE *, char *, short *);
50 char ** ProcessExecString(char *);
51 int ProcessContents(FiletypeData *);
52 Boolean IsLastSingle(char *);
53
54
55 /***************************************************************************
56  *
57  *  Extern variable declarations
58  *
59  ***************************************************************************/
60
61
62 /***************************************************************************
63  *
64  *  Global variable declarations
65  *
66  ***************************************************************************/
67
68 /* Action Keyword Table */
69 char keywordDB[][30] = { "ACTION"         ,
70                           "ICON"          ,
71                           "EXEC_STRING"   ,
72                           "DESCRIPTION"   ,
73                           "TYPE"          ,
74                           "WINDOW_TYPE"   ,
75                           "ARG_TYPE"      ,
76                           "LABEL"         ,
77                           '\0'            ,
78                      };
79
80 /* Max Number of fields in Action Keyword Table */
81 #define MAX_NUM_ACTION_FIELDS     8
82
83 /* Filetype Keyword Table */
84 char FiletypekeywordDB[][30] = { "DATA_ATTRIBUTES"       ,
85                                   "ICON"                 ,
86                                   "DESCRIPTION"          ,
87                                   "EXEC_STRING"          ,
88                                   "NAME_PATTERN"         ,
89                                   "PATH_PATTERN"         ,
90                                   "MODE"                 ,
91                                   "CONTENT"              ,
92                                   "ACTIONS"              ,
93                                   "DATA_ATTRIBUTES_NAME" ,
94                                   "DATA_CRITERIA"        ,
95                                   "WINDOW_TYPE"          ,
96                                   "ACTION"               ,
97                                   "ARG_TYPE"             ,
98                                   "MAP_ACTION"           ,
99                                   "TYPE"                 ,
100                                   "LABEL"                ,
101                                    '\0'                  ,
102                      };
103
104 /* Max Number of fields in Filetype Keyword Table */
105 #define MAX_NUM_FILETYPE_FIELDS     17
106
107
108 char *args[3],*fline;
109 int flinesize=0;
110 static int state = 0;
111
112
113 /*****************************************************************
114 **                                                              **
115 ** GetActionData(FILE *fp, ActionData *)                        **
116 **                                                              **
117 ** Description: Parses the action file and fills the data in the**
118 **              pointer pointing to the ActionData structure    **
119 **              passed as input.                                **
120 **                                                              **
121 ** Input      : Filepointer that points to the ActionFile and,  **
122 **              a pointer to the ActionData structure.          **
123 **                                                              **
124 ** Output     : 0 (No error).                                   **
125 **              1 (error).                                      **
126 **                                                              **
127 ** references : dtcreate.h, parser.h, and dtcreate spec.        **
128 **                                                              **
129 ******************************************************************/
130
131
132 int
133 GetActionData(FILE *fp, ActionData *ActionDataptr)
134 {
135 int         rc,manflds=0,len,first=TRUE,lastfld=0,fldid=-1;
136 char        linebuf[1024],**wordPairs,**execstr;
137
138
139         /* reset the read pointer to zero byte for fp */
140         rewind(fp);
141         /* Initialize the ActionData structure passed */
142         if(ActionDataptr)
143            memset(ActionDataptr,
144                        0,sizeof(ActionData));
145         else {
146 #ifdef DEBUG
147            printf("ActionDataptr is NULL\n");
148 #endif
149            return 1;
150         }
151
152         /* initialize the linebuf with NULL's  */
153         bzero(linebuf,sizeof(linebuf));
154         while (fgets (linebuf, sizeof (linebuf)-1, fp))
155         {
156            /* skip the complete line if it starts with a '{' or a comment ('#')  */
157            if(linebuf[0] == '{' || linebuf[0] == '#') continue;
158            /* If the first character is '}' reached the end of Action Stanza so quit */
159            if(linebuf[0] == '}')
160               break;
161            len = strlen (linebuf);
162            if (linebuf[len-1] == '\n')
163               linebuf[len-1] = '\0';
164            /* Get the keyword and value pair from the string linebuf */
165            /* On return, wordPairs[0] = keyword like ICON
166               and        wordPairs[1] = value for the keyword
167            */
168            if( (wordPairs = GetKeywordValuePairs(linebuf,&fldid,ACTION_TABLE)) != NULL)
169            {
170               if( first && strcmp(wordPairs[0],"ACTION") )
171               {
172 #ifdef DEBUG
173                   printf("first && strcmp(wordPairs[0],ACTION)\n");
174 #endif
175                   return 1;
176               }
177               else
178                   first = FALSE;
179               /* Update the mandatory fields counter */
180               if( !strcmp(wordPairs[0],"TYPE") ||
181                   !strcmp(wordPairs[0],"EXEC_STRING") ||
182                   !strcmp(wordPairs[0],"WINDOW_TYPE") )
183                      manflds++;
184               if( !strcmp(wordPairs[0],"WINDOW_TYPE") )
185               {
186                  if( !strcmp(wordPairs[1],"PERM_TERMINAL") )
187                     ActionDataptr->fsFlags |= CA_WT_PERMTERM;
188                  if( !strcmp(wordPairs[1],"TERMINAL") )
189                     ActionDataptr->fsFlags |= CA_WT_TERM;
190                  if( !strcmp(wordPairs[1],"NO_STDIO") )
191                     ActionDataptr->fsFlags |= CA_WT_XWINDOWS;
192               }
193               if( !strcmp(wordPairs[0],"ARG_TYPE") )
194                  ActionDataptr->fsFlags |= CA_DF_ONLYFTFILES;
195
196               /* if linebuf does not contain the keyword then everything
197               in wordPairs[0],else, wordPairs[0] contains the keyword
198               and wordpairs[1] contains the value.
199               */
200               if( wordPairs && wordPairs[0] && !wordPairs[1])
201               {
202                  /* fldid is returned by the GetKeywordValuePairs function.
203                  This id determines which field of the ActionDataptr will
204                  have the value. Please see KeywordDB array in parser.h
205                  for more details.
206                  */
207                  switch(fldid)
208                  {
209                      case 7:   /* next line for action_name */
210                                ActionDataptr->pszName=wordPairs[0];
211                                break;
212
213                      case 1:   /* next line for action_icon_name */
214                                ActionDataptr->pszIcon=wordPairs[0];
215                                break;
216
217                      case 2 :  /* next line for exec_string */
218                                ActionDataptr->pszCmd=wordPairs[0];
219                                break;
220
221                      case 3:   /* next line for action_help_text */
222                                ActionDataptr->pszHelp=wordPairs[0];
223                                break;
224
225                     default:   break;
226                  }
227              }
228              else if(wordPairs && wordPairs[1])
229              {
230                  if(fldid >= 0 && fldid <=2)
231                         state = 0;
232                  /* for fldid see the comments above */
233                  switch(fldid)
234                  {
235                      case 7:   /* first line for action_name */
236                                ActionDataptr->pszName=wordPairs[1];
237                                break;
238
239                      case 1:   /* first line for action_icon_name */
240                                ActionDataptr->pszIcon=wordPairs[1];
241                                break;
242
243                      case 2 :  /* first line for exec_string */
244                                ActionDataptr->pszCmd=wordPairs[1];
245                                break;
246
247                      case 3:   /* first line for action_help_text */
248                                state = HELP_TEXT;
249                                ActionDataptr->pszHelp=wordPairs[1];
250                                break;
251
252                     default:   state=0;break;
253                  }
254
255               }
256               /* reset the linebuf to NULL's */
257               bzero(linebuf,sizeof(linebuf));
258           }
259         }
260
261         state=0;
262         /* Done with retrieving Action Data */
263         /* Check if we got all the mandatory fields data */
264         if(manflds != 3) {
265 #ifdef DEBUG
266             printf("if(manflds != 3)\n");
267 #endif
268             return 1;
269         } else
270         {
271             /* Everything looks right so process the exec_string */
272             if( !(execstr = ProcessExecString(ActionDataptr->pszCmd)) )
273             {
274                 ActionDataptr->pszCmd = NULL;
275                 ActionDataptr->pszPrompt = 0;
276             }
277             else
278             {
279                 ActionDataptr->pszCmd = execstr[0];
280                 ActionDataptr->pszPrompt = execstr[1];
281                 free(execstr);
282             }
283             /* Got the ActionData,so, go get the FiletypeData */
284             ActionDataptr->papFiletypes =
285                         (FiletypeData **) GetFiletypeData(fp,(char *)(ActionDataptr->pszCmd),
286                                                          (short *)&(ActionDataptr->cFiletypes) );
287             if( !ActionDataptr->papFiletypes && ActionDataptr->cFiletypes > 0) {
288 #ifdef DEBUG
289                  printf("!ActionDataptr->papFiletypes && ActionDataptr->cFiletypes > 0)\n");
290 #endif
291                  return(1);  /* return 1 if error */
292             } else
293                  return(0);  /* return 0 if no error */
294         }
295
296
297 }
298
299 /*****************************************************************
300 **                                                              **
301 ** GetFiletypeData(FILE *fp, char *pszOpenCmd)                  **
302 **                                                              **
303 ** Description: Parses the action file and returns a pointer    **
304 **              that points to the data in the form of          **
305 **              FiletypeData structure (defined in dtcreate.h). **
306 **                                                              **
307 ** Input      : Filepointer that points to the ActionFile, and, **
308 **              a char pointer to the exec_string of the        **
309 **              ActionData structure as obtained in the GetAc-  **
310 **              -tionData function call.                        **
311 **                                                              **
312 ** Output     : Pointer to an array of FiletypeData structures  **
313 **              containing data for all the Filetypes,and,no of **
314 **              file types.                                     **
315 **                                                              **
316 ** references : dtcreate.h, parser.h, and dtcreate spec.        **
317 **                                                              **
318 ******************************************************************/
319
320 FiletypeData **
321 GetFiletypeData(FILE  *fp, char *pszOpenCmd, short *nftypes)
322 {
323 int         manflds=0,len,nfiletypes,previous=0,lastfld=0,fldid;
324 char        linebuf[1024],**wordPairs,**execstr;
325 FiletypeData  **ppFiletypeData,**ppnewFiletypeData;
326
327         wordPairs=0;
328         ppFiletypeData=0;
329         nfiletypes=0;
330
331         /* Initialize the linebuf */
332         bzero(linebuf,sizeof(linebuf));
333         while (fgets (linebuf, sizeof (linebuf)-1, fp))
334         {
335            /* If begin of a stanza skip and continue */
336            if(linebuf[0] == '{')
337            {
338                continue;
339            }
340
341            /* skip the rest of the line if a comment found */
342            if(linebuf[0] == '#') continue;
343
344            /* If end of a stanza check if all the mandatory fields are there */
345            if( linebuf[0] == '}' )
346            {
347                /* Check for atleast one field in DATA_ATTRIBUTES stanza */
348                if( previous == DATA_ATTRIBUTES && manflds != 1 )
349                {
350                    printf("Error in DATA_ATTR stanza of the FiletypeData\n");
351                    return NULL;
352                }
353                /* Check for atleast one field in DATA_CRITERIA stanza */
354                else if( previous == DATA_CRITERIA && manflds != 1 )
355                {
356                    printf("Error in DATA_CRITERIA stanza of the FiletypeData\n");
357                    return NULL;
358                }
359                /* Check for atleast two fields in ACTION_OPEN or ACTION_PRINT stanza */
360                else if( (previous == ACTION_OPEN || previous == ACTION_PRINT) )
361                {
362                    if( manflds != 4)
363                    {
364                       printf("Error in ACTION_OPEN/PRINT stanza of the FiletypeData\n");
365                       return NULL;
366                    }
367                }
368                /* Check for atleast three fields in ACTION_PRINT_FTYPE stanza */
369                else if( previous == ACTION_PRINT_FTYPE && manflds != 3 )
370                {
371                    printf("Error in ACTION_PRINT_FTYPE stanza of the FiletypeData\n");
372                    return NULL;
373                }
374                continue;
375            }
376            len = strlen (linebuf);
377            if (linebuf[len-1] == '\n')
378               linebuf[len-1] = '\0';
379
380            if( (wordPairs = GetKeywordValuePairs(linebuf,&fldid,FILETYPE_TABLE)) != NULL)
381            {
382               if( !strcmp(wordPairs[0],"DATA_ATTRIBUTES") )
383               {
384                 /* first filetype */
385                 if( previous == 0 )
386                 {
387                      /* Allocate a filetypedata pointer to an array of filetypedata records   */
388                      if( !ppFiletypeData)
389                      {
390                          if( (ppFiletypeData = (FiletypeData **)calloc(1,sizeof(FiletypeData *)))
391                                                   == NULL )
392                          {
393                                  printf("\n Cannot allocate memory\n");
394                                  return NULL;
395                          }
396                          /* Allocate a filetypedata record   */
397                          else
398                          {
399                                  if( (ppFiletypeData[nfiletypes] =
400                                  (FiletypeData *)calloc(1,sizeof(FiletypeData)) )
401                                                    == NULL )
402                                  {
403                                        printf("\n Cannot allocate memory\n");
404                                        return NULL;
405                                  }
406                           }
407                      }
408
409                      ppFiletypeData[nfiletypes]->pszOpenCmd = pszOpenCmd;
410                      previous = DATA_ATTRIBUTES;
411                      manflds=0;
412                 }
413                 else if(previous == ACTION_OPEN || previous == ACTION_PRINT)
414                 {
415                      /* New filetypedata started so allocate a new filetypedata ptr */
416                      if( (ppnewFiletypeData =
417                         (FiletypeData **)realloc((FiletypeData *)ppFiletypeData,
418                         nfiletypes+2 * sizeof(FiletypeData *)))
419                                               == NULL )
420                      {
421                           printf("\n Cannot allocate memory\n");
422                           return NULL;
423                      }
424                      else if(ppFiletypeData)
425                      {
426                           ppFiletypeData=ppnewFiletypeData;
427                           /* Process the contents field if any  */
428                           if(ProcessContents((FiletypeData *)ppFiletypeData[nfiletypes]) < 0 )
429                           {
430                                 printf("\n Error in Contents Data\n");
431                                 return NULL;
432                           }
433                          /* Everything looks right so process the exec_string */
434                           if( !(execstr = ProcessExecString((char *)ppFiletypeData[nfiletypes]->pszPrintCmd)) )
435                               ppFiletypeData[nfiletypes]->pszPrintCmd=NULL;
436                           else {
437                               ppFiletypeData[nfiletypes]->pszPrintCmd=execstr[0];
438                               free(execstr);
439                           }
440                           nfiletypes++;
441                           /* Allocate a new filetypedata record */
442                           if( (ppFiletypeData[nfiletypes] =
443                                 (FiletypeData *)calloc(1,sizeof(FiletypeData)) )
444                                                   == NULL )
445                           {
446                               printf("\n Cannot allocate memory\n");
447                               return NULL;
448                           }
449                           ppFiletypeData[nfiletypes]->pszOpenCmd = pszOpenCmd;
450                           previous = DATA_ATTRIBUTES;
451                           manflds=0;
452                      }
453
454                 }
455                 else
456                 {
457                      printf("Error in filetypedata \n");
458                      return NULL;
459                 }
460            }
461            else if( !strcmp(wordPairs[0],"DATA_CRITERIA") )
462            {
463                   if( previous == DATA_ATTRIBUTES )
464                   {
465                       previous = DATA_CRITERIA;
466                       manflds=0;
467                   }
468                   else
469                   {
470                       printf("Error in filetypedata \n");
471                       return NULL;
472                   }
473               }
474               else if( !strcmp(wordPairs[0],"ACTION") && !strcmp(wordPairs[1],"Open") )
475               {
476                   if( previous == DATA_CRITERIA )
477                   {
478                       previous = ACTION_OPEN;
479                       manflds=0;
480                   }
481                   else
482                   {
483                       printf("Error in filetypedata \n");
484                       return NULL;
485                   }
486               }
487            else if( !strcmp(wordPairs[0],"ACTION") && strcmp(wordPairs[1],"Open") &&
488                   strcmp(wordPairs[1], "Print")  )
489            {
490                   if( previous == ACTION_OPEN )
491                   {
492                       previous = ACTION_PRINT_FTYPE;
493                       manflds=0;
494                   }
495                   else
496                   {
497                       printf("Error in filetypedata \n");
498                       return NULL;
499                   }
500            }
501            else if( !strcmp(wordPairs[0],"ACTION") && !strcmp(wordPairs[1],"Print") )
502            {
503                   if( previous == ACTION_PRINT_FTYPE )
504                   {
505                       previous = ACTION_PRINT;
506                       manflds=0;
507                   }
508                   else
509                   {
510                       printf("Error in filetypedata \n");
511                       return NULL;
512                   }
513            }
514
515
516            /* update mandatory fields counter */
517            if( previous == DATA_ATTRIBUTES && strcmp(wordPairs[0],"DATA_ATTRIBUTES") )
518            {
519                   if( !strcmp(wordPairs[0],"ACTIONS") )
520                       manflds++;
521            }
522            else if( previous == DATA_CRITERIA )
523            {
524                   if( !strcmp(wordPairs[0],"DATA_ATTRIBUTES_NAME") )
525                       manflds++;
526            }
527            else if( previous == ACTION_OPEN || previous == ACTION_PRINT )
528            {
529                   if( !strcmp(wordPairs[0],"ARG_TYPE")   ||
530                       !strcmp(wordPairs[0],"TYPE")       ||
531                       !strcmp(wordPairs[0],"MAP_ACTION") ||
532                       !strcmp(wordPairs[0],"LABEL") )
533                       manflds++;
534            }
535            else if( previous == ACTION_PRINT_FTYPE )
536            {
537                   if( !strcmp(wordPairs[0],"TYPE") ||
538                       !strcmp(wordPairs[0],"WINDOW_TYPE") )
539                       manflds++;
540            }
541
542        }
543
544
545
546    if( wordPairs && !wordPairs[1] && wordPairs[0])
547            {
548               switch(fldid)
549               {
550                   case 0:    /* next line for filetype_name */
551                              ppFiletypeData[nfiletypes]->pszName=wordPairs[0];
552                              break;
553
554                   case 1:    /* next line for icon_name */
555                              ppFiletypeData[nfiletypes]->pszIcon=wordPairs[0];
556                              break;
557
558                   case 2 :   /* next line for help_text */
559                              ppFiletypeData[nfiletypes]->pszHelp=wordPairs[0];
560                              break;
561
562                   case 3:    /* next line for print_cmd */
563                              ppFiletypeData[nfiletypes]->pszPrintCmd=wordPairs[0];
564                              manflds++;
565                              break;
566                   case 4:    /* next line for name_pattern or path_pattern */
567                              ppFiletypeData[nfiletypes]->pszPattern=wordPairs[0];
568                              break;
569                   case 5:    /* next line for name_pattern or path_pattern */
570                              ppFiletypeData[nfiletypes]->pszPattern=wordPairs[0];
571                              break;
572                   case 6:    /* next line for mode */
573                              ppFiletypeData[nfiletypes]->pszPermissions=wordPairs[0];
574                              break;
575                   case 7:    /* next line for contents */
576                              ppFiletypeData[nfiletypes]->pszContents=wordPairs[0];
577                              break;
578
579                  default:    break;
580               }
581            }
582            else if(wordPairs && wordPairs[1])
583            {
584               switch(fldid)
585               {
586                   case 0:   /* first line for filetype_name */
587                             ppFiletypeData[nfiletypes]->pszName = wordPairs[1];
588                             break;
589
590                   case 1:   /* first line for icon_name */
591                             ppFiletypeData[nfiletypes]->pszIcon=wordPairs[1];
592                             break;
593
594                   case 2 :  /* first line for help_text */
595                             ppFiletypeData[nfiletypes]->pszHelp=wordPairs[1];
596                             break;
597
598                   case 3:   /* first line for print_cmd */
599                             ppFiletypeData[nfiletypes]->pszPrintCmd=wordPairs[1];
600                             manflds++;
601                             break;
602
603                   case 4:   /* first line for name_pattern or path_pattern */
604                             ppFiletypeData[nfiletypes]->pszPattern=wordPairs[1];
605                             break;
606
607                   case 5:   /* first line for name_pattern or path_pattern */
608                             ppFiletypeData[nfiletypes]->pszPattern=wordPairs[1];
609                             break;
610
611                   case 6:   /* first line for mode */
612                             ppFiletypeData[nfiletypes]->pszPermissions=wordPairs[1];
613                             break;
614
615                   case 7:   /* first line for contents */
616                             ppFiletypeData[nfiletypes]->pszContents=wordPairs[1];
617                             break;
618
619                  default:   break;
620               }
621
622            }
623
624               bzero(linebuf,sizeof(linebuf));
625         } /* end of while fgets */
626
627         /* Done with retrieving FiletypeData */
628         /* Check if we got all the mandatory fields data */
629         if( (previous == ACTION_OPEN  && manflds != 4) ||
630             (previous == ACTION_PRINT  && manflds != 4)   )
631             return NULL;
632         else if(ppFiletypeData)
633         {
634             /* Process Contents for the last file filetype if any */
635             if(ProcessContents((FiletypeData *)ppFiletypeData[nfiletypes]) < 0)
636                           {
637                                 printf("\n Error in Contents Data\n");
638                                 return NULL;
639                           }
640             /* Everything looks right so process the exec_string */
641             if(!(execstr =
642                     ProcessExecString((char *)ppFiletypeData[nfiletypes]->pszPrintCmd)) )
643                 ppFiletypeData[nfiletypes]->pszPrintCmd=NULL;
644             else
645                 ppFiletypeData[nfiletypes]->pszPrintCmd=execstr[0];
646             if( !ppFiletypeData[nfiletypes])
647                 ppFiletypeData[nfiletypes] = 0;
648             /* return number of filetypes */
649             *nftypes = nfiletypes+1;
650             return ppFiletypeData;
651
652         }
653         else
654             return NULL;
655
656 }
657
658 /*****************************************************************
659 **                                                              **
660 ** GetKeywordValuePairs(char *s, int *id, int table)            **
661 **                                                              **
662 ** Description: Parses the text string in *s and returns a      **
663 **              pointer to two strings that are Keyword and     **
664 **              values.However, it returns the complete string  **
665 **              in the first pointer if keyword not found.      **
666 **                                                              **
667 ** Input      : A character pointer pointing to text string.    **
668 **              An integer pointer to return the field id.      **
669 **              An integer value that determines which table to **
670 **              use (either ACTION_TABLE of FILETYPE_TABLE).    **
671 **              see definitions in parser.h                     **
672 **                                                              **
673 ** Output     : pointer to two pointers pointing to text strings**
674 **              fieldid in the id parameter.                    **
675 **                                                              **
676 ** references : dtcreate.h, parser.h, and dtcreate spec.        **
677 **                                                              **
678 ******************************************************************/
679
680 char **
681 GetKeywordValuePairs(char *s, int *id, int table)
682 {
683     char    *wordStart;
684     static int fldid=-1;
685     int        idx;
686
687         args[0] = args[1] = args[2] = NULL;
688         /* Skip all leading spaces */
689         while (*s && isspace (*s))
690             ++s;
691         /* Skip the complete line if a '#' character is found (comments)  */
692         if (!*s || *s == '#')
693             return NULL;
694         wordStart = s;
695         while (*s && *s != '#' && !isspace (*s))
696             ++s;
697         if (!args[0])
698         {
699             int szArgs0 = s - wordStart + 1;
700             args[0] = (char *)malloc (szArgs0);
701             if (!args[0])
702                 return NULL;
703             memset(args[0],0,szArgs0);
704         }
705         strncpy (args[0], wordStart, s - wordStart);
706         args[0][s-wordStart] = '\0';
707         if (!args[1])
708         {
709             int szArgs1 = strlen(s) + 1;
710             if(s)
711                args[1] = (char *)malloc (szArgs1);
712             if (!args[1])
713             {
714                 if(args[0])
715                 free(args[0]);
716                 return NULL;
717             }
718             memset(args[1],0,szArgs1);
719         }
720         /* Skip all leading spaces */
721         while (*s && isspace (*s))
722             ++s;
723         strcpy (args[1], s);
724         args[2]=NULL;
725         /* Check for whether args[0] is a keyword or not */
726         idx=0;
727         if( table == ACTION_TABLE )
728         {
729            /* Check for keyword in keywordDB defined in parser.h */
730            while((strcmp(keywordDB[idx],"")) && (strcmp(args[0],keywordDB[idx])) ) idx++;
731            if(idx >= 0 && idx < MAX_NUM_ACTION_FIELDS)
732               fldid = idx;
733         }
734         else if( table == FILETYPE_TABLE )
735         {
736            /* Check for keyword in FiletypekeywordDB defined in parser.h */
737            while((strcmp(FiletypekeywordDB[idx],"")) && (strcmp(args[0],FiletypekeywordDB[idx])) ) idx++;
738            if(idx >= 0 && idx < MAX_NUM_FILETYPE_FIELDS)
739               fldid = idx;
740         }
741         /* If no keyword found then keep the complete string
742            in the first array
743         */
744         if( (idx == MAX_NUM_ACTION_FIELDS && table == ACTION_TABLE)  ||
745             (idx == MAX_NUM_FILETYPE_FIELDS && table == FILETYPE_TABLE) )
746         {
747            char *temp4;
748
749            if( (temp4 = (char *)realloc(args[0],strlen(args[0])+strlen(args[1])+2) ) == NULL )
750            {
751                 printf("Cannot Allocate memory\n");
752                 return NULL;
753            }
754            args[0] = temp4;
755            strcat(args[0]," ");
756            strcat(args[0],args[1]);
757
758            if(args[1])
759            {
760               free(args[1]);
761               args[1]=NULL;
762            }
763            if( IsLastSingle(args[0]) && args[0][strlen(args[0])-1] == '\\' )
764                args[0][strlen(args[0])-1] = '\0';
765            if( (temp4 = (char *)realloc(fline,flinesize+strlen(args[0])+1)) == NULL)
766            {
767                 printf("Cannot Allocate memory\n");
768                 return NULL;
769            }
770           strcat(temp4,args[0]);
771           free(args[0]);
772           args[0]=temp4;
773         }
774
775     *id = fldid;  /* return field id   */
776     if(args[1] && IsLastSingle(args[1]) && args[1][strlen(args[1])-1] == '\\')
777        args[1][strlen(args[1])-1] = '\0';
778     if(args[0])
779         args[0][strlen(args[0])] = '\0';
780     if(args[1])
781         args[1][strlen(args[1])] = '\0';
782     if(args[0] && args[1])
783     {
784         fline = args[1];
785         flinesize=strlen(fline);
786     }
787     if(!args[1] && args[0])
788     {
789         fline = args[0];
790         flinesize=strlen(fline);
791     }
792     return args;
793 }
794
795
796 /*****************************************************************
797 **                                                              **
798 ** ProcessExecString(char *)                                    **
799 **                                                              **
800 ** Description: Parses the text string and returns two pointers,**
801 **              the first pointing to cmd part (if any)         **
802 **              the second pointing to prompt part (if any)     **
803 **              of either the ActionData structure type or      **
804 **              FiletypeData structure type. Please see         **
805 **              dtcreate.h for the above mentioned datastructure**
806 **              definitions and for the cmd and prompt fields   **
807 **                                                              **
808 ** Input      : A character pointer that points to the complete **
809 **              text string comprising the command and arguments**
810 **              and prompt (if any).                            **
811 **                                                              **
812 ** Limitation : Supports only ONE prompt.                       **
813 **                                                              **
814 ** Output     : Pointer to 3-element result array from malloc,  **
815 **              or NULL on error                                **
816 **                                                              **
817 ** Assumptions: a) Arg fields start with a '%' character.       **
818 **              b) Prompt string start and end with '"' chara-  **
819 **                 cter. Also, the prompt string comes after    **
820 **                 the Arg strings if any.                      **
821 **                                                              **
822 ** references : dtcreate.h, parser.h, and dtcreate spec.        **
823 **                                                              **
824 ******************************************************************/
825
826 char **
827 ProcessExecString(char *cmd)
828 {
829
830 char *s1, *s2,*s3,*s4,*argbuf,**exec_args;
831 int  done=FALSE, argfound=FALSE,promptfound=FALSE;
832
833         if (!cmd) {
834            return((char **)NULL);
835         }
836         s1=s2=s3=s4=argbuf=NULL;
837         exec_args = calloc(3, sizeof(char*));
838         if (!exec_args) return NULL;
839         /* Allocate buffer for the cmd string */
840         exec_args[0] = (char *)calloc(1,strlen(cmd)+1);
841         exec_args[1] = exec_args[2] = NULL;
842         /* check if any Args present */
843         s1=cmd;
844         while( !done )
845         {
846                 char *tmp;
847                 tmp=NULL;
848                 s4 = strstr(s1,"%Arg");
849                 if(s4)
850                 {
851                       if ( (s4-s1) > 0 )
852                       {
853                           strncat(exec_args[0],s1,(s4-s1));
854                           exec_args[0][strlen(exec_args[0])] = '\0';
855                       }
856                       s1 = s4;
857                       s2 = strchr(s1+1,'%');  /* at this point we got s1 to s2
858                                              covers the complete string
859                                              between %'s
860                                             */
861                       if(argbuf) { free(argbuf); argbuf = NULL; }
862                       if(s2)
863                       {
864                          argbuf = (char *)calloc(1,(s2-s1)+2);
865                          strncpy(argbuf,s1,(s2-s1)+1);
866                       }
867                       else
868                       {
869                          strcat(exec_args[0],s1);
870                          done=TRUE;
871                          continue;
872                       }
873                       argbuf[strlen(argbuf)]='\0';
874                       if( strncmp(argbuf,"%Arg_",5) &&
875                                strncmp(argbuf,"%Args%",6) &&
876                                strncmp(argbuf,"%Args\"",6)   )
877                       {
878                            strncat(exec_args[0],argbuf,strlen(argbuf)-1);
879                            exec_args[0][strlen(exec_args[0])] = '\0';
880                            s1=s2;
881                            continue;
882                       }
883                 }
884                 else if (s1 && *s1)
885                 {
886                      strcat(exec_args[0],s1);
887                      if(argbuf)   { free(argbuf); argbuf = NULL; }
888                      done = TRUE;
889                      continue;
890                 }
891                 else
892                 {
893                      done = TRUE;
894                      continue;
895                 }
896
897                   /* move s1 until a '_' or 's' */
898                   tmp = strchr(argbuf,'_');
899                   if(!tmp)
900                       tmp= strchr(argbuf,'s');
901                   strcat(exec_args[0],"$");
902                   argfound=TRUE;
903                   /* start of Arg processing */
904                   while (*tmp != '%' && *tmp != '"' )
905                   {
906                       if(*tmp == 's')
907                       {
908                          strcat(exec_args[0],"*");
909                          break;
910                       }
911                       if( *tmp > '0' && *tmp <= '9')
912                       {
913                          strncat(exec_args[0],tmp,1);
914                          exec_args[0][strlen(exec_args[0])] = '\0';
915                       }
916                       tmp++;
917                   }
918                 /* end of Arg processing */
919
920                 /* Get Prompt string if any */
921                 s3 = strchr(argbuf,'"');
922                 if(s3 && *(s3+1) != '"')
923                 {
924                       s3++;
925                       if(!promptfound)
926                       {
927                           if( (tmp = strchr(s3,'"')) )
928                           {
929                                promptfound=TRUE;
930                                exec_args[1] = (char *)calloc(1,(tmp-s3)+1);
931                                strncpy(exec_args[1],s3,(tmp-s3));
932                                exec_args[1][strlen(exec_args[1])] = '\0';
933                           }
934                       }
935                 }
936
937                 /* see if there is some stuff between the last '%'
938                    and the next first '%' of another Arg
939                 */
940                 if( argfound) s2++;
941                 argfound = FALSE;
942                 s1=s2;
943          }
944          if(argbuf) { free(argbuf); argbuf = NULL; }
945    return exec_args;
946 }
947
948 /*****************************************************************
949 **                                                              **
950 ** ProcessContents(FiletypeData *)                              **
951 **                                                              **
952 ** Description: Parses the text string in pszContents field and **
953 **              fills the sStart,fsFlags and pszContents fields **
954 **              of the filetypeData datastructure that is passed**
955 **              as input.                                       **
956 **                                                              **
957 ** Input      : A pointer of type FiletypeData defined in       **
958 **              dtcreate.h                                      **
959 **                                                              **
960 ** Output     : Fills the sStart, fsFlags and pszContents fields**
961 **              of the FiletypeData pointer and returns 0 (No   **
962 **              error or >0 (error) values.                     **
963 **                                                              **
964 ** Assumptions: Fields are separated by atleast one blank       **
965 **              character.                                      **
966 **                                                              **
967 ** references : dtcreate.h, parser.h, and dtcreate spec.        **
968 **                                                              **
969 ******************************************************************/
970
971 int
972 ProcessContents(FiletypeData *pFtD)
973 {
974
975 char    *s1,*tmp,*s2,buf[10],*cts;
976
977         s1=s2=tmp=cts=NULL;
978         bzero(buf,sizeof(buf));
979         /* simply return if there is no data in contents field */
980         if(!pFtD->pszContents)
981            return (0);
982         cts = (char *)calloc(1,strlen(pFtD->pszContents)+1);
983         strcpy(cts,pFtD->pszContents);
984         s1=cts;
985         free(pFtD->pszContents);
986         pFtD->pszContents=NULL;
987         /* Skip all leading spaces */
988         while( *s1 && isspace(*s1) )  s1++;
989         /* Get the sStart value if any */
990 /*
991         if( (s1 = strchr(cts,' ')) )
992 */
993         while( *s1 && !isspace(*s1) && *s1 != '\n') s1++;
994         if((s1-cts) > 0)
995         {
996            strncpy(buf,cts,(s1-cts));
997            buf[s1-cts]='\0';
998            pFtD->sStart=atoi(buf);
999         }
1000         while( *s1 && isspace(*s1) )  s1++;
1001
1002         /* Get the fsFlags value if any */
1003         tmp=s1;
1004         bzero(buf,sizeof(buf));
1005 /*
1006         if ( (tmp = strchr(s1,' ')) )
1007 */
1008         while( *tmp && !isspace(*tmp) && *tmp != '\n') tmp++;
1009         if((tmp-s1) > 0)
1010         {
1011            strncpy(buf,s1,(tmp-s1));
1012            buf[tmp-s1]='\0';
1013            if ( !strcmp(buf,"byte") )
1014                pFtD->fsFlags|=CA_FT_CNTBYTE;
1015            else if ( !strcmp(buf,"string") )
1016                pFtD->fsFlags|=CA_FT_CNTSTRING;
1017            else if ( !strcmp(buf,"long") )
1018                pFtD->fsFlags|=CA_FT_CNTLONG;
1019            else if ( !strcmp(buf,"short") )
1020                pFtD->fsFlags|=CA_FT_CNTSHORT;
1021            else
1022                return (-1);
1023         }
1024         while( *tmp && isspace(*tmp) )  tmp++;
1025         s2=tmp;
1026         /* Get the contents if any */
1027         if (*s2)
1028         {
1029               pFtD->pszContents =  (char *)calloc(1,strlen(s2)+1);
1030               strcpy(pFtD->pszContents,s2);
1031               free(cts);
1032
1033         }
1034
1035
1036  return 0;
1037 }
1038
1039 /*****************************************************************
1040 **                                                              **
1041 ** IsLastSingle(char *str)                                      **
1042 **                                                              **
1043 ** Description: returns TRUE if the last character of the       **
1044 **              string str is a single-byte character, returns  **
1045 **              FALSE if it is a multi-byte character.          **
1046 **                                                              **
1047 ******************************************************************/
1048
1049 Boolean
1050 IsLastSingle(char *str)
1051 {
1052     int n;
1053
1054     if(MB_CUR_MAX == 1)
1055         return(TRUE);
1056
1057     while(*str) {
1058         n = mblen(str, MB_CUR_MAX);
1059         str += n;
1060     }
1061     if(n > 1)
1062         return(FALSE);
1063     else
1064         return(TRUE);
1065 }