|
|
1.1 root 1: /* $Header: gram.y,v 1.6 87/05/24 22:11:00 jg Exp $ */
2:
3:
4: /*
5: * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
6: *
7: * All Rights Reserved
8: *
9: * Permission to use, copy, modify, and distribute this software and its
10: * documentation for any purpose and without fee is hereby granted,
11: * provided that the above copyright notice appear in all copies and that
12: * both that copyright notice and this permission notice appear in
13: * supporting documentation, and that the name of Digital Equipment
14: * Corporation not be used in advertising or publicity pertaining to
15: * distribution of the software without specific, written prior permission.
16: *
17: *
18: * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
19: * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
20: * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
21: * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22: * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
23: * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
24: * SOFTWARE.
25: */
26:
27:
28: /*
29: * MODIFICATION HISTORY
30: *
31: * 000 -- M. Gancarz, DEC Ultrix Engineering Group
32: * 001 -- Loretta Guarino Reid, DEC Ultrix Engineering Group
33: * Western Software Lab. Convert to X11.
34: */
35:
36: %{
37: #ifndef lint
38: static char *sccsid = "@(#)gram.y 3.8 1/24/86";
39: #endif
40:
41: #include <X11/copyright.h>
42: #include "uwm.h"
43:
44: /*
45: * Values returned by complex expression parser.
46: */
47: #define C_STRING 1 /* IsString. */
48: #define C_MENU 2 /* IsMenu. */
49: #define C_MAP 3 /* IsMap. */
50: #define C_MENUMAP 4 /* IsMenuMap. */
51:
52: static int ki; /* Keyword index. */
53: static int bkmask; /* Button/key mask. */
54: static int cmask; /* Context mask. */
55: static char msg[BUFSIZ]; /* Error message buffer. */
56: static char *menu_name; /* Menu name. */
57: static MenuInfo *menu_info; /* Menu info. */
58: static MenuLine *ml_ptr; /* Temporary menu line pointer. */
59: static char *hcolors[4]; /* Color values used in menu hdrs. */
60: static char *mcolors[2]; /* Color values used in menus. */
61: MenuLink *menu_link; /* Temporary menu link pointer. */
62:
63: char *calloc();
64:
65: %}
66:
67: %union {
68: char *sval;
69: int ival;
70: short shval;
71: struct _menuline *mlval;
72: struct _menuinfo *mival;
73: char **cval;
74: }
75:
76: %token NL
77: %token <sval> STRING
78: %token <ival> COMMENT
79: %type <ival> keyword
80: %type <ival> compexpr
81: %type <ival> keyexpr
82: %type <ival> kmask
83: %type <ival> contexpr
84: %type <ival> contmask
85: %type <ival> buttmodexpr
86: %type <ival> buttmodifier
87: %type <ival> buttexpr
88: %type <sval> menuname
89: %type <sval> strings
90: %type <sval> color
91: %type <cval> color2
92: %type <cval> color4
93: %type <mlval> menuexpr
94: %type <mlval> menulist
95: %type <mlval> menuline
96: %type <mlval> menuaction
97:
98: %% /* beginning of rules section */
99:
100: input: | input command
101: | input error command { yyerrok; }
102: ;
103:
104: command: boolvar term
105: | expr term
106: | COMMENT { Lineno++; }
107: | term
108: ;
109:
110: term: NL { Lineno++; }
111: | ';'
112: ;
113:
114: expr: keyword '=' compexpr
115: {
116: switch (KeywordTable[$1].type) {
117: case IsString:
118: if ($3 == C_STRING) {
119: strcpy(KeywordTable[$1].sptr,
120: yylval.sval);
121: } else {
122: yyerror("illegal construct");
123: }
124: free(yylval.sval);
125: break;
126: case IsNumeric:
127: if ($3 == C_STRING) {
128: *(KeywordTable[$1].nptr) =
129: y_atoi(yylval.sval);
130: } else yyerror("illegal construct");
131: free(yylval.sval);
132: break;
133: case IsBoolTrue:
134: case IsBoolFalse:
135: yyerror("illegal value assignment");
136: break;
137: case IsQuitFunction:
138: case IsFunction:
139: if ($3 == C_MAP) {
140: bindtofunc($1, bkmask, cmask, NULL);
141: } else yyerror("illegal construct");
142: break;
143: case IsDownFunction:
144: if (bkmask & ButtonUp) {
145: sprintf(msg,
146: "cannot bind %s to button up",
147: KeywordTable[$1].name);
148: yyerror(msg);
149: }
150: if ($3 == C_MAP) {
151: bindtofunc($1, bkmask, cmask, NULL);
152: } else yyerror("illegal construct");
153: break;
154: case IsMenuMap:
155: if (bkmask & ButtonUp) {
156: sprintf(msg,
157: "cannot bind %s to button up",
158: KeywordTable[$1].name);
159: yyerror(msg);
160: }
161: if ($3 == C_MENUMAP) {
162: bindtofunc
163: ($1, bkmask, cmask, menu_name);
164: } else yyerror("illegal construct");
165: break;
166: case IsMenu:
167: if ($3 == C_MENU) {
168: menu_info = stashmenuinfo(menu_name, ml_ptr, hcolors);
169: menu_link = stashmenulink(menu_info);
170: Menus = appendmenulink(Menus, menu_link);
171: } else yyerror("illegal menu construct");
172: break;
173: default:
174: yyerror("internal binding error");
175: break;
176: }
177: }
178: ;
179:
180: compexpr: keyexpr ':' contexpr ':' buttexpr
181: {
182: $$ = C_MAP;
183: bkmask = $1 | $5;
184: cmask = $3;
185: }
186: | keyexpr ':' contexpr ':' buttexpr ':' menuname
187: {
188: $$ = C_MENUMAP;
189: bkmask = $1 | $5;
190: cmask = $3;
191: menu_name = $7;
192: }
193: | STRING color4 menuexpr
194: {
195: $$ = C_MENU;
196: menu_name = $1;
197: ml_ptr = $3;
198: }
199: | STRING
200: { $$ = C_STRING; }
201: ;
202:
203: boolvar: STRING
204: {
205: ki = keywordlookup(yylval.sval);
206: switch (KeywordTable[ki].type) {
207: case IsBoolTrue:
208: *(KeywordTable[ki].bptr) = TRUE;
209: break;
210: case IsBoolFalse:
211: *(KeywordTable[ki].bptr) = FALSE;
212: break;
213: case IsParser:
214: (*KeywordTable[ki].fptr)();
215: break;
216: default:
217: yyerror("keyword error");
218: }
219: }
220: ;
221:
222: keyword: STRING {
223: $$ = keywordlookup(yylval.sval);
224: }
225: ;
226:
227: keyexpr: /* empty */
228: { $$ = 0; }
229: | kmask
230: { $$ = $1; }
231: | kmask '|' kmask
232: { $$ = $1 | $3; }
233: ;
234:
235: contexpr: /* empty */
236: { $$ = ROOT | WINDOW | ICON; }
237: | contmask
238: { $$ = $1; }
239: | contmask '|' contmask
240: { $$ = $1 | $3; }
241: | contmask '|' contmask '|' contmask
242: { $$ = $1 | $3 | $5; }
243: ;
244:
245: buttexpr: buttmodexpr
246: { $$ = CheckButtonState($1); }
247: ;
248:
249: kmask: STRING { $$ = keyexprlookup(yylval.sval); }
250:
251: contmask: STRING { $$ = contexprlookup(yylval.sval); }
252:
253: buttmodexpr: buttmodifier
254: { $$ = $1; }
255: | buttmodexpr buttmodifier
256: { $$ = $1 | $2; }
257: ;
258:
259: buttmodifier: STRING
260: { $$ = buttexprlookup(yylval.sval); }
261: ;
262:
263: menuname: STRING
264: { $$ = $1; }
265: ;
266:
267: menuexpr: '{' menulist '}'
268: { $$ = $2; }
269: ;
270:
271: menulist: menuline
272: { $$ = $1; }
273: | menulist menuline
274: { $$ = appendmenuline($1, $2); }
275: | menulist COMMENT
276: {
277: Lineno++;
278: $$ = $1;
279: }
280: | COMMENT
281: {
282: Lineno++;
283: $$ = NULL;
284: }
285: | term
286: { $$ = NULL; }
287: | menulist term
288: { $$ = $1; }
289: | error term
290: {
291: $$ = NULL;
292: yyerrok;
293: }
294: ;
295:
296: menuline: strings ':' color2 menuaction term
297: {
298: $4->name = $1;
299: $4->foreground = mcolors[0];
300: $4->background = mcolors[1];
301: $$ = $4;
302: }
303: ;
304:
305: menuaction: STRING
306: {
307: ki = keywordlookup(yylval.sval);
308: if ((ki != -1) &&
309: (KeywordTable[ki].type != IsFunction) &&
310: (KeywordTable[ki].type != IsQuitFunction) &&
311: (KeywordTable[ki].type != IsDownFunction)) {
312: sprintf(msg,
313: "menu action \"%s\" not a function",
314: KeywordTable[ki].name);
315: yyerror(msg);
316: }
317: ml_ptr = AllocMenuLine();
318: if (KeywordTable[ki].type == IsQuitFunction)
319: ml_ptr->type = IsImmFunction;
320: else ml_ptr->type = IsUwmFunction;
321: ml_ptr->func = KeywordTable[ki].fptr;
322: $$ = ml_ptr;
323: }
324: | STRING ':' menuname
325: {
326: ki = keywordlookup($1);
327: if (ki != -1 &&
328: KeywordTable[ki].type != IsMenuMap) {
329: sprintf(msg,
330: "menu action \"%s\" not a menu function",
331: KeywordTable[ki].name);
332: yyerror(msg);
333: }
334: ml_ptr = AllocMenuLine();
335: ml_ptr->type = IsMenuFunction;
336: ml_ptr->text = $3;
337: $$ = ml_ptr;
338: }
339: | '!' strings
340: {
341: $$ = StashMenuLine(IsShellCommand, $2);
342: }
343: | '^' strings
344: {
345: $$ = StashMenuLine(IsTextNL, $2);
346: }
347: | '|' strings
348: {
349: $$ = StashMenuLine(IsText, $2);
350: }
351: ;
352:
353: strings: STRING { $$ = yylval.sval; }
354: | strings STRING
355: { $$ = strconcat($1, $2); }
356: ;
357:
358: color4: '(' color ':' color ':' color ':' color ')'
359: {
360: hcolors[0] = $2;
361: hcolors[1] = $4;
362: hcolors[2] = $6;
363: hcolors[3] = $8;
364: $$ = hcolors;
365: }
366: | /* empty */
367: {
368: hcolors[0] = NULL;
369: hcolors[1] = NULL;
370: hcolors[2] = NULL;
371: hcolors[3] = NULL;
372: $$ = hcolors;
373: }
374: ;
375:
376: color2: '(' color ':' color ')' ':'
377: {
378: mcolors[0] = $2;
379: mcolors[1] = $4;
380: $$ = mcolors;
381: }
382: | /* empty */
383: {
384: mcolors[0] = NULL;
385: mcolors[1] = NULL;
386: $$ = mcolors;
387: }
388: ;
389:
390: color: STRING { $$ = yylval.sval; }
391: | /* empty */ { $$ = NULL; }
392: ;
393: %%
394:
395: /*
396: * Look up a string in the keyword table and return its index, else
397: * return -1.
398: */
399: keywordlookup(string)
400: char *string;
401: {
402: int i;
403:
404: for (i = 0; KeywordTable[i].name; i++) {
405: if (!strcmp(KeywordTable[i].name, string)) {
406: free(string);
407: return(i);
408: }
409: }
410: sprintf(msg,"keyword error: \"%s\"", string);
411: yyerror(msg);
412: free(string);
413: return(-1);
414: }
415:
416: /*
417: * Look up a string in the key expression table and return its mask, else
418: * return -1.
419: */
420: int keyexprlookup(string)
421: char *string;
422: {
423: int i;
424:
425: for (i = 0; KeyExprTbl[i].name; i++) {
426: if (!strcmp(KeyExprTbl[i].name, string)) {
427: free(string);
428: return(KeyExprTbl[i].mask);
429: }
430: }
431: sprintf(msg,"key expression error: \"%s\"", string);
432: yyerror(msg);
433: free(string);
434: return(-1);
435: }
436:
437: /*
438: * Look up a string in the context expression table and return its mask, else
439: * return -1.
440: */
441: contexprlookup(string)
442: char *string;
443: {
444: int i;
445:
446: for (i = 0; ContExprTbl[i].name; i++) {
447: if (!strcmp(ContExprTbl[i].name, string)) {
448: free(string);
449: return(ContExprTbl[i].mask);
450: }
451: }
452: sprintf(msg,"context expression error: \"%s\"", string);
453: yyerror(msg);
454: free(string);
455: return(-1);
456: }
457: /*
458: * Look up a string in the button expression table and return its mask, else
459: * return -1.
460: */
461: buttexprlookup(string)
462: char *string;
463: {
464: int i;
465:
466: for (i = 0; ButtModTbl[i].name; i++) {
467: if (!strcmp(ButtModTbl[i].name, string)) {
468: free(string);
469: return(ButtModTbl[i].mask);
470: }
471: }
472: sprintf(msg,"button modifier error: \"%s\"", string);
473: yyerror(msg);
474: free(string);
475: return(-1);
476: }
477:
478: /*
479: * Scan a string and return an integer. Report an error if any
480: * non-numeric characters are found.
481: */
482: y_atoi(s)
483: char *s;
484: {
485: int n = 0;
486:
487: while (*s) {
488: if (*s >= '0' && *s <= '9')
489: n = 10 * n + *s - '0';
490: else {
491: yyerror("non-numeric argument");
492: return(-1);
493: }
494: s++;
495: }
496: return(n);
497: }
498:
499: /*
500: * Append s2 to s1, extending s1 as necessary.
501: */
502: char *
503: strconcat(s1, s2)
504: char *s1, *s2;
505: {
506: char *malloc();
507: char *p;
508:
509: p = malloc(strlen(s1) + strlen(s2) + 2);
510: sprintf(p, "%s %s", s1, s2);
511: free(s1);
512: free(s2);
513: s1 = p;
514: return(s1);
515: }
516:
517: /*
518: * Check a button expression for errors.
519: */
520: int
521: CheckButtonState(expr)
522: int expr;
523: {
524: /*
525: * Check for one (and only one) button.
526: */
527: switch (expr & (LeftMask | MiddleMask | RightMask)) {
528: case 0:
529: yyerror("no button specified");
530: break;
531: case LeftMask:
532: break;
533: case MiddleMask:
534: break;
535: case RightMask:
536: break;
537: default:
538: yyerror("more than one button specified");
539: }
540:
541: /*
542: * Check for one (and only one) up/down/motion modifier.
543: */
544: switch (expr & (ButtonUp | ButtonDown | DeltaMotion)) {
545: case 0:
546: yyerror("no button action specified");
547: break;
548: case ButtonUp:
549: break;
550: case ButtonDown:
551: break;
552: case DeltaMotion:
553: break;
554: default:
555: yyerror("only one of up/down/motion may be specified");
556: }
557: return(expr);
558: }
559:
560: /*
561: * Bind button/key/context to a function.
562: */
563: bindtofunc(index, mask, context, name)
564: int index; /* Index into keyword table. */
565: int mask; /* Button/key/modifier mask. */
566: int context; /* ROOT, WINDOW, or ICON. */
567: char *name; /* Menu, if needed. */
568: {
569: if (context & ROOT)
570: setbinding(ROOT, index, mask, name);
571: if (context & ICON)
572: setbinding(ICON, index, mask, name);
573: if (context & WINDOW)
574: setbinding(WINDOW, index, mask, name);
575: }
576:
577: /*
578: * Allocate a Binding type and return a pointer.
579: */
580: Binding *
581: AllocBinding()
582: {
583: Binding *ptr;
584:
585: if (!(ptr = (Binding *)calloc(1, sizeof(Binding)))) {
586: fprintf(stderr, "Can't allocate binding--out of space\n");
587: exit(1);
588: }
589: return(ptr);
590: }
591:
592: /*
593: * Stash the data in a Binding.
594: */
595: setbinding(cont, i, m, mname)
596: int cont; /* Context: ROOT, WINDOW, or ICON. */
597: int i; /* Keyword table index. */
598: int m; /* Key/button/modifier mask. */
599: char *mname; /* Pointer to menu name, if needed. */
600: {
601: Binding *ptr;
602:
603: ptr = AllocBinding();
604: ptr->context = cont;
605: ptr->mask = m;
606: ptr->func = KeywordTable[i].fptr;
607: ptr->menuname = mname;
608:
609: switch (m & (LeftMask | MiddleMask | RightMask)) {
610: case LeftMask:
611: ptr->button = LeftButton;
612: break;
613: case MiddleMask:
614: ptr->button = MiddleButton;
615: break;
616: case RightMask:
617: ptr->button = RightButton;
618: break;
619: }
620: appendbinding(ptr);
621: }
622:
623: /*
624: * Append a Binding to the Bindings list.
625: */
626: appendbinding(binding)
627: Binding *binding;
628: {
629: Binding *ptr;
630:
631: if (Blist == NULL)
632: Blist = binding;
633: else {
634: for(ptr = Blist; ptr->next; ptr = ptr->next) /* NULL */;
635: ptr->next = binding;
636: ptr = ptr->next;
637: ptr->next = NULL;
638: }
639: }
640:
641: /*
642: * Allocate a menu line and return a pointer.
643: */
644: MenuLine *
645: AllocMenuLine()
646: {
647: MenuLine *ptr;
648:
649: if (!(ptr = (MenuLine *)calloc(1, sizeof(MenuLine)))) {
650: fprintf(stderr, "Can't allocate menu line--out of space\n");
651: exit(1);
652: }
653: return(ptr);
654: }
655:
656: /*
657: * Allocate a MenuInfo structure and return a pointer.
658: */
659: MenuInfo *
660: AllocMenuInfo()
661: {
662: MenuInfo *ptr;
663:
664: if (!(ptr = (MenuInfo *)calloc(1, sizeof(MenuInfo)))) {
665: fprintf(stderr, "Can't allocate menu storage--out of space\n");
666: exit(1);
667: }
668: return(ptr);
669: }
670:
671: /*
672: * Allocate a MenuLink structure and return a pointer.
673: */
674: MenuLink *
675: AllocMenuLink()
676: {
677: MenuLink *ptr;
678:
679: if (!(ptr = (MenuLink *)calloc(1, sizeof(MenuLink)))) {
680: fprintf(stderr, "Can't allocate menu linked list storage--out of space\n");
681: exit(1);
682: }
683: return(ptr);
684: }
685:
686: /*
687: * Stash the data in a menu line.
688: */
689: MenuLine *
690: StashMenuLine(type, string)
691: int type;
692: char *string;
693: {
694: MenuLine *ptr;
695:
696: ptr = AllocMenuLine();
697: ptr->type = type;
698: ptr->text = string;
699: return(ptr);
700: }
701:
702: /*
703: * Stash menu data in a MenuInfo structure;
704: */
705: MenuInfo *
706: stashmenuinfo(name, line, colors)
707: char *name;
708: MenuLine *line;
709: char *colors[];
710: {
711: MenuInfo *ptr;
712:
713: ptr = AllocMenuInfo();
714: ptr->name = name;
715: ptr->line = line;
716: ptr->foreground = colors[1];
717: ptr->background = colors[0];
718: ptr->fghighlight = colors[2];
719: ptr->bghighlight = colors[3];
720: return(ptr);
721: }
722:
723: /*
724: * Stash menu info data in a MenuLink structure;
725: */
726: MenuLink *
727: stashmenulink(menuinfo)
728: MenuInfo *menuinfo;
729: {
730: MenuLink *ptr;
731:
732: ptr = AllocMenuLink();
733: ptr->next = NULL;
734: ptr->menu = menuinfo;
735: return(ptr);
736: }
737:
738: /*
739: * Append a menu line to a linked list of menu lines.
740: */
741: MenuLine *
742: appendmenuline(list, line)
743: MenuLine *list;
744: MenuLine *line;
745: {
746: MenuLine *ptr;
747:
748: if (list == NULL)
749: list = line;
750: else {
751: for(ptr = list; ptr->next; ptr = ptr->next) /* NULL */;
752: ptr->next = line;
753: ptr = ptr->next;
754: ptr->next = NULL;
755: }
756: return(list);
757: }
758:
759: /*
760: * Append a menu to a linked list of menus.
761: */
762: MenuLink *
763: appendmenulink(list, link)
764: MenuLink *list;
765: MenuLink *link;
766: {
767: MenuLink *ptr;
768:
769: if (list == NULL)
770: list = link;
771: else {
772: for(ptr = list; ptr->next; ptr = ptr->next) /* NULL */;
773: ptr->next = link;
774: ptr = ptr->next;
775: ptr->next = NULL;
776: }
777: return(list);
778: }
779:
780: /*
781: * Reset all previous bindings and free the space allocated to them.
782: */
783: Bool ResetBindings()
784: {
785: Binding *ptr, *nextptr;
786:
787: for(ptr = Blist; ptr; ptr = nextptr) {
788: if(ptr->menuname) free(ptr->menuname);
789: nextptr = ptr->next;
790: free(ptr);
791: }
792: Blist = NULL;
793: }
794:
795: /*
796: * De-allocate all menus.
797: */
798: Bool ResetMenus()
799: {
800: MenuLink *mptr, *next_mptr;
801: register MenuLine *lptr, *next_lptr;
802:
803: for(mptr = Menus; mptr; mptr = next_mptr) {
804: free(mptr->menu->name);
805: for(lptr = mptr->menu->line; lptr; lptr = next_lptr) {
806: free(lptr->name);
807: if (lptr->text) free(lptr->text);
808: next_lptr = lptr->next;
809: free(lptr);
810: }
811: next_mptr = mptr->next;
812: free(mptr);
813: }
814: Menus = NULL;
815: }
816:
817: /*
818: * Set all numeric variables to zero and all boolean variables to FALSE.
819: */
820: Bool ResetVariables()
821: {
822: register int i;
823:
824: for (i = 0; KeywordTable[i].name; i++) {
825: switch (KeywordTable[i].type) {
826: case IsBoolTrue:
827: case IsBoolFalse:
828: *(KeywordTable[i].bptr) = FALSE;
829: break;
830: case IsNumeric:
831: *(KeywordTable[i].nptr) = 0;
832: break;
833: default:
834: break;
835: }
836: }
837: SetVarDefaults();
838: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.