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