1 %{ /*-*- Mode: C -*-*/
2 /**************************************************************************
3  ** Filename :       parser.y                                            **
4  ** Author   :       Edward Groenendaal                                  **
5  ** Date     :       31/1/91                                             **
6  ** Purpose  :       Parse the xdtm config file, build the data          **
7  **                  structures.                                         **
8  ** Changes  :       18-04-92, Edward Groenendaal                        **
9  **                  Added #if NeedFunctionPrototypes stuff              **
10  **************************************************************************/
11 /* touched by Lionel Mallet - 10/2/92 */
12 
13 #ifdef DEBUG_YACC
14 #include <X11/Intrinsic.h>
15 #endif
16 
17 #define YYDEBUG     1	/* allow yacc debugging */
18 #include "xdtm.h"
19 #include "parse.h"
20 #include "Ext/appl.h"
21 
22 #ifdef XPM
23 #include "xpm.h"
24 #endif
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <memory.h>
29 
30 #ifdef HAS_STRSTR
31 #define mystrstr(cs, ct)	strstr(cs, ct)
32 #else
33 extern char *mystrstr(char *, char *);
34 #endif
35 
36 #if defined(sco386) && defined(M_INTERNAT)   /* jcc */
37 #undef M_INTERNAT
38 #endif
39 
40 /* structure used to hold loaded bitmaps (pixmaps), the pixmaps referenced
41  * in the icon list are pointing into this structure.
42  */
43 typedef struct _iconTree {
44   String fullname;       /* index on this */
45   Pixmap icon;
46   Pixmap mask;
47   struct _iconTree *left;
48   struct _iconTree *right;
49 } iconTree;
50 
51 /* The variable stack frame, this stack holds the stack frames for use in
52  * calculating the scope of local variables in the config language.
53  */
54 typedef struct _varStack {
55   String *defpath;		/* path in this stack */
56   Cardinal dirinpath;		/* Number of dirs in path */
57   Boolean checkpath;		/* Whether to match over the whole path */
58   iconSelection *iconsel;       /* The level at which new iconprograms will
59 				 * be inserted.
60 				 */
61   iconPrefs *iconpref;		/* The point into the main icon structure
62 				 * at which this frame's results will be
63 				 * inserted.
64 				 */
65   typePrefs *current;		/* The level at which the new iconprefs
66 				 * will be inserted.
67 				 */
68   struct _varStack *next;	/* Next link in stack */
69 } varStack;
70 
71 /* Declarations of procedures defined after they have been referenced */
72 #if NeedFunctionPrototypes
73 public  typePrefs *newTypePref(void);
74 public  void       freeTypePref(typePrefs*);
75 private void       start_block(typePrefs*,iconPrefs*);
76 private void       end_block(void);
77 private String    *stringtopath(String, Cardinal*);
78 private int        lookupicon(String, Pixmap*, Pixmap*);
79 private iconPrefs *inserticonpref(iconPrefs*, iconPrefs*);
80 private String     strip_quotes(String);
81 private int        get_pixmap(String, iconTree**, Pixmap*, Pixmap*);
82 private void       set_path(String);
83 private void       set_icon(String, Boolean);
84 private void       set_deficon(String);
85 private void       set_cmd_is_first(void);
86 private void       newselection(String);
87 public  void       freeAppSelection(AppSelection*);
88 private void       setapp(int, String);
89 public  iconPrefs *newIconPref(void);
90 private void       freeIconPref(iconPrefs*);
91 private String     ExpandEnvVars(String);
92 private void       NewIconSelection(String);
93 private void       freeIconSelection(iconSelection*);
94 private void       NewIconProgram(String, String, int);
95 private void       freeAppProgram(AppProgram*);
96 private iconSelection *InsertIconSelection(iconSelection*, iconSelection*);
97 private iconSelection *InsertIconProgram(iconSelection*, AppProgram*);
98 private void       init_structs(void);
99 private void       free_structs(void);
100 private void       new_re(String re);
101 private void       new_type(int n);
102 private void       set_cmd(String s, int termopts);
103 
104 /* imported variables/procedures */
105 extern int parseerror;            /* quantity of parse errors so far */
106 extern int yylineno;              /* line number being parsed */
107 extern void yyerror(char *); /* normal error printing routine */
108 
109 #else
110 public  typePrefs *newTypePref();
111 public  void       freeTypePref();
112 private void       start_block();
113 private void       end_block();
114 private String    *stringtopath();
115 private int        lookupicon();
116 private iconPrefs *inserticonpref();
117 private String     strip_quotes();
118 private int        get_pixmap();
119 private void       set_path();
120 private void       set_icon();
121 private void       set_deficon();
122 private void       set_cmd_is_first();
123 private void       newselection();
124 public  void       freeAppSelection();
125 private void       setapp();
126 public  iconPrefs *newIconPref();
127 private void       freeIconPref();
128 private String     ExpandEnvVars();
129 private void       NewIconSelection();
130 private void       freeIconSelection();
131 private void       NewIconProgram();
132 private void       freeAppProgram();
133 private iconSelection *InsertIconSelection();
134 private iconSelection *InsertIconProgram();
135 private void       init_structs();
136 private void       free_structs();
137 private void       new_re();
138 private void       new_type();
139 private void       set_cmd();
140 
141 /* imported variables/procedures */
142 extern int parseerror;            /* quantity of parse errors so far */
143 extern int yylineno;              /* line number being parsed */
144 extern void yyerror();            /* normal error printing routine */
145 #endif
146 
147 #ifndef DEBUG_YACC
148 extern Widget topLevel;
149 #endif
150 
151 /* Variable declarations */
152 public  AppSelection **appselections;
153 public  typePrefs     *prefs;          /* preferneces */
154 private varStack      *varframe;       /* stack frames */
155 private iconTree      *icontable;      /* table of pixmaps */
156 private AppSelection  *current_selection;
157 private Cardinal       listindex;      /* index into current appprogram list */
158 private Cardinal       currentlistmax; /* current list appprogram size */
159 public  Cardinal       selectionindex; /* index into appselections */
160 
161 %} /* Start of YACC declarations */
162 
163 %start xdtmrc
164 
165 %union                              /* valid types */
166 {
167     int  number;                     /* number */
168     char *string;                    /* string */
169 }
170 
171 /* declare terminals with their types */
172 
173 %token <string> STRING_T
174 %token <number> IF_T SET_T ICON_T NAME_T PATH_T DEFICON_T TYPE_T CHECKPATH_T
175 %token <number> CMD_T
176 %token <number> TRUE_T FALSE_T IGNORE_T
177 %token <number> DIR_T FILE_T READ_T WRITE_T EXE_T BLOCK_T CHARACTER_T SLINK_T
178 %token <number> SOCKET_T FIFO_T
179 %token <number> MSEL_T OSEL_T NSEL_T ASEL_T DEFINE_T PROG_T OPTIONS_T TERMOPT_T
180 %token <number> DEFAPPL_T TERM_T NOTERM_T FIRST_T
181 %token <number> ASSIGN_T EQUAL_T SEMIC_T COMMA_T COLON_T
182 %token <number> O_PAR_T C_PAR_T O_BRACE_T C_BRACE_T
183 %token <value>  EOFTOKEN ERRORTOKEN
184 
185 /* types of non-terminals */
186 %type <string> identifier
187 %type <number> block type var option xdtmrc termopt
188 
189 %%    /* Beginning of rule section */
190 
191 xdtmrc       :   { init_structs(); }
192                  statements
193                  defines
194                  { free_structs(); }
195              ;
196 statements   :   /* Empty */
197              |   statements statement
198              ;
199 statement    :   ifstatement
200              |   setstatement SEMIC_T
201              |   setcmdstmt
202              |   defappl
203              ;
204 defines      :   defines define
205              |   define
206              ;
207 ifstatement  :   IF_T O_PAR_T expression C_PAR_T block
208              ;
209 setstatement :   SET_T var ASSIGN_T identifier { switch ($2) {
210                                                  case PATH_T:
211                                                    set_path($4);
212 						   break;
213 						 case ICON_T:
214 						   set_icon($4, False);
215 						   break;
216 						 case DEFICON_T:
217 						   set_deficon($4);
218 						   break;
219 						 }
220 					       }
221              |   SET_T CHECKPATH_T ASSIGN_T TRUE_T
222                        { varframe->checkpath = True; }
223              |   SET_T CHECKPATH_T ASSIGN_T FALSE_T
224                        { varframe->checkpath = False; }
225              |   SET_T IGNORE_T
226                        { set_icon("", True);}
227              ;
228 setcmdstmt   :   SET_T CMD_T ASSIGN_T FIRST_T SEMIC_T
229                        { set_cmd_is_first(); }
230              |   SET_T CMD_T ASSIGN_T identifier COMMA_T termopt SEMIC_T
231                        { set_cmd($4, $6);}
232              |   SET_T CMD_T ASSIGN_T identifier SEMIC_T
233                        { set_cmd($4, NOTERM);}
234 define       :   DEFINE_T identifier {newselection($2);} ASSIGN_T defineblock
235              ;
236 defappl      :   DEFAPPL_T identifier {NewIconSelection($2);} ASSIGN_T
237                  applblock
238              ;
239 block        :   O_BRACE_T
240                  statements {end_block();}
241                  C_BRACE_T
242              ;
243 defineblock  :   O_BRACE_T descriptions C_BRACE_T
244                  {current_selection->number = listindex;}
245              ;
246 applblock    :   O_BRACE_T appldescs C_BRACE_T
247              ;
248 descriptions :   /* Empty */
249              |   descriptions description
250              ;
251 appldescs    :   /* Empty */
252              |   appldescs appldesc
253              ;
254 description  :   O_BRACE_T
255 
256                  { /* Allocate a new AppProgram */
257 #ifndef DEBUG_YACC
258 		   current_selection->list[listindex] =
259 		     (AppProgram*) XtMalloc (sizeof(AppProgram));
260 		   current_selection->list[listindex]->count = 0;
261 #endif
262 		 }
263 
264                  NAME_T ASSIGN_T identifier SEMIC_T {setapp($3, $5);}
265 		 ICON_T ASSIGN_T identifier SEMIC_T {setapp($8, $10);}
266                  PROG_T ASSIGN_T identifier SEMIC_T {setapp($13, $15);}
267                  OPTIONS_T ASSIGN_T option SEMIC_T  {setapp($18, (String)$20);}
268                  optional_termopt
269                  {
270 #ifndef DEBUG_YACC
271                   /* Increment listindex, Thanks to Johan Widen for catching
272 		   * a bug here in version 1.0.
273 		   */
274 		   if (++listindex == currentlistmax) {
275 		     currentlistmax += APPPINC;
276 		     current_selection->list =
277 		       (AppProgram**)XtRealloc((char *)current_selection->list,
278 						sizeof(AppProgram*) *
279 						currentlistmax);
280 		   }
281 #endif
282 		 }
283 
284                  C_BRACE_T
285              ;
286 appldesc     :   O_BRACE_T identifier COLON_T identifier COMMA_T termopt
287                     C_BRACE_T
288                  {NewIconProgram($2, $4, $6);}
289              |   O_BRACE_T identifier COLON_T identifier
290                     C_BRACE_T
291                  {NewIconProgram($2, $4, NOTERM);}
292              ;
293 option       :   MSEL_T | OSEL_T | NSEL_T | ASEL_T
294              ;
295 optional_termopt: /* nothing */ {setapp(TERMOPT_T, (String)NOTERM);}
296              |   TERMOPT_T ASSIGN_T termopt SEMIC_T {setapp($1, (String)$3);}
297              ;
298 termopt      :   TERM_T        { $$ = TERM; }
299              |   NOTERM_T      { $$ = NOTERM; }
300              ;
301 expression   :   NAME_T EQUAL_T identifier { new_re($3); }
302              |   TYPE_T EQUAL_T type       { new_type($3); }
303              ;
304 identifier   :   STRING_T      {  $$=strip_quotes($1);
305 			       }
306              ;
307 type         :   DIR_T   | READ_T      | WRITE_T | EXE_T   | FILE_T   |
308                  BLOCK_T | CHARACTER_T | FIFO_T  | SLINK_T | SOCKET_T
309              ;
310 var          :   PATH_T | ICON_T | DEFICON_T
311              ;
312 %%
313 
314 /*****************************************************************************
315  *                               init_structs                                *
316  *****************************************************************************/
317 private void init_structs()
318 {
319   /* Initialise structures.. wow what a suprise :-) */
320 
321   Cardinal n;
322 
323 #ifdef DEBUG_YACC
324     XtToolkitInitialize();
325 #endif
326   /* Icon prefs = an empty type pref */
327   prefs = newTypePref();
328 
329   /* Icon table is empty, no icons loaded yet */
330   icontable = NULL;
331 
332   /* Default top level stack frame */
333   varframe = (varStack*) XtMalloc (sizeof(varStack));
334   varframe->defpath = stringtopath("/usr/lib/X11/bitmaps", &n);
335   varframe->dirinpath = n;
336   varframe->current = prefs;
337   varframe->checkpath = False;
338   varframe->iconpref = NULL;
339   varframe->next = NULL;
340 
341   /* initialise the Application Selection Lists Array */
342   listindex = 0;	/* First entry in the new selection list */
343   selectionindex = -1;  /* First selection list is 0 in the array */
344   appselections = (AppSelection**) XtMalloc (sizeof(AppSelection*) * APPPSIZE);
345 }
346 
347 /*****************************************************************************
348  *                              free_structs                                 *
349  *****************************************************************************/
free_structs()350 private void free_structs()
351 {
352   /* This procedure is called just before the parsing finishes, it free's
353    * the memory allocated to the internal structures used by the parser.
354    * Note: Doesn't get all of them.. but let's not get petty, what's a few
355    *       bytes once only in a program of this size?
356    */
357 
358   if (!parseerror) {
359     /* Free Varstack (Should Be Only One Level Left) */
360     XtFree((char *)varframe);
361 
362     selectionindex++; /* So that we know the correct number of selections */
363   }
364 }
365 
366 /*****************************************************************************
367  *                                newTypePref                                *
368  *****************************************************************************/
newTypePref()369 public typePrefs *newTypePref()
370 {
371   /* Allocate the memory for a new empty typePref, I suppose this
372    * procedure is not really needed on most machines, but what if
373    * a machine doesn't automatically fill all entries in a structure
374    * with NULL's ?
375    */
376 
377   typePrefs *tp;
378 
379   if (!parseerror) {
380     tp = (typePrefs*) XtMalloc (sizeof(typePrefs));
381     tp->iconprefs = NULL;
382     tp->dir = NULL;
383     tp->file = NULL;
384     tp->block = NULL;
385     tp->character = NULL;
386     tp->fifo = NULL;
387     tp->slink = NULL;
388     tp->socket = NULL;
389     tp->exe = NULL;
390     tp->read = NULL;
391     tp->write = NULL;
392 
393     return tp;
394   }
395   return (typePrefs *)NULL;
396 }
397 
398 /*****************************************************************************
399  *                                freeTypePref                                *
400  *****************************************************************************/
freeTypePref(tp)401 public void freeTypePref(tp)
402 typePrefs *tp;
403 {
404   /* Recursively free the memory for a typePref
405    */
406   if (tp == NULL) return;
407 
408   freeIconPref(tp->iconprefs);
409   freeTypePref(tp->dir);
410   freeTypePref(tp->file);
411   freeTypePref(tp->block);
412   freeTypePref(tp->character);
413   freeTypePref(tp->fifo);
414   freeTypePref(tp->slink);
415   freeTypePref(tp->socket);
416   freeTypePref(tp->exe);
417   freeTypePref(tp->read);
418   freeTypePref(tp->write);
419 
420   XtFree((char *)tp);
421 }
422 
423 /*****************************************************************************
424  *                                newIconPref                                *
425  *****************************************************************************/
newIconPref()426 public iconPrefs *newIconPref()
427 {
428   /* Allocate the memory for a new empty iconPref, I suppose this
429    * procedure is not really needed on most machines, but what if
430    * a machine doesn't automatically fill all entries in a structure
431    * with NULL's ?
432    */
433 
434   iconPrefs *ip;
435 
436   ip = (iconPrefs*) XtMalloc (sizeof(iconPrefs));
437   ip->expbuf = NULL;
438   ip->checkpath = False;
439   ip->extra = NULL;
440   ip->icon = None;
441   ip->mask = None;
442   ip->user_data = NULL;
443   ip->cmd_is_first = False;
444   ip->select = NULL;
445   ip->next = NULL;
446 
447   return(ip);
448 }
449 
450 /*****************************************************************************
451  *                                freeIconPref                                *
452  *****************************************************************************/
freeIconPref(ip)453 private void freeIconPref(ip)
454 iconPrefs *ip;
455 {
456   /* Recursively free the memory for an iconPref
457    */
458   if (ip == NULL) return;
459 
460   freeIconPref(ip->next);
461   if (ip->expbuf != NULL) XtFree((char *)ip->expbuf);;
462   freeTypePref((typePrefs *)ip->extra);
463   if (ip->user_data != NULL) {
464     if (ip->cmd_is_first == False) freeAppProgram(ip->user_data->cmd);
465     if (ip->user_data->menu != NULL)
466       XtDestroyWidget(ip->user_data->menu);
467     XtFree((char *)ip->user_data);
468   }
469   freeIconSelection(ip->select);
470 
471   XtFree((char *)ip);
472 }
473 
474 /*****************************************************************************
475  *                                start_block                                *
476  *****************************************************************************/
start_block(newpref,iconpref)477 private void start_block(newpref, iconpref)
478 typePrefs *newpref;
479 iconPrefs *iconpref;
480 {
481   /* A new block has been entered, create a new stack frame, inherit most
482    * stuff from the previous stack frame.
483    */
484 
485   /* Push new stack frame */
486   varStack *newframe;
487 
488   if (!parseerror) {
489     newframe = (varStack*) XtMalloc (sizeof(varStack));
490     newframe->defpath = varframe->defpath;
491     newframe->dirinpath = varframe->dirinpath;
492     newframe->current = newpref;
493     newframe->checkpath = varframe->checkpath;
494     newframe->iconpref = iconpref;
495     newframe->next = varframe;
496     varframe = newframe;
497   }
498 }
499 
500 /*****************************************************************************
501  *                                    end_block                              *
502  *****************************************************************************/
end_block()503 private void end_block()
504 {
505   /* End the current stack frame, check to see if the extra part of
506    * the iconPref has been used, if not free it.
507    * Pop the current stack from off the stack.
508    */
509 
510   if (!parseerror) {
511 
512     iconPrefs *tmpIconPref;
513     typePrefs *tmp = varframe->current;
514     varStack *tmpframe = varframe->next;
515 
516     if (tmp->iconprefs == NULL && tmp->dir == NULL &&
517 	tmp->file == NULL      && tmp->exe == NULL &&
518 	tmp->read == NULL      && tmp->write == NULL) {
519       XtFree((char *)tmp);
520       tmp = NULL;
521       tmpIconPref = varframe->iconpref;
522       tmpIconPref->extra = NULL;
523     }
524     XtFree((char *)varframe);
525     varframe = tmpframe;
526   }
527 }
528 
529 /*****************************************************************************
530  *                                     new_re                                *
531  *****************************************************************************/
new_re(re)532 private void new_re(re)
533 String re;
534 {
535   /* Create a new iconpref, put the compiled regular expression in it then
536    * insert it into the current iconprefs.
537    *
538    * - Takes a regular expression in the original string format. eg. "\.c$"
539    */
540 
541   if (!parseerror) {
542     iconPrefs *new, *tmp = varframe->current->iconprefs;
543 
544     new = newIconPref();
545     new->extra = (XtPointer) newTypePref();
546     new->expbuf = regcomp(re);
547     new->checkpath = varframe->checkpath;
548     varframe->current->iconprefs = inserticonpref(tmp, new);
549     start_block((typePrefs*)new->extra, (iconPrefs*)new);
550   }
551 }
552 
553 /*****************************************************************************
554  *                               new_type                                    *
555  *****************************************************************************/
new_type(n)556 private void new_type(n)
557 int n;
558 {
559   /* Allocate a typePref on dir, write etc. if neadbe, otherwise ignore
560    *
561    * - Takes a number representing which file feature to insert the typePref
562    *   on.
563    */
564 
565   if (!parseerror) {
566     typePrefs *typeprefs = varframe->current;
567     typePrefs *newpref = NULL;
568 
569     switch(n) {
570     case DIR_T:
571       if (typeprefs->dir == NULL)
572 	typeprefs->dir = newTypePref();
573       newpref = typeprefs->dir;
574       break;
575     case FILE_T:
576       if (typeprefs->file == NULL)
577 	typeprefs->file = newTypePref();
578       newpref = typeprefs->file;
579       break;
580     case BLOCK_T:
581       if (typeprefs->block == NULL)
582 	typeprefs->block = newTypePref();
583       newpref = typeprefs->block;
584       break;
585     case CHARACTER_T:
586       if (typeprefs->character == NULL)
587 	typeprefs->character = newTypePref();
588       newpref = typeprefs->character;
589       break;
590     case FIFO_T:
591       if (typeprefs->fifo == NULL)
592 	typeprefs->fifo = newTypePref();
593       newpref = typeprefs->fifo;
594       break;
595     case SLINK_T:
596       if (typeprefs->slink == NULL)
597 	typeprefs->slink = newTypePref();
598       newpref = typeprefs->slink;
599       break;
600     case SOCKET_T:
601       if (typeprefs->socket == NULL)
602 	typeprefs->socket = newTypePref();
603       newpref = typeprefs->socket;
604       break;
605     case EXE_T:
606       if (typeprefs->exe == NULL)
607 	typeprefs->exe = newTypePref();
608       newpref = typeprefs->exe;
609       break;
610     case READ_T:
611       if (typeprefs->read == NULL)
612 	typeprefs->read = newTypePref();
613       newpref = typeprefs->read;
614       break;
615     case WRITE_T:
616       if (typeprefs->write == NULL)
617 	typeprefs->write = newTypePref();
618       newpref = typeprefs->write;
619       break;
620     }
621     start_block(newpref, NULL);
622   }
623 }
624 
625 /*****************************************************************************
626  *                                   count_chr                               *
627  *****************************************************************************/
count_chr(s,c)628 public Cardinal count_chr(s, c)
629 String s;
630 char c;
631 {
632   /* Given a String and a character this function counts the number of
633    * occurences of that character in the string and returns the result.
634    *
635    * - Takes a string s within which to check for character c.
636    */
637 
638   Cardinal count=0;
639 
640   while(*s != '\0') {
641     if (*s == c) count++;
642     s++;
643   }
644   return count;
645 }
646 
647 /*****************************************************************************
648  *                                  stringtopath                             *
649  *****************************************************************************/
stringtopath(s,n)650 private String *stringtopath(s, n)
651 String s;
652 Cardinal *n;
653 {
654   /* Split a path into directories, put these into a linked list
655    * only directories starting with / or ~/ are allowed.
656    *
657    * - Takes a string containing the path delimited by colons, and
658    *   a pointer within which the number of directories in the
659    *   path is left.
660    * + Returns an array of directories.
661    */
662   String *result;
663   String p, tmp;
664 #ifdef DEBUG_YACC
665   String home;
666 #else
667   extern String home;
668 #endif
669 
670   *n = 0;
671 
672 #ifdef DEBUG_YACC
673     if ((home = (String) getenv("HOME")) == NULL) {
674     fprintf(stderr, "can\'t get environment variable HOME\n");
675     home = XtNewString("/");
676   } else
677     home = XtNewString(home);
678 #endif
679 
680   result = (String*) XtMalloc ((count_chr(s, ':')+3) * sizeof(String));
681   s = XtNewString(s);
682 
683   /* extract the directories from path 's' */
684 
685   p = strtok(s, ":");
686   while ( p != NULL) {
687     if (*p == '/')
688       result[(*n)++] = p;
689     else
690       if (*p == '~' && *(p+1) == '/') {
691 	tmp = (String) XtMalloc ((strlen(home) + strlen(p) + 2) * sizeof(char));
692 	strcpy(tmp, home);
693 	strcat(tmp, p+1);
694 	result[(*n)++] = tmp;
695       } else
696 	fprintf(stderr, "Warning: Directory \'%s\' not fully qualified, ignoring.\n%s",
697 		p, "         Must start with either / or ~/ .\n");
698     p = strtok(NULL, ":");
699   }
700 #ifdef DEBUG_YACC
701   XtFree((char *)home);
702 #endif
703   return(result);
704 }
705 
706 /*****************************************************************************
707  *                             inserticonpref                                *
708  *****************************************************************************/
inserticonpref(head,item)709 private iconPrefs *inserticonpref(head, item)
710 iconPrefs *head, *item;
711 {
712   /* Insert item into list starting with head, insert into the last
713    * position before the default.
714    *
715    * - Takes the head of the iconpref list and the iconpref list entry to
716    *   be inserted.
717    * + Returns the new iconpref list with the item inserted.
718    */
719 
720   iconPrefs *sec = NULL, *tmp = head;
721 
722   if (head == NULL) {
723     /* first element */
724     head=item;
725     head->next=NULL;
726   } else {
727     while (tmp->next != NULL) {
728       sec = tmp;
729       tmp = tmp->next;
730     }
731     if (tmp->expbuf == NULL) {
732       /* Already got a default */
733       if (item->expbuf != NULL) {
734 	/* Item is not a new default */
735 	item->next = tmp;
736 	if (sec != NULL)
737 	  sec->next = item;
738 	else
739 	  head = item;
740       } else { /* item->expbuf == NULL */
741 	  if ((tmp->icon == DUMMY) && (item->icon != DUMMY))
742 	    /* copy item icon into default iconPrefs */
743 	    tmp->icon = item->icon;
744 	  if (item->select != NULL) {
745 	      /* copy item iconSelection list into default iconPrefs */
746 	      iconSelection *head = tmp->select, *itemtmp = item->select ;
747 	      while (itemtmp != NULL) {
748 		  tmp->select = InsertIconSelection(head, itemtmp);
749 		  itemtmp = itemtmp->next;
750 	      }
751 	  }
752 	  if (!tmp->cmd_is_first && item->cmd_is_first)
753 	    tmp->cmd_is_first = True;
754 	  XtFree((char *)item);
755       }
756     } else { /* tmp->expbuf != NULL */
757       /* No default */
758       tmp->next = item;
759       item->next = NULL;
760     }
761   }
762   return(head);
763 }
764 
765 /*****************************************************************************
766  *                              strip_quotes                                 *
767  *****************************************************************************/
strip_quotes(s)768 private String strip_quotes(s)
769 String s;
770 {
771   /* This function is for stripping the first and last characters from a
772    * string. It is used for stripping the quotes off strings.
773    *
774    * - Takes a String with quotes.
775    * - Returns the String with quotes missing.
776    */
777   String new;
778 
779   *(s + (strlen(s)-1)) = '\0';
780   s++;
781   new = ExpandEnvVars(s);
782 
783   /* s is NOT free'd because it was supplied from the lexical analyzer,
784    * it's up to that to free it.
785    */
786   return(new);
787 }
788 
789 /*****************************************************************************
790  *                                 set_path                                  *
791  *****************************************************************************/
set_path(s)792 private void set_path(s)
793 String s;
794 {
795   /* Given a string containing a list of directories delimited by colons
796    * this procedure inserts these directories in teh form of an array of
797    * strings into the current stack frame.
798    */
799   Cardinal n;
800 
801   varframe->defpath = stringtopath(s, &n);
802   varframe->dirinpath = n;
803 }
804 
805 /*****************************************************************************
806  *                                set_icon                                   *
807  *****************************************************************************/
808 #if NeedFunctionPrototypes
set_icon(String s,Boolean ignore)809 private void set_icon(String s, Boolean ignore)
810 #else
811 private void set_icon(s, ignore)
812 String s;
813 Boolean ignore;
814 #endif
815 {
816   /* varframe->iconpref points to the iconpref into which this
817    * icon should be inserted. If it is NULL, then create a new
818    * one at varframe->current->iconprefs.
819    *
820    * - Takes an icon filename and/or a flag saying whether the current
821    *   iconpref should be ignored.
822    */
823 
824   typePrefs *frame = varframe->current;
825   iconPrefs *iconpref = varframe->iconpref,
826             *head = frame->iconprefs,
827             *new =  NULL;
828   int status;
829 
830   if (iconpref == NULL) {
831     new = newIconPref();
832     if (ignore==True) {
833       new->icon = DUMMY;
834     } else {
835       status = lookupicon(s, &(new->icon), &(new->mask));
836     }
837     frame->iconprefs = inserticonpref(head, new);
838   } else
839     if (ignore==True) {
840       iconpref->icon = DUMMY;
841     } else {
842       status = lookupicon(s, &(iconpref->icon), &(iconpref->mask));
843     }
844 }
845 
846 /*****************************************************************************
847  *                                set_deficon                                *
848  *****************************************************************************/
set_deficon(s)849 private void set_deficon(s)
850 String s;
851 {
852   /* Set the default icon in the current iconprefs list.
853    *
854    * - Takes the filename of the icon to be used.
855    */
856 
857   typePrefs *frame = varframe->current;
858   iconPrefs *iconpref, *head = frame->iconprefs;
859   int status;
860 
861   iconpref = newIconPref();
862   status = lookupicon(s, &(iconpref->icon), &(iconpref->mask));
863   frame->iconprefs = inserticonpref(head, iconpref);
864 
865 }
866 
867 /*****************************************************************************
868  *                                set_cmd_is_first                                   *
869  *****************************************************************************/
set_cmd_is_first()870 private void set_cmd_is_first()
871 {
872   /* varframe->iconpref points to the iconpref into which cmd_is_first
873    * should be set to True. If it is NULL, then create a new
874    * one at varframe->current->iconprefs.
875    *
876    */
877 
878   typePrefs *frame = varframe->current;
879   iconPrefs *iconpref = varframe->iconpref,
880             *head = frame->iconprefs,
881             *new =  NULL;
882 
883   if (iconpref == NULL) {
884     new = newIconPref();
885     new->cmd_is_first = True;
886     frame->iconprefs = inserticonpref(head, new);
887   } else
888     iconpref->cmd_is_first = True;
889 }
890 
891 /*****************************************************************************
892  *                                set_cmd                                    *
893  *****************************************************************************/
894 
set_cmd(s,termopts)895 private void set_cmd(s, termopts)
896 String s;
897 int termopts;
898 {
899   /* varframe->iconpref points to the iconpref into which this
900    * cmd should be inserted. If it is NULL, then create a new
901    * one at varframe->current->iconprefs.
902    */
903 
904   typePrefs *frame = varframe->current;
905   iconPrefs *iconpref = varframe->iconpref,
906             *head = frame->iconprefs,
907             *new =  NULL;
908   AppProgram *app = (AppProgram *) XtMalloc(sizeof(AppProgram));
909 #ifdef DEBUG_YACC
910     printf("DEBUG:        set_cmd %s\n", s);
911 #endif
912     app->string = XtNewString("default");
913     app->program = XtNewString(s);
914     app->options = O_SEL;
915     app->icon = (Pixmap)1; /* to avoid a bug in decrement_counter which uses
916 			      the icon field to know if node is dummy or not */
917     app->termopts = termopts;
918     app->count = 0;
919 
920   if (iconpref == NULL) {
921     /* A new iconpref.. insert the command, leave the icon to be defined later
922      * if it is not defined the icon will NOT be displayed.
923      */
924     new = newIconPref();
925     new->cmd_is_first = True;
926 
927     frame->iconprefs = inserticonpref(head, new);
928     NewIconSelection("default");
929     iconpref = new;
930   } else {
931       iconpref->cmd_is_first = True;
932       if (!iconpref->select) NewIconSelection("default");
933   }
934   iconpref->select = InsertIconProgram(iconpref->select, app);
935 }
936 
937 /*****************************************************************************
938  *                             lookupicon                                    *
939  *****************************************************************************/
lookupicon(icon,pixmap,mask)940 private int lookupicon(icon, pixmap, mask)
941 String icon;
942 Pixmap *pixmap, *mask;
943 {
944   /* Return the pixmap associated with the name 'icon' if none
945    * found NULL is returned.
946    */
947 
948   int status = 0;
949   String *path = varframe->defpath;
950   Cardinal pathsize = varframe->dirinpath;
951   Cardinal n;
952   String fullname = NULL;
953   String tmp;
954   FILE *result;
955 
956   /* Append 'icon' to each filename in current path, and check to see
957    * whether that file exists.
958    */
959 
960   n = 0;
961   do {
962     tmp = (String) XtMalloc ((strlen(icon) + strlen(path[n]) + 4) * sizeof(char));
963     tmp = strcpy(tmp, path[n]);
964     tmp = strcat(tmp, "/");
965     tmp = strcat(tmp, icon);
966     if ((result = fopen(tmp, "r")) != NULL) {
967       fullname = XtNewString(tmp);
968       fclose(result);
969       if ((status = get_pixmap(fullname, &icontable, pixmap, mask)))
970       {
971 	  /* unable to load the pixmap, continue search in other dirs */
972 	  XtFree((char *)fullname);
973 	  fullname = NULL;
974       }
975     }
976     XtFree((char *)tmp);
977   } while ((++n < pathsize) && (fullname == NULL));
978 
979   if (fullname == NULL)
980     fprintf(stderr,
981 	    "Warning: could not find/load icon '%s', default icon will be used instead.\n",
982 	    icon);
983 
984   return status;
985 }
986 
987 /*****************************************************************************
988  *                               get_pixmap                                  *
989  *****************************************************************************/
get_pixmap(fullname,tree,pixmap,mask)990 private int get_pixmap(fullname, tree, pixmap, mask)
991      String fullname;
992      iconTree **tree;
993      Pixmap *pixmap, *mask;
994 {
995   /* If the item is found in the tree, then item's contents are filled
996    * with that items, otherwise the Pixmap is created and the item is
997    * inserted into the tree.
998    */
999 
1000   int cmp, value = 0;
1001   int width, height;
1002   int x_hot, y_hot;
1003 #if NeedFunctionPrototypes
1004     extern int XdtmLocateIconFile(Screen *,char *,Pixmap *, Pixmap *,
1005 				  int *, int *, int *, int *);
1006 #else
1007     extern int XdtmLocateIconFile();
1008 #endif
1009   Screen  *scr = XtScreen(topLevel);
1010 
1011   if (*tree == NULL) {
1012     /* At a leaf, insert item */
1013       iconTree *item = (iconTree*) XtMalloc (sizeof(iconTree));
1014       item->fullname = fullname;
1015       item->icon = (Pixmap)NULL;
1016       item->mask = (Pixmap)NULL;
1017 #ifndef DEBUG_YACC
1018       value =
1019 	XdtmLocateIconFile(
1020 			   scr,
1021 			   item->fullname,
1022 			   &(item->icon),
1023 			   &(item->mask),
1024 			   &width,
1025 			   &height,
1026 			   &x_hot,
1027 			   &y_hot);
1028 #else
1029       item->icon = (Pixmap) DUMMY;
1030       item->mask = (Pixmap) DUMMY;
1031       printf("DEBUG: Loaded bitmap for %s\n", item->fullname);
1032 #endif
1033       item->left = NULL;
1034       item->right = NULL;
1035       *tree = item;
1036       *pixmap = item->icon;
1037       *mask = item->mask;
1038   } else {
1039       if ((cmp = strcmp((*tree)->fullname, fullname)) == 0) {
1040 	  /* Found it !!! */
1041 	  *pixmap = (*tree)->icon;
1042 	  *mask = (*tree)->mask;
1043 	  XtFree((char *)fullname);
1044       } else
1045 	if (cmp < 0)
1046 	  value = get_pixmap(fullname, &((*tree)->left), pixmap, mask);
1047 	else
1048 	  value = get_pixmap(fullname, &((*tree)->right), pixmap, mask);
1049   }
1050   return value;
1051 }
1052 
1053 /*****************************************************************************
1054  *                              newselection                                 *
1055  *****************************************************************************/
newselection(selection)1056 private void newselection(selection)
1057 String selection;
1058 {
1059   /* increment selectionindex, put selection string into next
1060    * appselection, increase size if appselections array if needed.
1061    *
1062    * - Takes the name of the new selection
1063    */
1064 
1065   static selectionmax = APPPSIZE;
1066 
1067   if (++selectionindex == selectionmax) {
1068     selectionmax += APPPINC;
1069     appselections = (AppSelection **) XtRealloc ((char *)appselections,
1070 						 sizeof(AppSelection*) *
1071 						 selectionmax);
1072   }
1073 
1074 #ifdef DEBUG_YACC
1075   printf("DEBUG: New selection %s\n", selection);
1076 #endif
1077 
1078   listindex = 0;
1079   current_selection = appselections[selectionindex] =
1080     (AppSelection*) XtMalloc (sizeof(AppSelection));
1081   current_selection->name = XtNewString(selection);
1082   current_selection->number = listindex;
1083   current_selection->list = (AppProgram**) XtMalloc (sizeof(AppProgram*) *
1084 						     APPPSIZE);
1085   currentlistmax = APPPSIZE;
1086 }
1087 
1088 /*****************************************************************************
1089  *                              freeAppSelection                                 *
1090  *****************************************************************************/
freeAppSelection(selection)1091 public void freeAppSelection(selection)
1092 AppSelection *selection;
1093 {
1094   if (selection == NULL) return;
1095 
1096   if (selection->name != NULL) XtFree(selection->name);
1097   if (selection->list != NULL) {
1098     Cardinal i;
1099 
1100     for (i = 0; i < selection->number; i++)
1101       freeAppProgram(selection->list[i]);
1102 
1103     XtFree((char *)selection->list);
1104   }
1105 
1106   XtFree((char *)selection);
1107 }
1108 
1109 /*****************************************************************************
1110  *                               setapp                                      *
1111  *****************************************************************************/
setapp(type,argument)1112 private void setapp(type, argument)
1113 int type;
1114 String argument;
1115 {
1116   /* Set part of the current program in the current selection list,
1117    * the part to be set is contained in type, the value it is to be set
1118    * to contained within argument.
1119    */
1120 
1121   AppProgram **proglist = current_selection->list;
1122   AppProgram *node = proglist[listindex];
1123   int status;
1124 
1125   switch(type) {
1126   case NAME_T:
1127     node->string = XtNewString(argument);
1128 #ifdef DEBUG_YACC
1129     printf("String: %s\n", argument);
1130 #endif
1131     break;
1132   case ICON_T:
1133     status = lookupicon(argument, &(node->icon), &(node->mask));
1134     break;
1135   case PROG_T:
1136     node->program = XtNewString(argument);
1137 #ifdef DEBUG_YACC
1138     printf("Program: %s\n", argument);
1139 #endif
1140     break;
1141   case OPTIONS_T:
1142     switch((int)argument) {
1143     case MSEL_T:
1144       node->options = M_SEL;
1145 #ifdef DEBUG_YACC
1146       printf("MSEL\n");
1147 #endif
1148       break;
1149     case OSEL_T:
1150       node->options = O_SEL;
1151 #ifdef DEBUG_YACC
1152       printf("OSEL\n");
1153 #endif
1154       break;
1155     case NSEL_T:
1156       node->options = N_SEL;
1157 #ifdef DEBUG_YACC
1158       printf("NSEL\n");
1159 #endif
1160       break;
1161     case ASEL_T:
1162       node->options = A_SEL;
1163 #ifdef DEBUG_YACC
1164       printf("ASEL\n");
1165 #endif
1166       break;
1167     default:
1168       fprintf(stderr, "Programmer Error: Bad argument to setapp.\n");
1169       break;
1170     }
1171     break;
1172   case TERMOPT_T:
1173     node->termopts = (int)argument;
1174     break;
1175   default:
1176     fprintf(stderr, "Programmer Error: Bad argument to setapp.\n");
1177     break;
1178   }
1179 }
1180 
1181 /*****************************************************************************
1182  *                            InsertIconProgram                              *
1183  *****************************************************************************/
1184 #if NeedFunctionPrototypes
InsertIconProgram(iconSelection * sel,AppProgram * item)1185 private iconSelection *InsertIconProgram(iconSelection *sel, AppProgram *item)
1186 #else
1187 private iconSelection *InsertIconProgram(sel, item)
1188      iconSelection *sel;
1189      AppProgram *item;
1190 #endif
1191 {
1192     /* Insert item into list starting with sel->applist, insert into the first
1193      * position.
1194      *
1195      * - Takes the iconSelection and the iconProgram to be inserted.
1196      * + Return the new iconSelection with the item inserted in list.
1197      */
1198 
1199     AppProgram **tmplist = (AppProgram **)XtCalloc(sel->number + 1,
1200 						   sizeof(AppProgram *));
1201 /*    bcopy(sel->applist, &tmplist[1], sel->number * sizeof(AppProgram *));*/
1202     memcpy(&tmplist[1], sel->applist, sel->number * sizeof(AppProgram *));
1203     tmplist[0] = item;
1204 
1205     XtFree((char *)sel->applist);
1206     sel->applist = tmplist;
1207     sel->number += 1;
1208 
1209     return sel;
1210 }
1211 
1212 /*****************************************************************************
1213  *                            InsertIconSelection                            *
1214  *****************************************************************************/
1215 #if NeedFunctionPrototypes
InsertIconSelection(iconSelection * head,iconSelection * item)1216 private iconSelection *InsertIconSelection(iconSelection *head,
1217 					   iconSelection *item)
1218 #else
1219 private iconSelection *InsertIconSelection(head, item)
1220      iconSelection *head;
1221      iconSelection *item;
1222 #endif
1223 {
1224     /* Insert item ito list starting with head, insert into the last
1225      * position.
1226      *
1227      * - Takes the head of the iconSelection of the current iconPref and
1228      *   the iconSelection to be inserted.
1229      * + Return the new iconSelection list with the item inserted.
1230      */
1231 
1232     iconSelection *tmp = head;
1233 
1234     if (head == NULL) {
1235 	/* first element */
1236 	head = item;
1237 	head->next = NULL;
1238     } else {
1239 	while (tmp->next != NULL) tmp = tmp->next;
1240 	tmp->next = item;
1241 	item->next = NULL;
1242     }
1243     return(head);
1244 }
1245 
1246 /*****************************************************************************
1247  *                            ExpandEnvVars                                  *
1248  *****************************************************************************/
1249 #if NeedFunctionPrototypes
ExpandEnvVars(String program)1250 private String ExpandEnvVars(String program)
1251 #else
1252 private String ExpandEnvVars(program)
1253      String program;
1254 #endif
1255 {
1256   /* Given the program with it's previous arguments, this procedure
1257    * will replace all ${foo} sequence by the value of the foo environment
1258    * variable or nothing if it doesn't exist.
1259    *
1260    * - Takes the program string.
1261    * + Returns the resultant command line.
1262    */
1263 #define CHAR sizeof(char)
1264 
1265     Cardinal i = 0, j = 0;
1266     String var, value, tmpl = program, ptr, pos, posvar;
1267     String terminator = "}", mark = "${";
1268     String cmd = XtCalloc(1, sizeof(char));
1269 
1270     /* find next mark */
1271     while ((pos = mystrstr(tmpl, mark))) {
1272 	/* allocate enough space */
1273 	cmd = XtRealloc(cmd, (pos - tmpl) + CHAR * (i + 1));
1274 	/* copy up to mark */
1275 	for (ptr = tmpl; ptr < pos; ptr++) cmd[i++] = *ptr;
1276 	cmd[i] = 0;
1277 	pos += 2;
1278 
1279 	/* search for env var name */
1280 	j = 0;
1281 	posvar = pos;
1282 	pos = mystrstr(posvar, terminator);
1283 	var = XtMalloc((pos - posvar) + CHAR);
1284 	for (ptr = posvar; ptr < pos; ptr++) var[j++] = *ptr;
1285 	var[j] = 0;
1286 
1287 	if ((value = (String)getenv(var)) != NULL) {
1288 	    cmd = XtRealloc(cmd,
1289 			    CHAR * (strlen(cmd) + strlen(value) + 1));
1290 	    strcat(cmd, value);
1291 	} else {
1292 	    fprintf(stderr,
1293 		    "Xdtm: can\'t get environnement variable %s\n", var);
1294 	}
1295 	XtFree(var);
1296 	var = NULL;
1297 
1298 	i = strlen(cmd);
1299 	pos++;
1300 	tmpl = pos;
1301     }
1302 
1303     /* copy remaining template string */
1304     if (strlen(tmpl)) {
1305 	cmd = XtRealloc(cmd, CHAR * (strlen(cmd) + strlen(tmpl) + 1));
1306 	strcat(cmd, tmpl);
1307     }
1308 
1309     return cmd;
1310 }
1311 
1312 
1313 /*****************************************************************************
1314  *                            NewIconProgram                                 *
1315  *****************************************************************************/
1316 #if NeedFunctionPrototypes
NewIconProgram(String label,String program,int options)1317 private void NewIconProgram(String label, String program, int options)
1318 #else
1319 private void NewIconProgram(label, program, options)
1320      String label;
1321      String program;
1322      int options;
1323 #endif
1324 {
1325     /* Create a new IconProgram struct filled with label and program,
1326      * insert it in the IconProgram list of the current IconSelection.
1327      *
1328      * - Takes the label and program to put in the struct.
1329      */
1330 
1331     iconSelection *iconsel = varframe->iconsel;
1332     AppProgram *new = (AppProgram *) XtMalloc(sizeof(AppProgram));
1333 
1334 #ifdef DEBUG_YACC
1335     printf("DEBUG:        NewIconProgram %s %s\n", label, program);
1336 #endif
1337     new->string = XtNewString(label);
1338     new->program = XtNewString(program);
1339     new->options = O_SEL;
1340     new->icon = DUMMY; /* to avoid a bug in decrement_counter which uses
1341 			      the icon field to know if node is dummy or not */
1342     new->termopts = options;
1343     new->count = 0;
1344 
1345     if (iconsel->number > 0) {
1346 	iconsel->number += 1;
1347 	iconsel->applist = (AppProgram **)XtRealloc((char *)iconsel->applist,
1348 						    iconsel-> number *
1349 						    sizeof(AppProgram *));
1350     } else {
1351 	iconsel->number = 1;
1352 	iconsel->applist = (AppProgram **)XtMalloc(sizeof(AppProgram *));
1353     }
1354 
1355     iconsel->applist[iconsel->number - 1] = new;
1356 }
1357 
1358 /*****************************************************************************
1359  *                            freeAppProgram                                 *
1360  *****************************************************************************/
freeAppProgram(app)1361 private void freeAppProgram(app)
1362 AppProgram *app;
1363 {
1364   if (app == NULL) return;
1365 
1366   if (app->string != NULL) XtFree(app->string);
1367   if (app->program != NULL) XtFree(app->program);
1368 
1369   XtFree((char *)app);
1370 }
1371 
1372 /*****************************************************************************
1373  *                            NewIconSelection                               *
1374  *****************************************************************************/
1375 #if NeedFunctionPrototypes
NewIconSelection(String name)1376 private void NewIconSelection(String name)
1377 #else
1378 private void NewIconSelection(name)
1379      String name;
1380 #endif
1381 {
1382     /* Create a new IconSelection struct filled with name, insert it
1383      * in the IconSelection list of the current iconPref.
1384      *
1385      * - Takes the name of the IconSelection to put in the struct.
1386      */
1387 
1388     typePrefs *frame = varframe->current;
1389     iconPrefs *iconpref = varframe->iconpref,
1390               *headicon = frame->iconprefs;
1391     iconSelection *new = (iconSelection *) XtMalloc(sizeof(iconSelection)),
1392                   *head;
1393 #ifdef DEBUG_YACC
1394     printf("DEBUG: NewIconSelection %s\n", name);
1395 #endif
1396     new->name = XtNewString(name);
1397     new->applist = NULL;
1398     new->number = 0;
1399     new->next = NULL;
1400 
1401     if (iconpref == NULL) {
1402 	iconpref = newIconPref();
1403 	iconpref->select = new;
1404 	frame->iconprefs = inserticonpref(headicon, iconpref);
1405     }
1406     else {
1407 	head = iconpref->select;
1408 	iconpref->select = InsertIconSelection(head, new);
1409     }
1410     varframe->iconsel = new;
1411 }
1412 
1413 /*****************************************************************************
1414  *                            freeIconSelection                                 *
1415  *****************************************************************************/
freeIconSelection(selection)1416 private void freeIconSelection(selection)
1417 iconSelection *selection;
1418 {
1419 
1420   if (selection == NULL) return;
1421 
1422   if (selection->name != NULL) XtFree(selection->name);
1423   if (selection->applist != NULL) {
1424     Cardinal i;
1425 
1426     for (i=0; i < selection->number; i++)
1427       freeAppProgram(selection->applist[i]);
1428 
1429     XtFree((char *)selection->applist);
1430   }
1431 
1432   freeIconSelection(selection->next);
1433 
1434   XtFree((char *)selection);
1435 }
1436 
1437 #ifdef DEBUG_YACC
1438 
1439 /*****************************************************************************
1440  *                                 main                                      *
1441  *****************************************************************************/
main()1442 main()
1443 {
1444   /* main for use when the real main is not linked, because we're in debug mode.
1445    */
1446 
1447   yyparse();   /* Parse the stdin */
1448   return(0);   /* Hey, it probably worked */
1449 }
1450 #endif
1451