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