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