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