Release 2.33.1
[external/binutils.git] / binutils / rcparse.y
1 %{ /* rcparse.y -- parser for Windows rc files
2    Copyright (C) 1997-2019 Free Software Foundation, Inc.
3    Written by Ian Lance Taylor, Cygnus Support.
4    Extended by Kai Tietz, Onevision.
5
6    This file is part of GNU Binutils.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21    02110-1301, USA.  */
22
23
24 /* This is a parser for Windows rc files.  It is based on the parser
25    by Gunther Ebert <gunther.ebert@ixos-leipzig.de>.  */
26
27 #include "sysdep.h"
28 #include "bfd.h"
29 #include "bucomm.h"
30 #include "libiberty.h"
31 #include "windres.h"
32 #include "safe-ctype.h"
33
34 /* The current language.  */
35
36 static unsigned short language;
37
38 /* The resource information during a sub statement.  */
39
40 static rc_res_res_info sub_res_info;
41
42 /* Dialog information.  This is built by the nonterminals styles and
43    controls.  */
44
45 static rc_dialog dialog;
46
47 /* This is used when building a style.  It is modified by the
48    nonterminal styleexpr.  */
49
50 static unsigned long style;
51
52 /* These are used when building a control.  They are set before using
53    control_params.  */
54
55 static rc_uint_type base_style;
56 static rc_uint_type default_style;
57 static rc_res_id class;
58 static rc_res_id res_text_field;
59 static unichar null_unichar;
60
61 /* This is used for COMBOBOX, LISTBOX and EDITTEXT which
62    do not allow resource 'text' field in control definition. */
63 static const rc_res_id res_null_text = { 1, {{0, &null_unichar}}};
64
65 %}
66
67 %union
68 {
69   rc_accelerator acc;
70   rc_accelerator *pacc;
71   rc_dialog_control *dialog_control;
72   rc_menuitem *menuitem;
73   struct
74   {
75     rc_rcdata_item *first;
76     rc_rcdata_item *last;
77   } rcdata;
78   rc_rcdata_item *rcdata_item;
79   rc_fixed_versioninfo *fixver;
80   rc_ver_info *verinfo;
81   rc_ver_stringtable *verstringtable;
82   rc_ver_stringinfo *verstring;
83   rc_ver_varinfo *vervar;
84   rc_toolbar_item *toobar_item;
85   rc_res_id id;
86   rc_res_res_info res_info;
87   struct
88   {
89     rc_uint_type on;
90     rc_uint_type off;
91   } memflags;
92   struct
93   {
94     rc_uint_type val;
95     /* Nonzero if this number was explicitly specified as long.  */
96     int dword;
97   } i;
98   rc_uint_type il;
99   rc_uint_type is;
100   const char *s;
101   struct
102   {
103     rc_uint_type length;
104     const char *s;
105   } ss;
106   unichar *uni;
107   struct
108   {
109     rc_uint_type length;
110     const unichar *s;
111   } suni;
112 };
113
114 %token BEG END
115 %token ACCELERATORS VIRTKEY ASCII NOINVERT SHIFT CONTROL ALT
116 %token BITMAP
117 %token CURSOR
118 %token DIALOG DIALOGEX EXSTYLE CAPTION CLASS STYLE
119 %token AUTO3STATE AUTOCHECKBOX AUTORADIOBUTTON CHECKBOX COMBOBOX CTEXT
120 %token DEFPUSHBUTTON EDITTEXT GROUPBOX LISTBOX LTEXT PUSHBOX PUSHBUTTON
121 %token RADIOBUTTON RTEXT SCROLLBAR STATE3 USERBUTTON
122 %token BEDIT HEDIT IEDIT
123 %token FONT
124 %token ICON
125 %token ANICURSOR ANIICON DLGINCLUDE DLGINIT FONTDIR HTML MANIFEST PLUGPLAY VXD TOOLBAR BUTTON
126 %token LANGUAGE CHARACTERISTICS VERSIONK
127 %token MENU MENUEX MENUITEM SEPARATOR POPUP CHECKED GRAYED HELP INACTIVE
128 %token MENUBARBREAK MENUBREAK
129 %token MESSAGETABLE
130 %token RCDATA
131 %token STRINGTABLE
132 %token VERSIONINFO FILEVERSION PRODUCTVERSION FILEFLAGSMASK FILEFLAGS
133 %token FILEOS FILETYPE FILESUBTYPE BLOCKSTRINGFILEINFO BLOCKVARFILEINFO
134 %token VALUE
135 %token <s> BLOCK
136 %token MOVEABLE FIXED PURE IMPURE PRELOAD LOADONCALL DISCARDABLE
137 %token NOT
138 %token <uni> QUOTEDUNISTRING
139 %token <s> QUOTEDSTRING STRING
140 %token <i> NUMBER
141 %token <suni> SIZEDUNISTRING
142 %token <ss> SIZEDSTRING
143 %token IGNORED_TOKEN
144
145 %type <pacc> acc_entries
146 %type <acc> acc_entry acc_event
147 %type <dialog_control> control control_params
148 %type <menuitem> menuitems menuitem menuexitems menuexitem
149 %type <rcdata> optrcdata_data optrcdata_data_int rcdata_data
150 %type <rcdata_item> opt_control_data
151 %type <fixver> fixedverinfo
152 %type <verinfo> verblocks
153 %type <verstringtable> verstringtables
154 %type <verstring> vervals
155 %type <vervar> vertrans
156 %type <toobar_item> toolbar_data
157 %type <res_info> suboptions memflags_move_discard memflags_move
158 %type <memflags> memflag
159 %type <id> id rcdata_id optresidc resref resid cresid
160 %type <il> exstyle parennumber
161 %type <il> numexpr posnumexpr cnumexpr optcnumexpr cposnumexpr
162 %type <is> acc_options acc_option menuitem_flags menuitem_flag
163 %type <s> file_name
164 %type <uni> res_unicode_string resname res_unicode_string_concat
165 %type <ss> sizedstring
166 %type <suni> sizedunistring res_unicode_sizedstring res_unicode_sizedstring_concat
167 %type <i> sizednumexpr sizedposnumexpr
168
169 %left '|'
170 %left '^'
171 %left '&'
172 %left '+' '-'
173 %left '*' '/' '%'
174 %right '~' NEG
175
176 %%
177
178 input:
179           /* empty */
180         | input accelerator
181         | input bitmap
182         | input cursor
183         | input dialog
184         | input font
185         | input icon
186         | input language
187         | input menu
188         | input menuex
189         | input messagetable
190         | input stringtable
191         | input toolbar
192         | input user
193         | input versioninfo
194         | input IGNORED_TOKEN
195         ;
196
197 /* Accelerator resources.  */
198
199 accelerator:
200           id ACCELERATORS suboptions BEG acc_entries END
201           {
202             define_accelerator ($1, &$3, $5);
203             if (yychar != YYEMPTY)
204               YYERROR;
205             rcparse_discard_strings ();
206           }
207         ;
208
209 acc_entries:
210           /* empty */
211           {
212             $$ = NULL;
213           }
214         | acc_entries acc_entry
215           {
216             rc_accelerator *a;
217
218             a = (rc_accelerator *) res_alloc (sizeof *a);
219             *a = $2;
220             if ($1 == NULL)
221               $$ = a;
222             else
223               {
224                 rc_accelerator **pp;
225
226                 for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
227                   ;
228                 *pp = a;
229                 $$ = $1;
230               }
231           }
232         ;
233
234 acc_entry:
235           acc_event cposnumexpr
236           {
237             $$ = $1;
238             $$.id = $2;
239           }
240         | acc_event cposnumexpr ',' acc_options
241           {
242             $$ = $1;
243             $$.id = $2;
244             $$.flags |= $4;
245             if (($$.flags & ACC_VIRTKEY) == 0
246                 && ($$.flags & (ACC_SHIFT | ACC_CONTROL)) != 0)
247               rcparse_warning (_("inappropriate modifiers for non-VIRTKEY"));
248           }
249         ;
250
251 acc_event:
252           QUOTEDSTRING
253           {
254             const char *s = $1;
255             char ch;
256
257             $$.next = NULL;
258             $$.id = 0;
259             ch = *s;
260             if (ch != '^')
261               $$.flags = 0;
262             else
263               {
264                 $$.flags = ACC_CONTROL | ACC_VIRTKEY;
265                 ++s;
266                 ch = TOUPPER (s[0]);
267               }
268             $$.key = ch;
269             if (s[1] != '\0')
270               rcparse_warning (_("accelerator should only be one character"));
271           }
272         | posnumexpr
273           {
274             $$.next = NULL;
275             $$.flags = 0;
276             $$.id = 0;
277             $$.key = $1;
278           }
279         ;
280
281 acc_options:
282           acc_option
283           {
284             $$ = $1;
285           }
286         | acc_options ',' acc_option
287           {
288             $$ = $1 | $3;
289           }
290         /* I've had one report that the comma is optional.  */
291         | acc_options acc_option
292           {
293             $$ = $1 | $2;
294           }
295         ;
296
297 acc_option:
298           VIRTKEY
299           {
300             $$ = ACC_VIRTKEY;
301           }
302         | ASCII
303           {
304             /* This is just the absence of VIRTKEY.  */
305             $$ = 0;
306           }
307         | NOINVERT
308           {
309             $$ = ACC_NOINVERT;
310           }
311         | SHIFT
312           {
313             $$ = ACC_SHIFT;
314           }
315         | CONTROL
316           {
317             $$ = ACC_CONTROL;
318           }
319         | ALT
320           {
321             $$ = ACC_ALT;
322           }
323         ;
324
325 /* Bitmap resources.  */
326
327 bitmap:
328           id BITMAP memflags_move file_name
329           {
330             define_bitmap ($1, &$3, $4);
331             if (yychar != YYEMPTY)
332               YYERROR;
333             rcparse_discard_strings ();
334           }
335         ;
336
337 /* Cursor resources.  */
338
339 cursor:
340           id CURSOR memflags_move_discard file_name
341           {
342             define_cursor ($1, &$3, $4);
343             if (yychar != YYEMPTY)
344               YYERROR;
345             rcparse_discard_strings ();
346           }
347         ;
348
349 /* Dialog resources.  */
350
351 dialog:
352           id DIALOG memflags_move exstyle posnumexpr cnumexpr cnumexpr
353             cnumexpr
354             {
355               memset (&dialog, 0, sizeof dialog);
356               dialog.x = $5;
357               dialog.y = $6;
358               dialog.width = $7;
359               dialog.height = $8;
360               dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU;
361               dialog.exstyle = $4;
362               dialog.menu.named = 1;
363               dialog.class.named = 1;
364               dialog.font = NULL;
365               dialog.ex = NULL;
366               dialog.controls = NULL;
367               sub_res_info = $3;
368               style = 0;
369             }
370             styles BEG controls END
371           {
372             define_dialog ($1, &sub_res_info, &dialog);
373             if (yychar != YYEMPTY)
374               YYERROR;
375             rcparse_discard_strings ();
376           }
377         | id DIALOGEX memflags_move exstyle posnumexpr cnumexpr cnumexpr
378             cnumexpr
379             {
380               memset (&dialog, 0, sizeof dialog);
381               dialog.x = $5;
382               dialog.y = $6;
383               dialog.width = $7;
384               dialog.height = $8;
385               dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU;
386               dialog.exstyle = $4;
387               dialog.menu.named = 1;
388               dialog.class.named = 1;
389               dialog.font = NULL;
390               dialog.ex = ((rc_dialog_ex *)
391                            res_alloc (sizeof (rc_dialog_ex)));
392               memset (dialog.ex, 0, sizeof (rc_dialog_ex));
393               dialog.controls = NULL;
394               sub_res_info = $3;
395               style = 0;
396             }
397             styles BEG controls END
398           {
399             define_dialog ($1, &sub_res_info, &dialog);
400             if (yychar != YYEMPTY)
401               YYERROR;
402             rcparse_discard_strings ();
403           }
404         | id DIALOGEX memflags_move exstyle posnumexpr cnumexpr cnumexpr
405             cnumexpr cnumexpr
406             {
407               memset (&dialog, 0, sizeof dialog);
408               dialog.x = $5;
409               dialog.y = $6;
410               dialog.width = $7;
411               dialog.height = $8;
412               dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU;
413               dialog.exstyle = $4;
414               dialog.menu.named = 1;
415               dialog.class.named = 1;
416               dialog.font = NULL;
417               dialog.ex = ((rc_dialog_ex *)
418                            res_alloc (sizeof (rc_dialog_ex)));
419               memset (dialog.ex, 0, sizeof (rc_dialog_ex));
420               dialog.ex->help = $9;
421               dialog.controls = NULL;
422               sub_res_info = $3;
423               style = 0;
424             }
425             styles BEG controls END
426           {
427             define_dialog ($1, &sub_res_info, &dialog);
428             if (yychar != YYEMPTY)
429               YYERROR;
430             rcparse_discard_strings ();
431           }
432         ;
433
434 exstyle:
435           /* empty */
436           {
437             $$ = 0;
438           }
439         | EXSTYLE '=' numexpr
440           {
441             $$ = $3;
442           }
443         ;
444
445 styles:
446           /* empty */
447         | styles CAPTION res_unicode_string_concat
448           {
449             dialog.style |= WS_CAPTION;
450             style |= WS_CAPTION;
451             dialog.caption = $3;
452           }
453         | styles CLASS id
454           {
455             dialog.class = $3;
456           }
457         | styles STYLE
458             styleexpr
459           {
460             dialog.style = style;
461           }
462         | styles EXSTYLE numexpr
463           {
464             dialog.exstyle = $3;
465           }
466         | styles CLASS res_unicode_string_concat
467           {
468             res_unistring_to_id (& dialog.class, $3);
469           }
470         | styles FONT numexpr ',' res_unicode_string_concat
471           {
472             dialog.style |= DS_SETFONT;
473             style |= DS_SETFONT;
474             dialog.pointsize = $3;
475             dialog.font = $5;
476             if (dialog.ex != NULL)
477               {
478                 dialog.ex->weight = 0;
479                 dialog.ex->italic = 0;
480                 dialog.ex->charset = 1;
481               }
482           }
483         | styles FONT numexpr ',' res_unicode_string_concat cnumexpr
484           {
485             dialog.style |= DS_SETFONT;
486             style |= DS_SETFONT;
487             dialog.pointsize = $3;
488             dialog.font = $5;
489             if (dialog.ex == NULL)
490               rcparse_warning (_("extended FONT requires DIALOGEX"));
491             else
492               {
493                 dialog.ex->weight = $6;
494                 dialog.ex->italic = 0;
495                 dialog.ex->charset = 1;
496               }
497           }
498         | styles FONT numexpr ',' res_unicode_string_concat cnumexpr cnumexpr
499           {
500             dialog.style |= DS_SETFONT;
501             style |= DS_SETFONT;
502             dialog.pointsize = $3;
503             dialog.font = $5;
504             if (dialog.ex == NULL)
505               rcparse_warning (_("extended FONT requires DIALOGEX"));
506             else
507               {
508                 dialog.ex->weight = $6;
509                 dialog.ex->italic = $7;
510                 dialog.ex->charset = 1;
511               }
512           }
513         | styles FONT numexpr ',' res_unicode_string_concat cnumexpr cnumexpr cnumexpr
514           {
515             dialog.style |= DS_SETFONT;
516             style |= DS_SETFONT;
517             dialog.pointsize = $3;
518             dialog.font = $5;
519             if (dialog.ex == NULL)
520               rcparse_warning (_("extended FONT requires DIALOGEX"));
521             else
522               {
523                 dialog.ex->weight = $6;
524                 dialog.ex->italic = $7;
525                 dialog.ex->charset = $8;
526               }
527           }
528         | styles MENU id
529           {
530             dialog.menu = $3;
531           }
532         | styles CHARACTERISTICS numexpr
533           {
534             sub_res_info.characteristics = $3;
535           }
536         | styles LANGUAGE numexpr cnumexpr
537           {
538             sub_res_info.language = $3 | ($4 << SUBLANG_SHIFT);
539           }
540         | styles VERSIONK numexpr
541           {
542             sub_res_info.version = $3;
543           }
544         ;
545
546 controls:
547           /* empty */
548         | controls control
549           {
550             rc_dialog_control **pp;
551
552             for (pp = &dialog.controls; *pp != NULL; pp = &(*pp)->next)
553               ;
554             *pp = $2;
555           }
556         ;
557
558 control:
559           AUTO3STATE optresidc
560             {
561               default_style = BS_AUTO3STATE | WS_TABSTOP;
562               base_style = BS_AUTO3STATE;
563               class.named = 0;
564               class.u.id = CTL_BUTTON;
565               res_text_field = $2;
566             }
567             control_params
568           {
569             $$ = $4;
570           }
571         | AUTOCHECKBOX optresidc
572             {
573               default_style = BS_AUTOCHECKBOX | WS_TABSTOP;
574               base_style = BS_AUTOCHECKBOX;
575               class.named = 0;
576               class.u.id = CTL_BUTTON;
577               res_text_field = $2;
578             }
579             control_params
580           {
581             $$ = $4;
582           }
583         | AUTORADIOBUTTON optresidc
584             {
585               default_style = BS_AUTORADIOBUTTON | WS_TABSTOP;
586               base_style = BS_AUTORADIOBUTTON;
587               class.named = 0;
588               class.u.id = CTL_BUTTON;
589               res_text_field = $2;
590             }
591             control_params
592           {
593             $$ = $4;
594           }
595         | BEDIT optresidc
596             {
597               default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
598               base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
599               class.named = 0;
600               class.u.id = CTL_EDIT;
601               res_text_field = $2;
602             }
603             control_params
604           {
605             $$ = $4;
606             if (dialog.ex == NULL)
607               rcparse_warning (_("BEDIT requires DIALOGEX"));
608             res_string_to_id (&$$->class, "BEDIT");
609           }
610         | CHECKBOX optresidc
611             {
612               default_style = BS_CHECKBOX | WS_TABSTOP;
613               base_style = BS_CHECKBOX | WS_TABSTOP;
614               class.named = 0;
615               class.u.id = CTL_BUTTON;
616               res_text_field = $2;
617             }
618             control_params
619           {
620             $$ = $4;
621           }
622         | COMBOBOX
623             {
624               /* This is as per MSDN documentation.  With some (???)
625                  versions of MS rc.exe their is no default style.  */
626               default_style = CBS_SIMPLE | WS_TABSTOP;
627               base_style = 0;
628               class.named = 0;
629               class.u.id = CTL_COMBOBOX;
630               res_text_field = res_null_text;
631             }
632             control_params
633           {
634             $$ = $3;
635           }
636         | CONTROL optresidc numexpr cresid control_styleexpr cnumexpr
637             cnumexpr cnumexpr cnumexpr optcnumexpr opt_control_data
638           {
639             $$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10);
640             if ($11 != NULL)
641               {
642                 if (dialog.ex == NULL)
643                   rcparse_warning (_("control data requires DIALOGEX"));
644                 $$->data = $11;
645               }
646           }
647         | CONTROL optresidc numexpr cresid control_styleexpr cnumexpr
648             cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data
649           {
650             $$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10);
651             if (dialog.ex == NULL)
652               rcparse_warning (_("help ID requires DIALOGEX"));
653             $$->help = $11;
654             $$->data = $12;
655           }
656         | CTEXT optresidc
657             {
658               default_style = SS_CENTER | WS_GROUP;
659               base_style = SS_CENTER;
660               class.named = 0;
661               class.u.id = CTL_STATIC;
662               res_text_field = $2;
663             }
664             control_params
665           {
666             $$ = $4;
667           }
668         | DEFPUSHBUTTON optresidc
669             {
670               default_style = BS_DEFPUSHBUTTON | WS_TABSTOP;
671               base_style = BS_DEFPUSHBUTTON | WS_TABSTOP;
672               class.named = 0;
673               class.u.id = CTL_BUTTON;
674               res_text_field = $2;
675             }
676             control_params
677           {
678             $$ = $4;
679           }
680         | EDITTEXT
681             {
682               default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
683               base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
684               class.named = 0;
685               class.u.id = CTL_EDIT;
686               res_text_field = res_null_text;
687             }
688             control_params
689           {
690             $$ = $3;
691           }
692         | GROUPBOX optresidc
693             {
694               default_style = BS_GROUPBOX;
695               base_style = BS_GROUPBOX;
696               class.named = 0;
697               class.u.id = CTL_BUTTON;
698               res_text_field = $2;
699             }
700             control_params
701           {
702             $$ = $4;
703           }
704         | HEDIT optresidc
705             {
706               default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
707               base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
708               class.named = 0;
709               class.u.id = CTL_EDIT;
710               res_text_field = $2;
711             }
712             control_params
713           {
714             $$ = $4;
715             if (dialog.ex == NULL)
716               rcparse_warning (_("IEDIT requires DIALOGEX"));
717             res_string_to_id (&$$->class, "HEDIT");
718           }
719         | ICON resref numexpr cnumexpr cnumexpr opt_control_data
720           {
721             $$ = define_icon_control ($2, $3, $4, $5, 0, 0, 0, $6,
722                                       dialog.ex);
723           }
724         | ICON resref numexpr cnumexpr cnumexpr cnumexpr cnumexpr
725             opt_control_data
726           {
727             $$ = define_icon_control ($2, $3, $4, $5, 0, 0, 0, $8,
728                                       dialog.ex);
729           }
730         | ICON resref numexpr cnumexpr cnumexpr cnumexpr cnumexpr
731             icon_styleexpr optcnumexpr opt_control_data
732           {
733             $$ = define_icon_control ($2, $3, $4, $5, style, $9, 0, $10,
734                                       dialog.ex);
735           }
736         | ICON resref numexpr cnumexpr cnumexpr cnumexpr cnumexpr
737             icon_styleexpr cnumexpr cnumexpr opt_control_data
738           {
739             $$ = define_icon_control ($2, $3, $4, $5, style, $9, $10, $11,
740                                       dialog.ex);
741           }
742         | IEDIT optresidc
743             {
744               default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
745               base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
746               class.named = 0;
747               class.u.id = CTL_EDIT;
748               res_text_field = $2;
749             }
750             control_params
751           {
752             $$ = $4;
753             if (dialog.ex == NULL)
754               rcparse_warning (_("IEDIT requires DIALOGEX"));
755             res_string_to_id (&$$->class, "IEDIT");
756           }
757         | LISTBOX
758             {
759               default_style = LBS_NOTIFY | WS_BORDER;
760               base_style = LBS_NOTIFY | WS_BORDER;
761               class.named = 0;
762               class.u.id = CTL_LISTBOX;
763               res_text_field = res_null_text;
764             }
765             control_params
766           {
767             $$ = $3;
768           }
769         | LTEXT optresidc
770             {
771               default_style = SS_LEFT | WS_GROUP;
772               base_style = SS_LEFT;
773               class.named = 0;
774               class.u.id = CTL_STATIC;
775               res_text_field = $2;
776             }
777             control_params
778           {
779             $$ = $4;
780           }
781         | PUSHBOX optresidc
782             {
783               default_style = BS_PUSHBOX | WS_TABSTOP;
784               base_style = BS_PUSHBOX;
785               class.named = 0;
786               class.u.id = CTL_BUTTON;
787             }
788             control_params
789           {
790             $$ = $4;
791           }
792         | PUSHBUTTON optresidc
793             {
794               default_style = BS_PUSHBUTTON | WS_TABSTOP;
795               base_style = BS_PUSHBUTTON | WS_TABSTOP;
796               class.named = 0;
797               class.u.id = CTL_BUTTON;
798               res_text_field = $2;
799             }
800             control_params
801           {
802             $$ = $4;
803           }
804         | RADIOBUTTON optresidc
805             {
806               default_style = BS_RADIOBUTTON | WS_TABSTOP;
807               base_style = BS_RADIOBUTTON;
808               class.named = 0;
809               class.u.id = CTL_BUTTON;
810               res_text_field = $2;
811             }
812             control_params
813           {
814             $$ = $4;
815           }
816         | RTEXT optresidc
817             {
818               default_style = SS_RIGHT | WS_GROUP;
819               base_style = SS_RIGHT;
820               class.named = 0;
821               class.u.id = CTL_STATIC;
822               res_text_field = $2;
823             }
824             control_params
825           {
826             $$ = $4;
827           }
828         | SCROLLBAR
829             {
830               default_style = SBS_HORZ;
831               base_style = 0;
832               class.named = 0;
833               class.u.id = CTL_SCROLLBAR;
834               res_text_field = res_null_text;
835             }
836             control_params
837           {
838             $$ = $3;
839           }
840         | STATE3 optresidc
841             {
842               default_style = BS_3STATE | WS_TABSTOP;
843               base_style = BS_3STATE;
844               class.named = 0;
845               class.u.id = CTL_BUTTON;
846               res_text_field = $2;
847             }
848             control_params
849           {
850             $$ = $4;
851           }
852         | USERBUTTON resref numexpr ',' numexpr ',' numexpr ','
853             numexpr ',' numexpr ','
854             { style = WS_CHILD | WS_VISIBLE; }
855             styleexpr optcnumexpr
856           {
857             rc_res_id cid;
858             cid.named = 0;
859             cid.u.id = CTL_BUTTON;
860             $$ = define_control ($2, $3, $5, $7, $9, $11, cid,
861                                  style, $15);
862           }
863         ;
864
865 /* Parameters for a control.  The static variables DEFAULT_STYLE,
866    BASE_STYLE, and CLASS must be initialized before this nonterminal
867    is used.  DEFAULT_STYLE is the style to use if no style expression
868    is specified.  BASE_STYLE is the base style to use if a style
869    expression is specified; the style expression modifies the base
870    style.  CLASS is the class of the control.  */
871
872 control_params:
873           numexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data
874           {
875             $$ = define_control (res_text_field, $1, $2, $3, $4, $5, class,
876                                  default_style | WS_CHILD | WS_VISIBLE, 0);
877             if ($6 != NULL)
878               {
879                 if (dialog.ex == NULL)
880                   rcparse_warning (_("control data requires DIALOGEX"));
881                 $$->data = $6;
882               }
883           }
884         | numexpr cnumexpr cnumexpr cnumexpr cnumexpr
885             control_params_styleexpr optcnumexpr opt_control_data
886           {
887             $$ = define_control (res_text_field, $1, $2, $3, $4, $5, class, style, $7);
888             if ($8 != NULL)
889               {
890                 if (dialog.ex == NULL)
891                   rcparse_warning (_("control data requires DIALOGEX"));
892                 $$->data = $8;
893               }
894           }
895         | numexpr cnumexpr cnumexpr cnumexpr cnumexpr
896             control_params_styleexpr cnumexpr cnumexpr opt_control_data
897           {
898             $$ = define_control (res_text_field, $1, $2, $3, $4, $5, class, style, $7);
899             if (dialog.ex == NULL)
900               rcparse_warning (_("help ID requires DIALOGEX"));
901             $$->help = $8;
902             $$->data = $9;
903           }
904         ;
905
906 cresid:
907           ',' resid
908           {
909             if ($2.named)
910               res_unistring_to_id (&$$, $2.u.n.name);
911             else
912               $$=$2;
913           }
914         ;
915
916 optresidc:
917           /* empty */
918           {
919             res_string_to_id (&$$, "");
920           }
921         | resid ',' { $$=$1; }
922         ;
923
924 resid:
925           posnumexpr
926           {
927             $$.named = 0;
928             $$.u.id = $1;
929           }
930         | res_unicode_string_concat
931           {
932             $$.named = 1;
933             $$.u.n.name = $1;
934             $$.u.n.length = unichar_len ($1);
935           }
936         ;
937
938 opt_control_data:
939           /* empty */
940           {
941             $$ = NULL;
942           }
943         | BEG optrcdata_data END
944           {
945             $$ = $2.first;
946           }
947         ;
948
949 /* These only exist to parse a reduction out of a common case.  */
950
951 control_styleexpr:
952           ','
953           { style = WS_CHILD | WS_VISIBLE; }
954           styleexpr
955         ;
956
957 icon_styleexpr:
958           ','
959           { style = SS_ICON | WS_CHILD | WS_VISIBLE; }
960           styleexpr
961         ;
962
963 control_params_styleexpr:
964           ','
965           { style = base_style | WS_CHILD | WS_VISIBLE; }
966           styleexpr
967         ;
968
969 /* Font resources.  */
970
971 font:
972           id FONT memflags_move_discard file_name
973           {
974             define_font ($1, &$3, $4);
975             if (yychar != YYEMPTY)
976               YYERROR;
977             rcparse_discard_strings ();
978           }
979         ;
980
981 /* Icon resources.  */
982
983 icon:
984           id ICON memflags_move_discard file_name
985           {
986             define_icon ($1, &$3, $4);
987             if (yychar != YYEMPTY)
988               YYERROR;
989             rcparse_discard_strings ();
990           }
991         ;
992
993 /* Language command.  This changes the static variable language, which
994    affects all subsequent resources.  */
995
996 language:
997           LANGUAGE numexpr cnumexpr
998           {
999             language = $2 | ($3 << SUBLANG_SHIFT);
1000           }
1001         ;
1002
1003 /* Menu resources.  */
1004
1005 menu:
1006           id MENU suboptions BEG menuitems END
1007           {
1008             define_menu ($1, &$3, $5);
1009             if (yychar != YYEMPTY)
1010               YYERROR;
1011             rcparse_discard_strings ();
1012           }
1013         ;
1014
1015 menuitems:
1016           /* empty */
1017           {
1018             $$ = NULL;
1019           }
1020         | menuitems menuitem
1021           {
1022             if ($1 == NULL)
1023               $$ = $2;
1024             else
1025               {
1026                 rc_menuitem **pp;
1027
1028                 for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
1029                   ;
1030                 *pp = $2;
1031                 $$ = $1;
1032               }
1033           }
1034         ;
1035
1036 menuitem:
1037           MENUITEM res_unicode_string_concat cnumexpr menuitem_flags
1038           {
1039             $$ = define_menuitem ($2, $3, $4, 0, 0, NULL);
1040           }
1041         | MENUITEM SEPARATOR
1042           {
1043             $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL);
1044           }
1045         | POPUP res_unicode_string_concat menuitem_flags BEG menuitems END
1046           {
1047             $$ = define_menuitem ($2, 0, $3, 0, 0, $5);
1048           }
1049         ;
1050
1051 menuitem_flags:
1052           /* empty */
1053           {
1054             $$ = 0;
1055           }
1056         | menuitem_flags ',' menuitem_flag
1057           {
1058             $$ = $1 | $3;
1059           }
1060         | menuitem_flags menuitem_flag
1061           {
1062             $$ = $1 | $2;
1063           }
1064         ;
1065
1066 menuitem_flag:
1067           CHECKED
1068           {
1069             $$ = MENUITEM_CHECKED;
1070           }
1071         | GRAYED
1072           {
1073             $$ = MENUITEM_GRAYED;
1074           }
1075         | HELP
1076           {
1077             $$ = MENUITEM_HELP;
1078           }
1079         | INACTIVE
1080           {
1081             $$ = MENUITEM_INACTIVE;
1082           }
1083         | MENUBARBREAK
1084           {
1085             $$ = MENUITEM_MENUBARBREAK;
1086           }
1087         | MENUBREAK
1088           {
1089             $$ = MENUITEM_MENUBREAK;
1090           }
1091         ;
1092
1093 /* Menuex resources.  */
1094
1095 menuex:
1096           id MENUEX suboptions BEG menuexitems END
1097           {
1098             define_menu ($1, &$3, $5);
1099             if (yychar != YYEMPTY)
1100               YYERROR;
1101             rcparse_discard_strings ();
1102           }
1103         ;
1104
1105 menuexitems:
1106           /* empty */
1107           {
1108             $$ = NULL;
1109           }
1110         | menuexitems menuexitem
1111           {
1112             if ($1 == NULL)
1113               $$ = $2;
1114             else
1115               {
1116                 rc_menuitem **pp;
1117
1118                 for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
1119                   ;
1120                 *pp = $2;
1121                 $$ = $1;
1122               }
1123           }
1124         ;
1125
1126 menuexitem:
1127           MENUITEM res_unicode_string_concat
1128           {
1129             $$ = define_menuitem ($2, 0, 0, 0, 0, NULL);
1130           }
1131         | MENUITEM res_unicode_string_concat cnumexpr
1132           {
1133             $$ = define_menuitem ($2, $3, 0, 0, 0, NULL);
1134           }
1135         | MENUITEM res_unicode_string_concat cnumexpr cnumexpr optcnumexpr
1136           {
1137             $$ = define_menuitem ($2, $3, $4, $5, 0, NULL);
1138           }
1139         | MENUITEM SEPARATOR
1140           {
1141             $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL);
1142           }
1143         | POPUP res_unicode_string_concat BEG menuexitems END
1144           {
1145             $$ = define_menuitem ($2, 0, 0, 0, 0, $4);
1146           }
1147         | POPUP res_unicode_string_concat cnumexpr BEG menuexitems END
1148           {
1149             $$ = define_menuitem ($2, $3, 0, 0, 0, $5);
1150           }
1151         | POPUP res_unicode_string_concat cnumexpr cnumexpr BEG menuexitems END
1152           {
1153             $$ = define_menuitem ($2, $3, $4, 0, 0, $6);
1154           }
1155         | POPUP res_unicode_string_concat cnumexpr cnumexpr cnumexpr optcnumexpr
1156             BEG menuexitems END
1157           {
1158             $$ = define_menuitem ($2, $3, $4, $5, $6, $8);
1159           }
1160         ;
1161
1162 /* Messagetable resources.  */
1163
1164 messagetable:
1165           id MESSAGETABLE memflags_move file_name
1166           {
1167             define_messagetable ($1, &$3, $4);
1168             if (yychar != YYEMPTY)
1169               YYERROR;
1170             rcparse_discard_strings ();
1171           }
1172         ;
1173
1174 /* We use a different lexing algorithm, because rcdata strings may
1175    contain embedded null bytes, and we need to know the length to use.  */
1176
1177 optrcdata_data:
1178           {
1179             rcparse_rcdata ();
1180           }
1181           optrcdata_data_int
1182           {
1183             rcparse_normal ();
1184             $$ = $2;
1185           }
1186         ;
1187
1188 optrcdata_data_int:
1189           /* empty */
1190           {
1191             $$.first = NULL;
1192             $$.last = NULL;
1193           }
1194         | rcdata_data
1195           {
1196             $$ = $1;
1197           }
1198         ;
1199
1200 rcdata_data:
1201           sizedstring
1202           {
1203             rc_rcdata_item *ri;
1204
1205             ri = define_rcdata_string ($1.s, $1.length);
1206             $$.first = ri;
1207             $$.last = ri;
1208           }
1209         | sizedunistring
1210           {
1211             rc_rcdata_item *ri;
1212
1213             ri = define_rcdata_unistring ($1.s, $1.length);
1214             $$.first = ri;
1215             $$.last = ri;
1216           }
1217         | sizednumexpr
1218           {
1219             rc_rcdata_item *ri;
1220
1221             ri = define_rcdata_number ($1.val, $1.dword);
1222             $$.first = ri;
1223             $$.last = ri;
1224           }
1225         | rcdata_data ',' sizedstring
1226           {
1227             rc_rcdata_item *ri;
1228
1229             ri = define_rcdata_string ($3.s, $3.length);
1230             $$.first = $1.first;
1231             $1.last->next = ri;
1232             $$.last = ri;
1233           }
1234         | rcdata_data ',' sizedunistring
1235           {
1236             rc_rcdata_item *ri;
1237
1238             ri = define_rcdata_unistring ($3.s, $3.length);
1239             $$.first = $1.first;
1240             $1.last->next = ri;
1241             $$.last = ri;
1242           }
1243         | rcdata_data ',' sizednumexpr
1244           {
1245             rc_rcdata_item *ri;
1246
1247             ri = define_rcdata_number ($3.val, $3.dword);
1248             $$.first = $1.first;
1249             $1.last->next = ri;
1250             $$.last = ri;
1251           }
1252         | rcdata_data ','
1253           {
1254             $$=$1;
1255           }
1256         ;
1257
1258 /* Stringtable resources.  */
1259
1260 stringtable:
1261           STRINGTABLE suboptions BEG
1262             { sub_res_info = $2; rcparse_rcdata (); }
1263             string_data END { rcparse_normal (); }
1264         ;
1265
1266 string_data:
1267           /* empty */
1268         | string_data numexpr res_unicode_sizedstring_concat
1269           {
1270             define_stringtable (&sub_res_info, $2, $3.s, $3.length);
1271             rcparse_discard_strings ();
1272           }
1273         | string_data numexpr ',' res_unicode_sizedstring_concat
1274           {
1275             define_stringtable (&sub_res_info, $2, $4.s, $4.length);
1276             rcparse_discard_strings ();
1277           }
1278         | string_data error
1279           {
1280             rcparse_warning (_("invalid stringtable resource."));
1281             abort ();
1282           }
1283         ;
1284
1285 rcdata_id:
1286         id
1287           {
1288             $$=$1;
1289           }
1290       | HTML
1291         {
1292           $$.named = 0;
1293           $$.u.id = 23;
1294         }
1295       | RCDATA
1296         {
1297           $$.named = 0;
1298           $$.u.id = RT_RCDATA;
1299         }
1300       | MANIFEST
1301         {
1302           $$.named = 0;
1303           $$.u.id = RT_MANIFEST;
1304         }
1305       | PLUGPLAY
1306         {
1307           $$.named = 0;
1308           $$.u.id = RT_PLUGPLAY;
1309         }
1310       | VXD
1311         {
1312           $$.named = 0;
1313           $$.u.id = RT_VXD;
1314         }
1315       | DLGINCLUDE
1316         {
1317           $$.named = 0;
1318           $$.u.id = RT_DLGINCLUDE;
1319         }
1320       | DLGINIT
1321         {
1322           $$.named = 0;
1323           $$.u.id = RT_DLGINIT;
1324         }
1325       | ANICURSOR
1326         {
1327           $$.named = 0;
1328           $$.u.id = RT_ANICURSOR;
1329         }
1330       | ANIICON
1331         {
1332           $$.named = 0;
1333           $$.u.id = RT_ANIICON;
1334         }
1335       ;
1336
1337 /* User defined resources.  We accept general suboptions in the
1338    file_name case to keep the parser happy.  */
1339
1340 user:
1341           id rcdata_id suboptions BEG optrcdata_data END
1342           {
1343             define_user_data ($1, $2, &$3, $5.first);
1344             if (yychar != YYEMPTY)
1345               YYERROR;
1346             rcparse_discard_strings ();
1347           }
1348         | id rcdata_id suboptions file_name
1349           {
1350             define_user_file ($1, $2, &$3, $4);
1351             if (yychar != YYEMPTY)
1352               YYERROR;
1353             rcparse_discard_strings ();
1354           }
1355         ;
1356
1357 toolbar:
1358         id TOOLBAR suboptions numexpr cnumexpr BEG toolbar_data END
1359         {
1360           define_toolbar ($1, &$3, $4, $5, $7);
1361         }
1362         ;
1363
1364 toolbar_data: /* empty */ { $$= NULL; }
1365         | toolbar_data BUTTON id
1366         {
1367           rc_toolbar_item *c,*n;
1368           c = $1;
1369           n= (rc_toolbar_item *)
1370               res_alloc (sizeof (rc_toolbar_item));
1371           if (c != NULL)
1372             while (c->next != NULL)
1373               c = c->next;
1374           n->prev = c;
1375           n->next = NULL;
1376           if (c != NULL)
1377             c->next = n;
1378           n->id = $3;
1379           if ($1 == NULL)
1380             $$ = n;
1381           else
1382             $$ = $1;
1383         }
1384         | toolbar_data SEPARATOR
1385         {
1386           rc_toolbar_item *c,*n;
1387           c = $1;
1388           n= (rc_toolbar_item *)
1389               res_alloc (sizeof (rc_toolbar_item));
1390           if (c != NULL)
1391             while (c->next != NULL)
1392               c = c->next;
1393           n->prev = c;
1394           n->next = NULL;
1395           if (c != NULL)
1396             c->next = n;
1397           n->id.named = 0;
1398           n->id.u.id = 0;
1399           if ($1 == NULL)
1400             $$ = n;
1401           else
1402             $$ = $1;
1403         }
1404         ;
1405
1406 /* Versioninfo resources.  */
1407
1408 versioninfo:
1409           id VERSIONINFO fixedverinfo BEG verblocks END
1410           {
1411             define_versioninfo ($1, language, $3, $5);
1412             if (yychar != YYEMPTY)
1413               YYERROR;
1414             rcparse_discard_strings ();
1415           }
1416         ;
1417
1418 fixedverinfo:
1419           /* empty */
1420           {
1421             $$ = ((rc_fixed_versioninfo *)
1422                   res_alloc (sizeof (rc_fixed_versioninfo)));
1423             memset ($$, 0, sizeof (rc_fixed_versioninfo));
1424           }
1425         | fixedverinfo FILEVERSION numexpr optcnumexpr optcnumexpr
1426           optcnumexpr
1427           {
1428             $1->file_version_ms = ($3 << 16) | ($4 & 0xffff);
1429             $1->file_version_ls = ($5 << 16) | ($6 & 0xffff);
1430             $$ = $1;
1431           }
1432         | fixedverinfo PRODUCTVERSION numexpr optcnumexpr optcnumexpr
1433           optcnumexpr
1434           {
1435             $1->product_version_ms = ($3 << 16) | ($4 & 0xffff);
1436             $1->product_version_ls = ($5 << 16) | ($6 & 0xffff);
1437             $$ = $1;
1438           }
1439         | fixedverinfo FILEFLAGSMASK numexpr
1440           {
1441             $1->file_flags_mask = $3;
1442             $$ = $1;
1443           }
1444         | fixedverinfo FILEFLAGS numexpr
1445           {
1446             $1->file_flags = $3;
1447             $$ = $1;
1448           }
1449         | fixedverinfo FILEOS numexpr
1450           {
1451             $1->file_os = $3;
1452             $$ = $1;
1453           }
1454         | fixedverinfo FILETYPE numexpr
1455           {
1456             $1->file_type = $3;
1457             $$ = $1;
1458           }
1459         | fixedverinfo FILESUBTYPE numexpr
1460           {
1461             $1->file_subtype = $3;
1462             $$ = $1;
1463           }
1464         ;
1465
1466 /* To handle verblocks successfully, the lexer handles BLOCK
1467    specially.  A BLOCK "StringFileInfo" is returned as
1468    BLOCKSTRINGFILEINFO.  A BLOCK "VarFileInfo" is returned as
1469    BLOCKVARFILEINFO.  A BLOCK with some other string returns BLOCK
1470    with the string as the value.  */
1471
1472 verblocks:
1473           /* empty */
1474           {
1475             $$ = NULL;
1476           }
1477         | verblocks BLOCKSTRINGFILEINFO BEG verstringtables END
1478           {
1479             $$ = append_ver_stringfileinfo ($1, $4);
1480           }
1481         | verblocks BLOCKVARFILEINFO BEG VALUE res_unicode_string_concat vertrans END
1482           {
1483             $$ = append_ver_varfileinfo ($1, $5, $6);
1484           }
1485         ;
1486
1487 verstringtables:
1488       /* empty */
1489           {
1490             $$ = NULL;
1491           }
1492         | verstringtables BLOCK BEG vervals END
1493           {
1494             $$ = append_ver_stringtable ($1, $2, $4);
1495           }
1496         ;
1497
1498 vervals:
1499           /* empty */
1500           {
1501             $$ = NULL;
1502           }
1503         | vervals VALUE res_unicode_string_concat ',' res_unicode_string_concat
1504           {
1505             $$ = append_verval ($1, $3, $5);
1506           }
1507         ;
1508
1509 vertrans:
1510           /* empty */
1511           {
1512             $$ = NULL;
1513           }
1514         | vertrans cnumexpr cnumexpr
1515           {
1516             $$ = append_vertrans ($1, $2, $3);
1517           }
1518         ;
1519
1520 /* A resource ID.  */
1521
1522 id:
1523           posnumexpr
1524           {
1525             $$.named = 0;
1526             $$.u.id = $1;
1527           }
1528         | resname
1529           {
1530             res_unistring_to_id (&$$, $1);
1531           }
1532         ;
1533
1534 /* A resource reference.  */
1535
1536 resname:
1537           res_unicode_string
1538           {
1539             $$ = $1;
1540           }
1541         | STRING
1542           {
1543             unichar *h = NULL;
1544             unicode_from_ascii ((rc_uint_type *) NULL, &h, $1);
1545             $$ = h;
1546           }
1547         ;
1548
1549
1550 resref:
1551           posnumexpr ','
1552           {
1553             $$.named = 0;
1554             $$.u.id = $1;
1555           }
1556         | resname
1557           {
1558             res_unistring_to_id (&$$, $1);
1559           }
1560         | resname ','
1561           {
1562             res_unistring_to_id (&$$, $1);
1563           }
1564         ;
1565
1566 /* Generic suboptions.  These may appear before the BEGIN in any
1567    multiline statement.  */
1568
1569 suboptions:
1570           /* empty */
1571           {
1572             memset (&$$, 0, sizeof (rc_res_res_info));
1573             $$.language = language;
1574             /* FIXME: Is this the right default?  */
1575             $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_PURE | MEMFLAG_DISCARDABLE;
1576           }
1577         | suboptions memflag
1578           {
1579             $$ = $1;
1580             $$.memflags |= $2.on;
1581             $$.memflags &=~ $2.off;
1582           }
1583         | suboptions CHARACTERISTICS numexpr
1584           {
1585             $$ = $1;
1586             $$.characteristics = $3;
1587           }
1588         | suboptions LANGUAGE numexpr cnumexpr
1589           {
1590             $$ = $1;
1591             $$.language = $3 | ($4 << SUBLANG_SHIFT);
1592           }
1593         | suboptions VERSIONK numexpr
1594           {
1595             $$ = $1;
1596             $$.version = $3;
1597           }
1598         ;
1599
1600 /* Memory flags which default to MOVEABLE and DISCARDABLE.  */
1601
1602 memflags_move_discard:
1603           /* empty */
1604           {
1605             memset (&$$, 0, sizeof (rc_res_res_info));
1606             $$.language = language;
1607             $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_DISCARDABLE;
1608           }
1609         | memflags_move_discard memflag
1610           {
1611             $$ = $1;
1612             $$.memflags |= $2.on;
1613             $$.memflags &=~ $2.off;
1614           }
1615         ;
1616
1617 /* Memory flags which default to MOVEABLE.  */
1618
1619 memflags_move:
1620           /* empty */
1621           {
1622             memset (&$$, 0, sizeof (rc_res_res_info));
1623             $$.language = language;
1624             $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_PURE | MEMFLAG_DISCARDABLE;
1625           }
1626         | memflags_move memflag
1627           {
1628             $$ = $1;
1629             $$.memflags |= $2.on;
1630             $$.memflags &=~ $2.off;
1631           }
1632         ;
1633
1634 /* Memory flags.  This returns a struct with two integers, because we
1635    sometimes want to set bits and we sometimes want to clear them.  */
1636
1637 memflag:
1638           MOVEABLE
1639           {
1640             $$.on = MEMFLAG_MOVEABLE;
1641             $$.off = 0;
1642           }
1643         | FIXED
1644           {
1645             $$.on = 0;
1646             $$.off = MEMFLAG_MOVEABLE;
1647           }
1648         | PURE
1649           {
1650             $$.on = MEMFLAG_PURE;
1651             $$.off = 0;
1652           }
1653         | IMPURE
1654           {
1655             $$.on = 0;
1656             $$.off = MEMFLAG_PURE;
1657           }
1658         | PRELOAD
1659           {
1660             $$.on = MEMFLAG_PRELOAD;
1661             $$.off = 0;
1662           }
1663         | LOADONCALL
1664           {
1665             $$.on = 0;
1666             $$.off = MEMFLAG_PRELOAD;
1667           }
1668         | DISCARDABLE
1669           {
1670             $$.on = MEMFLAG_DISCARDABLE;
1671             $$.off = 0;
1672           }
1673         ;
1674
1675 /* A file name.  */
1676
1677 file_name:
1678           QUOTEDSTRING
1679           {
1680             $$ = $1;
1681           }
1682         | STRING
1683           {
1684             $$ = $1;
1685           }
1686         ;
1687
1688 /* Concat string */
1689 res_unicode_string_concat:
1690           res_unicode_string
1691           {
1692             $$ = $1;
1693           }
1694         |
1695           res_unicode_string_concat res_unicode_string
1696           {
1697             rc_uint_type l1 = unichar_len ($1);
1698             rc_uint_type l2 = unichar_len ($2);
1699             unichar *h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar));
1700             if (l1 != 0)
1701               memcpy (h, $1, l1 * sizeof (unichar));
1702             if (l2 != 0)
1703               memcpy (h + l1, $2, l2  * sizeof (unichar));
1704             h[l1 + l2] = 0;
1705             $$ = h;
1706           }
1707         ;
1708
1709 res_unicode_string:
1710           QUOTEDUNISTRING
1711           {
1712             $$ = unichar_dup ($1);
1713           }
1714         | QUOTEDSTRING
1715           {
1716             unichar *h = NULL;
1717             unicode_from_ascii ((rc_uint_type *) NULL, &h, $1);
1718             $$ = h;
1719           }
1720         ;
1721
1722 res_unicode_sizedstring:
1723           sizedunistring
1724           {
1725             $$ = $1;
1726           }
1727         | sizedstring
1728           {
1729             unichar *h = NULL;
1730             rc_uint_type l = 0;
1731             unicode_from_ascii_len (&l, &h, $1.s, $1.length);
1732             $$.s = h;
1733             $$.length = l;
1734           }
1735         ;
1736
1737 /* Concat string */
1738 res_unicode_sizedstring_concat:
1739           res_unicode_sizedstring
1740           {
1741             $$ = $1;
1742           }
1743         |
1744           res_unicode_sizedstring_concat res_unicode_sizedstring
1745           {
1746             rc_uint_type l1 = $1.length;
1747             rc_uint_type l2 = $2.length;
1748             unichar *h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar));
1749             if (l1 != 0)
1750               memcpy (h, $1.s, l1 * sizeof (unichar));
1751             if (l2 != 0)
1752               memcpy (h + l1, $2.s, l2  * sizeof (unichar));
1753             h[l1 + l2] = 0;
1754             $$.length = l1 + l2;
1755             $$.s = h;
1756           }
1757         ;
1758
1759 sizedstring:
1760           SIZEDSTRING
1761           {
1762             $$ = $1;
1763           }
1764         | sizedstring SIZEDSTRING
1765           {
1766             rc_uint_type l = $1.length + $2.length;
1767             char *h = (char *) res_alloc (l);
1768             memcpy (h, $1.s, $1.length);
1769             memcpy (h + $1.length, $2.s, $2.length);
1770             $$.s = h;
1771             $$.length = l;
1772           }
1773         ;
1774
1775 sizedunistring:
1776           SIZEDUNISTRING
1777           {
1778             $$ = $1;
1779           }
1780         | sizedunistring SIZEDUNISTRING
1781           {
1782             rc_uint_type l = $1.length + $2.length;
1783             unichar *h = (unichar *) res_alloc (l * sizeof (unichar));
1784             memcpy (h, $1.s, $1.length * sizeof (unichar));
1785             memcpy (h + $1.length, $2.s, $2.length  * sizeof (unichar));
1786             $$.s = h;
1787             $$.length = l;
1788           }
1789         ;
1790
1791 /* A style expression.  This changes the static variable STYLE.  We do
1792    it this way because rc appears to permit a style to be set to
1793    something like
1794        WS_GROUP | NOT WS_TABSTOP
1795    to mean that a default of WS_TABSTOP should be removed.  Anything
1796    which wants to accept a style must first set STYLE to the default
1797    value.  The styleexpr nonterminal will change STYLE as specified by
1798    the user.  Note that we do not accept arbitrary expressions here,
1799    just numbers separated by '|'.  */
1800
1801 styleexpr:
1802           parennumber
1803           {
1804             style |= $1;
1805           }
1806         | NOT parennumber
1807           {
1808             style &=~ $2;
1809           }
1810         | styleexpr '|' parennumber
1811           {
1812             style |= $3;
1813           }
1814         | styleexpr '|' NOT parennumber
1815           {
1816             style &=~ $4;
1817           }
1818         ;
1819
1820 parennumber:
1821           NUMBER
1822           {
1823             $$ = $1.val;
1824           }
1825         | '(' numexpr ')'
1826           {
1827             $$ = $2;
1828           }
1829         ;
1830
1831 /* An optional expression with a leading comma.  */
1832
1833 optcnumexpr:
1834           /* empty */
1835           {
1836             $$ = 0;
1837           }
1838         | cnumexpr
1839           {
1840             $$ = $1;
1841           }
1842         ;
1843
1844 /* An expression with a leading comma.  */
1845
1846 cnumexpr:
1847           ',' numexpr
1848           {
1849             $$ = $2;
1850           }
1851         ;
1852
1853 /* A possibly negated numeric expression.  */
1854
1855 numexpr:
1856           sizednumexpr
1857           {
1858             $$ = $1.val;
1859           }
1860         ;
1861
1862 /* A possibly negated expression with a size.  */
1863
1864 sizednumexpr:
1865           NUMBER
1866           {
1867             $$ = $1;
1868           }
1869         | '(' sizednumexpr ')'
1870           {
1871             $$ = $2;
1872           }
1873         | '~' sizednumexpr %prec '~'
1874           {
1875             $$.val = ~ $2.val;
1876             $$.dword = $2.dword;
1877           }
1878         | '-' sizednumexpr %prec NEG
1879           {
1880             $$.val = - $2.val;
1881             $$.dword = $2.dword;
1882           }
1883         | sizednumexpr '*' sizednumexpr
1884           {
1885             $$.val = $1.val * $3.val;
1886             $$.dword = $1.dword || $3.dword;
1887           }
1888         | sizednumexpr '/' sizednumexpr
1889           {
1890             $$.val = $1.val / ($3.val ? $3.val : 1);
1891             $$.dword = $1.dword || $3.dword;
1892           }
1893         | sizednumexpr '%' sizednumexpr
1894           {
1895             $$.val = $1.val % ($3.val ? $3.val : 1);
1896             $$.dword = $1.dword || $3.dword;
1897           }
1898         | sizednumexpr '+' sizednumexpr
1899           {
1900             $$.val = $1.val + $3.val;
1901             $$.dword = $1.dword || $3.dword;
1902           }
1903         | sizednumexpr '-' sizednumexpr
1904           {
1905             $$.val = $1.val - $3.val;
1906             $$.dword = $1.dword || $3.dword;
1907           }
1908         | sizednumexpr '&' sizednumexpr
1909           {
1910             $$.val = $1.val & $3.val;
1911             $$.dword = $1.dword || $3.dword;
1912           }
1913         | sizednumexpr '^' sizednumexpr
1914           {
1915             $$.val = $1.val ^ $3.val;
1916             $$.dword = $1.dword || $3.dword;
1917           }
1918         | sizednumexpr '|' sizednumexpr
1919           {
1920             $$.val = $1.val | $3.val;
1921             $$.dword = $1.dword || $3.dword;
1922           }
1923         ;
1924
1925 /* An expression with a leading comma which does not use unary
1926    negation.  */
1927
1928 cposnumexpr:
1929           ',' posnumexpr
1930           {
1931             $$ = $2;
1932           }
1933         ;
1934
1935 /* An expression which does not use unary negation.  */
1936
1937 posnumexpr:
1938           sizedposnumexpr
1939           {
1940             $$ = $1.val;
1941           }
1942         ;
1943
1944 /* An expression which does not use unary negation.  We separate unary
1945    negation to avoid parsing conflicts when two numeric expressions
1946    appear consecutively.  */
1947
1948 sizedposnumexpr:
1949           NUMBER
1950           {
1951             $$ = $1;
1952           }
1953         | '(' sizednumexpr ')'
1954           {
1955             $$ = $2;
1956           }
1957         | '~' sizednumexpr %prec '~'
1958           {
1959             $$.val = ~ $2.val;
1960             $$.dword = $2.dword;
1961           }
1962         | sizedposnumexpr '*' sizednumexpr
1963           {
1964             $$.val = $1.val * $3.val;
1965             $$.dword = $1.dword || $3.dword;
1966           }
1967         | sizedposnumexpr '/' sizednumexpr
1968           {
1969             $$.val = $1.val / ($3.val ? $3.val : 1);
1970             $$.dword = $1.dword || $3.dword;
1971           }
1972         | sizedposnumexpr '%' sizednumexpr
1973           {
1974             /* PR 17512: file: 89105a25.  */
1975             $$.val = $1.val % ($3.val ? $3.val : 1);
1976             $$.dword = $1.dword || $3.dword;
1977           }
1978         | sizedposnumexpr '+' sizednumexpr
1979           {
1980             $$.val = $1.val + $3.val;
1981             $$.dword = $1.dword || $3.dword;
1982           }
1983         | sizedposnumexpr '-' sizednumexpr
1984           {
1985             $$.val = $1.val - $3.val;
1986             $$.dword = $1.dword || $3.dword;
1987           }
1988         | sizedposnumexpr '&' sizednumexpr
1989           {
1990             $$.val = $1.val & $3.val;
1991             $$.dword = $1.dword || $3.dword;
1992           }
1993         | sizedposnumexpr '^' sizednumexpr
1994           {
1995             $$.val = $1.val ^ $3.val;
1996             $$.dword = $1.dword || $3.dword;
1997           }
1998         | sizedposnumexpr '|' sizednumexpr
1999           {
2000             $$.val = $1.val | $3.val;
2001             $$.dword = $1.dword || $3.dword;
2002           }
2003         ;
2004
2005 %%
2006
2007 /* Set the language from the command line.  */
2008
2009 void
2010 rcparse_set_language (int lang)
2011 {
2012   language = lang;
2013 }