Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / binutils / binutils / rcparse.y
1 %{ /* rcparse.y -- parser for Windows rc files
2    Copyright 1997, 1998, 1999, 2000, 2001, 2002 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 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> optstringc 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 | ACC_ALT)) != 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 optstringc 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 optstringc 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 optstringc 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 optstringc 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 QUOTEDSTRING ',' numexpr ',' numexpr ',' numexpr ','
813             numexpr ',' numexpr ',' 
814             { style = WS_CHILD | WS_VISIBLE; }
815             styleexpr optcnumexpr
816           {
817             $$ = define_control ($2, $4, $6, $8, $10, $12, CTL_BUTTON,
818                                  style, $16);
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           optstringc 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         | optstringc 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         | optstringc 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 optstringc:
865           /* empty */
866           {
867             $$ = NULL;
868           }
869         | QUOTEDSTRING
870           {
871             $$ = $1;
872           }
873         | QUOTEDSTRING ','
874           {
875             $$ = $1;
876           }
877         ;
878
879 opt_control_data:
880           /* empty */
881           {
882             $$ = NULL;
883           }
884         | BEG optrcdata_data END
885           {
886             $$ = $2.first;
887           }
888         ;
889
890 /* These only exist to parse a reduction out of a common case.  */
891
892 control_styleexpr:
893           ','
894           { style = WS_CHILD | WS_VISIBLE; }
895           styleexpr
896         ;
897
898 icon_styleexpr:
899           ','
900           { style = SS_ICON | WS_CHILD | WS_VISIBLE; }
901           styleexpr
902         ;
903
904 control_params_styleexpr:
905           ','
906           { style = base_style | WS_CHILD | WS_VISIBLE; }
907           styleexpr
908         ;
909
910 /* Font resources.  */
911
912 font:
913           id FONT memflags_move_discard file_name
914           {
915             define_font ($1, &$3, $4);
916             if (yychar != YYEMPTY)
917               YYERROR;
918             rcparse_discard_strings ();
919           }
920         ;
921
922 /* Icon resources.  */
923
924 icon:
925           id ICON memflags_move_discard file_name
926           {
927             define_icon ($1, &$3, $4);
928             if (yychar != YYEMPTY)
929               YYERROR;
930             rcparse_discard_strings ();
931           }
932         ;
933
934 /* Language command.  This changes the static variable language, which
935    affects all subsequent resources.  */
936
937 language:
938           LANGUAGE numexpr cnumexpr
939           {
940             language = $2 | ($3 << SUBLANG_SHIFT);
941           }
942         ;
943
944 /* Menu resources.  */
945
946 menu:
947           id MENU suboptions BEG menuitems END
948           {
949             define_menu ($1, &$3, $5);
950             if (yychar != YYEMPTY)
951               YYERROR;
952             rcparse_discard_strings ();
953           }
954         ;
955
956 menuitems:
957           /* empty */
958           {
959             $$ = NULL;
960           }
961         | menuitems menuitem
962           {
963             if ($1 == NULL)
964               $$ = $2;
965             else
966               {
967                 struct menuitem **pp;
968
969                 for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
970                   ;
971                 *pp = $2;
972                 $$ = $1;
973               }
974           }
975         ;
976
977 menuitem:
978           MENUITEM QUOTEDSTRING cnumexpr menuitem_flags
979           {
980             $$ = define_menuitem ($2, $3, $4, 0, 0, NULL);
981           }
982         | MENUITEM SEPARATOR
983           {
984             $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL);
985           }
986         | POPUP QUOTEDSTRING menuitem_flags BEG menuitems END
987           {
988             $$ = define_menuitem ($2, 0, $3, 0, 0, $5);
989           }
990         ;
991
992 menuitem_flags:
993           /* empty */
994           {
995             $$ = 0;
996           }
997         | menuitem_flags ',' menuitem_flag
998           {
999             $$ = $1 | $3;
1000           }
1001         | menuitem_flags menuitem_flag
1002           {
1003             $$ = $1 | $2;
1004           }
1005         ;
1006
1007 menuitem_flag:
1008           CHECKED
1009           {
1010             $$ = MENUITEM_CHECKED;
1011           }
1012         | GRAYED
1013           {
1014             $$ = MENUITEM_GRAYED;
1015           }
1016         | HELP
1017           {
1018             $$ = MENUITEM_HELP;
1019           }
1020         | INACTIVE
1021           {
1022             $$ = MENUITEM_INACTIVE;
1023           }
1024         | MENUBARBREAK
1025           {
1026             $$ = MENUITEM_MENUBARBREAK;
1027           }
1028         | MENUBREAK
1029           {
1030             $$ = MENUITEM_MENUBREAK;
1031           }
1032         ;
1033
1034 /* Menuex resources.  */
1035
1036 menuex:
1037           id MENUEX suboptions BEG menuexitems END
1038           {
1039             define_menu ($1, &$3, $5);
1040             if (yychar != YYEMPTY)
1041               YYERROR;
1042             rcparse_discard_strings ();
1043           }
1044         ;
1045
1046 menuexitems:
1047           /* empty */
1048           {
1049             $$ = NULL;
1050           }
1051         | menuexitems menuexitem
1052           {
1053             if ($1 == NULL)
1054               $$ = $2;
1055             else
1056               {
1057                 struct menuitem **pp;
1058
1059                 for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
1060                   ;
1061                 *pp = $2;
1062                 $$ = $1;
1063               }
1064           }
1065         ;
1066
1067 menuexitem:
1068           MENUITEM QUOTEDSTRING
1069           {
1070             $$ = define_menuitem ($2, 0, 0, 0, 0, NULL);
1071           }
1072         | MENUITEM QUOTEDSTRING cnumexpr
1073           {
1074             $$ = define_menuitem ($2, $3, 0, 0, 0, NULL);
1075           }
1076         | MENUITEM QUOTEDSTRING cnumexpr cnumexpr optcnumexpr
1077           {
1078             $$ = define_menuitem ($2, $3, $4, $5, 0, NULL);
1079           }
1080         | MENUITEM SEPARATOR
1081           {
1082             $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL);
1083           }
1084         | POPUP QUOTEDSTRING BEG menuexitems END
1085           {
1086             $$ = define_menuitem ($2, 0, 0, 0, 0, $4);
1087           }
1088         | POPUP QUOTEDSTRING cnumexpr BEG menuexitems END
1089           {
1090             $$ = define_menuitem ($2, $3, 0, 0, 0, $5);
1091           }
1092         | POPUP QUOTEDSTRING cnumexpr cnumexpr BEG menuexitems END
1093           {
1094             $$ = define_menuitem ($2, $3, $4, 0, 0, $6);
1095           }
1096         | POPUP QUOTEDSTRING cnumexpr cnumexpr cnumexpr optcnumexpr
1097             BEG menuexitems END
1098           {
1099             $$ = define_menuitem ($2, $3, $4, $5, $6, $8);
1100           }
1101         ;
1102
1103 /* Messagetable resources.  */
1104
1105 messagetable:
1106           id MESSAGETABLE memflags_move file_name
1107           {
1108             define_messagetable ($1, &$3, $4);
1109             if (yychar != YYEMPTY)
1110               YYERROR;
1111             rcparse_discard_strings ();
1112           }
1113         ;
1114
1115 /* Rcdata resources.  */
1116
1117 rcdata:
1118           id RCDATA suboptions BEG optrcdata_data END
1119           {
1120             define_rcdata ($1, &$3, $5.first);
1121             if (yychar != YYEMPTY)
1122               YYERROR;
1123             rcparse_discard_strings ();
1124           }
1125         ;
1126
1127 /* We use a different lexing algorithm, because rcdata strings may
1128    contain embedded null bytes, and we need to know the length to use.  */
1129
1130 optrcdata_data:
1131           {
1132             rcparse_rcdata ();
1133           }
1134           optrcdata_data_int
1135           {
1136             rcparse_normal ();
1137             $$ = $2;
1138           }
1139         ;
1140
1141 optrcdata_data_int:
1142           /* empty */
1143           {
1144             $$.first = NULL;
1145             $$.last = NULL;
1146           }
1147         | rcdata_data
1148           {
1149             $$ = $1;
1150           }
1151         ;
1152
1153 rcdata_data:
1154           SIZEDSTRING
1155           {
1156             struct rcdata_item *ri;
1157
1158             ri = define_rcdata_string ($1.s, $1.length);
1159             $$.first = ri;
1160             $$.last = ri;
1161           }
1162         | sizednumexpr
1163           {
1164             struct rcdata_item *ri;
1165
1166             ri = define_rcdata_number ($1.val, $1.dword);
1167             $$.first = ri;
1168             $$.last = ri;
1169           }
1170         | rcdata_data ',' SIZEDSTRING
1171           {
1172             struct rcdata_item *ri;
1173
1174             ri = define_rcdata_string ($3.s, $3.length);
1175             $$.first = $1.first;
1176             $1.last->next = ri;
1177             $$.last = ri;
1178           }
1179         | rcdata_data ',' sizednumexpr
1180           {
1181             struct rcdata_item *ri;
1182
1183             ri = define_rcdata_number ($3.val, $3.dword);
1184             $$.first = $1.first;
1185             $1.last->next = ri;
1186             $$.last = ri;
1187           }
1188         ;
1189
1190 /* Stringtable resources.  */
1191
1192 stringtable:
1193           STRINGTABLE suboptions BEG 
1194             { sub_res_info = $2; }
1195             string_data END
1196         ;
1197
1198 string_data:
1199           /* empty */
1200         | string_data numexpr QUOTEDSTRING
1201           {
1202             define_stringtable (&sub_res_info, $2, $3);
1203             if (yychar != YYEMPTY)
1204               YYERROR;
1205             rcparse_discard_strings ();
1206           }
1207         | string_data numexpr ',' QUOTEDSTRING
1208           {
1209             define_stringtable (&sub_res_info, $2, $4);
1210             if (yychar != YYEMPTY)
1211               YYERROR;
1212             rcparse_discard_strings ();
1213           }
1214         ;
1215
1216 /* User defined resources.  We accept general suboptions in the
1217    file_name case to keep the parser happy.  */
1218
1219 user:
1220           id id suboptions BEG optrcdata_data END
1221           {
1222             define_user_data ($1, $2, &$3, $5.first);
1223             if (yychar != YYEMPTY)
1224               YYERROR;
1225             rcparse_discard_strings ();
1226           }
1227         | id id suboptions file_name
1228           {
1229             define_user_file ($1, $2, &$3, $4);
1230             if (yychar != YYEMPTY)
1231               YYERROR;
1232             rcparse_discard_strings ();
1233           }
1234         ;
1235
1236 /* Versioninfo resources.  */
1237
1238 versioninfo:
1239           id VERSIONINFO fixedverinfo BEG verblocks END
1240           {
1241             define_versioninfo ($1, language, $3, $5);
1242             if (yychar != YYEMPTY)
1243               YYERROR;
1244             rcparse_discard_strings ();
1245           }
1246         ;
1247
1248 fixedverinfo:
1249           /* empty */
1250           {
1251             $$ = ((struct fixed_versioninfo *)
1252                   res_alloc (sizeof (struct fixed_versioninfo)));
1253             memset ($$, 0, sizeof (struct fixed_versioninfo));
1254           }
1255         | fixedverinfo FILEVERSION numexpr cnumexpr cnumexpr cnumexpr
1256           {
1257             $1->file_version_ms = ($3 << 16) | $4;
1258             $1->file_version_ls = ($5 << 16) | $6;
1259             $$ = $1;
1260           }
1261         | fixedverinfo PRODUCTVERSION numexpr cnumexpr cnumexpr cnumexpr
1262           {
1263             $1->product_version_ms = ($3 << 16) | $4;
1264             $1->product_version_ls = ($5 << 16) | $6;
1265             $$ = $1;
1266           }
1267         | fixedverinfo FILEFLAGSMASK numexpr
1268           {
1269             $1->file_flags_mask = $3;
1270             $$ = $1;
1271           }
1272         | fixedverinfo FILEFLAGS numexpr
1273           {
1274             $1->file_flags = $3;
1275             $$ = $1;
1276           }
1277         | fixedverinfo FILEOS numexpr
1278           {
1279             $1->file_os = $3;
1280             $$ = $1;
1281           }
1282         | fixedverinfo FILETYPE numexpr
1283           {
1284             $1->file_type = $3;
1285             $$ = $1;
1286           }
1287         | fixedverinfo FILESUBTYPE numexpr
1288           {
1289             $1->file_subtype = $3;
1290             $$ = $1;
1291           }
1292         ;
1293
1294 /* To handle verblocks successfully, the lexer handles BLOCK
1295    specially.  A BLOCK "StringFileInfo" is returned as
1296    BLOCKSTRINGFILEINFO.  A BLOCK "VarFileInfo" is returned as
1297    BLOCKVARFILEINFO.  A BLOCK with some other string returns BLOCK
1298    with the string as the value.  */
1299
1300 verblocks:
1301           /* empty */
1302           {
1303             $$ = NULL;
1304           }
1305         | verblocks BLOCKSTRINGFILEINFO BEG BLOCK BEG vervals END END
1306           {
1307             $$ = append_ver_stringfileinfo ($1, $4, $6);
1308           }
1309         | verblocks BLOCKVARFILEINFO BEG VALUE QUOTEDSTRING vertrans END
1310           {
1311             $$ = append_ver_varfileinfo ($1, $5, $6);
1312           }
1313         ;
1314
1315 vervals:
1316           /* empty */
1317           {
1318             $$ = NULL;
1319           }
1320         | vervals VALUE QUOTEDSTRING ',' QUOTEDSTRING
1321           {
1322             $$ = append_verval ($1, $3, $5);
1323           }
1324         ;
1325
1326 vertrans:
1327           /* empty */
1328           {
1329             $$ = NULL;
1330           }
1331         | vertrans cnumexpr cnumexpr
1332           {
1333             $$ = append_vertrans ($1, $2, $3);
1334           }
1335         ;
1336
1337 /* A resource ID.  */
1338
1339 id:
1340           posnumexpr
1341           {
1342             $$.named = 0;
1343             $$.u.id = $1;
1344           }
1345         | STRING
1346           {
1347             char *copy, *s;
1348
1349             /* It seems that resource ID's are forced to upper case.  */
1350             copy = xstrdup ($1);
1351             for (s = copy; *s != '\0'; s++)
1352               *s = TOUPPER (*s);
1353             res_string_to_id (&$$, copy);
1354             free (copy);
1355           }
1356         ;
1357
1358 /* A resource reference.  */
1359
1360 resname:
1361           QUOTEDSTRING
1362           {
1363             $$ = $1;
1364           }
1365         | QUOTEDSTRING ','
1366           {
1367             $$ = $1;
1368           }
1369         | STRING ','
1370           {
1371             $$ = $1;
1372           }
1373         ;
1374
1375
1376 resref:
1377           posnumexpr ','
1378           {
1379             $$.named = 0;
1380             $$.u.id = $1;
1381           }
1382         | resname
1383           {
1384             char *copy, *s;
1385
1386             /* It seems that resource ID's are forced to upper case.  */
1387             copy = xstrdup ($1);
1388             for (s = copy; *s != '\0'; s++)
1389               *s = TOUPPER (*s);
1390             res_string_to_id (&$$, copy);
1391             free (copy);
1392           }
1393         ;
1394
1395 /* Generic suboptions.  These may appear before the BEGIN in any
1396    multiline statement.  */
1397
1398 suboptions:
1399           /* empty */
1400           {
1401             memset (&$$, 0, sizeof (struct res_res_info));
1402             $$.language = language;
1403             /* FIXME: Is this the right default?  */
1404             $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_PURE | MEMFLAG_DISCARDABLE;
1405           }
1406         | suboptions memflag
1407           {
1408             $$ = $1;
1409             $$.memflags |= $2.on;
1410             $$.memflags &=~ $2.off;
1411           }
1412         | suboptions CHARACTERISTICS numexpr
1413           {
1414             $$ = $1;
1415             $$.characteristics = $3;
1416           }
1417         | suboptions LANGUAGE numexpr cnumexpr
1418           {
1419             $$ = $1;
1420             $$.language = $3 | ($4 << SUBLANG_SHIFT);
1421           }
1422         | suboptions VERSIONK numexpr
1423           {
1424             $$ = $1;
1425             $$.version = $3;
1426           }
1427         ;
1428
1429 /* Memory flags which default to MOVEABLE and DISCARDABLE.  */
1430
1431 memflags_move_discard:
1432           /* empty */
1433           {
1434             memset (&$$, 0, sizeof (struct res_res_info));
1435             $$.language = language;
1436             $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_DISCARDABLE;
1437           }
1438         | memflags_move_discard memflag
1439           {
1440             $$ = $1;
1441             $$.memflags |= $2.on;
1442             $$.memflags &=~ $2.off;
1443           }
1444         ;
1445
1446 /* Memory flags which default to MOVEABLE.  */
1447
1448 memflags_move:
1449           /* empty */
1450           {
1451             memset (&$$, 0, sizeof (struct res_res_info));
1452             $$.language = language;
1453             $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_PURE | MEMFLAG_DISCARDABLE;
1454           }
1455         | memflags_move memflag
1456           {
1457             $$ = $1;
1458             $$.memflags |= $2.on;
1459             $$.memflags &=~ $2.off;
1460           }
1461         ;
1462
1463 /* Memory flags.  This returns a struct with two integers, because we
1464    sometimes want to set bits and we sometimes want to clear them.  */
1465
1466 memflag:
1467           MOVEABLE
1468           {
1469             $$.on = MEMFLAG_MOVEABLE;
1470             $$.off = 0;
1471           }
1472         | FIXED
1473           {
1474             $$.on = 0;
1475             $$.off = MEMFLAG_MOVEABLE;
1476           }
1477         | PURE
1478           {
1479             $$.on = MEMFLAG_PURE;
1480             $$.off = 0;
1481           }
1482         | IMPURE
1483           {
1484             $$.on = 0;
1485             $$.off = MEMFLAG_PURE;
1486           }
1487         | PRELOAD
1488           {
1489             $$.on = MEMFLAG_PRELOAD;
1490             $$.off = 0;
1491           }
1492         | LOADONCALL
1493           {
1494             $$.on = 0;
1495             $$.off = MEMFLAG_PRELOAD;
1496           }
1497         | DISCARDABLE
1498           {
1499             $$.on = MEMFLAG_DISCARDABLE;
1500             $$.off = 0;
1501           }
1502         ;
1503
1504 /* A file name.  */
1505
1506 file_name:
1507           QUOTEDSTRING
1508           {
1509             $$ = $1;
1510           }
1511         | STRING
1512           {
1513             $$ = $1;
1514           }
1515         ;
1516
1517 /* A style expression.  This changes the static variable STYLE.  We do
1518    it this way because rc appears to permit a style to be set to
1519    something like
1520        WS_GROUP | NOT WS_TABSTOP
1521    to mean that a default of WS_TABSTOP should be removed.  Anything
1522    which wants to accept a style must first set STYLE to the default
1523    value.  The styleexpr nonterminal will change STYLE as specified by
1524    the user.  Note that we do not accept arbitrary expressions here,
1525    just numbers separated by '|'.  */
1526
1527 styleexpr:
1528           parennumber
1529           {
1530             style |= $1;
1531           }
1532         | NOT parennumber
1533           {
1534             style &=~ $2;
1535           }
1536         | styleexpr '|' parennumber
1537           {
1538             style |= $3;
1539           }
1540         | styleexpr '|' NOT parennumber
1541           {
1542             style &=~ $4;
1543           }
1544         ;
1545
1546 parennumber:
1547           NUMBER
1548           {
1549             $$ = $1.val;
1550           }
1551         | '(' numexpr ')'
1552           {
1553             $$ = $2;
1554           }
1555         ;
1556
1557 /* An optional expression with a leading comma.  */
1558
1559 optcnumexpr:
1560           /* empty */
1561           {
1562             $$ = 0;
1563           }
1564         | cnumexpr
1565           {
1566             $$ = $1;
1567           }
1568         ;
1569
1570 /* An expression with a leading comma.  */
1571
1572 cnumexpr:
1573           ',' numexpr
1574           {
1575             $$ = $2;
1576           }
1577         ;
1578
1579 /* A possibly negated numeric expression.  */
1580
1581 numexpr:
1582           sizednumexpr
1583           {
1584             $$ = $1.val;
1585           }
1586         ;
1587
1588 /* A possibly negated expression with a size.  */
1589
1590 sizednumexpr:
1591           NUMBER
1592           {
1593             $$ = $1;
1594           }
1595         | '(' sizednumexpr ')'
1596           {
1597             $$ = $2;
1598           }
1599         | '~' sizednumexpr %prec '~'
1600           {
1601             $$.val = ~ $2.val;
1602             $$.dword = $2.dword;
1603           }
1604         | '-' sizednumexpr %prec NEG
1605           {
1606             $$.val = - $2.val;
1607             $$.dword = $2.dword;
1608           }
1609         | sizednumexpr '*' sizednumexpr
1610           {
1611             $$.val = $1.val * $3.val;
1612             $$.dword = $1.dword || $3.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         ;
1650
1651 /* An expression with a leading comma which does not use unary
1652    negation.  */
1653
1654 cposnumexpr:
1655           ',' posnumexpr
1656           {
1657             $$ = $2;
1658           }
1659         ;
1660
1661 /* An expression which does not use unary negation.  */
1662
1663 posnumexpr:
1664           sizedposnumexpr
1665           {
1666             $$ = $1.val;
1667           }
1668         ;
1669
1670 /* An expression which does not use unary negation.  We separate unary
1671    negation to avoid parsing conflicts when two numeric expressions
1672    appear consecutively.  */
1673
1674 sizedposnumexpr:
1675           NUMBER
1676           {
1677             $$ = $1;
1678           }
1679         | '(' sizednumexpr ')'
1680           {
1681             $$ = $2;
1682           }
1683         | '~' sizednumexpr %prec '~'
1684           {
1685             $$.val = ~ $2.val;
1686             $$.dword = $2.dword;
1687           }
1688         | sizedposnumexpr '*' sizednumexpr
1689           {
1690             $$.val = $1.val * $3.val;
1691             $$.dword = $1.dword || $3.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         ;
1729
1730 %%
1731
1732 /* Set the language from the command line.  */
1733
1734 void
1735 rcparse_set_language (lang)
1736      int lang;
1737 {
1738   language = lang;
1739 }