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