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