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
34static unsigned short language;
35
36/* The resource information during a sub statement.  */
37
38static struct res_res_info sub_res_info;
39
40/* Dialog information.  This is built by the nonterminals styles and
41   controls.  */
42
43static struct dialog dialog;
44
45/* This is used when building a style.  It is modified by the
46   nonterminal styleexpr.  */
47
48static unsigned long style;
49
50/* These are used when building a control.  They are set before using
51   control_params.  */
52
53static unsigned long base_style;
54static unsigned long default_style;
55static unsigned long class;
56static struct res_id res_text_field;
57static unichar null_unichar;
58
59/* This is used for COMBOBOX, LISTBOX and EDITTEXT which
60   do not allow resource 'text' field in control definition. */
61static 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
161input:
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
182accelerator:
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
192acc_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
217acc_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
234acc_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
265acc_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
281acc_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
311bitmap:
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
323cursor:
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
335dialog:
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
418exstyle:
419	  /* empty */
420	  {
421	    $$ = 0;
422	  }
423	| EXSTYLE '=' numexpr
424	  {
425	    $$ = $3;
426	  }
427	;
428
429styles:
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
530controls:
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
542control:
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
857control_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
891optresidc:
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
911opt_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
924control_styleexpr:
925	  ','
926	  { style = WS_CHILD | WS_VISIBLE; }
927	  styleexpr
928	;
929
930icon_styleexpr:
931	  ','
932	  { style = SS_ICON | WS_CHILD | WS_VISIBLE; }
933	  styleexpr
934	;
935
936control_params_styleexpr:
937	  ','
938	  { style = base_style | WS_CHILD | WS_VISIBLE; }
939	  styleexpr
940	;
941
942/* Font resources.  */
943
944font:
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
956icon:
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
969language:
970	  LANGUAGE numexpr cnumexpr
971	  {
972	    language = $2 | ($3 << SUBLANG_SHIFT);
973	  }
974	;
975
976/* Menu resources.  */
977
978menu:
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
988menuitems:
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
1009menuitem:
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
1024menuitem_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
1039menuitem_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
1068menuex:
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
1078menuexitems:
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
1099menuexitem:
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
1137messagetable:
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
1149rcdata:
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
1169optrcdata_data:
1170	  {
1171	    rcparse_rcdata ();
1172	  }
1173	  optrcdata_data_int
1174	  {
1175	    rcparse_normal ();
1176	    $$ = $2;
1177	  }
1178	;
1179
1180optrcdata_data_int:
1181	  /* empty */
1182	  {
1183	    $$.first = NULL;
1184	    $$.last = NULL;
1185	  }
1186	| rcdata_data
1187	  {
1188	    $$ = $1;
1189	  }
1190	;
1191
1192rcdata_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
1231stringtable:
1232	  STRINGTABLE suboptions BEG
1233	    { sub_res_info = $2; }
1234	    string_data END
1235	;
1236
1237string_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
1258user:
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
1277versioninfo:
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
1287fixedverinfo:
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
1339verblocks:
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
1354vervals:
1355	  /* empty */
1356	  {
1357	    $$ = NULL;
1358	  }
1359	| vervals VALUE QUOTEDSTRING ',' QUOTEDSTRING
1360	  {
1361	    $$ = append_verval ($1, $3, $5);
1362	  }
1363	;
1364
1365vertrans:
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
1378id:
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
1399resname:
1400	  QUOTEDSTRING
1401	  {
1402	    $$ = $1;
1403	  }
1404	| QUOTEDSTRING ','
1405	  {
1406	    $$ = $1;
1407	  }
1408	| STRING ','
1409	  {
1410	    $$ = $1;
1411	  }
1412	;
1413
1414
1415resref:
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
1437suboptions:
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
1470memflags_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
1487memflags_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
1505memflag:
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
1545file_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
1566styleexpr:
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
1585parennumber:
1586	  NUMBER
1587	  {
1588	    $$ = $1.val;
1589	  }
1590	| '(' numexpr ')'
1591	  {
1592	    $$ = $2;
1593	  }
1594	;
1595
1596/* An optional expression with a leading comma.  */
1597
1598optcnumexpr:
1599	  /* empty */
1600	  {
1601	    $$ = 0;
1602	  }
1603	| cnumexpr
1604	  {
1605	    $$ = $1;
1606	  }
1607	;
1608
1609/* An expression with a leading comma.  */
1610
1611cnumexpr:
1612	  ',' numexpr
1613	  {
1614	    $$ = $2;
1615	  }
1616	;
1617
1618/* A possibly negated numeric expression.  */
1619
1620numexpr:
1621	  sizednumexpr
1622	  {
1623	    $$ = $1.val;
1624	  }
1625	;
1626
1627/* A possibly negated expression with a size.  */
1628
1629sizednumexpr:
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
1693cposnumexpr:
1694	  ',' posnumexpr
1695	  {
1696	    $$ = $2;
1697	  }
1698	;
1699
1700/* An expression which does not use unary negation.  */
1701
1702posnumexpr:
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
1713sizedposnumexpr:
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
1773void
1774rcparse_set_language (int lang)
1775{
1776  language = lang;
1777}
1778