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