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