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