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