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