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