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