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