PR binutils/647
[external/binutils.git] / binutils / rcparse.y
1 %{ /* rcparse.y -- parser for Windows rc files
2    Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005
3    Free Software Foundation, Inc.
4    Written by Ian Lance Taylor, Cygnus Support.
5
6    This file is part of GNU Binutils.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21    02111-1307, USA.  */
22
23 /* This is a parser for Windows rc files.  It is based on the parser
24    by Gunther Ebert <gunther.ebert@ixos-leipzig.de>.  */
25
26 #include "bfd.h"
27 #include "bucomm.h"
28 #include "libiberty.h"
29 #include "windres.h"
30 #include "safe-ctype.h"
31
32 /* The current language.  */
33
34 static unsigned short language;
35
36 /* The resource information during a sub statement.  */
37
38 static struct res_res_info sub_res_info;
39
40 /* Dialog information.  This is built by the nonterminals styles and
41    controls.  */
42
43 static struct dialog dialog;
44
45 /* This is used when building a style.  It is modified by the
46    nonterminal styleexpr.  */
47
48 static unsigned long style;
49
50 /* These are used when building a control.  They are set before using
51    control_params.  */
52
53 static unsigned long base_style;
54 static unsigned long default_style;
55 static unsigned long class;
56 static struct res_id res_text_field;
57
58 /* This is used for COMBOBOX, LISTBOX and EDITTEXT which
59    do not allow resource 'text' field in control definition. */
60 static const struct res_id res_null_text = { 1, {{0, L""}}};
61
62 %}
63
64 %union
65 {
66   struct accelerator acc;
67   struct accelerator *pacc;
68   struct dialog_control *dialog_control;
69   struct menuitem *menuitem;
70   struct
71   {
72     struct rcdata_item *first;
73     struct rcdata_item *last;
74   } rcdata;
75   struct rcdata_item *rcdata_item;
76   struct stringtable_data *stringtable;
77   struct fixed_versioninfo *fixver;
78   struct ver_info *verinfo;
79   struct ver_stringinfo *verstring;
80   struct ver_varinfo *vervar;
81   struct res_id id;
82   struct res_res_info res_info;
83   struct
84   {
85     unsigned short on;
86     unsigned short off;
87   } memflags;
88   struct
89   {
90     unsigned long val;
91     /* Nonzero if this number was explicitly specified as long.  */
92     int dword;
93   } i;
94   unsigned long il;
95   unsigned short is;
96   const char *s;
97   struct
98   {
99     unsigned long length;
100     const char *s;
101   } ss;
102 };
103
104 %token BEG END
105 %token ACCELERATORS VIRTKEY ASCII NOINVERT SHIFT CONTROL ALT
106 %token BITMAP
107 %token CURSOR
108 %token DIALOG DIALOGEX EXSTYLE CAPTION CLASS STYLE
109 %token AUTO3STATE AUTOCHECKBOX AUTORADIOBUTTON CHECKBOX COMBOBOX CTEXT
110 %token DEFPUSHBUTTON EDITTEXT GROUPBOX LISTBOX LTEXT PUSHBOX PUSHBUTTON
111 %token RADIOBUTTON RTEXT SCROLLBAR STATE3 USERBUTTON
112 %token BEDIT HEDIT IEDIT
113 %token FONT
114 %token ICON
115 %token LANGUAGE CHARACTERISTICS VERSIONK
116 %token MENU MENUEX MENUITEM SEPARATOR POPUP CHECKED GRAYED HELP INACTIVE
117 %token MENUBARBREAK MENUBREAK
118 %token MESSAGETABLE
119 %token RCDATA
120 %token STRINGTABLE
121 %token VERSIONINFO FILEVERSION PRODUCTVERSION FILEFLAGSMASK FILEFLAGS
122 %token FILEOS FILETYPE FILESUBTYPE BLOCKSTRINGFILEINFO BLOCKVARFILEINFO
123 %token VALUE
124 %token <s> BLOCK
125 %token MOVEABLE FIXED PURE IMPURE PRELOAD LOADONCALL DISCARDABLE
126 %token NOT
127 %token <s> QUOTEDSTRING STRING
128 %token <i> NUMBER
129 %token <ss> SIZEDSTRING
130 %token IGNORED_TOKEN
131
132 %type <pacc> acc_entries
133 %type <acc> acc_entry acc_event
134 %type <dialog_control> control control_params
135 %type <menuitem> menuitems menuitem menuexitems menuexitem
136 %type <rcdata> optrcdata_data optrcdata_data_int rcdata_data
137 %type <rcdata_item> opt_control_data
138 %type <fixver> fixedverinfo
139 %type <verinfo> verblocks
140 %type <verstring> vervals
141 %type <vervar> vertrans
142 %type <res_info> suboptions memflags_move_discard memflags_move
143 %type <memflags> memflag
144 %type <id> id optresidc resref
145 %type <il> exstyle parennumber
146 %type <il> numexpr posnumexpr cnumexpr optcnumexpr cposnumexpr
147 %type <is> acc_options acc_option menuitem_flags menuitem_flag
148 %type <s> file_name resname
149 %type <i> sizednumexpr sizedposnumexpr
150
151 %left '|'
152 %left '^'
153 %left '&'
154 %left '+' '-'
155 %left '*' '/' '%'
156 %right '~' NEG
157
158 %%
159
160 input:
161           /* empty */
162         | input accelerator
163         | input bitmap
164         | input cursor
165         | input dialog
166         | input font
167         | input icon
168         | input language
169         | input menu
170         | input menuex
171         | input messagetable
172         | input rcdata
173         | input stringtable
174         | input user
175         | input versioninfo
176         | input IGNORED_TOKEN
177         ;
178
179 /* Accelerator resources.  */
180
181 accelerator:
182           id ACCELERATORS suboptions BEG acc_entries END
183           {
184             define_accelerator ($1, &$3, $5);
185             if (yychar != YYEMPTY)
186               YYERROR;
187             rcparse_discard_strings ();
188           }
189         ;
190
191 acc_entries:
192           /* empty */
193           {
194             $$ = NULL;
195           }
196         | acc_entries acc_entry
197           {
198             struct accelerator *a;
199
200             a = (struct accelerator *) res_alloc (sizeof *a);
201             *a = $2;
202             if ($1 == NULL)
203               $$ = a;
204             else
205               {
206                 struct accelerator **pp;
207
208                 for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
209                   ;
210                 *pp = a;
211                 $$ = $1;
212               }
213           }
214         ;
215
216 acc_entry:
217           acc_event cposnumexpr
218           {
219             $$ = $1;
220             $$.id = $2;
221           }
222         | acc_event cposnumexpr ',' acc_options
223           {
224             $$ = $1;
225             $$.id = $2;
226             $$.flags |= $4;
227             if (($$.flags & ACC_VIRTKEY) == 0
228                 && ($$.flags & (ACC_SHIFT | ACC_CONTROL)) != 0)
229               rcparse_warning (_("inappropriate modifiers for non-VIRTKEY"));
230           }
231         ;
232
233 acc_event:
234           QUOTEDSTRING
235           {
236             const char *s = $1;
237             char ch;
238
239             $$.next = NULL;
240             $$.id = 0;
241             ch = *s;
242             if (ch != '^')
243               $$.flags = 0;
244             else
245               {
246                 $$.flags = ACC_CONTROL | ACC_VIRTKEY;
247                 ++s;
248                 ch = *s;
249                 ch = TOUPPER (ch);
250               }
251             $$.key = ch;
252             if (s[1] != '\0')
253               rcparse_warning (_("accelerator should only be one character"));
254           }
255         | posnumexpr
256           {
257             $$.next = NULL;
258             $$.flags = 0;
259             $$.id = 0;
260             $$.key = $1;
261           }
262         ;
263
264 acc_options:
265           acc_option
266           {
267             $$ = $1;
268           }
269         | acc_options ',' acc_option
270           {
271             $$ = $1 | $3;
272           }
273         /* I've had one report that the comma is optional.  */
274         | acc_options acc_option
275           {
276             $$ = $1 | $2;
277           }
278         ;
279
280 acc_option:
281           VIRTKEY
282           {
283             $$ = ACC_VIRTKEY;
284           }
285         | ASCII
286           {
287             /* This is just the absence of VIRTKEY.  */
288             $$ = 0;
289           }
290         | NOINVERT
291           {
292             $$ = ACC_NOINVERT;
293           }
294         | SHIFT
295           {
296             $$ = ACC_SHIFT;
297           }
298         | CONTROL
299           {
300             $$ = ACC_CONTROL;
301           }
302         | ALT
303           {
304             $$ = ACC_ALT;
305           }
306         ;
307
308 /* Bitmap resources.  */
309
310 bitmap:
311           id BITMAP memflags_move file_name
312           {
313             define_bitmap ($1, &$3, $4);
314             if (yychar != YYEMPTY)
315               YYERROR;
316             rcparse_discard_strings ();
317           }
318         ;
319
320 /* Cursor resources.  */
321
322 cursor:
323           id CURSOR memflags_move_discard file_name
324           {
325             define_cursor ($1, &$3, $4);
326             if (yychar != YYEMPTY)
327               YYERROR;
328             rcparse_discard_strings ();
329           }
330         ;
331
332 /* Dialog resources.  */
333
334 dialog:
335           id DIALOG memflags_move exstyle posnumexpr cnumexpr cnumexpr
336             cnumexpr
337             {
338               memset (&dialog, 0, sizeof dialog);
339               dialog.x = $5;
340               dialog.y = $6;
341               dialog.width = $7;
342               dialog.height = $8;
343               dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU;
344               dialog.exstyle = $4;
345               dialog.menu.named = 1;
346               dialog.class.named = 1;
347               dialog.font = NULL;
348               dialog.ex = NULL;
349               dialog.controls = NULL;
350               sub_res_info = $3;
351               style = 0;
352             }
353             styles BEG controls END
354           {
355             define_dialog ($1, &sub_res_info, &dialog);
356             if (yychar != YYEMPTY)
357               YYERROR;
358             rcparse_discard_strings ();
359           }
360         | id DIALOGEX memflags_move exstyle posnumexpr cnumexpr cnumexpr
361             cnumexpr
362             {
363               memset (&dialog, 0, sizeof dialog);
364               dialog.x = $5;
365               dialog.y = $6;
366               dialog.width = $7;
367               dialog.height = $8;
368               dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU;
369               dialog.exstyle = $4;
370               dialog.menu.named = 1;
371               dialog.class.named = 1;
372               dialog.font = NULL;
373               dialog.ex = ((struct dialog_ex *)
374                            res_alloc (sizeof (struct dialog_ex)));
375               memset (dialog.ex, 0, sizeof (struct dialog_ex));
376               dialog.controls = NULL;
377               sub_res_info = $3;
378               style = 0;
379             }
380             styles BEG controls END
381           {
382             define_dialog ($1, &sub_res_info, &dialog);
383             if (yychar != YYEMPTY)
384               YYERROR;
385             rcparse_discard_strings ();
386           }
387         | id DIALOGEX memflags_move exstyle posnumexpr cnumexpr cnumexpr
388             cnumexpr cnumexpr
389             {
390               memset (&dialog, 0, sizeof dialog);
391               dialog.x = $5;
392               dialog.y = $6;
393               dialog.width = $7;
394               dialog.height = $8;
395               dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU;
396               dialog.exstyle = $4;
397               dialog.menu.named = 1;
398               dialog.class.named = 1;
399               dialog.font = NULL;
400               dialog.ex = ((struct dialog_ex *)
401                            res_alloc (sizeof (struct dialog_ex)));
402               memset (dialog.ex, 0, sizeof (struct dialog_ex));
403               dialog.ex->help = $9;
404               dialog.controls = NULL;
405               sub_res_info = $3;
406               style = 0;
407             }
408             styles BEG controls END
409           {
410             define_dialog ($1, &sub_res_info, &dialog);
411             if (yychar != YYEMPTY)
412               YYERROR;
413             rcparse_discard_strings ();
414           }
415         ;
416
417 exstyle:
418           /* empty */
419           {
420             $$ = 0;
421           }
422         | EXSTYLE '=' numexpr
423           {
424             $$ = $3;
425           }
426         ;
427
428 styles:
429           /* empty */
430         | styles CAPTION QUOTEDSTRING
431           {
432             dialog.style |= WS_CAPTION;
433             style |= WS_CAPTION;
434             unicode_from_ascii ((int *) NULL, &dialog.caption, $3);
435           }
436         | styles CLASS id
437           {
438             dialog.class = $3;
439           }
440         | styles STYLE
441             styleexpr
442           {
443             dialog.style = style;
444           }
445         | styles EXSTYLE numexpr
446           {
447             dialog.exstyle = $3;
448           }
449         | styles CLASS QUOTEDSTRING
450           {
451             res_string_to_id (& dialog.class, $3);
452           }
453         | styles FONT numexpr ',' QUOTEDSTRING
454           {
455             dialog.style |= DS_SETFONT;
456             style |= DS_SETFONT;
457             dialog.pointsize = $3;
458             unicode_from_ascii ((int *) NULL, &dialog.font, $5);
459             if (dialog.ex != NULL)
460               {
461                 dialog.ex->weight = 0;
462                 dialog.ex->italic = 0;
463                 dialog.ex->charset = 1;
464               }
465           }
466         | styles FONT numexpr ',' QUOTEDSTRING cnumexpr
467           {
468             dialog.style |= DS_SETFONT;
469             style |= DS_SETFONT;
470             dialog.pointsize = $3;
471             unicode_from_ascii ((int *) NULL, &dialog.font, $5);
472             if (dialog.ex == NULL)
473               rcparse_warning (_("extended FONT requires DIALOGEX"));
474             else
475               {
476                 dialog.ex->weight = $6;
477                 dialog.ex->italic = 0;
478                 dialog.ex->charset = 1;
479               }
480           }
481         | styles FONT numexpr ',' QUOTEDSTRING cnumexpr cnumexpr
482           {
483             dialog.style |= DS_SETFONT;
484             style |= DS_SETFONT;
485             dialog.pointsize = $3;
486             unicode_from_ascii ((int *) NULL, &dialog.font, $5);
487             if (dialog.ex == NULL)
488               rcparse_warning (_("extended FONT requires DIALOGEX"));
489             else
490               {
491                 dialog.ex->weight = $6;
492                 dialog.ex->italic = $7;
493                 dialog.ex->charset = 1;
494               }
495           }
496         | styles FONT numexpr ',' QUOTEDSTRING cnumexpr cnumexpr cnumexpr
497           {
498             dialog.style |= DS_SETFONT;
499             style |= DS_SETFONT;
500             dialog.pointsize = $3;
501             unicode_from_ascii ((int *) NULL, &dialog.font, $5);
502             if (dialog.ex == NULL)
503               rcparse_warning (_("extended FONT requires DIALOGEX"));
504             else
505               {
506                 dialog.ex->weight = $6;
507                 dialog.ex->italic = $7;
508                 dialog.ex->charset = $8;
509               }
510           }
511         | styles MENU id
512           {
513             dialog.menu = $3;
514           }
515         | styles CHARACTERISTICS numexpr
516           {
517             sub_res_info.characteristics = $3;
518           }
519         | styles LANGUAGE numexpr cnumexpr
520           {
521             sub_res_info.language = $3 | ($4 << SUBLANG_SHIFT);
522           }
523         | styles VERSIONK numexpr
524           {
525             sub_res_info.version = $3;
526           }
527         ;
528
529 controls:
530           /* empty */
531         | controls control
532           {
533             struct dialog_control **pp;
534
535             for (pp = &dialog.controls; *pp != NULL; pp = &(*pp)->next)
536               ;
537             *pp = $2;
538           }
539         ;
540
541 control:
542           AUTO3STATE optresidc
543             {
544               default_style = BS_AUTO3STATE | WS_TABSTOP;
545               base_style = BS_AUTO3STATE;
546               class = CTL_BUTTON;
547               res_text_field = $2;      
548             }
549             control_params
550           {
551             $$ = $4;
552           }
553         | AUTOCHECKBOX optresidc
554             {
555               default_style = BS_AUTOCHECKBOX | WS_TABSTOP;
556               base_style = BS_AUTOCHECKBOX;
557               class = CTL_BUTTON;
558               res_text_field = $2;      
559             }
560             control_params
561           {
562             $$ = $4;
563           }
564         | AUTORADIOBUTTON optresidc
565             {
566               default_style = BS_AUTORADIOBUTTON | WS_TABSTOP;
567               base_style = BS_AUTORADIOBUTTON;
568               class = CTL_BUTTON;
569               res_text_field = $2;      
570             }
571             control_params
572           {
573             $$ = $4;
574           }
575         | BEDIT optresidc
576             {
577               default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
578               base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
579               class = CTL_EDIT;
580               res_text_field = $2;      
581             }
582             control_params
583           {
584             $$ = $4;
585             if (dialog.ex == NULL)
586               rcparse_warning (_("BEDIT requires DIALOGEX"));
587             res_string_to_id (&$$->class, "BEDIT");
588           }
589         | CHECKBOX optresidc
590             {
591               default_style = BS_CHECKBOX | WS_TABSTOP;
592               base_style = BS_CHECKBOX | WS_TABSTOP;
593               class = CTL_BUTTON;
594               res_text_field = $2;      
595             }
596             control_params
597           {
598             $$ = $4;
599           }
600         | COMBOBOX
601             {
602               /* This is as per MSDN documentation.  With some (???)
603                  versions of MS rc.exe their is no default style.  */
604               default_style = CBS_SIMPLE | WS_TABSTOP;
605               base_style = 0;
606               class = CTL_COMBOBOX;
607               res_text_field = res_null_text;   
608             }
609             control_params
610           {
611             $$ = $3;
612           }
613         | CONTROL optresidc numexpr cnumexpr control_styleexpr cnumexpr
614             cnumexpr cnumexpr cnumexpr optcnumexpr opt_control_data
615           {
616             $$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10);
617             if ($11 != NULL)
618               {
619                 if (dialog.ex == NULL)
620                   rcparse_warning (_("control data requires DIALOGEX"));
621                 $$->data = $11;
622               }
623           }
624         | CONTROL optresidc numexpr cnumexpr control_styleexpr cnumexpr
625             cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data
626           {
627             $$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10);
628             if (dialog.ex == NULL)
629               rcparse_warning (_("help ID requires DIALOGEX"));
630             $$->help = $11;
631             $$->data = $12;
632           }
633         | CONTROL optresidc numexpr ',' QUOTEDSTRING control_styleexpr
634             cnumexpr cnumexpr cnumexpr cnumexpr optcnumexpr opt_control_data
635           {
636             $$ = define_control ($2, $3, $7, $8, $9, $10, 0, style, $11);
637             if ($12 != NULL)
638               {
639                 if (dialog.ex == NULL)
640                   rcparse_warning ("control data requires DIALOGEX");
641                 $$->data = $12;
642               }
643             $$->class.named = 1;
644             unicode_from_ascii (&$$->class.u.n.length, &$$->class.u.n.name, $5);
645           }
646         | CONTROL optresidc numexpr ',' QUOTEDSTRING control_styleexpr
647             cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data
648           {
649             $$ = define_control ($2, $3, $7, $8, $9, $10, 0, style, $11);
650             if (dialog.ex == NULL)
651               rcparse_warning ("help ID requires DIALOGEX");
652             $$->help = $12;
653             $$->data = $13;
654             $$->class.named = 1;
655             unicode_from_ascii (&$$->class.u.n.length, &$$->class.u.n.name, $5);
656           }
657         | CTEXT optresidc
658             {
659               default_style = SS_CENTER | WS_GROUP;
660               base_style = SS_CENTER;
661               class = CTL_STATIC;
662               res_text_field = $2;      
663             }
664             control_params
665           {
666             $$ = $4;
667           }
668         | DEFPUSHBUTTON optresidc
669             {
670               default_style = BS_DEFPUSHBUTTON | WS_TABSTOP;
671               base_style = BS_DEFPUSHBUTTON | WS_TABSTOP;
672               class = CTL_BUTTON;
673               res_text_field = $2;      
674             }
675             control_params
676           {
677             $$ = $4;
678           }
679         | EDITTEXT
680             {
681               default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
682               base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
683               class = CTL_EDIT;
684               res_text_field = res_null_text;   
685             }
686             control_params
687           {
688             $$ = $3;
689           }
690         | GROUPBOX optresidc
691             {
692               default_style = BS_GROUPBOX;
693               base_style = BS_GROUPBOX;
694               class = CTL_BUTTON;
695               res_text_field = $2;      
696             }
697             control_params
698           {
699             $$ = $4;
700           }
701         | HEDIT optresidc
702             {
703               default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
704               base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
705               class = CTL_EDIT;
706               res_text_field = $2;      
707             }
708             control_params
709           {
710             $$ = $4;
711             if (dialog.ex == NULL)
712               rcparse_warning (_("IEDIT requires DIALOGEX"));
713             res_string_to_id (&$$->class, "HEDIT");
714           }
715         | ICON resref numexpr cnumexpr cnumexpr opt_control_data
716           {
717             $$ = define_icon_control ($2, $3, $4, $5, 0, 0, 0, $6,
718                                       dialog.ex);
719           }
720         | ICON resref numexpr cnumexpr cnumexpr cnumexpr cnumexpr
721             opt_control_data
722           {
723             $$ = define_icon_control ($2, $3, $4, $5, 0, 0, 0, $8,
724                                       dialog.ex);
725           }
726         | ICON resref numexpr cnumexpr cnumexpr cnumexpr cnumexpr
727             icon_styleexpr optcnumexpr opt_control_data
728           {
729             $$ = define_icon_control ($2, $3, $4, $5, style, $9, 0, $10,
730                                       dialog.ex);
731           }
732         | ICON resref numexpr cnumexpr cnumexpr cnumexpr cnumexpr
733             icon_styleexpr cnumexpr cnumexpr opt_control_data
734           {
735             $$ = define_icon_control ($2, $3, $4, $5, style, $9, $10, $11,
736                                       dialog.ex);
737           }
738         | IEDIT optresidc
739             {
740               default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
741               base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
742               class = CTL_EDIT;
743               res_text_field = $2;      
744             }
745             control_params
746           {
747             $$ = $4;
748             if (dialog.ex == NULL)
749               rcparse_warning (_("IEDIT requires DIALOGEX"));
750             res_string_to_id (&$$->class, "IEDIT");
751           }
752         | LISTBOX
753             {
754               default_style = LBS_NOTIFY | WS_BORDER;
755               base_style = LBS_NOTIFY | WS_BORDER;
756               class = CTL_LISTBOX;
757               res_text_field = res_null_text;   
758             }
759             control_params
760           {
761             $$ = $3;
762           }
763         | LTEXT optresidc
764             {
765               default_style = SS_LEFT | WS_GROUP;
766               base_style = SS_LEFT;
767               class = CTL_STATIC;
768               res_text_field = $2;      
769             }
770             control_params
771           {
772             $$ = $4;
773           }
774         | PUSHBOX optresidc
775             {
776               default_style = BS_PUSHBOX | WS_TABSTOP;
777               base_style = BS_PUSHBOX;
778               class = CTL_BUTTON;
779             }
780             control_params
781           {
782             $$ = $4;
783           }
784         | PUSHBUTTON optresidc
785             {
786               default_style = BS_PUSHBUTTON | WS_TABSTOP;
787               base_style = BS_PUSHBUTTON | WS_TABSTOP;
788               class = CTL_BUTTON;
789               res_text_field = $2;      
790             }
791             control_params
792           {
793             $$ = $4;
794           }
795         | RADIOBUTTON optresidc
796             {
797               default_style = BS_RADIOBUTTON | WS_TABSTOP;
798               base_style = BS_RADIOBUTTON;
799               class = CTL_BUTTON;
800               res_text_field = $2;      
801             }
802             control_params
803           {
804             $$ = $4;
805           }
806         | RTEXT optresidc
807             {
808               default_style = SS_RIGHT | WS_GROUP;
809               base_style = SS_RIGHT;
810               class = CTL_STATIC;
811               res_text_field = $2;      
812             }
813             control_params
814           {
815             $$ = $4;
816           }
817         | SCROLLBAR
818             {
819               default_style = SBS_HORZ;
820               base_style = 0;
821               class = CTL_SCROLLBAR;
822               res_text_field = res_null_text;   
823             }
824             control_params
825           {
826             $$ = $3;
827           }
828         | STATE3 optresidc
829             {
830               default_style = BS_3STATE | WS_TABSTOP;
831               base_style = BS_3STATE;
832               class = CTL_BUTTON;
833               res_text_field = $2;      
834             }
835             control_params
836           {
837             $$ = $4;
838           }
839         | USERBUTTON resref numexpr ',' numexpr ',' numexpr ','
840             numexpr ',' numexpr ',' 
841             { style = WS_CHILD | WS_VISIBLE; }
842             styleexpr optcnumexpr
843           {
844             $$ = define_control ($2, $3, $5, $7, $9, $11, CTL_BUTTON,
845                                  style, $15);
846           }
847         ;
848
849 /* Parameters for a control.  The static variables DEFAULT_STYLE,
850    BASE_STYLE, and CLASS must be initialized before this nonterminal
851    is used.  DEFAULT_STYLE is the style to use if no style expression
852    is specified.  BASE_STYLE is the base style to use if a style
853    expression is specified; the style expression modifies the base
854    style.  CLASS is the class of the control.  */
855
856 control_params:
857           numexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data
858           {
859             $$ = define_control (res_text_field, $1, $2, $3, $4, $5, class,
860                                  default_style | WS_CHILD | WS_VISIBLE, 0);
861             if ($6 != NULL)
862               {
863                 if (dialog.ex == NULL)
864                   rcparse_warning (_("control data requires DIALOGEX"));
865                 $$->data = $6;
866               }
867           }
868         | numexpr cnumexpr cnumexpr cnumexpr cnumexpr
869             control_params_styleexpr optcnumexpr opt_control_data
870           {
871             $$ = define_control (res_text_field, $1, $2, $3, $4, $5, class, style, $7);
872             if ($8 != NULL)
873               {
874                 if (dialog.ex == NULL)
875                   rcparse_warning (_("control data requires DIALOGEX"));
876                 $$->data = $8;
877               }
878           }
879         | numexpr cnumexpr cnumexpr cnumexpr cnumexpr
880             control_params_styleexpr cnumexpr cnumexpr opt_control_data
881           {
882             $$ = define_control (res_text_field, $1, $2, $3, $4, $5, class, style, $7);
883             if (dialog.ex == NULL)
884               rcparse_warning (_("help ID requires DIALOGEX"));
885             $$->help = $8;
886             $$->data = $9;
887           }
888         ;
889
890 optresidc:
891           /* empty */
892           {
893             res_string_to_id (&$$, "");
894           }
895         | posnumexpr ','
896           {
897             $$.named = 0;
898             $$.u.id = $1;
899           }
900         | QUOTEDSTRING
901           {
902             res_string_to_id (&$$, $1);
903           }
904         | QUOTEDSTRING ','
905           {
906             res_string_to_id (&$$, $1);
907           }
908         ;
909
910 opt_control_data:
911           /* empty */
912           {
913             $$ = NULL;
914           }
915         | BEG optrcdata_data END
916           {
917             $$ = $2.first;
918           }
919         ;
920
921 /* These only exist to parse a reduction out of a common case.  */
922
923 control_styleexpr:
924           ','
925           { style = WS_CHILD | WS_VISIBLE; }
926           styleexpr
927         ;
928
929 icon_styleexpr:
930           ','
931           { style = SS_ICON | WS_CHILD | WS_VISIBLE; }
932           styleexpr
933         ;
934
935 control_params_styleexpr:
936           ','
937           { style = base_style | WS_CHILD | WS_VISIBLE; }
938           styleexpr
939         ;
940
941 /* Font resources.  */
942
943 font:
944           id FONT memflags_move_discard file_name
945           {
946             define_font ($1, &$3, $4);
947             if (yychar != YYEMPTY)
948               YYERROR;
949             rcparse_discard_strings ();
950           }
951         ;
952
953 /* Icon resources.  */
954
955 icon:
956           id ICON memflags_move_discard file_name
957           {
958             define_icon ($1, &$3, $4);
959             if (yychar != YYEMPTY)
960               YYERROR;
961             rcparse_discard_strings ();
962           }
963         ;
964
965 /* Language command.  This changes the static variable language, which
966    affects all subsequent resources.  */
967
968 language:
969           LANGUAGE numexpr cnumexpr
970           {
971             language = $2 | ($3 << SUBLANG_SHIFT);
972           }
973         ;
974
975 /* Menu resources.  */
976
977 menu:
978           id MENU suboptions BEG menuitems END
979           {
980             define_menu ($1, &$3, $5);
981             if (yychar != YYEMPTY)
982               YYERROR;
983             rcparse_discard_strings ();
984           }
985         ;
986
987 menuitems:
988           /* empty */
989           {
990             $$ = NULL;
991           }
992         | menuitems menuitem
993           {
994             if ($1 == NULL)
995               $$ = $2;
996             else
997               {
998                 struct menuitem **pp;
999
1000                 for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
1001                   ;
1002                 *pp = $2;
1003                 $$ = $1;
1004               }
1005           }
1006         ;
1007
1008 menuitem:
1009           MENUITEM QUOTEDSTRING cnumexpr menuitem_flags
1010           {
1011             $$ = define_menuitem ($2, $3, $4, 0, 0, NULL);
1012           }
1013         | MENUITEM SEPARATOR
1014           {
1015             $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL);
1016           }
1017         | POPUP QUOTEDSTRING menuitem_flags BEG menuitems END
1018           {
1019             $$ = define_menuitem ($2, 0, $3, 0, 0, $5);
1020           }
1021         ;
1022
1023 menuitem_flags:
1024           /* empty */
1025           {
1026             $$ = 0;
1027           }
1028         | menuitem_flags ',' menuitem_flag
1029           {
1030             $$ = $1 | $3;
1031           }
1032         | menuitem_flags menuitem_flag
1033           {
1034             $$ = $1 | $2;
1035           }
1036         ;
1037
1038 menuitem_flag:
1039           CHECKED
1040           {
1041             $$ = MENUITEM_CHECKED;
1042           }
1043         | GRAYED
1044           {
1045             $$ = MENUITEM_GRAYED;
1046           }
1047         | HELP
1048           {
1049             $$ = MENUITEM_HELP;
1050           }
1051         | INACTIVE
1052           {
1053             $$ = MENUITEM_INACTIVE;
1054           }
1055         | MENUBARBREAK
1056           {
1057             $$ = MENUITEM_MENUBARBREAK;
1058           }
1059         | MENUBREAK
1060           {
1061             $$ = MENUITEM_MENUBREAK;
1062           }
1063         ;
1064
1065 /* Menuex resources.  */
1066
1067 menuex:
1068           id MENUEX suboptions BEG menuexitems END
1069           {
1070             define_menu ($1, &$3, $5);
1071             if (yychar != YYEMPTY)
1072               YYERROR;
1073             rcparse_discard_strings ();
1074           }
1075         ;
1076
1077 menuexitems:
1078           /* empty */
1079           {
1080             $$ = NULL;
1081           }
1082         | menuexitems menuexitem
1083           {
1084             if ($1 == NULL)
1085               $$ = $2;
1086             else
1087               {
1088                 struct menuitem **pp;
1089
1090                 for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
1091                   ;
1092                 *pp = $2;
1093                 $$ = $1;
1094               }
1095           }
1096         ;
1097
1098 menuexitem:
1099           MENUITEM QUOTEDSTRING
1100           {
1101             $$ = define_menuitem ($2, 0, 0, 0, 0, NULL);
1102           }
1103         | MENUITEM QUOTEDSTRING cnumexpr
1104           {
1105             $$ = define_menuitem ($2, $3, 0, 0, 0, NULL);
1106           }
1107         | MENUITEM QUOTEDSTRING cnumexpr cnumexpr optcnumexpr
1108           {
1109             $$ = define_menuitem ($2, $3, $4, $5, 0, NULL);
1110           }
1111         | MENUITEM SEPARATOR
1112           {
1113             $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL);
1114           }
1115         | POPUP QUOTEDSTRING BEG menuexitems END
1116           {
1117             $$ = define_menuitem ($2, 0, 0, 0, 0, $4);
1118           }
1119         | POPUP QUOTEDSTRING cnumexpr BEG menuexitems END
1120           {
1121             $$ = define_menuitem ($2, $3, 0, 0, 0, $5);
1122           }
1123         | POPUP QUOTEDSTRING cnumexpr cnumexpr BEG menuexitems END
1124           {
1125             $$ = define_menuitem ($2, $3, $4, 0, 0, $6);
1126           }
1127         | POPUP QUOTEDSTRING cnumexpr cnumexpr cnumexpr optcnumexpr
1128             BEG menuexitems END
1129           {
1130             $$ = define_menuitem ($2, $3, $4, $5, $6, $8);
1131           }
1132         ;
1133
1134 /* Messagetable resources.  */
1135
1136 messagetable:
1137           id MESSAGETABLE memflags_move file_name
1138           {
1139             define_messagetable ($1, &$3, $4);
1140             if (yychar != YYEMPTY)
1141               YYERROR;
1142             rcparse_discard_strings ();
1143           }
1144         ;
1145
1146 /* Rcdata resources.  */
1147
1148 rcdata:
1149           id RCDATA suboptions BEG optrcdata_data END
1150           {
1151             define_rcdata ($1, &$3, $5.first);
1152             if (yychar != YYEMPTY)
1153               YYERROR;
1154             rcparse_discard_strings ();
1155           }
1156         | id RCDATA suboptions file_name
1157           {
1158             define_rcdata_file ($1, &$3, $4);
1159             if (yychar != YYEMPTY)
1160               YYERROR;
1161             rcparse_discard_strings ();
1162           }
1163         ;
1164
1165 /* We use a different lexing algorithm, because rcdata strings may
1166    contain embedded null bytes, and we need to know the length to use.  */
1167
1168 optrcdata_data:
1169           {
1170             rcparse_rcdata ();
1171           }
1172           optrcdata_data_int
1173           {
1174             rcparse_normal ();
1175             $$ = $2;
1176           }
1177         ;
1178
1179 optrcdata_data_int:
1180           /* empty */
1181           {
1182             $$.first = NULL;
1183             $$.last = NULL;
1184           }
1185         | rcdata_data
1186           {
1187             $$ = $1;
1188           }
1189         ;
1190
1191 rcdata_data:
1192           SIZEDSTRING
1193           {
1194             struct rcdata_item *ri;
1195
1196             ri = define_rcdata_string ($1.s, $1.length);
1197             $$.first = ri;
1198             $$.last = ri;
1199           }
1200         | sizednumexpr
1201           {
1202             struct rcdata_item *ri;
1203
1204             ri = define_rcdata_number ($1.val, $1.dword);
1205             $$.first = ri;
1206             $$.last = ri;
1207           }
1208         | rcdata_data ',' SIZEDSTRING
1209           {
1210             struct rcdata_item *ri;
1211
1212             ri = define_rcdata_string ($3.s, $3.length);
1213             $$.first = $1.first;
1214             $1.last->next = ri;
1215             $$.last = ri;
1216           }
1217         | rcdata_data ',' sizednumexpr
1218           {
1219             struct rcdata_item *ri;
1220
1221             ri = define_rcdata_number ($3.val, $3.dword);
1222             $$.first = $1.first;
1223             $1.last->next = ri;
1224             $$.last = ri;
1225           }
1226         ;
1227
1228 /* Stringtable resources.  */
1229
1230 stringtable:
1231           STRINGTABLE suboptions BEG 
1232             { sub_res_info = $2; }
1233             string_data END
1234         ;
1235
1236 string_data:
1237           /* empty */
1238         | string_data numexpr QUOTEDSTRING
1239           {
1240             define_stringtable (&sub_res_info, $2, $3);
1241             if (yychar != YYEMPTY)
1242               YYERROR;
1243             rcparse_discard_strings ();
1244           }
1245         | string_data numexpr ',' QUOTEDSTRING
1246           {
1247             define_stringtable (&sub_res_info, $2, $4);
1248             if (yychar != YYEMPTY)
1249               YYERROR;
1250             rcparse_discard_strings ();
1251           }
1252         ;
1253
1254 /* User defined resources.  We accept general suboptions in the
1255    file_name case to keep the parser happy.  */
1256
1257 user:
1258           id id suboptions BEG optrcdata_data END
1259           {
1260             define_user_data ($1, $2, &$3, $5.first);
1261             if (yychar != YYEMPTY)
1262               YYERROR;
1263             rcparse_discard_strings ();
1264           }
1265         | id id suboptions file_name
1266           {
1267             define_user_file ($1, $2, &$3, $4);
1268             if (yychar != YYEMPTY)
1269               YYERROR;
1270             rcparse_discard_strings ();
1271           }
1272         ;
1273
1274 /* Versioninfo resources.  */
1275
1276 versioninfo:
1277           id VERSIONINFO fixedverinfo BEG verblocks END
1278           {
1279             define_versioninfo ($1, language, $3, $5);
1280             if (yychar != YYEMPTY)
1281               YYERROR;
1282             rcparse_discard_strings ();
1283           }
1284         ;
1285
1286 fixedverinfo:
1287           /* empty */
1288           {
1289             $$ = ((struct fixed_versioninfo *)
1290                   res_alloc (sizeof (struct fixed_versioninfo)));
1291             memset ($$, 0, sizeof (struct fixed_versioninfo));
1292           }
1293         | fixedverinfo FILEVERSION numexpr cnumexpr cnumexpr cnumexpr
1294           {
1295             $1->file_version_ms = ($3 << 16) | $4;
1296             $1->file_version_ls = ($5 << 16) | $6;
1297             $$ = $1;
1298           }
1299         | fixedverinfo PRODUCTVERSION numexpr cnumexpr cnumexpr cnumexpr
1300           {
1301             $1->product_version_ms = ($3 << 16) | $4;
1302             $1->product_version_ls = ($5 << 16) | $6;
1303             $$ = $1;
1304           }
1305         | fixedverinfo FILEFLAGSMASK numexpr
1306           {
1307             $1->file_flags_mask = $3;
1308             $$ = $1;
1309           }
1310         | fixedverinfo FILEFLAGS numexpr
1311           {
1312             $1->file_flags = $3;
1313             $$ = $1;
1314           }
1315         | fixedverinfo FILEOS numexpr
1316           {
1317             $1->file_os = $3;
1318             $$ = $1;
1319           }
1320         | fixedverinfo FILETYPE numexpr
1321           {
1322             $1->file_type = $3;
1323             $$ = $1;
1324           }
1325         | fixedverinfo FILESUBTYPE numexpr
1326           {
1327             $1->file_subtype = $3;
1328             $$ = $1;
1329           }
1330         ;
1331
1332 /* To handle verblocks successfully, the lexer handles BLOCK
1333    specially.  A BLOCK "StringFileInfo" is returned as
1334    BLOCKSTRINGFILEINFO.  A BLOCK "VarFileInfo" is returned as
1335    BLOCKVARFILEINFO.  A BLOCK with some other string returns BLOCK
1336    with the string as the value.  */
1337
1338 verblocks:
1339           /* empty */
1340           {
1341             $$ = NULL;
1342           }
1343         | verblocks BLOCKSTRINGFILEINFO BEG BLOCK BEG vervals END END
1344           {
1345             $$ = append_ver_stringfileinfo ($1, $4, $6);
1346           }
1347         | verblocks BLOCKVARFILEINFO BEG VALUE QUOTEDSTRING vertrans END
1348           {
1349             $$ = append_ver_varfileinfo ($1, $5, $6);
1350           }
1351         ;
1352
1353 vervals:
1354           /* empty */
1355           {
1356             $$ = NULL;
1357           }
1358         | vervals VALUE QUOTEDSTRING ',' QUOTEDSTRING
1359           {
1360             $$ = append_verval ($1, $3, $5);
1361           }
1362         ;
1363
1364 vertrans:
1365           /* empty */
1366           {
1367             $$ = NULL;
1368           }
1369         | vertrans cnumexpr cnumexpr
1370           {
1371             $$ = append_vertrans ($1, $2, $3);
1372           }
1373         ;
1374
1375 /* A resource ID.  */
1376
1377 id:
1378           posnumexpr
1379           {
1380             $$.named = 0;
1381             $$.u.id = $1;
1382           }
1383         | STRING
1384           {
1385             char *copy, *s;
1386
1387             /* It seems that resource ID's are forced to upper case.  */
1388             copy = xstrdup ($1);
1389             for (s = copy; *s != '\0'; s++)
1390               *s = TOUPPER (*s);
1391             res_string_to_id (&$$, copy);
1392             free (copy);
1393           }
1394         ;
1395
1396 /* A resource reference.  */
1397
1398 resname:
1399           QUOTEDSTRING
1400           {
1401             $$ = $1;
1402           }
1403         | QUOTEDSTRING ','
1404           {
1405             $$ = $1;
1406           }
1407         | STRING ','
1408           {
1409             $$ = $1;
1410           }
1411         ;
1412
1413
1414 resref:
1415           posnumexpr ','
1416           {
1417             $$.named = 0;
1418             $$.u.id = $1;
1419           }
1420         | resname
1421           {
1422             char *copy, *s;
1423
1424             /* It seems that resource ID's are forced to upper case.  */
1425             copy = xstrdup ($1);
1426             for (s = copy; *s != '\0'; s++)
1427               *s = TOUPPER (*s);
1428             res_string_to_id (&$$, copy);
1429             free (copy);
1430           }
1431         ;
1432
1433 /* Generic suboptions.  These may appear before the BEGIN in any
1434    multiline statement.  */
1435
1436 suboptions:
1437           /* empty */
1438           {
1439             memset (&$$, 0, sizeof (struct res_res_info));
1440             $$.language = language;
1441             /* FIXME: Is this the right default?  */
1442             $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_PURE | MEMFLAG_DISCARDABLE;
1443           }
1444         | suboptions memflag
1445           {
1446             $$ = $1;
1447             $$.memflags |= $2.on;
1448             $$.memflags &=~ $2.off;
1449           }
1450         | suboptions CHARACTERISTICS numexpr
1451           {
1452             $$ = $1;
1453             $$.characteristics = $3;
1454           }
1455         | suboptions LANGUAGE numexpr cnumexpr
1456           {
1457             $$ = $1;
1458             $$.language = $3 | ($4 << SUBLANG_SHIFT);
1459           }
1460         | suboptions VERSIONK numexpr
1461           {
1462             $$ = $1;
1463             $$.version = $3;
1464           }
1465         ;
1466
1467 /* Memory flags which default to MOVEABLE and DISCARDABLE.  */
1468
1469 memflags_move_discard:
1470           /* empty */
1471           {
1472             memset (&$$, 0, sizeof (struct res_res_info));
1473             $$.language = language;
1474             $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_DISCARDABLE;
1475           }
1476         | memflags_move_discard memflag
1477           {
1478             $$ = $1;
1479             $$.memflags |= $2.on;
1480             $$.memflags &=~ $2.off;
1481           }
1482         ;
1483
1484 /* Memory flags which default to MOVEABLE.  */
1485
1486 memflags_move:
1487           /* empty */
1488           {
1489             memset (&$$, 0, sizeof (struct res_res_info));
1490             $$.language = language;
1491             $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_PURE | MEMFLAG_DISCARDABLE;
1492           }
1493         | memflags_move memflag
1494           {
1495             $$ = $1;
1496             $$.memflags |= $2.on;
1497             $$.memflags &=~ $2.off;
1498           }
1499         ;
1500
1501 /* Memory flags.  This returns a struct with two integers, because we
1502    sometimes want to set bits and we sometimes want to clear them.  */
1503
1504 memflag:
1505           MOVEABLE
1506           {
1507             $$.on = MEMFLAG_MOVEABLE;
1508             $$.off = 0;
1509           }
1510         | FIXED
1511           {
1512             $$.on = 0;
1513             $$.off = MEMFLAG_MOVEABLE;
1514           }
1515         | PURE
1516           {
1517             $$.on = MEMFLAG_PURE;
1518             $$.off = 0;
1519           }
1520         | IMPURE
1521           {
1522             $$.on = 0;
1523             $$.off = MEMFLAG_PURE;
1524           }
1525         | PRELOAD
1526           {
1527             $$.on = MEMFLAG_PRELOAD;
1528             $$.off = 0;
1529           }
1530         | LOADONCALL
1531           {
1532             $$.on = 0;
1533             $$.off = MEMFLAG_PRELOAD;
1534           }
1535         | DISCARDABLE
1536           {
1537             $$.on = MEMFLAG_DISCARDABLE;
1538             $$.off = 0;
1539           }
1540         ;
1541
1542 /* A file name.  */
1543
1544 file_name:
1545           QUOTEDSTRING
1546           {
1547             $$ = $1;
1548           }
1549         | STRING
1550           {
1551             $$ = $1;
1552           }
1553         ;
1554
1555 /* A style expression.  This changes the static variable STYLE.  We do
1556    it this way because rc appears to permit a style to be set to
1557    something like
1558        WS_GROUP | NOT WS_TABSTOP
1559    to mean that a default of WS_TABSTOP should be removed.  Anything
1560    which wants to accept a style must first set STYLE to the default
1561    value.  The styleexpr nonterminal will change STYLE as specified by
1562    the user.  Note that we do not accept arbitrary expressions here,
1563    just numbers separated by '|'.  */
1564
1565 styleexpr:
1566           parennumber
1567           {
1568             style |= $1;
1569           }
1570         | NOT parennumber
1571           {
1572             style &=~ $2;
1573           }
1574         | styleexpr '|' parennumber
1575           {
1576             style |= $3;
1577           }
1578         | styleexpr '|' NOT parennumber
1579           {
1580             style &=~ $4;
1581           }
1582         ;
1583
1584 parennumber:
1585           NUMBER
1586           {
1587             $$ = $1.val;
1588           }
1589         | '(' numexpr ')'
1590           {
1591             $$ = $2;
1592           }
1593         ;
1594
1595 /* An optional expression with a leading comma.  */
1596
1597 optcnumexpr:
1598           /* empty */
1599           {
1600             $$ = 0;
1601           }
1602         | cnumexpr
1603           {
1604             $$ = $1;
1605           }
1606         ;
1607
1608 /* An expression with a leading comma.  */
1609
1610 cnumexpr:
1611           ',' numexpr
1612           {
1613             $$ = $2;
1614           }
1615         ;
1616
1617 /* A possibly negated numeric expression.  */
1618
1619 numexpr:
1620           sizednumexpr
1621           {
1622             $$ = $1.val;
1623           }
1624         ;
1625
1626 /* A possibly negated expression with a size.  */
1627
1628 sizednumexpr:
1629           NUMBER
1630           {
1631             $$ = $1;
1632           }
1633         | '(' sizednumexpr ')'
1634           {
1635             $$ = $2;
1636           }
1637         | '~' sizednumexpr %prec '~'
1638           {
1639             $$.val = ~ $2.val;
1640             $$.dword = $2.dword;
1641           }
1642         | '-' sizednumexpr %prec NEG
1643           {
1644             $$.val = - $2.val;
1645             $$.dword = $2.dword;
1646           }
1647         | sizednumexpr '*' sizednumexpr
1648           {
1649             $$.val = $1.val * $3.val;
1650             $$.dword = $1.dword || $3.dword;
1651           }
1652         | sizednumexpr '/' sizednumexpr
1653           {
1654             $$.val = $1.val / $3.val;
1655             $$.dword = $1.dword || $3.dword;
1656           }
1657         | sizednumexpr '%' sizednumexpr
1658           {
1659             $$.val = $1.val % $3.val;
1660             $$.dword = $1.dword || $3.dword;
1661           }
1662         | sizednumexpr '+' sizednumexpr
1663           {
1664             $$.val = $1.val + $3.val;
1665             $$.dword = $1.dword || $3.dword;
1666           }
1667         | sizednumexpr '-' sizednumexpr
1668           {
1669             $$.val = $1.val - $3.val;
1670             $$.dword = $1.dword || $3.dword;
1671           }
1672         | sizednumexpr '&' sizednumexpr
1673           {
1674             $$.val = $1.val & $3.val;
1675             $$.dword = $1.dword || $3.dword;
1676           }
1677         | sizednumexpr '^' sizednumexpr
1678           {
1679             $$.val = $1.val ^ $3.val;
1680             $$.dword = $1.dword || $3.dword;
1681           }
1682         | sizednumexpr '|' sizednumexpr
1683           {
1684             $$.val = $1.val | $3.val;
1685             $$.dword = $1.dword || $3.dword;
1686           }
1687         ;
1688
1689 /* An expression with a leading comma which does not use unary
1690    negation.  */
1691
1692 cposnumexpr:
1693           ',' posnumexpr
1694           {
1695             $$ = $2;
1696           }
1697         ;
1698
1699 /* An expression which does not use unary negation.  */
1700
1701 posnumexpr:
1702           sizedposnumexpr
1703           {
1704             $$ = $1.val;
1705           }
1706         ;
1707
1708 /* An expression which does not use unary negation.  We separate unary
1709    negation to avoid parsing conflicts when two numeric expressions
1710    appear consecutively.  */
1711
1712 sizedposnumexpr:
1713           NUMBER
1714           {
1715             $$ = $1;
1716           }
1717         | '(' sizednumexpr ')'
1718           {
1719             $$ = $2;
1720           }
1721         | '~' sizednumexpr %prec '~'
1722           {
1723             $$.val = ~ $2.val;
1724             $$.dword = $2.dword;
1725           }
1726         | sizedposnumexpr '*' sizednumexpr
1727           {
1728             $$.val = $1.val * $3.val;
1729             $$.dword = $1.dword || $3.dword;
1730           }
1731         | sizedposnumexpr '/' sizednumexpr
1732           {
1733             $$.val = $1.val / $3.val;
1734             $$.dword = $1.dword || $3.dword;
1735           }
1736         | sizedposnumexpr '%' sizednumexpr
1737           {
1738             $$.val = $1.val % $3.val;
1739             $$.dword = $1.dword || $3.dword;
1740           }
1741         | sizedposnumexpr '+' sizednumexpr
1742           {
1743             $$.val = $1.val + $3.val;
1744             $$.dword = $1.dword || $3.dword;
1745           }
1746         | sizedposnumexpr '-' sizednumexpr
1747           {
1748             $$.val = $1.val - $3.val;
1749             $$.dword = $1.dword || $3.dword;
1750           }
1751         | sizedposnumexpr '&' sizednumexpr
1752           {
1753             $$.val = $1.val & $3.val;
1754             $$.dword = $1.dword || $3.dword;
1755           }
1756         | sizedposnumexpr '^' sizednumexpr
1757           {
1758             $$.val = $1.val ^ $3.val;
1759             $$.dword = $1.dword || $3.dword;
1760           }
1761         | sizedposnumexpr '|' sizednumexpr
1762           {
1763             $$.val = $1.val | $3.val;
1764             $$.dword = $1.dword || $3.dword;
1765           }
1766         ;
1767
1768 %%
1769
1770 /* Set the language from the command line.  */
1771
1772 void
1773 rcparse_set_language (int lang)
1774 {
1775   language = lang;
1776 }