OSDN Git Service

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