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
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;
55static 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. */
59static 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
159input:
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
180accelerator:
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
190acc_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
215acc_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
232acc_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
263acc_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
279acc_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
309bitmap:
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
321cursor:
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
333dialog:
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
416exstyle:
417	  /* empty */
418	  {
419	    $$ = 0;
420	  }
421	| EXSTYLE '=' numexpr
422	  {
423	    $$ = $3;
424	  }
425	;
426
427styles:
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
528controls:
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
540control:
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
855control_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
889optresidc:
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
909opt_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
922control_styleexpr:
923	  ','
924	  { style = WS_CHILD | WS_VISIBLE; }
925	  styleexpr
926	;
927
928icon_styleexpr:
929	  ','
930	  { style = SS_ICON | WS_CHILD | WS_VISIBLE; }
931	  styleexpr
932	;
933
934control_params_styleexpr:
935	  ','
936	  { style = base_style | WS_CHILD | WS_VISIBLE; }
937	  styleexpr
938	;
939
940/* Font resources.  */
941
942font:
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
954icon:
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
967language:
968	  LANGUAGE numexpr cnumexpr
969	  {
970	    language = $2 | ($3 << SUBLANG_SHIFT);
971	  }
972	;
973
974/* Menu resources.  */
975
976menu:
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
986menuitems:
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
1007menuitem:
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
1022menuitem_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
1037menuitem_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
1066menuex:
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
1076menuexitems:
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
1097menuexitem:
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
1135messagetable:
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
1147rcdata:
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
1160optrcdata_data:
1161	  {
1162	    rcparse_rcdata ();
1163	  }
1164	  optrcdata_data_int
1165	  {
1166	    rcparse_normal ();
1167	    $$ = $2;
1168	  }
1169	;
1170
1171optrcdata_data_int:
1172	  /* empty */
1173	  {
1174	    $$.first = NULL;
1175	    $$.last = NULL;
1176	  }
1177	| rcdata_data
1178	  {
1179	    $$ = $1;
1180	  }
1181	;
1182
1183rcdata_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
1222stringtable:
1223	  STRINGTABLE suboptions BEG
1224	    { sub_res_info = $2; }
1225	    string_data END
1226	;
1227
1228string_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
1249user:
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
1268versioninfo:
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
1278fixedverinfo:
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
1330verblocks:
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
1345vervals:
1346	  /* empty */
1347	  {
1348	    $$ = NULL;
1349	  }
1350	| vervals VALUE QUOTEDSTRING ',' QUOTEDSTRING
1351	  {
1352	    $$ = append_verval ($1, $3, $5);
1353	  }
1354	;
1355
1356vertrans:
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
1369id:
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
1390resname:
1391	  QUOTEDSTRING
1392	  {
1393	    $$ = $1;
1394	  }
1395	| QUOTEDSTRING ','
1396	  {
1397	    $$ = $1;
1398	  }
1399	| STRING ','
1400	  {
1401	    $$ = $1;
1402	  }
1403	;
1404
1405
1406resref:
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
1428suboptions:
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
1461memflags_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
1478memflags_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
1496memflag:
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
1536file_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
1557styleexpr:
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
1576parennumber:
1577	  NUMBER
1578	  {
1579	    $$ = $1.val;
1580	  }
1581	| '(' numexpr ')'
1582	  {
1583	    $$ = $2;
1584	  }
1585	;
1586
1587/* An optional expression with a leading comma.  */
1588
1589optcnumexpr:
1590	  /* empty */
1591	  {
1592	    $$ = 0;
1593	  }
1594	| cnumexpr
1595	  {
1596	    $$ = $1;
1597	  }
1598	;
1599
1600/* An expression with a leading comma.  */
1601
1602cnumexpr:
1603	  ',' numexpr
1604	  {
1605	    $$ = $2;
1606	  }
1607	;
1608
1609/* A possibly negated numeric expression.  */
1610
1611numexpr:
1612	  sizednumexpr
1613	  {
1614	    $$ = $1.val;
1615	  }
1616	;
1617
1618/* A possibly negated expression with a size.  */
1619
1620sizednumexpr:
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
1684cposnumexpr:
1685	  ',' posnumexpr
1686	  {
1687	    $$ = $2;
1688	  }
1689	;
1690
1691/* An expression which does not use unary negation.  */
1692
1693posnumexpr:
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
1704sizedposnumexpr:
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
1764void
1765rcparse_set_language (int lang)
1766{
1767  language = lang;
1768}
1769