1 /*****************************************************************************/
2 /**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **/
3 /**                          Salt Lake City, Utah                           **/
4 /**  Portions Copyright 1989 by the Massachusetts Institute of Technology   **/
5 /**                        Cambridge, Massachusetts                         **/
6 /**                                                                         **/
7 /**                           All Rights Reserved                           **/
8 /**                                                                         **/
9 /**    Permission to use, copy, modify, and distribute this software and    **/
10 /**    its documentation  for  any  purpose  and  without  fee is hereby    **/
11 /**    granted, provided that the above copyright notice appear  in  all    **/
12 /**    copies and that both  that  copyright  notice  and  this  permis-    **/
13 /**    sion  notice appear in supporting  documentation,  and  that  the    **/
14 /**    names of Evans & Sutherland and M.I.T. not be used in advertising    **/
15 /**    in publicity pertaining to distribution of the  software  without    **/
16 /**    specific, written prior permission.                                  **/
17 /**                                                                         **/
18 /**    EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD    **/
19 /**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **/
20 /**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL EVANS & SUTHERLAND OR    **/
21 /**    M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL  DAM-    **/
22 /**    AGES OR  ANY DAMAGES WHATSOEVER  RESULTING FROM LOSS OF USE, DATA    **/
23 /**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **/
24 /**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **/
25 /**    OR PERFORMANCE OF THIS SOFTWARE.                                     **/
26 /*****************************************************************************/
27 
28 
29 /***********************************************************************
30  *
31  * $XConsortium: gram.y,v 1.91 91/02/08 18:21:56 dave Exp $
32  *
33  * .twmrc command grammer
34  *
35  * 07-Jan-86 Thomas E. LaStrange	File created
36  * 11-Nov-90 Dave Sternlicht            Adding SaveColors
37  * 10-Oct-90 David M. Sternlicht        Storing saved colors on root
38  *
39  ***********************************************************************/
40 
41 %{
42 #ifndef YYBISON			/* bison includes stdio.h automatically */
43 #include <stdio.h>
44 #endif
45 #include <ctype.h>
46 #include "twm.h"
47 #include "menus.h"
48 #include "list.h"
49 #include "util.h"
50 #include "screen.h"
51 #include "parse.h"
52 #include <X11/Xos.h>
53 #include <X11/Xmu/CharSet.h>
54 
55 static char *Action = "";
56 static char *Name = "";
57 static MenuRoot	*root, *pull = NULL;
58 static int  menu_default_index;
59 
60 static MenuRoot *GetRoot();
61 
62 static Bool CheckWarpScreenArg(), CheckWarpRingArg();
63 static Bool CheckColormapArg();
64 static void GotButton(), GotKey(), GotTitleButton();
65 #ifdef RJC
66 extern char *CacheAndNameIconImage();
67 #endif
68 
69 static char *ptr;
70 static name_list **list;
71 static int cont = 0;
72 static int color;
73 int mods = 0;
74 char	*menu_name = NULL;		/* if we are reading a menu */
75 MenuRoot   *input_menu;
76 
77 unsigned int mods_used = (ShiftMask | ControlMask | Mod1Mask);
78 
79 extern int do_single_keyword(), do_string_keyword(), do_number_keyword();
80 extern name_list **do_colorlist_keyword();
81 extern int do_color_keyword(), do_string_savecolor();
82 extern int yylineno;
83 %}
84 
85 %union
86 {
87     int num;
88     char *ptr;
89     struct {
90 	short  ltype;
91 	char  *lval;
92     } match;
93     struct {
94 	char  *gstring;
95 	short itterate;
96     } geom;
97 };
98 
99 %token <num> LB RB LP RP MENUS MENU BUTTON DEFAULT_FUNCTION PLUS MINUS
100 %token <num> ASTERISK GREATER
101 %token <num> ALL OR CURSORS PIXMAPS ICONS COLOR SAVECOLOR MONOCHROME FUNCTION
102 %token <num> ICONMGR_SHOW ICONMGR WINDOW_FUNCTION ZOOM ICONMGRS
103 %token <num> ICONMGR_GEOMETRY ICONMGR_NOSHOW MAKE_TITLE
104 %token <num> ICONIFY_BY_UNMAPPING DONT_ICONIFY_BY_UNMAPPING STICKY
105 %token <num> NO_TITLE AUTO_RAISE NO_HILITE ICON_REGION
106 %token <num> META SHIFT LOCK CONTROL WINDOW TITLE ICON ROOT FRAME
107 %token <num> COLON EQUALS TILDE SQUEEZE_TITLE DONT_SQUEEZE_TITLE
108 %token <num> SQUEEZE_ICON DONT_SQUEEZE_ICON
109 %token <num> START_ICONIFIED NO_TITLE_HILITE TITLE_HILITE
110 %token <num> MOVE RESIZE WAIT_CURS SELECT KILL LEFT_TITLEBUTTON RIGHT_TITLEBUTTON
111 %token <num> NUMBER KEYWORD MKEYWORD NKEYWORD CKEYWORD CLKEYWORD FKEYWORD
112 %token <num> FSKEYWORD SKEYWORD DKEYWORD JKEYWORD PKEYWORD WINDOW_RING
113 %token <num> WARP_CURSOR ERRORTOKEN NO_STACKMODE ICON_TITLE NO_ICON_TITLE
114 %token <ptr> STRING REGEXP
115 
116 %type <ptr> string regexp
117 %type <geom> geometry
118 %type <match> matcher
119 %type <num> action button number signed_number full fullkey def_indicator
120 
121 %start file
122 
123 /*
124  * Notice that this grammar reads tvtwmrc files *and* menu files.  It would
125  * make more sense to have two separate parsers, but it is not possible
126  * to have two yacc grammars in one program without non portable hackery
127  * (so far as I know).
128  */
129 
130 %%
131 file		: twmrc { input_menu = NULL; }
132 		| menufile { input_menu = root; }
133 		| menutreefile {input_menu = GetRoot(menu_name, NULL, NULL); }
134 		;
135 
136 menufile	: { root = GetRoot(menu_name, NULL, NULL); }
137 		  menu_body
138 		;
139 
140 menutreefile	: menu_definition
141 		| menutreefile menu_definition
142 		;
143 
144 twmrc		: /* Empty */
145 		| stmts
146 		;
147 
148 stmts		: stmt
149 		| stmts stmt
150 		| stmts menu_definition
151 		;
152 
153 stmt		: error	{ printf("error in statements\n"); }
154 		| noarg
155 		| sarg
156 		| narg
157 		| squeeze
158 		| ICON_REGION geometry DKEYWORD DKEYWORD number number
159 					{ AddIconRegion("", LTYPE_ANYTHING,
160 							$2.gstring, $2.itterate,
161 							$3, $4, $5, $6); }
162 		| ICON_REGION matcher geometry DKEYWORD DKEYWORD number number
163 					{ AddIconRegion($2.lval, $2.ltype,
164 							$3.gstring, $3.itterate,
165 							$4, $5, $6, $7); }
166 		| ICONMGR_GEOMETRY string number	{ if (Scr->FirstTime)
167 						  {
168 						    Scr->iconmgr.geometry=$2;
169 						    Scr->iconmgr.columns=$3;
170 						  }
171 						}
172 		| ICONMGR_GEOMETRY string	{ if (Scr->FirstTime)
173 						    Scr->iconmgr.geometry = $2;
174 						}
175 		| ZOOM number		{ if (Scr->FirstTime)
176 					  {
177 						Scr->DoZoom = TRUE;
178 						Scr->ZoomCount = $2;
179 					  }
180 					}
181 		| ZOOM			{ if (Scr->FirstTime)
182 						Scr->DoZoom = TRUE; }
183 		| PIXMAPS pixmap_list	{}
184 		| CURSORS cursor_list	{}
185 		| ICONIFY_BY_UNMAPPING	{ list = &Scr->IconifyByUn; }
186 		  win_list
187 		| ICONIFY_BY_UNMAPPING	{ if (Scr->FirstTime)
188 		    Scr->IconifyByUnmapping = TRUE; }
189 		| LEFT_TITLEBUTTON string EQUALS action {
190 					  GotTitleButton ($2, $4, False);
191 					}
192 		| RIGHT_TITLEBUTTON string EQUALS action {
193 					  GotTitleButton ($2, $4, True);
194 					}
195 		| button string		{ root = GetRoot($2, NULLSTR, NULLSTR);
196 					  Scr->Mouse[$1][C_ROOT][0].func = F_MENU;
197 					  Scr->Mouse[$1][C_ROOT][0].menu = root;
198 					}
199 		| button action		{ Scr->Mouse[$1][C_ROOT][0].func = $2;
200 					  if ($2 == F_MENU)
201 					  {
202 					    pull->prev = NULL;
203 					    Scr->Mouse[$1][C_ROOT][0].menu = pull;
204 					  }
205 					  else
206 					  {
207 					    root = GetRoot(TWM_ROOT,NULLSTR,NULLSTR);
208 					    Scr->Mouse[$1][C_ROOT][0].item =
209 						AddToMenu(root,"x",Action,
210 							  NULLSTR,$2,NULLSTR,NULLSTR);
211 					  }
212 					  Action = "";
213 					  pull = NULL;
214 					}
215 		| string fullkey	{ GotKey($1, $2); }
216 		| button full		{ GotButton($1, $2); }
217 		| DONT_ICONIFY_BY_UNMAPPING { list = &Scr->DontIconify; }
218 		  win_list
219 		| ICONMGR_NOSHOW	{ list = &Scr->IconMgrNoShow; }
220 		  win_list
221 		| ICONMGR_NOSHOW	{ Scr->IconManagerDontShow = TRUE; }
222 		| ICONMGRS		{ list = &Scr->IconMgrs; }
223 		  iconm_list
224 		| ICONMGR_SHOW		{ list = &Scr->IconMgrShow; }
225 		  win_list
226 		| NO_TITLE_HILITE	{ list = &Scr->NoTitleHighlight; }
227 		  win_list
228 		| NO_TITLE_HILITE	{ if (Scr->FirstTime)
229 						Scr->TitleHighlight = FALSE; }
230 		| NO_HILITE		{ list = &Scr->NoHighlight; }
231 		  win_list
232 		| NO_HILITE		{ if (Scr->FirstTime)
233 						Scr->Highlight = FALSE; }
234 		| NO_STACKMODE		{ list = &Scr->NoStackModeL; }
235 		  win_list
236 		| NO_STACKMODE		{ if (Scr->FirstTime)
237 						Scr->StackMode = FALSE; }
238 		| NO_TITLE		{ list = &Scr->NoTitle; }
239 		  win_list
240 		| NO_TITLE		{ if (Scr->FirstTime)
241 						Scr->NoTitlebar = TRUE; }
242 		| NO_ICON_TITLE		{ list = &Scr->NoIconTitleL; }
243 		  win_list
244 		| NO_ICON_TITLE		{ if (Scr->FirstTime)
245 						Scr->NoIconTitle = TRUE; }
246 		| ICON_TITLE		{ list = &Scr->IconTitleL; }
247 		  win_list
248 		| MAKE_TITLE		{ list = &Scr->MakeTitle; }
249 		  win_list
250 		| START_ICONIFIED	{ list = &Scr->StartIconified; }
251 		  win_list
252 		| AUTO_RAISE		{ list = &Scr->AutoRaise; }
253 		  win_list
254 		| STICKY		{ list = &Scr->StickyL; }
255 		  win_list
256 		| FUNCTION string	{ root = GetRoot($2, NULLSTR, NULLSTR); }
257 		  function
258 		| ICONS 		{ list = &Scr->IconNames; }
259 		  icon_list
260 		| COLOR 		{ color = COLOR; }
261 		  color_list
262 		| SAVECOLOR		{ }
263 		  save_color_list
264 		| MONOCHROME 		{ color = MONOCHROME; }
265 		  color_list
266 		| DEFAULT_FUNCTION action { Scr->DefaultFunction.func = $2;
267 					  if ($2 == F_MENU)
268 					  {
269 					    pull->prev = NULL;
270 					    Scr->DefaultFunction.menu = pull;
271 					  }
272 					  else
273 					  {
274 					    root = GetRoot(TWM_ROOT,NULLSTR,NULLSTR);
275 					    Scr->DefaultFunction.item =
276 						AddToMenu(root,"x",Action,
277 							  NULLSTR,$2, NULLSTR, NULLSTR);
278 					  }
279 					  Action = "";
280 					  pull = NULL;
281 					}
282 		| WINDOW_FUNCTION action { Scr->WindowFunction.func = $2;
283 					   root = GetRoot(TWM_ROOT,NULLSTR,NULLSTR);
284 					   Scr->WindowFunction.item =
285 						AddToMenu(root,"x",Action,
286 							  NULLSTR,$2, NULLSTR, NULLSTR);
287 					   Action = "";
288 					   pull = NULL;
289 					}
290 		| WARP_CURSOR		{ list = &Scr->WarpCursorL; }
291 		  win_list
292 		| WARP_CURSOR		{ if (Scr->FirstTime)
293 					    Scr->WarpCursor = TRUE; }
294 		| WINDOW_RING		{ list = &Scr->WindowRingL; }
295 		  win_list
296 		;
297 
298 
299 noarg		: KEYWORD		{ if (!do_single_keyword ($1)) {
300 					    twmrc_error_prefix();
301 					    fprintf (stderr,
302 					"unknown singleton keyword %d\n",
303 						     $1);
304 					    ParseError = 1;
305 					  }
306 					}
307 		;
308 
309 sarg		: SKEYWORD string	{ if (!do_string_keyword ($1, $2)) {
310 					    twmrc_error_prefix();
311 					    fprintf (stderr,
312 				"unknown string keyword %d (value \"%s\")\n",
313 						     $1, $2);
314 					    ParseError = 1;
315 					  }
316 					}
317 		| SKEYWORD string COLON string {
318 #ifdef RJC
319 #define kws_UnknownIcon	7
320 			if ($1 != kws_UnknownIcon)
321 			    yyerror("syntax error");
322 			else if (Scr->FirstTime) {
323 			    char *full_name=CacheAndNameIconImage($2, $4);
324 			    if (full_name != NULL) {
325 				if (!do_string_keyword ($1, full_name)) {
326 				    twmrc_error_prefix();
327 				    fprintf (stderr,
328 			"unknown string keyword %d (value \"%s\")\n",
329 						$1, full_name);
330 				    ParseError = 1;
331 				}
332 			    } else {
333 				twmrc_error_prefix();
334 				fprintf(stderr, "can't access bitmap and mask %s, %s\n",
335 				$2, $4);
336 			    }
337 			}
338 #else
339 			yyerror("\"pixmap\" : \"mask\" syntax no longer supported");
340 #endif
341 			}
342 		;
343 
344 narg		: NKEYWORD number	{ if (!do_number_keyword ($1, $2)) {
345 					    twmrc_error_prefix();
346 					    fprintf (stderr,
347 				"unknown numeric keyword %d (value %d)\n",
348 						     $1, $2);
349 					    ParseError = 1;
350 					  }
351 					}
352 		;
353 
354 
355 
356 full		: EQUALS keys COLON contexts COLON action  { $$ = $6; }
357 		;
358 
359 fullkey		: EQUALS keys COLON contextkeys COLON action  { $$ = $6; }
360 		;
361 
362 keys		: /* Empty */
363 		| keys key
364 		;
365 
366 key		: META			{ mods |= Mod1Mask; }
367 		| SHIFT			{ mods |= ShiftMask; }
368 		| LOCK			{ mods |= LockMask; }
369 		| CONTROL		{ mods |= ControlMask; }
370 		| META number		{ if ($2 < 1 || $2 > 5) {
371 					     twmrc_error_prefix();
372 					     fprintf (stderr,
373 				"bad modifier number (%d), must be 1-5\n",
374 						      $2);
375 					     ParseError = 1;
376 					  } else {
377 					     mods |= (Mod1Mask << ($2 - 1));
378 					  }
379 					}
380 		| OR			{ }
381 		;
382 
383 contexts	: /* Empty */
384 		| contexts context
385 		;
386 
387 context		: WINDOW		{ cont |= C_WINDOW_BIT; }
388 		| TITLE			{ cont |= C_TITLE_BIT; }
389 		| ICON			{ cont |= C_ICON_BIT; }
390 		| ROOT			{ cont |= C_ROOT_BIT; }
391 		| FRAME			{ cont |= C_FRAME_BIT; }
392 		| ICONMGR		{ cont |= C_ICONMGR_BIT; }
393 		| META			{ cont |= C_ICONMGR_BIT; }
394 		| ALL			{ cont |= C_ALL_BITS; }
395 		| OR			{  }
396 		;
397 
398 contextkeys	: /* Empty */
399 		| contextkeys contextkey
400 		;
401 
402 contextkey	: WINDOW		{ cont |= C_WINDOW_BIT; }
403 		| TITLE			{ cont |= C_TITLE_BIT; }
404 		| ICON			{ cont |= C_ICON_BIT; }
405 		| ROOT			{ cont |= C_ROOT_BIT; }
406 		| FRAME			{ cont |= C_FRAME_BIT; }
407 		| ICONMGR		{ cont |= C_ICONMGR_BIT; }
408 		| META			{ cont |= C_ICONMGR_BIT; }
409 		| ALL			{ cont |= C_ALL_BITS; }
410 		| OR			{ }
411 		| string		{ Name = $1; cont |= C_NAME_BIT; }
412 		;
413 
414 
415 pixmap_list	: LB pixmap_entries RB
416 		{ }
417 		;
418 
419 pixmap_entries	: /* Empty */
420 		| pixmap_entries pixmap_entry
421 		;
422 
423 pixmap_entry	:  PKEYWORD string { do_pixmap_keyword($1,$2); }
424 		;
425 
426 
427 cursor_list	: LB cursor_entries RB
428 		{ }
429 		;
430 
431 cursor_entries	: /* Empty */
432 		| cursor_entries cursor_entry
433 		;
434 
435 cursor_entry	: FRAME string string {
436 			NewBitmapCursor(&Scr->FrameCursor, $2, $3); }
437 		| FRAME string	{
438 			NewFontCursor(&Scr->FrameCursor, $2); }
439 		| TITLE string string {
440 			NewBitmapCursor(&Scr->TitleCursor, $2, $3); }
441 		| TITLE string {
442 			NewFontCursor(&Scr->TitleCursor, $2); }
443 		| ICON string string {
444 			NewBitmapCursor(&Scr->IconCursor, $2, $3); }
445 		| ICON string {
446 			NewFontCursor(&Scr->IconCursor, $2); }
447 		| ICONMGR string string {
448 			NewBitmapCursor(&Scr->IconMgrCursor, $2, $3); }
449 		| ICONMGR string {
450 			NewFontCursor(&Scr->IconMgrCursor, $2); }
451 		| BUTTON string string {
452 			NewBitmapCursor(&Scr->ButtonCursor, $2, $3); }
453 		| BUTTON string {
454 			NewFontCursor(&Scr->ButtonCursor, $2); }
455 		| MOVE string string {
456 			NewBitmapCursor(&Scr->MoveCursor, $2, $3); }
457 		| MOVE string {
458 			NewFontCursor(&Scr->MoveCursor, $2); }
459 		| RESIZE string string {
460 			NewBitmapCursor(&Scr->ResizeCursor, $2, $3); }
461 		| RESIZE string {
462 			NewFontCursor(&Scr->ResizeCursor, $2); }
463 		| WAIT_CURS string string {
464 			NewBitmapCursor(&Scr->WaitCursor, $2, $3); }
465 		| WAIT_CURS string {
466 			NewFontCursor(&Scr->WaitCursor, $2); }
467 		| MENU string string {
468 			NewBitmapCursor(&Scr->MenuCursor, $2, $3); }
469 		| MENU string {
470 			NewFontCursor(&Scr->MenuCursor, $2); }
471 		| SELECT string string {
472 			NewBitmapCursor(&Scr->SelectCursor, $2, $3); }
473 		| SELECT string {
474 			NewFontCursor(&Scr->SelectCursor, $2); }
475 		| KILL string string {
476 			NewBitmapCursor(&Scr->DestroyCursor, $2, $3); }
477 		| KILL string {
478 			NewFontCursor(&Scr->DestroyCursor, $2); }
479 		;
480 
481 color_list	: LB color_entries RB
482 		{ }
483 		;
484 
485 
486 color_entries	: /* Empty */
487 		| color_entries color_entry
488 		;
489 
490 color_entry	: CLKEYWORD string	{ if (!do_colorlist_keyword ($1, color,
491 								     $2)) {
492 					    twmrc_error_prefix();
493 					    fprintf (stderr,
494 			"unhandled list color keyword %d (string \"%s\")\n",
495 						     $1, $2);
496 					    ParseError = 1;
497 					  }
498 					}
499 		| CLKEYWORD string	{ list = do_colorlist_keyword($1,color,
500 								      $2);
501 					  if (!list) {
502 					    twmrc_error_prefix();
503 					    fprintf (stderr,
504 			"unhandled color list keyword %d (string \"%s\")\n",
505 						     $1, $2);
506 					    ParseError = 1;
507 					  }
508 					}
509 		  win_color_list
510 		| CKEYWORD string	{ if (!do_color_keyword ($1, color,
511 								 $2)) {
512 					    twmrc_error_prefix();
513 					    fprintf (stderr,
514 			"unhandled color keyword %d (string \"%s\")\n",
515 						     $1, $2);
516 					    ParseError = 1;
517 					  }
518 					}
519 		;
520 
521 save_color_list : LB s_color_entries RB
522 		{ }
523                 ;
524 
525 s_color_entries : /* Empty */
526                 | s_color_entries s_color_entry
527                 ;
528 
529 s_color_entry   : string            { do_string_savecolor(color, $1); }
530                 | CLKEYWORD         { do_var_savecolor($1); }
531                 ;
532 
533 win_color_list	: LB win_color_entries RB
534 		{ }
535 		;
536 
537 win_color_entries	: /* Empty */
538 		| win_color_entries win_color_entry
539 		;
540 
541 win_color_entry	: matcher string	{ if (Scr->FirstTime &&
542 					      color == Scr->Monochrome)
543 					    AddToList(list, $1.lval, $1.ltype,
544 							$2); }
545 		;
546 
547 squeeze		: SQUEEZE_TITLE {
548 				    if (HasShape) Scr->SqueezeTitle = TRUE;
549 				}
550 		| SQUEEZE_TITLE { list = &Scr->SqueezeTitleL; }
551 		  LB win_sqz_entries RB
552 		| DONT_SQUEEZE_TITLE { Scr->SqueezeTitle = FALSE; }
553 		| DONT_SQUEEZE_TITLE { list = &Scr->DontSqueezeTitleL; }
554 		  win_list
555 		| SQUEEZE_ICON { if (HasShape) Scr->SqueezeIcon = TRUE; }
556 		| DONT_SQUEEZE_ICON { if (HasShape) Scr->SqueezeIcon = FALSE; }
557 		| SQUEEZE_ICON { list = &Scr->SqueezeIconL; }
558 		  win_list
559 		| DONT_SQUEEZE_ICON { list = &Scr->DontSqueezeIconL; }
560 		  win_list
561 		;
562 
563 win_sqz_entries	: /* Empty */
564 		| win_sqz_entries matcher JKEYWORD signed_number number	{
565 				if (Scr->FirstTime) {
566 				   do_squeeze_entry (list, $2.lval, $2.ltype,
567 							$3, $4, $5);
568 				}
569 			}
570 		;
571 
572 
573 iconm_list	: LB iconm_entries RB
574 		{ }
575 		;
576 
577 iconm_entries	: /* Empty */
578 		| iconm_entries iconm_entry
579 		;
580 
581 iconm_entry	: matcher string number	{ if (Scr->FirstTime)
582 					    AddToList(list, $1.lval, $1.ltype, (char *)
583 						AllocateIconManager($1.lval, NULLSTR,
584 							$2, $3));
585 					}
586 		| matcher string string number
587 					{ if (Scr->FirstTime)
588 					    AddToList(list, $1.lval, $1.ltype, (char *)
589 						AllocateIconManager($1.lval, $2,
590 						$3, $4));
591 					}
592 		;
593 
594 win_list	: LB win_entries RB
595 		{ }
596 		;
597 
598 win_entries	: /* Empty */
599 		| win_entries win_entry
600 		;
601 
602 win_entry	: matcher		{ if (Scr->FirstTime)
603 					    AddToList(list, $1.lval, $1.ltype, 0);
604 					}
605 		;
606 
607 icon_list	: LB icon_entries RB
608 		{ }
609 		;
610 
611 icon_entries	: /* Empty */
612 		| icon_entries icon_entry
613 		;
614 
615 icon_entry	: matcher string		{ if (Scr->FirstTime)
616 						AddToList(list, $1.lval, $1.ltype, $2); }
617 		| matcher string COLON string	{
618 			if (Scr->FirstTime) {
619 #ifdef RJC
620 			    char *full_name=CacheAndNameIconImage($2, $4);
621 			    if (full_name != NULL)
622 				AddToList(list, $1.lval, $1.ltype, full_name);
623 			    else {
624 				twmrc_error_prefix();
625 				fprintf(stderr, "can't access bitmap and mask %s, %s\n",
626 				$2, $4);
627 			    }
628 #else
629 			yyerror("\"pixmap\" : \"mask\" syntax no longer supported");
630 #endif /* RJC */
631 				}
632 		}
633 		;
634 
635 function	: LB function_entries RB
636 		{ }
637 		;
638 
639 function_entries: /* Empty */
640 		| function_entries function_entry
641 		;
642 
643 function_entry	: action		{ AddToMenu(root, "", Action, NULLSTR, $1,
644 						NULLSTR, NULLSTR);
645 					  Action = "";
646 					}
647 		;
648 
649 menu_definition	: MENU string LP string COLON string RP {
650 					root = GetRoot($2, $4, $6); }
651 		  menu
652 		| MENU string { root = GetRoot($2, NULLSTR, NULLSTR); }
653 		  menu
654 		;
655 
656 menu		: menu_body
657 		| string	{
658 				root->file = ExpandFilename($1);
659 				root->real_menu = TRUE;
660 				}
661 		;
662 
663 menu_body	: {
664 			if (Scr->SetupDone == TRUE) {
665 			    DestroyMenu(root);
666 			    root->first = NULL;
667 			    root->items = 0;
668 			    root->width = 0;
669 			    root->mapped = NEVER_MAPPED;
670 			}
671 			menu_default_index = 0;
672 		  }
673 		  LB menu_entries RB {
674 			if (Scr->SetupDone == TRUE) {
675 			    MakeMenu(root);
676 			}
677 			root->real_menu = TRUE;
678 			root->def = menu_default_index;
679 		  }
680 		;
681 
682 menu_entries	: /* Empty */
683 		| menu_entries menu_entry
684 		;
685 
686 menu_entry	: def_indicator string action
687 					{ AddToMenu(root, $2, Action, pull, $3,
688 						NULLSTR, NULLSTR);
689 					  Action = "";
690 					  pull = NULL;
691 					  if ($1) {
692 					    if (menu_default_index)
693 					      yyerror("two defaults in menu");
694 					    else if ($1 == 1)
695 					      menu_default_index = root->items;
696 					    else if ($1 == 2)
697 					      menu_default_index =
698 								(-root->items);
699 					  }
700 					}
701 		| def_indicator string LP string COLON string RP action
702 					{ AddToMenu(root, $2, Action, pull, $8,
703 						$4, $6);
704 					  Action = "";
705 					  pull = NULL;
706 					  if ($1) {
707 					    if (menu_default_index)
708 					      yyerror("two defaults in menu");
709 					    else if ($1 == 1)
710 					      menu_default_index = root->items;
711 					    else if ($1 == 2)
712 					      menu_default_index =
713 								(-root->items);
714 					  }
715 					}
716 		;
717 
718 def_indicator	: /* EMPTY */		{ $$ = 0; }
719 		| GREATER		{ $$ = 1; }
720 		| GREATER GREATER	{ $$ = 2; }
721 		;
722 
723 action		: FKEYWORD	{ $$ = $1; }
724 		| FSKEYWORD string {
725 				$$ = $1;
726 				Action = $2;
727 				switch ($1) {
728 				  case F_MENU:
729 				    pull = GetRoot ($2, NULLSTR,NULLSTR);
730 				    pull->prev = NULL;
731 				    break;
732 				  case F_WARPRING:
733 				    if (!CheckWarpRingArg (Action)) {
734 					twmrc_error_prefix();
735 					fprintf (stderr,
736 			"ignoring invalid f.warptoring argument \"%s\"\n",
737 						 Action);
738 					$$ = F_NOP;
739 				    }
740 				  case F_WARPTOSCREEN:
741 				    if (!CheckWarpScreenArg (Action)) {
742 					twmrc_error_prefix();
743 					fprintf (stderr,
744 			"ignoring invalid f.warptoscreen argument \"%s\"\n",
745 					         Action);
746 					$$ = F_NOP;
747 				    }
748 				    break;
749 				  case F_COLORMAP:
750 				    if (CheckColormapArg (Action)) {
751 					$$ = F_COLORMAP;
752 				    } else {
753 					twmrc_error_prefix();
754 					fprintf (stderr,
755 			"ignoring invalid f.colormap argument \"%s\"\n",
756 						 Action);
757 					$$ = F_NOP;
758 				    }
759 				    break;
760 				} /* end switch */
761 			    }
762 		| FSKEYWORD string COLON string {
763 				$$ = $1;
764 				Action = $4;
765 				pull = GetRoot ($2, NULLSTR,NULLSTR);
766 				pull->prev = NULL;
767 				break;
768 			    }
769 		;
770 
771 
772 signed_number	: number		{ $$ = $1; }
773 		| PLUS number		{ $$ = $2; }
774 		| MINUS number		{ $$ = -($2); }
775 		;
776 
777 button		: BUTTON number		{ $$ = $2;
778 					  if ($2 == 0)
779 						yyerror("bad button 0");
780 
781 					  if ($2 > MAX_BUTTONS)
782 					  {
783 						$$ = 0;
784 						yyerror("button number too large");
785 					  }
786 					}
787 		;
788 
789 matcher		: string		{
790 					$$.ltype = LTYPE_ANY_STRING;
791 					$$.lval = $1;
792 					}
793 		| regexp		{
794 					$$.ltype = LTYPE_ANY_REGEXP;
795 					$$.lval = $1;
796 					}
797 		| MKEYWORD EQUALS string {
798 					$$.lval = $3;
799 					$$.ltype = $1 | LTYPE_STRING;
800 					}
801 		| MKEYWORD TILDE regexp {
802 					$$.lval = $3;
803 					$$.ltype = $1 | LTYPE_REGEXP;
804 					}
805 		;
806 
807 geometry	: string		{ $$.gstring = $1;
808 					  $$.itterate = FALSE;
809 					}
810 		| string ASTERISK	{ $$.gstring = $1;
811 					  $$.itterate = TRUE;
812 					}
813 		;
814 
815 string		: STRING		{ ptr = (char *)malloc(strlen($1)+1);
816 					  strcpy(ptr, $1);
817 					  RemoveDQuote(ptr);
818 					  $$ = ptr;
819 					}
820 
821 regexp		: REGEXP		{ ptr = (char *)malloc(strlen($1));
822 					  /* chop off the '/'s */
823 					  strcpy(ptr, $1+1);
824 					  ptr[strlen(ptr)-1] = '\0';
825 					  $$ = ptr;
826 					}
827 
828 number		: NUMBER		{ $$ = $1; }
829 		;
830 
831 %%
yyerror(s)832 yyerror(s) char *s;
833 {
834     twmrc_error_prefix();
835     fprintf (stderr, "error in input file:  %s\n", s ? s : "");
836     fprintf (stderr, ": %s", current_input_line());
837     ParseError = 1;
838 }
RemoveDQuote(str)839 RemoveDQuote(str)
840 char *str;
841 {
842     register char *i, *o;
843     register n;
844     register count;
845 
846     for (i=str+1, o=str; *i && *i != '\"'; o++)
847     {
848 	if (*i == '\\')
849 	{
850 	    switch (*++i)
851 	    {
852 	    case 'n':
853 		*o = '\n';
854 		i++;
855 		break;
856 	    case 'b':
857 		*o = '\b';
858 		i++;
859 		break;
860 	    case 'r':
861 		*o = '\r';
862 		i++;
863 		break;
864 	    case 't':
865 		*o = '\t';
866 		i++;
867 		break;
868 	    case 'f':
869 		*o = '\f';
870 		i++;
871 		break;
872 	    case '0':
873 		if (*++i == 'x')
874 		    goto hex;
875 		else
876 		    --i;
877 	    case '1': case '2': case '3':
878 	    case '4': case '5': case '6': case '7':
879 		n = 0;
880 		count = 0;
881 		while (*i >= '0' && *i <= '7' && count < 3)
882 		{
883 		    n = (n<<3) + (*i++ - '0');
884 		    count++;
885 		}
886 		*o = n;
887 		break;
888 	    hex:
889 	    case 'x':
890 		n = 0;
891 		count = 0;
892 		while (i++, count++ < 2)
893 		{
894 		    if (*i >= '0' && *i <= '9')
895 			n = (n<<4) + (*i - '0');
896 		    else if (*i >= 'a' && *i <= 'f')
897 			n = (n<<4) + (*i - 'a') + 10;
898 		    else if (*i >= 'A' && *i <= 'F')
899 			n = (n<<4) + (*i - 'A') + 10;
900 		    else
901 			break;
902 		}
903 		*o = n;
904 		break;
905 	    case '\n':
906 		i++;	/* punt */
907 		o--;	/* to account for o++ at end of loop */
908 		break;
909 	    case '\"':
910 	    case '\'':
911 	    case '\\':
912 	    default:
913 		*o = *i++;
914 		break;
915 	    }
916 	}
917 	else
918 	    *o = *i++;
919     }
920     *o = '\0';
921 }
922 
GetRoot(name,fore,back)923 static MenuRoot *GetRoot(name, fore, back)
924 char *name;
925 char *fore, *back;
926 {
927     MenuRoot *tmp;
928 
929     tmp = FindMenuRoot(name);
930     if (tmp == NULL)
931 	tmp = NewMenuRoot(name);
932 
933     if (fore)
934     {
935 	int save;
936 
937 	save = Scr->FirstTime;
938 	Scr->FirstTime = TRUE;
939 	GetColor(COLOR, &tmp->hi_fore, fore);
940 	GetColor(COLOR, &tmp->hi_back, back);
941 	Scr->FirstTime = save;
942     }
943 
944     return tmp;
945 }
946 
GotButton(butt,func)947 static void GotButton(butt, func)
948 int butt, func;
949 {
950     int i;
951 
952     for (i = 0; i < NUM_CONTEXTS; i++)
953     {
954 	if ((cont & (1 << i)) == 0)
955 	    continue;
956 
957 	Scr->Mouse[butt][i][mods].func = func;
958 	if (func == F_MENU || func == F_MENUFUNC)
959 	{
960 	    pull->prev = NULL;
961 	    Scr->Mouse[butt][i][mods].menu = pull;
962 	}
963 	else
964 	{
965 	    root = GetRoot(TWM_ROOT, NULLSTR, NULLSTR);
966 	    Scr->Mouse[butt][i][mods].item = AddToMenu(root,"x",Action,
967 		    NULLSTR, func, NULLSTR, NULLSTR);
968 	}
969     }
970     Action = "";
971     pull = NULL;
972     cont = 0;
973     mods_used |= mods;
974     mods = 0;
975 }
976 
GotKey(key,func)977 static void GotKey(key, func)
978 char *key;
979 int func;
980 {
981     int i;
982 
983     for (i = 0; i < NUM_CONTEXTS; i++)
984     {
985 	if ((cont & (1 << i)) == 0)
986 	  continue;
987 	if (!AddFuncKey(key, i, mods, func, Name, Action))
988 	  break;
989     }
990 
991     Action = "";
992     pull = NULL;
993     cont = 0;
994     mods_used |= mods;
995     mods = 0;
996 }
997 
998 
GotTitleButton(bitmapname,func,rightside)999 static void GotTitleButton (bitmapname, func, rightside)
1000     char *bitmapname;
1001     int func;
1002     Bool rightside;
1003 {
1004     if (!CreateTitleButton (bitmapname, func, Action, pull, rightside, True)) {
1005 	twmrc_error_prefix();
1006 	fprintf (stderr,
1007 		 "unable to create %s titlebutton \"%s\"\n",
1008 		 rightside ? "right" : "left", bitmapname);
1009     }
1010     Action = "";
1011     pull = NULL;
1012 }
1013 
CheckWarpScreenArg(s)1014 static Bool CheckWarpScreenArg (s)
1015     register char *s;
1016 {
1017     XmuCopyISOLatin1Lowered (s, s);
1018 
1019     if (strcmp (s,  WARPSCREEN_NEXT) == 0 ||
1020 	strcmp (s,  WARPSCREEN_PREV) == 0 ||
1021 	strcmp (s,  WARPSCREEN_BACK) == 0)
1022       return True;
1023 
1024     for (; *s && isascii(*s) && isdigit(*s); s++) ; /* SUPPRESS 530 */
1025     return (*s ? False : True);
1026 }
1027 
1028 
CheckWarpRingArg(s)1029 static Bool CheckWarpRingArg (s)
1030     register char *s;
1031 {
1032     XmuCopyISOLatin1Lowered (s, s);
1033 
1034     if (strcmp (s,  WARPSCREEN_NEXT) == 0 ||
1035 	strcmp (s,  WARPSCREEN_PREV) == 0)
1036       return True;
1037 
1038     return False;
1039 }
1040 
1041 
CheckColormapArg(s)1042 static Bool CheckColormapArg (s)
1043     register char *s;
1044 {
1045     XmuCopyISOLatin1Lowered (s, s);
1046 
1047     if (strcmp (s, COLORMAP_NEXT) == 0 ||
1048 	strcmp (s, COLORMAP_PREV) == 0 ||
1049 	strcmp (s, COLORMAP_DEFAULT) == 0)
1050       return True;
1051 
1052     return False;
1053 }
1054 
1055 
twmrc_error_prefix()1056 twmrc_error_prefix ()
1057 {
1058     fprintf (stderr, "%s:  line %d:  ", ProgramName, yylineno);
1059 }
1060