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