1 /*****************************************************************************/
2 /*
3 
4 Copyright 1989, 1998  The Open Group
5 
6 Permission to use, copy, modify, distribute, and sell this software and its
7 documentation for any purpose is hereby granted without fee, provided that
8 the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
10 documentation.
11 
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14 
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22 Except as contained in this notice, the name of The Open Group shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from The Open Group.
25 
26 */
27 /**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **/
28 /**                          Salt Lake City, Utah                           **/
29 /**                        Cambridge, Massachusetts                         **/
30 /**                                                                         **/
31 /**                           All Rights Reserved                           **/
32 /**                                                                         **/
33 /**    Permission to use, copy, modify, and distribute this software and    **/
34 /**    its documentation  for  any  purpose  and  without  fee is hereby    **/
35 /**    granted, provided that the above copyright notice appear  in  all    **/
36 /**    copies and that both  that  copyright  notice  and  this  permis-    **/
37 /**    sion  notice appear in supporting  documentation,  and  that  the    **/
38 /**    name of Evans & Sutherland not be used in advertising    **/
39 /**    in publicity pertaining to distribution of the  software  without    **/
40 /**    specific, written prior permission.                                  **/
41 /**                                                                         **/
42 /**    EVANS & SUTHERLAND DISCLAIMs ALL WARRANTIES WITH REGARD    **/
43 /**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **/
44 /**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL EVANS & SUTHERLAND    **/
45 /**    BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL  DAM-    **/
46 /**    AGES OR  ANY DAMAGES WHATSOEVER  RESULTING FROM LOSS OF USE, DATA    **/
47 /**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **/
48 /**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **/
49 /**    OR PERFORMANCE OF THIS SOFTWARE.                                     **/
50 /*****************************************************************************/
51 
52 
53 /***********************************************************************
54  *
55  * $Xorg: gram.y,v 1.4 2001/02/09 02:05:36 xorgcvs Exp $
56  *
57  * .twmrc command grammer
58  *
59  * 07-Jan-86 Thomas E. LaStrange	File created
60  * 11-Nov-90 Dave Sternlicht            Adding SaveColors
61  * 10-Oct-90 David M. Sternlicht        Storing saved colors on root
62  *
63  * $XFree86: xc/programs/twm/gram.y,v 3.8 2002/10/16 21:33:03 tsi Exp $
64  *
65  ***********************************************************************/
66 
67 %{
68 #include <stdio.h>
69 #include <ctype.h>
70 #include "twm.h"
71 #include "menus.h"
72 #include "list.h"
73 #include "util.h"
74 #include "screen.h"
75 #include "parse.h"
76 #include "add_window.h"
77 #include "icons.h"
78 #include <X11/Xos.h>
79 #include <X11/Xmu/CharSet.h>
80 
81 static char empty[1];
82 static char *Action = empty;
83 static char *Name = empty;
84 static MenuRoot	*root, *pull = NULL;
85 
86 static MenuRoot *GetRoot ( const char *name, const char *fore, const char *back );
87 static void GotButton ( int butt, int func );
88 static void GotKey ( char *key, int func );
89 static void GotTitleButton ( char *bitmapname, int func, Bool rightside );
90 static Bool CheckWarpScreenArg ( char *s );
91 static Bool CheckWarpRingArg ( char *s );
92 static Bool CheckColormapArg ( char *s );
93 static void RemoveDQuote ( char *str );
94 
95 static char *ptr;
96 static name_list **list;
97 static int cont = 0;
98 static int color;
99 int mods = 0;
100 unsigned int mods_used = (ShiftMask | ControlMask | Mod1Mask);
101 
102 extern int yylineno;
103 static void yyerror ( const char *s );
104 
105 %}
106 
107 %union
108 {
109     int num;
110     char *ptr;
111 };
112 
113 %token <num> LB RB LP RP MENUS MENU BUTTON DEFAULT_FUNCTION PLUS MINUS
114 %token <num> ALL OR CURSORS PIXMAPS ICONS COLOR SAVECOLOR MONOCHROME FUNCTION
115 %token <num> ICONMGR_SHOW ICONMGR WINDOW_FUNCTION ZOOM ICONMGRS
116 %token <num> ICONMGR_GEOMETRY ICONMGR_NOSHOW MAKE_TITLE GRAYSCALE
117 %token <num> ICONIFY_BY_UNMAPPING DONT_ICONIFY_BY_UNMAPPING
118 %token <num> NO_TITLE AUTO_RAISE NO_HILITE ICON_REGION
119 %token <num> META SHIFT LOCK CONTROL WINDOW TITLE ICON ROOT FRAME
120 %token <num> COLON EQUALS SQUEEZE_TITLE DONT_SQUEEZE_TITLE
121 %token <num> START_ICONIFIED NO_TITLE_HILITE TITLE_HILITE
122 %token <num> MOVE RESIZE WAIT SELECT KILL LEFT_TITLEBUTTON RIGHT_TITLEBUTTON
123 %token <num> NUMBER KEYWORD NKEYWORD CKEYWORD CLKEYWORD FKEYWORD FSKEYWORD
124 %token <num> SKEYWORD DKEYWORD JKEYWORD WINDOW_RING WARP_CURSOR ERRORTOKEN
125 %token <num> NO_STACKMODE
126 %token <ptr> STRING
127 
128 %type <ptr> string
129 %type <num> pixmap_list cursor_list color_list save_color_list stmt
130 %type <num> win_color_list iconm_list win_list icon_list function menu
131 %type <num> noarg sarg error narg squeeze color_entry
132 %type <num> action button number signed_number full fullkey
133 
134 %start twmrc
135 
136 %%
137 twmrc		: stmts
138 		;
139 
140 stmts		: /* Empty */
141 		| stmts stmt
142 		;
143 
144 stmt		: error
145 		| noarg
146 		| sarg
147 		| narg
148 		| squeeze
149 		| ICON_REGION string DKEYWORD DKEYWORD number number
150 					{ AddIconRegion($2, $3, $4, $5, $6); }
151 		| ICONMGR_GEOMETRY string number	{ if (Scr->FirstTime)
152 						  {
153 						    Scr->iconmgr.geometry=$2;
154 						    Scr->iconmgr.columns=$3;
155 						  }
156 						}
157 		| ICONMGR_GEOMETRY string	{ if (Scr->FirstTime)
158 						    Scr->iconmgr.geometry = $2;
159 						}
160 		| ZOOM number		{ if (Scr->FirstTime)
161 					  {
162 						Scr->DoZoom = TRUE;
163 						Scr->ZoomCount = (short)$2;
164 					  }
165 					}
166 		| ZOOM			{ if (Scr->FirstTime)
167 						Scr->DoZoom = TRUE; }
168 		| PIXMAPS pixmap_list	{}
169 		| CURSORS cursor_list	{}
170 		| ICONIFY_BY_UNMAPPING	{ list = &Scr->IconifyByUn; }
171 		  win_list
172 		| ICONIFY_BY_UNMAPPING	{ if (Scr->FirstTime)
173 		    Scr->IconifyByUnmapping = TRUE; }
174 		| LEFT_TITLEBUTTON string EQUALS action {
175 					  GotTitleButton ($2, $4, False);
176 					}
177 		| RIGHT_TITLEBUTTON string EQUALS action {
178 					  GotTitleButton ($2, $4, True);
179 					}
180 		| button string		{ root = GetRoot($2, NULLSTR, NULLSTR);
181 					  Scr->Mouse[$1][C_ROOT][0].func = F_MENU;
182 					  Scr->Mouse[$1][C_ROOT][0].menu = root;
183 					}
184 		| button action		{ Scr->Mouse[$1][C_ROOT][0].func = $2;
185 					  if ($2 == F_MENU)
186 					  {
187 					    pull->prev = NULL;
188 					    Scr->Mouse[$1][C_ROOT][0].menu = pull;
189 					  }
190 					  else
191 					  {
192 					    root = GetRoot(TWM_ROOT,NULLSTR,NULLSTR);
193 					    Scr->Mouse[$1][C_ROOT][0].item =
194 						AddToMenu(root,"x",Action,
195 							  NULL,$2,NULLSTR,NULLSTR);
196 					  }
197 					  Action = empty;
198 					  pull = NULL;
199 					}
200 		| string fullkey	{ GotKey($1, $2); }
201 		| button full		{ GotButton($1, $2); }
202 		| DONT_ICONIFY_BY_UNMAPPING { list = &Scr->DontIconify; }
203 		  win_list
204 		| ICONMGR_NOSHOW	{ list = &Scr->IconMgrNoShow; }
205 		  win_list
206 		| ICONMGR_NOSHOW	{ Scr->IconManagerDontShow = TRUE; }
207 		| ICONMGRS		{ list = &Scr->IconMgrs; }
208 		  iconm_list
209 		| ICONMGR_SHOW		{ list = &Scr->IconMgrShow; }
210 		  win_list
211 		| NO_TITLE_HILITE	{ list = &Scr->NoTitleHighlight; }
212 		  win_list
213 		| NO_TITLE_HILITE	{ if (Scr->FirstTime)
214 						Scr->TitleHighlight = FALSE; }
215 		| NO_HILITE		{ list = &Scr->NoHighlight; }
216 		  win_list
217 		| NO_HILITE		{ if (Scr->FirstTime)
218 						Scr->Highlight = FALSE; }
219 		| NO_STACKMODE		{ list = &Scr->NoStackModeL; }
220 		  win_list
221 		| NO_STACKMODE		{ if (Scr->FirstTime)
222 						Scr->StackMode = FALSE; }
223 		| NO_TITLE		{ list = &Scr->NoTitle; }
224 		  win_list
225 		| NO_TITLE		{ if (Scr->FirstTime)
226 						Scr->NoTitlebar = TRUE; }
227 		| MAKE_TITLE		{ list = &Scr->MakeTitle; }
228 		  win_list
229 		| START_ICONIFIED	{ list = &Scr->StartIconified; }
230 		  win_list
231 		| AUTO_RAISE		{ list = &Scr->AutoRaise; }
232 		  win_list
233 		| MENU string LP string COLON string RP	{
234 					root = GetRoot($2, $4, $6); }
235 		  menu			{ root->real_menu = TRUE;}
236 		| MENU string 		{ root = GetRoot($2, NULLSTR, NULLSTR); }
237 		  menu			{ root->real_menu = TRUE; }
238 		| FUNCTION string	{ root = GetRoot($2, NULLSTR, NULLSTR); }
239 		  function
240 		| ICONS 		{ list = &Scr->IconNames; }
241 		  icon_list
242 		| COLOR 		{ color = COLOR; }
243 		  color_list
244 		| GRAYSCALE 		{ color = GRAYSCALE; }
245   		  color_list
246 		| SAVECOLOR
247                   save_color_list
248 		| MONOCHROME 		{ color = MONOCHROME; }
249 	          color_list
250 		| DEFAULT_FUNCTION action { Scr->DefaultFunction.func = $2;
251 					  if ($2 == F_MENU)
252 					  {
253 					    pull->prev = NULL;
254 					    Scr->DefaultFunction.menu = pull;
255 					  }
256 					  else
257 					  {
258 					    root = GetRoot(TWM_ROOT,NULLSTR,NULLSTR);
259 					    Scr->DefaultFunction.item =
260 						AddToMenu(root,"x",Action,
261 							  NULL,$2, NULLSTR, NULLSTR);
262 					  }
263 					  Action = empty;
264 					  pull = NULL;
265 					}
266 		| WINDOW_FUNCTION action { Scr->WindowFunction.func = $2;
267 					   root = GetRoot(TWM_ROOT,NULLSTR,NULLSTR);
268 					   Scr->WindowFunction.item =
269 						AddToMenu(root,"x",Action,
270 							  NULL,$2, NULLSTR, NULLSTR);
271 					   Action = empty;
272 					   pull = NULL;
273 					}
274 		| WARP_CURSOR		{ list = &Scr->WarpCursorL; }
275 		  win_list
276 		| WARP_CURSOR		{ if (Scr->FirstTime)
277 					    Scr->WarpCursor = TRUE; }
278 		| WINDOW_RING		{ list = &Scr->WindowRingL; }
279 		  win_list
280 		;
281 
282 
283 noarg		: KEYWORD		{ if (!do_single_keyword ($1)) {
284 					    twmrc_error_prefix();
285 					    fprintf (stderr,
286 					"unknown singleton keyword %d\n",
287 						     $1);
288 					    ParseError = 1;
289 					  }
290 					}
291 		;
292 
293 sarg		: SKEYWORD string	{ if (!do_string_keyword ($1, $2)) {
294 					    twmrc_error_prefix();
295 					    fprintf (stderr,
296 				"unknown string keyword %d (value \"%s\")\n",
297 						     $1, $2);
298 					    ParseError = 1;
299 					  }
300 					}
301 		;
302 
303 narg		: NKEYWORD number	{ if (!do_number_keyword ($1, $2)) {
304 					    twmrc_error_prefix();
305 					    fprintf (stderr,
306 				"unknown numeric keyword %d (value %d)\n",
307 						     $1, $2);
308 					    ParseError = 1;
309 					  }
310 					}
311 		;
312 
313 
314 
315 full		: EQUALS keys COLON contexts COLON action  { $$ = $6; }
316 		;
317 
318 fullkey		: EQUALS keys COLON contextkeys COLON action  { $$ = $6; }
319 		;
320 
321 keys		: /* Empty */
322 		| keys key
323 		;
324 
325 key		: META			{ mods |= Mod1Mask; }
326 		| SHIFT			{ mods |= ShiftMask; }
327 		| LOCK			{ mods |= LockMask; }
328 		| CONTROL		{ mods |= ControlMask; }
329 		| META number		{ if ($2 < 1 || $2 > 5) {
330 					     twmrc_error_prefix();
331 					     fprintf (stderr,
332 				"bad modifier number (%d), must be 1-5\n",
333 						      $2);
334 					     ParseError = 1;
335 					  } else {
336 					     mods |= (Mod1Mask << ($2 - 1));
337 					  }
338 					}
339 		| OR			{ }
340 		;
341 
342 contexts	: /* Empty */
343 		| contexts context
344 		;
345 
346 context		: WINDOW		{ cont |= C_WINDOW_BIT; }
347 		| TITLE			{ cont |= C_TITLE_BIT; }
348 		| ICON			{ cont |= C_ICON_BIT; }
349 		| ROOT			{ cont |= C_ROOT_BIT; }
350 		| FRAME			{ cont |= C_FRAME_BIT; }
351 		| ICONMGR		{ cont |= C_ICONMGR_BIT; }
352 		| META			{ cont |= C_ICONMGR_BIT; }
353 		| ALL			{ cont |= C_ALL_BITS; }
354 		| OR			{  }
355 		;
356 
357 contextkeys	: /* Empty */
358 		| contextkeys contextkey
359 		;
360 
361 contextkey	: WINDOW		{ cont |= C_WINDOW_BIT; }
362 		| TITLE			{ cont |= C_TITLE_BIT; }
363 		| ICON			{ cont |= C_ICON_BIT; }
364 		| ROOT			{ cont |= C_ROOT_BIT; }
365 		| FRAME			{ cont |= C_FRAME_BIT; }
366 		| ICONMGR		{ cont |= C_ICONMGR_BIT; }
367 		| META			{ cont |= C_ICONMGR_BIT; }
368 		| ALL			{ cont |= C_ALL_BITS; }
369 		| OR			{ }
370 		| string		{ Name = $1; cont |= C_NAME_BIT; }
371 		;
372 
373 
374 pixmap_list	: LB pixmap_entries RB
375 		;
376 
377 pixmap_entries	: /* Empty */
378 		| pixmap_entries pixmap_entry
379 		;
380 
381 pixmap_entry	: TITLE_HILITE string { SetHighlightPixmap ($2); }
382 		;
383 
384 
385 cursor_list	: LB cursor_entries RB
386 		;
387 
388 cursor_entries	: /* Empty */
389 		| cursor_entries cursor_entry
390 		;
391 
392 cursor_entry	: FRAME string string {
393 			NewBitmapCursor(&Scr->FrameCursor, $2, $3); }
394 		| FRAME string	{
395 			NewFontCursor(&Scr->FrameCursor, $2); }
396 		| TITLE string string {
397 			NewBitmapCursor(&Scr->TitleCursor, $2, $3); }
398 		| TITLE string {
399 			NewFontCursor(&Scr->TitleCursor, $2); }
400 		| ICON string string {
401 			NewBitmapCursor(&Scr->IconCursor, $2, $3); }
402 		| ICON string {
403 			NewFontCursor(&Scr->IconCursor, $2); }
404 		| ICONMGR string string {
405 			NewBitmapCursor(&Scr->IconMgrCursor, $2, $3); }
406 		| ICONMGR string {
407 			NewFontCursor(&Scr->IconMgrCursor, $2); }
408 		| BUTTON string string {
409 			NewBitmapCursor(&Scr->ButtonCursor, $2, $3); }
410 		| BUTTON string {
411 			NewFontCursor(&Scr->ButtonCursor, $2); }
412 		| MOVE string string {
413 			NewBitmapCursor(&Scr->MoveCursor, $2, $3); }
414 		| MOVE string {
415 			NewFontCursor(&Scr->MoveCursor, $2); }
416 		| RESIZE string string {
417 			NewBitmapCursor(&Scr->ResizeCursor, $2, $3); }
418 		| RESIZE string {
419 			NewFontCursor(&Scr->ResizeCursor, $2); }
420 		| WAIT string string {
421 			NewBitmapCursor(&Scr->WaitCursor, $2, $3); }
422 		| WAIT string {
423 			NewFontCursor(&Scr->WaitCursor, $2); }
424 		| MENU string string {
425 			NewBitmapCursor(&Scr->MenuCursor, $2, $3); }
426 		| MENU string {
427 			NewFontCursor(&Scr->MenuCursor, $2); }
428 		| SELECT string string {
429 			NewBitmapCursor(&Scr->SelectCursor, $2, $3); }
430 		| SELECT string {
431 			NewFontCursor(&Scr->SelectCursor, $2); }
432 		| KILL string string {
433 			NewBitmapCursor(&Scr->DestroyCursor, $2, $3); }
434 		| KILL string {
435 			NewFontCursor(&Scr->DestroyCursor, $2); }
436 		;
437 
438 color_list	: LB color_entries RB
439 		;
440 
441 
442 color_entries	: /* Empty */
443 		| color_entries color_entry
444 		;
445 
446 color_entry	: CLKEYWORD string	{ if (!do_colorlist_keyword ($1, color,
447 								     $2)) {
448 					    twmrc_error_prefix();
449 					    fprintf (stderr,
450 			"unhandled list color keyword %d (string \"%s\")\n",
451 						     $1, $2);
452 					    ParseError = 1;
453 					  }
454 					}
455 		| CLKEYWORD string	{ list = do_colorlist_keyword($1,color,
456 								      $2);
457 					  if (!list) {
458 					    twmrc_error_prefix();
459 					    fprintf (stderr,
460 			"unhandled color list keyword %d (string \"%s\")\n",
461 						     $1, $2);
462 					    ParseError = 1;
463 					  }
464 					}
465 		  win_color_list	{ /* No action */; }
466 		| CKEYWORD string	{ if (!do_color_keyword ($1, color,
467 								 $2)) {
468 					    twmrc_error_prefix();
469 					    fprintf (stderr,
470 			"unhandled color keyword %d (string \"%s\")\n",
471 						     $1, $2);
472 					    ParseError = 1;
473 					  }
474 					}
475 		;
476 
477 save_color_list : LB s_color_entries RB
478                 ;
479 
480 s_color_entries : /* Empty */
481                 | s_color_entries s_color_entry
482                 ;
483 
484 s_color_entry   : string            { do_string_savecolor(color, $1); }
485                 | CLKEYWORD         { do_var_savecolor($1); }
486                 ;
487 
488 win_color_list	: LB win_color_entries RB
489 		;
490 
491 win_color_entries	: /* Empty */
492 		| win_color_entries win_color_entry
493 		;
494 
495 win_color_entry	: string string		{ if (Scr->FirstTime &&
496 					      color == Scr->Monochrome)
497 					    AddToList(list, $1, $2); }
498 		;
499 
500 squeeze		: SQUEEZE_TITLE {
501 				    if (HasShape) Scr->SqueezeTitle = TRUE;
502 				}
503 		| SQUEEZE_TITLE { list = &Scr->SqueezeTitleL;
504 				  if (HasShape && Scr->SqueezeTitle == -1)
505 				    Scr->SqueezeTitle = TRUE;
506 				}
507 		  LB win_sqz_entries RB
508 		| DONT_SQUEEZE_TITLE { Scr->SqueezeTitle = FALSE; }
509 		| DONT_SQUEEZE_TITLE { list = &Scr->DontSqueezeTitleL; }
510 		  win_list
511 		;
512 
513 win_sqz_entries	: /* Empty */
514 		| win_sqz_entries string JKEYWORD signed_number number	{
515 				if (Scr->FirstTime) {
516 				   do_squeeze_entry (list, $2, $3, $4, $5);
517 				}
518 			}
519 		;
520 
521 
522 iconm_list	: LB iconm_entries RB
523 		;
524 
525 iconm_entries	: /* Empty */
526 		| iconm_entries iconm_entry
527 		;
528 
529 iconm_entry	: string string number	{ if (Scr->FirstTime)
530 					    AddToList(list, $1, (char *)
531 						AllocateIconManager($1, NULLSTR,
532 							$2,$3));
533 					}
534 		| string string string number
535 					{ if (Scr->FirstTime)
536 					    AddToList(list, $1, (char *)
537 						AllocateIconManager($1,$2,
538 						$3, $4));
539 					}
540 		;
541 
542 win_list	: LB win_entries RB
543 		;
544 
545 win_entries	: /* Empty */
546 		| win_entries win_entry
547 		;
548 
549 win_entry	: string		{ if (Scr->FirstTime)
550 					    AddToList(list, $1, 0);
551 					}
552 		;
553 
554 icon_list	: LB icon_entries RB
555 		;
556 
557 icon_entries	: /* Empty */
558 		| icon_entries icon_entry
559 		;
560 
561 icon_entry	: string string		{ if (Scr->FirstTime) AddToList(list, $1, $2); }
562 		;
563 
564 function	: LB function_entries RB
565 		;
566 
567 function_entries: /* Empty */
568 		| function_entries function_entry
569 		;
570 
571 function_entry	: action		{ AddToMenu(root, empty, Action, NULL, $1,
572 						NULLSTR, NULLSTR);
573 					  Action = empty;
574 					}
575 		;
576 
577 menu		: LB menu_entries RB
578 		;
579 
580 menu_entries	: /* Empty */
581 		| menu_entries menu_entry
582 		;
583 
584 menu_entry	: string action		{ AddToMenu(root, $1, Action, pull, $2,
585 						NULLSTR, NULLSTR);
586 					  Action = empty;
587 					  pull = NULL;
588 					}
589 		| string LP string COLON string RP action {
590 					  AddToMenu(root, $1, Action, pull, $7,
591 						$3, $5);
592 					  Action = empty;
593 					  pull = NULL;
594 					}
595 		;
596 
597 action		: FKEYWORD	{ $$ = $1; }
598 		| FSKEYWORD string {
599 				$$ = $1;
600 				Action = $2;
601 				switch ($1) {
602 				  case F_MENU:
603 				    pull = GetRoot ($2, NULLSTR,NULLSTR);
604 				    pull->prev = root;
605 				    break;
606 				  case F_WARPRING:
607 				    if (!CheckWarpRingArg (Action)) {
608 					twmrc_error_prefix();
609 					fprintf (stderr,
610 			"ignoring invalid f.warptoring argument \"%s\"\n",
611 						 Action);
612 					$$ = F_NOP;
613 				    }
614 				    break;
615 				  case F_WARPTOSCREEN:
616 				    if (!CheckWarpScreenArg (Action)) {
617 					twmrc_error_prefix();
618 					fprintf (stderr,
619 			"ignoring invalid f.warptoscreen argument \"%s\"\n",
620 					         Action);
621 					$$ = F_NOP;
622 				    }
623 				    break;
624 				  case F_COLORMAP:
625 				    if (CheckColormapArg (Action)) {
626 					$$ = F_COLORMAP;
627 				    } else {
628 					twmrc_error_prefix();
629 					fprintf (stderr,
630 			"ignoring invalid f.colormap argument \"%s\"\n",
631 						 Action);
632 					$$ = F_NOP;
633 				    }
634 				    break;
635 				} /* end switch */
636 				   }
637 		;
638 
639 
640 signed_number	: number		{ $$ = $1; }
641 		| PLUS number		{ $$ = $2; }
642 		| MINUS number		{ $$ = -($2); }
643 		;
644 
645 button		: BUTTON number		{ $$ = $2;
646 					  if ($2 == 0)
647 						yyerror("bad button 0");
648 
649 					  if ($2 > MAX_BUTTONS)
650 					  {
651 						$$ = 0;
652 						yyerror("button number too large");
653 					  }
654 					}
655 		;
656 
657 string		: STRING		{ ptr = strdup($1);
658 					  RemoveDQuote(ptr);
659 					  $$ = ptr;
660 					}
661 		;
662 number		: NUMBER		{ $$ = $1; }
663 		;
664 
665 %%
666 static void
667 yyerror(const char *s)
668 {
669     twmrc_error_prefix();
670     fprintf (stderr, "error in input file:  %s\n", s ? s : "");
671     ParseError = 1;
672 }
673 
674 static void
RemoveDQuote(char * str)675 RemoveDQuote(char *str)
676 {
677     register char *i, *o;
678     register int n;
679     register int count;
680 
681     for (i=str+1, o=str; *i && *i != '\"'; o++)
682     {
683 	if (*i == '\\')
684 	{
685 	    switch (*++i)
686 	    {
687 	    case 'n':
688 		*o = '\n';
689 		i++;
690 		break;
691 	    case 'b':
692 		*o = '\b';
693 		i++;
694 		break;
695 	    case 'r':
696 		*o = '\r';
697 		i++;
698 		break;
699 	    case 't':
700 		*o = '\t';
701 		i++;
702 		break;
703 	    case 'f':
704 		*o = '\f';
705 		i++;
706 		break;
707 	    case '0':
708 		if (*++i == 'x')
709 		    goto hex;
710 		else
711 		    --i;
712 		/* FALLTHRU */
713 	    case '1': case '2': case '3':
714 	    case '4': case '5': case '6': case '7':
715 		n = 0;
716 		count = 0;
717 		while (*i >= '0' && *i <= '7' && count < 3)
718 		{
719 		    n = (n<<3) + (*i++ - '0');
720 		    count++;
721 		}
722 		*o = (char)n;
723 		break;
724 	    hex:
725 	    case 'x':
726 		n = 0;
727 		count = 0;
728 		while (i++, count++ < 2)
729 		{
730 		    if (*i >= '0' && *i <= '9')
731 			n = (n<<4) + (*i - '0');
732 		    else if (*i >= 'a' && *i <= 'f')
733 			n = (n<<4) + (*i - 'a') + 10;
734 		    else if (*i >= 'A' && *i <= 'F')
735 			n = (n<<4) + (*i - 'A') + 10;
736 		    else
737 			break;
738 		}
739 		*o = (char)n;
740 		break;
741 	    case '\n':
742 		i++;	/* punt */
743 		o--;	/* to account for o++ at end of loop */
744 		break;
745 	    case '\"':
746 	    case '\'':
747 	    case '\\':
748 	    default:
749 		*o = *i++;
750 		break;
751 	    }
752 	}
753 	else
754 	    *o = *i++;
755     }
756     *o = '\0';
757 }
758 
GetRoot(const char * name,const char * fore,const char * back)759 static MenuRoot *GetRoot(const char *name, const char* fore, const char *back)
760 {
761     MenuRoot *tmp;
762 
763     tmp = FindMenuRoot(name);
764     if (tmp == NULL)
765 	tmp = NewMenuRoot(name);
766 
767     if (fore)
768     {
769 	int save;
770 
771 	save = Scr->FirstTime;
772 	Scr->FirstTime = TRUE;
773 	GetColor(COLOR, &tmp->hi_fore, fore);
774 	GetColor(COLOR, &tmp->hi_back, back);
775 	Scr->FirstTime = (short)save;
776     }
777 
778     return tmp;
779 }
780 
GotButton(int butt,int func)781 static void GotButton(int butt, int func)
782 {
783     int i;
784 
785     for (i = 0; i < NUM_CONTEXTS; i++)
786     {
787 	if ((cont & (1 << i)) == 0)
788 	    continue;
789 
790 	Scr->Mouse[butt][i][mods].func = func;
791 	if (func == F_MENU)
792 	{
793 	    pull->prev = NULL;
794 	    Scr->Mouse[butt][i][mods].menu = pull;
795 	}
796 	else
797 	{
798 	    root = GetRoot(TWM_ROOT, NULLSTR, NULLSTR);
799 	    Scr->Mouse[butt][i][mods].item = AddToMenu(root,"x",Action,
800 		    NULL, func, NULLSTR, NULLSTR);
801 	}
802     }
803     Action = empty;
804     pull = NULL;
805     cont = 0;
806     mods_used |= (unsigned)mods;
807     mods = 0;
808 }
809 
GotKey(char * key,int func)810 static void GotKey(char *key, int func)
811 {
812     int i;
813 
814     for (i = 0; i < NUM_CONTEXTS; i++)
815     {
816 	if ((cont & (1 << i)) == 0)
817 	  continue;
818 	if (!AddFuncKey(key, i, mods, func, Name, Action))
819 	  break;
820     }
821 
822     Action = empty;
823     pull = NULL;
824     cont = 0;
825     mods_used |= (unsigned)mods;
826     mods = 0;
827 }
828 
829 
GotTitleButton(char * bitmapname,int func,Bool rightside)830 static void GotTitleButton (char *bitmapname, int func, Bool rightside)
831 {
832     if (!CreateTitleButton (bitmapname, func, Action, pull, rightside, True)) {
833 	twmrc_error_prefix();
834 	fprintf (stderr,
835 		 "unable to create %s titlebutton \"%s\"\n",
836 		 rightside ? "right" : "left", bitmapname);
837     }
838     Action = empty;
839     pull = NULL;
840 }
841 
CheckWarpScreenArg(char * s)842 static Bool CheckWarpScreenArg (char *s)
843 {
844     XmuCopyISOLatin1Lowered (s, s);
845 
846     if (strcmp (s,  WARPSCREEN_NEXT) == 0 ||
847 	strcmp (s,  WARPSCREEN_PREV) == 0 ||
848 	strcmp (s,  WARPSCREEN_BACK) == 0)
849       return True;
850 
851     for (; *s && isascii(*s) && isdigit(*s); s++) ; /* SUPPRESS 530 */
852     return (*s ? False : True);
853 }
854 
855 
CheckWarpRingArg(char * s)856 static Bool CheckWarpRingArg (char *s)
857 {
858     XmuCopyISOLatin1Lowered (s, s);
859 
860     if (strcmp (s,  WARPSCREEN_NEXT) == 0 ||
861 	strcmp (s,  WARPSCREEN_PREV) == 0)
862       return True;
863 
864     return False;
865 }
866 
867 
CheckColormapArg(char * s)868 static Bool CheckColormapArg (char *s)
869 {
870     XmuCopyISOLatin1Lowered (s, s);
871 
872     if (strcmp (s, COLORMAP_NEXT) == 0 ||
873 	strcmp (s, COLORMAP_PREV) == 0 ||
874 	strcmp (s, COLORMAP_DEFAULT) == 0)
875       return True;
876 
877     return False;
878 }
879 
880 
881 void
twmrc_error_prefix(void)882 twmrc_error_prefix (void)
883 {
884     fprintf (stderr, "%s:  line %d:  ", ProgramName, yylineno);
885 }
886