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