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