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