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