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