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