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