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