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