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