rcparse.y revision 38889
138889Sjdp%{ /* rcparse.y -- parser for Windows rc files
238889Sjdp   Copyright 1997 Free Software Foundation, Inc.
338889Sjdp   Written by Ian Lance Taylor, Cygnus Support.
438889Sjdp
538889Sjdp   This file is part of GNU Binutils.
638889Sjdp
738889Sjdp   This program is free software; you can redistribute it and/or modify
838889Sjdp   it under the terms of the GNU General Public License as published by
938889Sjdp   the Free Software Foundation; either version 2 of the License, or
1038889Sjdp   (at your option) any later version.
1138889Sjdp
1238889Sjdp   This program is distributed in the hope that it will be useful,
1338889Sjdp   but WITHOUT ANY WARRANTY; without even the implied warranty of
1438889Sjdp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1538889Sjdp   GNU General Public License for more details.
1638889Sjdp
1738889Sjdp   You should have received a copy of the GNU General Public License
1838889Sjdp   along with this program; if not, write to the Free Software
1938889Sjdp   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
2038889Sjdp   02111-1307, USA.  */
2138889Sjdp
2238889Sjdp/* This is a parser for Windows rc files.  It is based on the parser
2338889Sjdp   by Gunther Ebert <gunther.ebert@ixos-leipzig.de>.  */
2438889Sjdp
2538889Sjdp#include "bfd.h"
2638889Sjdp#include "bucomm.h"
2738889Sjdp#include "libiberty.h"
2838889Sjdp#include "windres.h"
2938889Sjdp
3038889Sjdp#include <ctype.h>
3138889Sjdp
3238889Sjdp/* The current language.  */
3338889Sjdp
3438889Sjdpstatic unsigned short language;
3538889Sjdp
3638889Sjdp/* The resource information during a sub statement.  */
3738889Sjdp
3838889Sjdpstatic struct res_res_info sub_res_info;
3938889Sjdp
4038889Sjdp/* Dialog information.  This is built by the nonterminals styles and
4138889Sjdp   controls.  */
4238889Sjdp
4338889Sjdpstatic struct dialog dialog;
4438889Sjdp
4538889Sjdp/* This is used when building a style.  It is modified by the
4638889Sjdp   nonterminal styleexpr.  */
4738889Sjdp
4838889Sjdpstatic unsigned long style;
4938889Sjdp
5038889Sjdp/* These are used when building a control.  They are set before using
5138889Sjdp   control_params.  */
5238889Sjdp
5338889Sjdpstatic unsigned long base_style;
5438889Sjdpstatic unsigned long default_style;
5538889Sjdpstatic unsigned long class;
5638889Sjdp
5738889Sjdp%}
5838889Sjdp
5938889Sjdp%union
6038889Sjdp{
6138889Sjdp  struct accelerator acc;
6238889Sjdp  struct accelerator *pacc;
6338889Sjdp  struct dialog_control *dialog_control;
6438889Sjdp  struct menuitem *menuitem;
6538889Sjdp  struct
6638889Sjdp  {
6738889Sjdp    struct rcdata_item *first;
6838889Sjdp    struct rcdata_item *last;
6938889Sjdp  } rcdata;
7038889Sjdp  struct rcdata_item *rcdata_item;
7138889Sjdp  struct stringtable_data *stringtable;
7238889Sjdp  struct fixed_versioninfo *fixver;
7338889Sjdp  struct ver_info *verinfo;
7438889Sjdp  struct ver_stringinfo *verstring;
7538889Sjdp  struct ver_varinfo *vervar;
7638889Sjdp  struct res_id id;
7738889Sjdp  struct res_res_info res_info;
7838889Sjdp  struct
7938889Sjdp  {
8038889Sjdp    unsigned short on;
8138889Sjdp    unsigned short off;
8238889Sjdp  } memflags;
8338889Sjdp  struct
8438889Sjdp  {
8538889Sjdp    unsigned long val;
8638889Sjdp    /* Nonzero if this number was explicitly specified as long.  */
8738889Sjdp    int dword;
8838889Sjdp  } i;
8938889Sjdp  unsigned long il;
9038889Sjdp  unsigned short is;
9138889Sjdp  const char *s;
9238889Sjdp  struct
9338889Sjdp  {
9438889Sjdp    unsigned long length;
9538889Sjdp    const char *s;
9638889Sjdp  } ss;
9738889Sjdp};
9838889Sjdp
9938889Sjdp%token BEG END
10038889Sjdp%token ACCELERATORS VIRTKEY ASCII NOINVERT SHIFT CONTROL ALT
10138889Sjdp%token BITMAP
10238889Sjdp%token CURSOR
10338889Sjdp%token DIALOG DIALOGEX EXSTYLE CAPTION CLASS STYLE
10438889Sjdp%token AUTO3STATE AUTOCHECKBOX AUTORADIOBUTTON CHECKBOX COMBOBOX CTEXT
10538889Sjdp%token DEFPUSHBUTTON EDITTEXT GROUPBOX LISTBOX LTEXT PUSHBOX PUSHBUTTON
10638889Sjdp%token RADIOBUTTON RTEXT SCROLLBAR STATE3 USERBUTTON
10738889Sjdp%token BEDIT HEDIT IEDIT
10838889Sjdp%token FONT
10938889Sjdp%token ICON
11038889Sjdp%token LANGUAGE CHARACTERISTICS VERSIONK
11138889Sjdp%token MENU MENUEX MENUITEM SEPARATOR POPUP CHECKED GRAYED HELP INACTIVE
11238889Sjdp%token MENUBARBREAK MENUBREAK
11338889Sjdp%token MESSAGETABLE
11438889Sjdp%token RCDATA
11538889Sjdp%token STRINGTABLE
11638889Sjdp%token VERSIONINFO FILEVERSION PRODUCTVERSION FILEFLAGSMASK FILEFLAGS
11738889Sjdp%token FILEOS FILETYPE FILESUBTYPE BLOCKSTRINGFILEINFO BLOCKVARFILEINFO
11838889Sjdp%token VALUE
11938889Sjdp%token <s> BLOCK
12038889Sjdp%token MOVEABLE FIXED PURE IMPURE PRELOAD LOADONCALL DISCARDABLE
12138889Sjdp%token NOT
12238889Sjdp%token <s> QUOTEDSTRING STRING
12338889Sjdp%token <i> NUMBER
12438889Sjdp%token <ss> SIZEDSTRING
12538889Sjdp
12638889Sjdp%type <pacc> acc_entries
12738889Sjdp%type <acc> acc_entry acc_event
12838889Sjdp%type <dialog_control> control control_params
12938889Sjdp%type <menuitem> menuitems menuitem menuexitems menuexitem
13038889Sjdp%type <rcdata> optrcdata_data optrcdata_data_int rcdata_data
13138889Sjdp%type <rcdata_item> opt_control_data
13238889Sjdp%type <fixver> fixedverinfo
13338889Sjdp%type <verinfo> verblocks
13438889Sjdp%type <verstring> vervals
13538889Sjdp%type <vervar> vertrans
13638889Sjdp%type <res_info> suboptions memflags_move_discard memflags_move
13738889Sjdp%type <memflags> memflag
13838889Sjdp%type <id> id
13938889Sjdp%type <il> exstyle parennumber
14038889Sjdp%type <il> numexpr posnumexpr cnumexpr optcnumexpr cposnumexpr
14138889Sjdp%type <is> acc_options acc_option menuitem_flags menuitem_flag
14238889Sjdp%type <s> optstringc file_name
14338889Sjdp%type <i> sizednumexpr sizedposnumexpr
14438889Sjdp
14538889Sjdp%left '|'
14638889Sjdp%left '^'
14738889Sjdp%left '&'
14838889Sjdp%left '+' '-'
14938889Sjdp%left '*' '/' '%'
15038889Sjdp%right '~' NEG
15138889Sjdp
15238889Sjdp%%
15338889Sjdp
15438889Sjdpinput:
15538889Sjdp	  /* empty */
15638889Sjdp	| input newcmd accelerator
15738889Sjdp	| input newcmd bitmap
15838889Sjdp	| input newcmd cursor
15938889Sjdp	| input newcmd dialog
16038889Sjdp	| input newcmd font
16138889Sjdp	| input newcmd icon
16238889Sjdp	| input newcmd language
16338889Sjdp	| input newcmd menu
16438889Sjdp	| input newcmd menuex
16538889Sjdp	| input newcmd messagetable
16638889Sjdp	| input newcmd rcdata
16738889Sjdp	| input newcmd stringtable
16838889Sjdp	| input newcmd user
16938889Sjdp	| input newcmd versioninfo
17038889Sjdp	;
17138889Sjdp
17238889Sjdpnewcmd:
17338889Sjdp	  /* empty */
17438889Sjdp	  {
17538889Sjdp	    rcparse_discard_strings ();
17638889Sjdp	  }
17738889Sjdp	;
17838889Sjdp
17938889Sjdp/* Accelerator resources.  */
18038889Sjdp
18138889Sjdpaccelerator:
18238889Sjdp	  id ACCELERATORS suboptions BEG acc_entries END
18338889Sjdp	  {
18438889Sjdp	    define_accelerator ($1, &$3, $5);
18538889Sjdp	  }
18638889Sjdp	;
18738889Sjdp
18838889Sjdpacc_entries:
18938889Sjdp	  /* empty */
19038889Sjdp	  {
19138889Sjdp	    $$ = NULL;
19238889Sjdp	  }
19338889Sjdp	| acc_entries acc_entry
19438889Sjdp	  {
19538889Sjdp	    struct accelerator *a;
19638889Sjdp
19738889Sjdp	    a = (struct accelerator *) res_alloc (sizeof *a);
19838889Sjdp	    *a = $2;
19938889Sjdp	    if ($1 == NULL)
20038889Sjdp	      $$ = a;
20138889Sjdp	    else
20238889Sjdp	      {
20338889Sjdp		struct accelerator **pp;
20438889Sjdp
20538889Sjdp		for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
20638889Sjdp		  ;
20738889Sjdp		*pp = a;
20838889Sjdp		$$ = $1;
20938889Sjdp	      }
21038889Sjdp	  }
21138889Sjdp	;
21238889Sjdp
21338889Sjdpacc_entry:
21438889Sjdp	  acc_event cposnumexpr
21538889Sjdp	  {
21638889Sjdp	    $$ = $1;
21738889Sjdp	    $$.id = $2;
21838889Sjdp	  }
21938889Sjdp	| acc_event cposnumexpr ',' acc_options
22038889Sjdp	  {
22138889Sjdp	    $$ = $1;
22238889Sjdp	    $$.id = $2;
22338889Sjdp	    $$.flags |= $4;
22438889Sjdp	    if (($$.flags & ACC_VIRTKEY) == 0
22538889Sjdp		&& ($$.flags & (ACC_SHIFT | ACC_CONTROL | ACC_ALT)) != 0)
22638889Sjdp	      rcparse_warning ("inappropriate modifiers for non-VIRTKEY");
22738889Sjdp	  }
22838889Sjdp	;
22938889Sjdp
23038889Sjdpacc_event:
23138889Sjdp	  QUOTEDSTRING
23238889Sjdp	  {
23338889Sjdp	    const char *s = $1;
23438889Sjdp	    char ch;
23538889Sjdp
23638889Sjdp	    $$.next = NULL;
23738889Sjdp	    $$.id = 0;
23838889Sjdp	    ch = *s;
23938889Sjdp	    if (ch != '^')
24038889Sjdp	      $$.flags = 0;
24138889Sjdp	    else
24238889Sjdp	      {
24338889Sjdp		$$.flags = ACC_CONTROL | ACC_VIRTKEY;
24438889Sjdp		++s;
24538889Sjdp		ch = *s;
24638889Sjdp		ch = toupper ((unsigned char) ch);
24738889Sjdp	      }
24838889Sjdp	    $$.key = ch;
24938889Sjdp	    if (s[1] != '\0')
25038889Sjdp	      rcparse_warning ("accelerator should only be one character");
25138889Sjdp	  }
25238889Sjdp	| posnumexpr
25338889Sjdp	  {
25438889Sjdp	    $$.next = NULL;
25538889Sjdp	    $$.flags = 0;
25638889Sjdp	    $$.id = 0;
25738889Sjdp	    $$.key = $1;
25838889Sjdp	  }
25938889Sjdp	;
26038889Sjdp
26138889Sjdpacc_options:
26238889Sjdp	  acc_option
26338889Sjdp	  {
26438889Sjdp	    $$ = $1;
26538889Sjdp	  }
26638889Sjdp	| acc_options ',' acc_option
26738889Sjdp	  {
26838889Sjdp	    $$ = $1 | $3;
26938889Sjdp	  }
27038889Sjdp	/* I've had one report that the comma is optional.  */
27138889Sjdp	| acc_options acc_option
27238889Sjdp	  {
27338889Sjdp	    $$ = $1 | $2;
27438889Sjdp	  }
27538889Sjdp	;
27638889Sjdp
27738889Sjdpacc_option:
27838889Sjdp	  VIRTKEY
27938889Sjdp	  {
28038889Sjdp	    $$ = ACC_VIRTKEY;
28138889Sjdp	  }
28238889Sjdp	| ASCII
28338889Sjdp	  {
28438889Sjdp	    /* This is just the absence of VIRTKEY.  */
28538889Sjdp	    $$ = 0;
28638889Sjdp	  }
28738889Sjdp	| NOINVERT
28838889Sjdp	  {
28938889Sjdp	    $$ = ACC_NOINVERT;
29038889Sjdp	  }
29138889Sjdp	| SHIFT
29238889Sjdp	  {
29338889Sjdp	    $$ = ACC_SHIFT;
29438889Sjdp	  }
29538889Sjdp	| CONTROL
29638889Sjdp	  {
29738889Sjdp	    $$ = ACC_CONTROL;
29838889Sjdp	  }
29938889Sjdp	| ALT
30038889Sjdp	  {
30138889Sjdp	    $$ = ACC_ALT;
30238889Sjdp	  }
30338889Sjdp	;
30438889Sjdp
30538889Sjdp/* Bitmap resources.  */
30638889Sjdp
30738889Sjdpbitmap:
30838889Sjdp	  id BITMAP memflags_move file_name
30938889Sjdp	  {
31038889Sjdp	    define_bitmap ($1, &$3, $4);
31138889Sjdp	  }
31238889Sjdp	;
31338889Sjdp
31438889Sjdp/* Cursor resources.  */
31538889Sjdp
31638889Sjdpcursor:
31738889Sjdp	  id CURSOR memflags_move_discard file_name
31838889Sjdp	  {
31938889Sjdp	    define_cursor ($1, &$3, $4);
32038889Sjdp	  }
32138889Sjdp	;
32238889Sjdp
32338889Sjdp/* Dialog resources.  */
32438889Sjdp
32538889Sjdpdialog:
32638889Sjdp	  id DIALOG memflags_move exstyle posnumexpr cnumexpr cnumexpr
32738889Sjdp	    cnumexpr
32838889Sjdp	    {
32938889Sjdp	      memset (&dialog, 0, sizeof dialog);
33038889Sjdp	      dialog.x = $5;
33138889Sjdp	      dialog.y = $6;
33238889Sjdp	      dialog.width = $7;
33338889Sjdp	      dialog.height = $8;
33438889Sjdp	      dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU;
33538889Sjdp	      dialog.exstyle = $4;
33638889Sjdp	      dialog.menu.named = 1;
33738889Sjdp	      dialog.class.named = 1;
33838889Sjdp	      dialog.font = NULL;
33938889Sjdp	      dialog.ex = NULL;
34038889Sjdp	      dialog.controls = NULL;
34138889Sjdp	      sub_res_info = $3;
34238889Sjdp	    }
34338889Sjdp	    styles BEG controls END
34438889Sjdp	  {
34538889Sjdp	    define_dialog ($1, &sub_res_info, &dialog);
34638889Sjdp	  }
34738889Sjdp	| id DIALOGEX memflags_move exstyle posnumexpr cnumexpr cnumexpr
34838889Sjdp	    cnumexpr
34938889Sjdp	    {
35038889Sjdp	      memset (&dialog, 0, sizeof dialog);
35138889Sjdp	      dialog.x = $5;
35238889Sjdp	      dialog.y = $6;
35338889Sjdp	      dialog.width = $7;
35438889Sjdp	      dialog.height = $8;
35538889Sjdp	      dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU;
35638889Sjdp	      dialog.exstyle = $4;
35738889Sjdp	      dialog.menu.named = 1;
35838889Sjdp	      dialog.class.named = 1;
35938889Sjdp	      dialog.font = NULL;
36038889Sjdp	      dialog.ex = ((struct dialog_ex *)
36138889Sjdp			   res_alloc (sizeof (struct dialog_ex)));
36238889Sjdp	      memset (dialog.ex, 0, sizeof (struct dialog_ex));
36338889Sjdp	      dialog.controls = NULL;
36438889Sjdp	      sub_res_info = $3;
36538889Sjdp	    }
36638889Sjdp	    styles BEG controls END
36738889Sjdp	  {
36838889Sjdp	    define_dialog ($1, &sub_res_info, &dialog);
36938889Sjdp	  }
37038889Sjdp	| id DIALOGEX memflags_move exstyle posnumexpr cnumexpr cnumexpr
37138889Sjdp	    cnumexpr cnumexpr
37238889Sjdp	    {
37338889Sjdp	      memset (&dialog, 0, sizeof dialog);
37438889Sjdp	      dialog.x = $5;
37538889Sjdp	      dialog.y = $6;
37638889Sjdp	      dialog.width = $7;
37738889Sjdp	      dialog.height = $8;
37838889Sjdp	      dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU;
37938889Sjdp	      dialog.exstyle = $4;
38038889Sjdp	      dialog.menu.named = 1;
38138889Sjdp	      dialog.class.named = 1;
38238889Sjdp	      dialog.font = NULL;
38338889Sjdp	      dialog.ex = ((struct dialog_ex *)
38438889Sjdp			   res_alloc (sizeof (struct dialog_ex)));
38538889Sjdp	      memset (dialog.ex, 0, sizeof (struct dialog_ex));
38638889Sjdp	      dialog.ex->help = $9;
38738889Sjdp	      dialog.controls = NULL;
38838889Sjdp	      sub_res_info = $3;
38938889Sjdp	    }
39038889Sjdp	    styles BEG controls END
39138889Sjdp	  {
39238889Sjdp	    define_dialog ($1, &sub_res_info, &dialog);
39338889Sjdp	  }
39438889Sjdp	;
39538889Sjdp
39638889Sjdpexstyle:
39738889Sjdp	  /* empty */
39838889Sjdp	  {
39938889Sjdp	    $$ = 0;
40038889Sjdp	  }
40138889Sjdp	| EXSTYLE '=' numexpr
40238889Sjdp	  {
40338889Sjdp	    $$ = $3;
40438889Sjdp	  }
40538889Sjdp	;
40638889Sjdp
40738889Sjdpstyles:
40838889Sjdp	  /* empty */
40938889Sjdp	| styles CAPTION QUOTEDSTRING
41038889Sjdp	  {
41138889Sjdp	    unicode_from_ascii ((int *) NULL, &dialog.caption, $3);
41238889Sjdp	  }
41338889Sjdp	| styles CLASS id
41438889Sjdp	  {
41538889Sjdp	    dialog.class = $3;
41638889Sjdp	  }
41738889Sjdp	| styles STYLE
41838889Sjdp	    { style = dialog.style; }
41938889Sjdp	    styleexpr
42038889Sjdp	  {
42138889Sjdp	    dialog.style = style;
42238889Sjdp	  }
42338889Sjdp	| styles EXSTYLE numexpr
42438889Sjdp	  {
42538889Sjdp	    dialog.exstyle = $3;
42638889Sjdp	  }
42738889Sjdp	| styles FONT numexpr ',' QUOTEDSTRING
42838889Sjdp	  {
42938889Sjdp	    dialog.style |= DS_SETFONT;
43038889Sjdp	    dialog.pointsize = $3;
43138889Sjdp	    unicode_from_ascii ((int *) NULL, &dialog.font, $5);
43238889Sjdp	  }
43338889Sjdp	| styles FONT numexpr ',' QUOTEDSTRING cnumexpr cnumexpr
43438889Sjdp	  {
43538889Sjdp	    dialog.style |= DS_SETFONT;
43638889Sjdp	    dialog.pointsize = $3;
43738889Sjdp	    unicode_from_ascii ((int *) NULL, &dialog.font, $5);
43838889Sjdp	    if (dialog.ex == NULL)
43938889Sjdp	      rcparse_warning ("extended FONT requires DIALOGEX");
44038889Sjdp	    else
44138889Sjdp	      {
44238889Sjdp		dialog.ex->weight = $6;
44338889Sjdp		dialog.ex->italic = $7;
44438889Sjdp	      }
44538889Sjdp	  }
44638889Sjdp	| styles MENU id
44738889Sjdp	  {
44838889Sjdp	    dialog.menu = $3;
44938889Sjdp	  }
45038889Sjdp	| styles CHARACTERISTICS numexpr
45138889Sjdp	  {
45238889Sjdp	    sub_res_info.characteristics = $3;
45338889Sjdp	  }
45438889Sjdp	| styles LANGUAGE numexpr cnumexpr
45538889Sjdp	  {
45638889Sjdp	    sub_res_info.language = $3 | ($4 << 8);
45738889Sjdp	  }
45838889Sjdp	| styles VERSIONK numexpr
45938889Sjdp	  {
46038889Sjdp	    sub_res_info.version = $3;
46138889Sjdp	  }
46238889Sjdp	;
46338889Sjdp
46438889Sjdpcontrols:
46538889Sjdp	  /* empty */
46638889Sjdp	| controls control
46738889Sjdp	  {
46838889Sjdp	    struct dialog_control **pp;
46938889Sjdp
47038889Sjdp	    for (pp = &dialog.controls; *pp != NULL; pp = &(*pp)->next)
47138889Sjdp	      ;
47238889Sjdp	    *pp = $2;
47338889Sjdp	  }
47438889Sjdp	;
47538889Sjdp
47638889Sjdpcontrol:
47738889Sjdp	  AUTO3STATE
47838889Sjdp	    {
47938889Sjdp	      default_style = BS_AUTO3STATE | WS_TABSTOP;
48038889Sjdp	      base_style = BS_AUTO3STATE;
48138889Sjdp	      class = CTL_BUTTON;
48238889Sjdp	    }
48338889Sjdp	    control_params
48438889Sjdp	  {
48538889Sjdp	    $$ = $3;
48638889Sjdp	  }
48738889Sjdp	| AUTOCHECKBOX
48838889Sjdp	    {
48938889Sjdp	      default_style = BS_AUTOCHECKBOX | WS_TABSTOP;
49038889Sjdp	      base_style = BS_AUTOCHECKBOX;
49138889Sjdp	      class = CTL_BUTTON;
49238889Sjdp	    }
49338889Sjdp	    control_params
49438889Sjdp	  {
49538889Sjdp	    $$ = $3;
49638889Sjdp	  }
49738889Sjdp	| AUTORADIOBUTTON
49838889Sjdp	    {
49938889Sjdp	      default_style = BS_AUTORADIOBUTTON | WS_TABSTOP;
50038889Sjdp	      base_style = BS_AUTORADIOBUTTON;
50138889Sjdp	      class = CTL_BUTTON;
50238889Sjdp	    }
50338889Sjdp	    control_params
50438889Sjdp	  {
50538889Sjdp	    $$ = $3;
50638889Sjdp	  }
50738889Sjdp	| BEDIT
50838889Sjdp	    {
50938889Sjdp	      default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
51038889Sjdp	      base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
51138889Sjdp	      class = CTL_EDIT;
51238889Sjdp	    }
51338889Sjdp	    control_params
51438889Sjdp	  {
51538889Sjdp	    $$ = $3;
51638889Sjdp	    if (dialog.ex == NULL)
51738889Sjdp	      rcparse_warning ("IEDIT requires DIALOGEX");
51838889Sjdp	    res_string_to_id (&$$->class, "BEDIT");
51938889Sjdp	  }
52038889Sjdp	| CHECKBOX
52138889Sjdp	    {
52238889Sjdp	      default_style = BS_CHECKBOX | WS_TABSTOP;
52338889Sjdp	      base_style = BS_CHECKBOX | WS_TABSTOP;
52438889Sjdp	      class = CTL_BUTTON;
52538889Sjdp	    }
52638889Sjdp	    control_params
52738889Sjdp	  {
52838889Sjdp	    $$ = $3;
52938889Sjdp	  }
53038889Sjdp	| COMBOBOX
53138889Sjdp	    {
53238889Sjdp	      default_style = CBS_SIMPLE | WS_TABSTOP;
53338889Sjdp	      base_style = 0;
53438889Sjdp	      class = CTL_COMBOBOX;
53538889Sjdp	    }
53638889Sjdp	    control_params
53738889Sjdp	  {
53838889Sjdp	    $$ = $3;
53938889Sjdp	  }
54038889Sjdp	| CONTROL optstringc numexpr cnumexpr control_styleexpr cnumexpr
54138889Sjdp	    cnumexpr cnumexpr cnumexpr optcnumexpr opt_control_data
54238889Sjdp	  {
54338889Sjdp	    $$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10);
54438889Sjdp	    if ($11 != NULL)
54538889Sjdp	      {
54638889Sjdp		if (dialog.ex == NULL)
54738889Sjdp		  rcparse_warning ("control data requires DIALOGEX");
54838889Sjdp		$$->data = $11;
54938889Sjdp	      }
55038889Sjdp	  }
55138889Sjdp	| CONTROL optstringc numexpr cnumexpr control_styleexpr cnumexpr
55238889Sjdp	    cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data
55338889Sjdp	  {
55438889Sjdp	    $$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10);
55538889Sjdp	    if (dialog.ex == NULL)
55638889Sjdp	      rcparse_warning ("help ID requires DIALOGEX");
55738889Sjdp	    $$->help = $11;
55838889Sjdp	    $$->data = $12;
55938889Sjdp	  }
56038889Sjdp	| CTEXT
56138889Sjdp	    {
56238889Sjdp	      default_style = SS_CENTER | WS_GROUP;
56338889Sjdp	      base_style = SS_CENTER;
56438889Sjdp	      class = CTL_STATIC;
56538889Sjdp	    }
56638889Sjdp	    control_params
56738889Sjdp	  {
56838889Sjdp	    $$ = $3;
56938889Sjdp	  }
57038889Sjdp	| DEFPUSHBUTTON
57138889Sjdp	    {
57238889Sjdp	      default_style = BS_DEFPUSHBUTTON | WS_TABSTOP;
57338889Sjdp	      base_style = BS_DEFPUSHBUTTON | WS_TABSTOP;
57438889Sjdp	      class = CTL_BUTTON;
57538889Sjdp	    }
57638889Sjdp	    control_params
57738889Sjdp	  {
57838889Sjdp	    $$ = $3;
57938889Sjdp	  }
58038889Sjdp	| EDITTEXT
58138889Sjdp	    {
58238889Sjdp	      default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
58338889Sjdp	      base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
58438889Sjdp	      class = CTL_EDIT;
58538889Sjdp	    }
58638889Sjdp	    control_params
58738889Sjdp	  {
58838889Sjdp	    $$ = $3;
58938889Sjdp	  }
59038889Sjdp	| GROUPBOX
59138889Sjdp	    {
59238889Sjdp	      default_style = BS_GROUPBOX;
59338889Sjdp	      base_style = BS_GROUPBOX;
59438889Sjdp	      class = CTL_BUTTON;
59538889Sjdp	    }
59638889Sjdp	    control_params
59738889Sjdp	  {
59838889Sjdp	    $$ = $3;
59938889Sjdp	  }
60038889Sjdp	| HEDIT
60138889Sjdp	    {
60238889Sjdp	      default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
60338889Sjdp	      base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
60438889Sjdp	      class = CTL_EDIT;
60538889Sjdp	    }
60638889Sjdp	    control_params
60738889Sjdp	  {
60838889Sjdp	    $$ = $3;
60938889Sjdp	    if (dialog.ex == NULL)
61038889Sjdp	      rcparse_warning ("IEDIT requires DIALOGEX");
61138889Sjdp	    res_string_to_id (&$$->class, "HEDIT");
61238889Sjdp	  }
61338889Sjdp	| ICON optstringc numexpr cnumexpr cnumexpr opt_control_data
61438889Sjdp	  {
61538889Sjdp	    $$ = define_control ($2, $3, $4, $5, 0, 0, CTL_STATIC,
61638889Sjdp				 SS_ICON | WS_CHILD | WS_VISIBLE, 0);
61738889Sjdp	    if ($6 != NULL)
61838889Sjdp	      {
61938889Sjdp		if (dialog.ex == NULL)
62038889Sjdp		  rcparse_warning ("control data requires DIALOGEX");
62138889Sjdp		$$->data = $6;
62238889Sjdp	      }
62338889Sjdp	  }
62438889Sjdp	| ICON optstringc numexpr cnumexpr cnumexpr cnumexpr cnumexpr
62538889Sjdp	    icon_styleexpr optcnumexpr opt_control_data
62638889Sjdp	  {
62738889Sjdp    	    $$ = define_control ($2, $3, $4, $5, $6, $7, CTL_STATIC,
62838889Sjdp				 style, $9);
62938889Sjdp	    if ($10 != NULL)
63038889Sjdp	      {
63138889Sjdp		if (dialog.ex == NULL)
63238889Sjdp		  rcparse_warning ("control data requires DIALOGEX");
63338889Sjdp		$$->data = $10;
63438889Sjdp	      }
63538889Sjdp	  }
63638889Sjdp	| ICON optstringc numexpr cnumexpr cnumexpr cnumexpr cnumexpr
63738889Sjdp	    icon_styleexpr cnumexpr cnumexpr opt_control_data
63838889Sjdp	  {
63938889Sjdp    	    $$ = define_control ($2, $3, $4, $5, $6, $7, CTL_STATIC,
64038889Sjdp				 style, $9);
64138889Sjdp	    if (dialog.ex == NULL)
64238889Sjdp	      rcparse_warning ("help ID requires DIALOGEX");
64338889Sjdp	    $$->help = $10;
64438889Sjdp	    $$->data = $11;
64538889Sjdp	  }
64638889Sjdp	| IEDIT
64738889Sjdp	    {
64838889Sjdp	      default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
64938889Sjdp	      base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
65038889Sjdp	      class = CTL_EDIT;
65138889Sjdp	    }
65238889Sjdp	    control_params
65338889Sjdp	  {
65438889Sjdp	    $$ = $3;
65538889Sjdp	    if (dialog.ex == NULL)
65638889Sjdp	      rcparse_warning ("IEDIT requires DIALOGEX");
65738889Sjdp	    res_string_to_id (&$$->class, "IEDIT");
65838889Sjdp	  }
65938889Sjdp	| LISTBOX
66038889Sjdp	    {
66138889Sjdp	      default_style = LBS_NOTIFY | WS_BORDER;
66238889Sjdp	      base_style = LBS_NOTIFY | WS_BORDER;
66338889Sjdp	      class = CTL_LISTBOX;
66438889Sjdp	    }
66538889Sjdp	    control_params
66638889Sjdp	  {
66738889Sjdp	    $$ = $3;
66838889Sjdp	  }
66938889Sjdp	| LTEXT
67038889Sjdp	    {
67138889Sjdp	      default_style = SS_LEFT | WS_GROUP;
67238889Sjdp	      base_style = SS_LEFT;
67338889Sjdp	      class = CTL_STATIC;
67438889Sjdp	    }
67538889Sjdp	    control_params
67638889Sjdp	  {
67738889Sjdp	    $$ = $3;
67838889Sjdp	  }
67938889Sjdp	| PUSHBOX
68038889Sjdp	    {
68138889Sjdp	      default_style = BS_PUSHBOX | WS_TABSTOP;
68238889Sjdp	      base_style = BS_PUSHBOX;
68338889Sjdp	      class = CTL_BUTTON;
68438889Sjdp	    }
68538889Sjdp	    control_params
68638889Sjdp	  {
68738889Sjdp	    $$ = $3;
68838889Sjdp	  }
68938889Sjdp	| PUSHBUTTON
69038889Sjdp	    {
69138889Sjdp	      default_style = BS_PUSHBUTTON | WS_TABSTOP;
69238889Sjdp	      base_style = BS_PUSHBUTTON | WS_TABSTOP;
69338889Sjdp	      class = CTL_BUTTON;
69438889Sjdp	    }
69538889Sjdp	    control_params
69638889Sjdp	  {
69738889Sjdp	    $$ = $3;
69838889Sjdp	  }
69938889Sjdp	| RADIOBUTTON
70038889Sjdp	    {
70138889Sjdp	      default_style = BS_RADIOBUTTON | WS_TABSTOP;
70238889Sjdp	      base_style = BS_RADIOBUTTON;
70338889Sjdp	      class = CTL_BUTTON;
70438889Sjdp	    }
70538889Sjdp	    control_params
70638889Sjdp	  {
70738889Sjdp	    $$ = $3;
70838889Sjdp	  }
70938889Sjdp	| RTEXT
71038889Sjdp	    {
71138889Sjdp	      default_style = SS_RIGHT | WS_GROUP;
71238889Sjdp	      base_style = SS_RIGHT;
71338889Sjdp	      class = CTL_STATIC;
71438889Sjdp	    }
71538889Sjdp	    control_params
71638889Sjdp	  {
71738889Sjdp	    $$ = $3;
71838889Sjdp	  }
71938889Sjdp	| SCROLLBAR
72038889Sjdp	    {
72138889Sjdp	      default_style = SBS_HORZ;
72238889Sjdp	      base_style = 0;
72338889Sjdp	      class = CTL_SCROLLBAR;
72438889Sjdp	    }
72538889Sjdp	    control_params
72638889Sjdp	  {
72738889Sjdp	    $$ = $3;
72838889Sjdp	  }
72938889Sjdp	| STATE3
73038889Sjdp	    {
73138889Sjdp	      default_style = BS_3STATE | WS_TABSTOP;
73238889Sjdp	      base_style = BS_3STATE;
73338889Sjdp	      class = CTL_BUTTON;
73438889Sjdp	    }
73538889Sjdp	    control_params
73638889Sjdp	  {
73738889Sjdp	    $$ = $3;
73838889Sjdp	  }
73938889Sjdp	| USERBUTTON QUOTEDSTRING ',' numexpr ',' numexpr ',' numexpr ','
74038889Sjdp	    numexpr ',' numexpr ','
74138889Sjdp	    { style = WS_CHILD | WS_VISIBLE; }
74238889Sjdp	    styleexpr optcnumexpr
74338889Sjdp	  {
74438889Sjdp	    $$ = define_control ($2, $4, $6, $8, $10, $12, CTL_BUTTON,
74538889Sjdp				 style, $16);
74638889Sjdp	  }
74738889Sjdp	;
74838889Sjdp
74938889Sjdp/* Parameters for a control.  The static variables DEFAULT_STYLE,
75038889Sjdp   BASE_STYLE, and CLASS must be initialized before this nonterminal
75138889Sjdp   is used.  DEFAULT_STYLE is the style to use if no style expression
75238889Sjdp   is specified.  BASE_STYLE is the base style to use if a style
75338889Sjdp   expression is specified; the style expression modifies the base
75438889Sjdp   style.  CLASS is the class of the control.  */
75538889Sjdp
75638889Sjdpcontrol_params:
75738889Sjdp	  optstringc numexpr cnumexpr cnumexpr cnumexpr cnumexpr
75838889Sjdp	    opt_control_data
75938889Sjdp	  {
76038889Sjdp	    $$ = define_control ($1, $2, $3, $4, $5, $6, class,
76138889Sjdp				 default_style | WS_CHILD | WS_VISIBLE, 0);
76238889Sjdp	    if ($7 != NULL)
76338889Sjdp	      {
76438889Sjdp		if (dialog.ex == NULL)
76538889Sjdp		  rcparse_warning ("control data requires DIALOGEX");
76638889Sjdp		$$->data = $7;
76738889Sjdp	      }
76838889Sjdp	  }
76938889Sjdp	| optstringc numexpr cnumexpr cnumexpr cnumexpr cnumexpr
77038889Sjdp	    control_params_styleexpr optcnumexpr opt_control_data
77138889Sjdp	  {
77238889Sjdp	    $$ = define_control ($1, $2, $3, $4, $5, $6, class, style, $8);
77338889Sjdp	    if ($9 != NULL)
77438889Sjdp	      {
77538889Sjdp		if (dialog.ex == NULL)
77638889Sjdp		  rcparse_warning ("control data requires DIALOGEX");
77738889Sjdp		$$->data = $9;
77838889Sjdp	      }
77938889Sjdp	  }
78038889Sjdp	| optstringc numexpr cnumexpr cnumexpr cnumexpr cnumexpr
78138889Sjdp	    control_params_styleexpr cnumexpr cnumexpr opt_control_data
78238889Sjdp	  {
78338889Sjdp	    $$ = define_control ($1, $2, $3, $4, $5, $6, class, style, $8);
78438889Sjdp	    if (dialog.ex == NULL)
78538889Sjdp	      rcparse_warning ("help ID requires DIALOGEX");
78638889Sjdp	    $$->help = $9;
78738889Sjdp	    $$->data = $10;
78838889Sjdp	  }
78938889Sjdp	;
79038889Sjdp
79138889Sjdpoptstringc:
79238889Sjdp	  /* empty */
79338889Sjdp	  {
79438889Sjdp	    $$ = NULL;
79538889Sjdp	  }
79638889Sjdp	| QUOTEDSTRING ','
79738889Sjdp	  {
79838889Sjdp	    $$ = $1;
79938889Sjdp	  }
80038889Sjdp	;
80138889Sjdp
80238889Sjdpopt_control_data:
80338889Sjdp	  /* empty */
80438889Sjdp	  {
80538889Sjdp	    $$ = NULL;
80638889Sjdp	  }
80738889Sjdp	| BEG optrcdata_data END
80838889Sjdp	  {
80938889Sjdp	    $$ = $2.first;
81038889Sjdp	  }
81138889Sjdp	;
81238889Sjdp
81338889Sjdp/* These only exist to parse a reduction out of a common case.  */
81438889Sjdp
81538889Sjdpcontrol_styleexpr:
81638889Sjdp	  ','
81738889Sjdp	  { style = WS_CHILD | WS_VISIBLE; }
81838889Sjdp	  styleexpr
81938889Sjdp	;
82038889Sjdp
82138889Sjdpicon_styleexpr:
82238889Sjdp	  ','
82338889Sjdp	  { style = SS_ICON | WS_CHILD | WS_VISIBLE; }
82438889Sjdp	  styleexpr
82538889Sjdp	;
82638889Sjdp
82738889Sjdpcontrol_params_styleexpr:
82838889Sjdp	  ','
82938889Sjdp	  { style = base_style | WS_CHILD | WS_VISIBLE; }
83038889Sjdp	  styleexpr
83138889Sjdp	;
83238889Sjdp
83338889Sjdp/* Font resources.  */
83438889Sjdp
83538889Sjdpfont:
83638889Sjdp	  id FONT memflags_move_discard file_name
83738889Sjdp	  {
83838889Sjdp	    define_font ($1, &$3, $4);
83938889Sjdp	  }
84038889Sjdp	;
84138889Sjdp
84238889Sjdp/* Icon resources.  */
84338889Sjdp
84438889Sjdpicon:
84538889Sjdp	  id ICON memflags_move_discard file_name
84638889Sjdp	  {
84738889Sjdp	    define_icon ($1, &$3, $4);
84838889Sjdp	  }
84938889Sjdp	;
85038889Sjdp
85138889Sjdp/* Language command.  This changes the static variable language, which
85238889Sjdp   affects all subsequent resources.  */
85338889Sjdp
85438889Sjdplanguage:
85538889Sjdp	  LANGUAGE numexpr cnumexpr
85638889Sjdp	  {
85738889Sjdp	    language = $2 | ($3 << 8);
85838889Sjdp	  }
85938889Sjdp	;
86038889Sjdp
86138889Sjdp/* Menu resources.  */
86238889Sjdp
86338889Sjdpmenu:
86438889Sjdp	  id MENU suboptions BEG menuitems END
86538889Sjdp	  {
86638889Sjdp	    define_menu ($1, &$3, $5);
86738889Sjdp	  }
86838889Sjdp	;
86938889Sjdp
87038889Sjdpmenuitems:
87138889Sjdp	  /* empty */
87238889Sjdp	  {
87338889Sjdp	    $$ = NULL;
87438889Sjdp	  }
87538889Sjdp	| menuitems menuitem
87638889Sjdp	  {
87738889Sjdp	    if ($1 == NULL)
87838889Sjdp	      $$ = $2;
87938889Sjdp	    else
88038889Sjdp	      {
88138889Sjdp		struct menuitem **pp;
88238889Sjdp
88338889Sjdp		for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
88438889Sjdp		  ;
88538889Sjdp		*pp = $2;
88638889Sjdp		$$ = $1;
88738889Sjdp	      }
88838889Sjdp	  }
88938889Sjdp	;
89038889Sjdp
89138889Sjdpmenuitem:
89238889Sjdp	  MENUITEM QUOTEDSTRING cnumexpr menuitem_flags
89338889Sjdp	  {
89438889Sjdp	    $$ = define_menuitem ($2, $3, $4, 0, 0, NULL);
89538889Sjdp	  }
89638889Sjdp	| MENUITEM SEPARATOR
89738889Sjdp	  {
89838889Sjdp	    $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL);
89938889Sjdp	  }
90038889Sjdp	| POPUP QUOTEDSTRING menuitem_flags BEG menuitems END
90138889Sjdp	  {
90238889Sjdp	    $$ = define_menuitem ($2, 0, $3, 0, 0, $5);
90338889Sjdp	  }
90438889Sjdp	;
90538889Sjdp
90638889Sjdpmenuitem_flags:
90738889Sjdp	  /* empty */
90838889Sjdp	  {
90938889Sjdp	    $$ = 0;
91038889Sjdp	  }
91138889Sjdp	| menuitem_flags ',' menuitem_flag
91238889Sjdp	  {
91338889Sjdp	    $$ = $1 | $3;
91438889Sjdp	  }
91538889Sjdp	| menuitem_flags menuitem_flag
91638889Sjdp	  {
91738889Sjdp	    $$ = $1 | $2;
91838889Sjdp	  }
91938889Sjdp	;
92038889Sjdp
92138889Sjdpmenuitem_flag:
92238889Sjdp	  CHECKED
92338889Sjdp	  {
92438889Sjdp	    $$ = MENUITEM_CHECKED;
92538889Sjdp	  }
92638889Sjdp	| GRAYED
92738889Sjdp	  {
92838889Sjdp	    $$ = MENUITEM_GRAYED;
92938889Sjdp	  }
93038889Sjdp	| HELP
93138889Sjdp	  {
93238889Sjdp	    $$ = MENUITEM_HELP;
93338889Sjdp	  }
93438889Sjdp	| INACTIVE
93538889Sjdp	  {
93638889Sjdp	    $$ = MENUITEM_INACTIVE;
93738889Sjdp	  }
93838889Sjdp	| MENUBARBREAK
93938889Sjdp	  {
94038889Sjdp	    $$ = MENUITEM_MENUBARBREAK;
94138889Sjdp	  }
94238889Sjdp	| MENUBREAK
94338889Sjdp	  {
94438889Sjdp	    $$ = MENUITEM_MENUBREAK;
94538889Sjdp	  }
94638889Sjdp	;
94738889Sjdp
94838889Sjdp/* Menuex resources.  */
94938889Sjdp
95038889Sjdpmenuex:
95138889Sjdp	  id MENUEX suboptions BEG menuexitems END
95238889Sjdp	  {
95338889Sjdp	    define_menu ($1, &$3, $5);
95438889Sjdp	  }
95538889Sjdp	;
95638889Sjdp
95738889Sjdpmenuexitems:
95838889Sjdp	  /* empty */
95938889Sjdp	  {
96038889Sjdp	    $$ = NULL;
96138889Sjdp	  }
96238889Sjdp	| menuexitems menuexitem
96338889Sjdp	  {
96438889Sjdp	    if ($1 == NULL)
96538889Sjdp	      $$ = $2;
96638889Sjdp	    else
96738889Sjdp	      {
96838889Sjdp		struct menuitem **pp;
96938889Sjdp
97038889Sjdp		for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
97138889Sjdp		  ;
97238889Sjdp		*pp = $2;
97338889Sjdp		$$ = $1;
97438889Sjdp	      }
97538889Sjdp	  }
97638889Sjdp	;
97738889Sjdp
97838889Sjdpmenuexitem:
97938889Sjdp	  MENUITEM QUOTEDSTRING
98038889Sjdp	  {
98138889Sjdp	    $$ = define_menuitem ($2, 0, 0, 0, 0, NULL);
98238889Sjdp	  }
98338889Sjdp	| MENUITEM QUOTEDSTRING cnumexpr
98438889Sjdp	  {
98538889Sjdp	    $$ = define_menuitem ($2, $3, 0, 0, 0, NULL);
98638889Sjdp	  }
98738889Sjdp	| MENUITEM QUOTEDSTRING cnumexpr cnumexpr optcnumexpr
98838889Sjdp	  {
98938889Sjdp	    $$ = define_menuitem ($2, $3, $4, $5, 0, NULL);
99038889Sjdp	  }
99138889Sjdp	| POPUP QUOTEDSTRING BEG menuexitems END
99238889Sjdp	  {
99338889Sjdp	    $$ = define_menuitem ($2, 0, 0, 0, 0, $4);
99438889Sjdp	  }
99538889Sjdp	| POPUP QUOTEDSTRING cnumexpr BEG menuexitems END
99638889Sjdp	  {
99738889Sjdp	    $$ = define_menuitem ($2, $3, 0, 0, 0, $5);
99838889Sjdp	  }
99938889Sjdp	| POPUP QUOTEDSTRING cnumexpr cnumexpr BEG menuexitems END
100038889Sjdp	  {
100138889Sjdp	    $$ = define_menuitem ($2, $3, $4, 0, 0, $6);
100238889Sjdp	  }
100338889Sjdp	| POPUP QUOTEDSTRING cnumexpr cnumexpr cnumexpr optcnumexpr
100438889Sjdp	    BEG menuexitems END
100538889Sjdp	  {
100638889Sjdp	    $$ = define_menuitem ($2, $3, $4, $5, $6, $8);
100738889Sjdp	  }
100838889Sjdp	;
100938889Sjdp
101038889Sjdp/* Messagetable resources.  */
101138889Sjdp
101238889Sjdpmessagetable:
101338889Sjdp	  id MESSAGETABLE memflags_move file_name
101438889Sjdp	  {
101538889Sjdp	    define_messagetable ($1, &$3, $4);
101638889Sjdp	  }
101738889Sjdp	;
101838889Sjdp
101938889Sjdp/* Rcdata resources.  */
102038889Sjdp
102138889Sjdprcdata:
102238889Sjdp	  id RCDATA suboptions BEG optrcdata_data END
102338889Sjdp	  {
102438889Sjdp	    define_rcdata ($1, &$3, $5.first);
102538889Sjdp	  }
102638889Sjdp	;
102738889Sjdp
102838889Sjdp/* We use a different lexing algorithm, because rcdata strings may
102938889Sjdp   contain embedded null bytes, and we need to know the length to use.  */
103038889Sjdp
103138889Sjdpoptrcdata_data:
103238889Sjdp	  {
103338889Sjdp	    rcparse_rcdata ();
103438889Sjdp	  }
103538889Sjdp	  optrcdata_data_int
103638889Sjdp	  {
103738889Sjdp	    rcparse_normal ();
103838889Sjdp	    $$ = $2;
103938889Sjdp	  }
104038889Sjdp	;
104138889Sjdp
104238889Sjdpoptrcdata_data_int:
104338889Sjdp	  /* empty */
104438889Sjdp	  {
104538889Sjdp	    $$.first = NULL;
104638889Sjdp	    $$.last = NULL;
104738889Sjdp	  }
104838889Sjdp	| rcdata_data
104938889Sjdp	  {
105038889Sjdp	    $$ = $1;
105138889Sjdp	  }
105238889Sjdp	;
105338889Sjdp
105438889Sjdprcdata_data:
105538889Sjdp	  SIZEDSTRING
105638889Sjdp	  {
105738889Sjdp	    struct rcdata_item *ri;
105838889Sjdp
105938889Sjdp	    ri = define_rcdata_string ($1.s, $1.length);
106038889Sjdp	    $$.first = ri;
106138889Sjdp	    $$.last = ri;
106238889Sjdp	  }
106338889Sjdp	| sizednumexpr
106438889Sjdp	  {
106538889Sjdp	    struct rcdata_item *ri;
106638889Sjdp
106738889Sjdp	    ri = define_rcdata_number ($1.val, $1.dword);
106838889Sjdp	    $$.first = ri;
106938889Sjdp	    $$.last = ri;
107038889Sjdp	  }
107138889Sjdp	| rcdata_data ',' SIZEDSTRING
107238889Sjdp	  {
107338889Sjdp	    struct rcdata_item *ri;
107438889Sjdp
107538889Sjdp	    ri = define_rcdata_string ($3.s, $3.length);
107638889Sjdp	    $$.first = $1.first;
107738889Sjdp	    $1.last->next = ri;
107838889Sjdp	    $$.last = ri;
107938889Sjdp	  }
108038889Sjdp	| rcdata_data ',' sizednumexpr
108138889Sjdp	  {
108238889Sjdp	    struct rcdata_item *ri;
108338889Sjdp
108438889Sjdp	    ri = define_rcdata_number ($3.val, $3.dword);
108538889Sjdp	    $$.first = $1.first;
108638889Sjdp	    $1.last->next = ri;
108738889Sjdp	    $$.last = ri;
108838889Sjdp	  }
108938889Sjdp	;
109038889Sjdp
109138889Sjdp/* Stringtable resources.  */
109238889Sjdp
109338889Sjdpstringtable:
109438889Sjdp	  STRINGTABLE suboptions BEG
109538889Sjdp	    { sub_res_info = $2; }
109638889Sjdp	    string_data END
109738889Sjdp	;
109838889Sjdp
109938889Sjdpstring_data:
110038889Sjdp	  /* empty */
110138889Sjdp	| string_data numexpr QUOTEDSTRING
110238889Sjdp	  {
110338889Sjdp	    define_stringtable (&sub_res_info, $2, $3);
110438889Sjdp	  }
110538889Sjdp	| string_data numexpr ',' QUOTEDSTRING
110638889Sjdp	  {
110738889Sjdp	    define_stringtable (&sub_res_info, $2, $4);
110838889Sjdp	  }
110938889Sjdp	;
111038889Sjdp
111138889Sjdp/* User defined resources.  We accept general suboptions in the
111238889Sjdp   file_name case to keep the parser happy.  */
111338889Sjdp
111438889Sjdpuser:
111538889Sjdp	  id id suboptions BEG optrcdata_data END
111638889Sjdp	  {
111738889Sjdp	    define_user_data ($1, $2, &$3, $5.first);
111838889Sjdp	  }
111938889Sjdp	| id id suboptions file_name
112038889Sjdp	  {
112138889Sjdp	    define_user_file ($1, $2, &$3, $4);
112238889Sjdp	  }
112338889Sjdp	;
112438889Sjdp
112538889Sjdp/* Versioninfo resources.  */
112638889Sjdp
112738889Sjdpversioninfo:
112838889Sjdp	  id VERSIONINFO fixedverinfo BEG verblocks END
112938889Sjdp	  {
113038889Sjdp	    define_versioninfo ($1, language, $3, $5);
113138889Sjdp	  }
113238889Sjdp	;
113338889Sjdp
113438889Sjdpfixedverinfo:
113538889Sjdp	  /* empty */
113638889Sjdp	  {
113738889Sjdp	    $$ = ((struct fixed_versioninfo *)
113838889Sjdp		  res_alloc (sizeof (struct fixed_versioninfo)));
113938889Sjdp	    memset ($$, 0, sizeof (struct fixed_versioninfo));
114038889Sjdp	  }
114138889Sjdp	| fixedverinfo FILEVERSION numexpr cnumexpr cnumexpr cnumexpr
114238889Sjdp	  {
114338889Sjdp	    $1->file_version_ms = ($3 << 16) | $4;
114438889Sjdp	    $1->file_version_ls = ($5 << 16) | $6;
114538889Sjdp	    $$ = $1;
114638889Sjdp	  }
114738889Sjdp	| fixedverinfo PRODUCTVERSION numexpr cnumexpr cnumexpr cnumexpr
114838889Sjdp	  {
114938889Sjdp	    $1->product_version_ms = ($3 << 16) | $4;
115038889Sjdp	    $1->product_version_ls = ($5 << 16) | $6;
115138889Sjdp	    $$ = $1;
115238889Sjdp	  }
115338889Sjdp	| fixedverinfo FILEFLAGSMASK numexpr
115438889Sjdp	  {
115538889Sjdp	    $1->file_flags_mask = $3;
115638889Sjdp	    $$ = $1;
115738889Sjdp	  }
115838889Sjdp	| fixedverinfo FILEFLAGS numexpr
115938889Sjdp	  {
116038889Sjdp	    $1->file_flags = $3;
116138889Sjdp	    $$ = $1;
116238889Sjdp	  }
116338889Sjdp	| fixedverinfo FILEOS numexpr
116438889Sjdp	  {
116538889Sjdp	    $1->file_os = $3;
116638889Sjdp	    $$ = $1;
116738889Sjdp	  }
116838889Sjdp	| fixedverinfo FILETYPE numexpr
116938889Sjdp	  {
117038889Sjdp	    $1->file_type = $3;
117138889Sjdp	    $$ = $1;
117238889Sjdp	  }
117338889Sjdp	| fixedverinfo FILESUBTYPE numexpr
117438889Sjdp	  {
117538889Sjdp	    $1->file_subtype = $3;
117638889Sjdp	    $$ = $1;
117738889Sjdp	  }
117838889Sjdp	;
117938889Sjdp
118038889Sjdp/* To handle verblocks successfully, the lexer handles BLOCK
118138889Sjdp   specially.  A BLOCK "StringFileInfo" is returned as
118238889Sjdp   BLOCKSTRINGFILEINFO.  A BLOCK "VarFileInfo" is returned as
118338889Sjdp   BLOCKVARFILEINFO.  A BLOCK with some other string returns BLOCK
118438889Sjdp   with the string as the value.  */
118538889Sjdp
118638889Sjdpverblocks:
118738889Sjdp	  /* empty */
118838889Sjdp	  {
118938889Sjdp	    $$ = NULL;
119038889Sjdp	  }
119138889Sjdp	| verblocks BLOCKSTRINGFILEINFO BEG BLOCK BEG vervals END END
119238889Sjdp	  {
119338889Sjdp	    $$ = append_ver_stringfileinfo ($1, $4, $6);
119438889Sjdp	  }
119538889Sjdp	| verblocks BLOCKVARFILEINFO BEG VALUE QUOTEDSTRING vertrans END
119638889Sjdp	  {
119738889Sjdp	    $$ = append_ver_varfileinfo ($1, $5, $6);
119838889Sjdp	  }
119938889Sjdp	;
120038889Sjdp
120138889Sjdpvervals:
120238889Sjdp	  /* empty */
120338889Sjdp	  {
120438889Sjdp	    $$ = NULL;
120538889Sjdp	  }
120638889Sjdp	| vervals VALUE QUOTEDSTRING ',' QUOTEDSTRING
120738889Sjdp	  {
120838889Sjdp	    $$ = append_verval ($1, $3, $5);
120938889Sjdp	  }
121038889Sjdp	;
121138889Sjdp
121238889Sjdpvertrans:
121338889Sjdp	  /* empty */
121438889Sjdp	  {
121538889Sjdp	    $$ = NULL;
121638889Sjdp	  }
121738889Sjdp	| vertrans cnumexpr cnumexpr
121838889Sjdp	  {
121938889Sjdp	    $$ = append_vertrans ($1, $2, $3);
122038889Sjdp	  }
122138889Sjdp	;
122238889Sjdp
122338889Sjdp/* A resource ID.  */
122438889Sjdp
122538889Sjdpid:
122638889Sjdp	  posnumexpr
122738889Sjdp	  {
122838889Sjdp	    $$.named = 0;
122938889Sjdp	    $$.u.id = $1;
123038889Sjdp	  }
123138889Sjdp	| STRING
123238889Sjdp	  {
123338889Sjdp	    char *copy, *s;
123438889Sjdp
123538889Sjdp	    /* It seems that resource ID's are forced to upper case.  */
123638889Sjdp	    copy = xstrdup ($1);
123738889Sjdp	    for (s = copy; *s != '\0'; s++)
123838889Sjdp	      if (islower (*s))
123938889Sjdp		*s = toupper (*s);
124038889Sjdp	    res_string_to_id (&$$, copy);
124138889Sjdp	    free (copy);
124238889Sjdp	  }
124338889Sjdp	;
124438889Sjdp
124538889Sjdp/* Generic suboptions.  These may appear before the BEGIN in any
124638889Sjdp   multiline statement.  */
124738889Sjdp
124838889Sjdpsuboptions:
124938889Sjdp	  /* empty */
125038889Sjdp	  {
125138889Sjdp	    memset (&$$, 0, sizeof (struct res_res_info));
125238889Sjdp	    $$.language = language;
125338889Sjdp	    /* FIXME: Is this the right default?  */
125438889Sjdp	    $$.memflags = MEMFLAG_MOVEABLE;
125538889Sjdp	  }
125638889Sjdp	| suboptions memflag
125738889Sjdp	  {
125838889Sjdp	    $$ = $1;
125938889Sjdp	    $$.memflags |= $2.on;
126038889Sjdp	    $$.memflags &=~ $2.off;
126138889Sjdp	  }
126238889Sjdp	| suboptions CHARACTERISTICS numexpr
126338889Sjdp	  {
126438889Sjdp	    $$ = $1;
126538889Sjdp	    $$.characteristics = $3;
126638889Sjdp	  }
126738889Sjdp	| suboptions LANGUAGE numexpr cnumexpr
126838889Sjdp	  {
126938889Sjdp	    $$ = $1;
127038889Sjdp	    $$.language = $3 | ($4 << 8);
127138889Sjdp	  }
127238889Sjdp	| suboptions VERSIONK numexpr
127338889Sjdp	  {
127438889Sjdp	    $$ = $1;
127538889Sjdp	    $$.version = $3;
127638889Sjdp	  }
127738889Sjdp	;
127838889Sjdp
127938889Sjdp/* Memory flags which default to MOVEABLE and DISCARDABLE.  */
128038889Sjdp
128138889Sjdpmemflags_move_discard:
128238889Sjdp	  /* empty */
128338889Sjdp	  {
128438889Sjdp	    memset (&$$, 0, sizeof (struct res_res_info));
128538889Sjdp	    $$.language = language;
128638889Sjdp	    $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_DISCARDABLE;
128738889Sjdp	  }
128838889Sjdp	| memflags_move_discard memflag
128938889Sjdp	  {
129038889Sjdp	    $$ = $1;
129138889Sjdp	    $$.memflags |= $2.on;
129238889Sjdp	    $$.memflags &=~ $2.off;
129338889Sjdp	  }
129438889Sjdp	;
129538889Sjdp
129638889Sjdp/* Memory flags which default to MOVEABLE.  */
129738889Sjdp
129838889Sjdpmemflags_move:
129938889Sjdp	  /* empty */
130038889Sjdp	  {
130138889Sjdp	    memset (&$$, 0, sizeof (struct res_res_info));
130238889Sjdp	    $$.language = language;
130338889Sjdp	    $$.memflags = MEMFLAG_MOVEABLE;
130438889Sjdp	  }
130538889Sjdp	| memflags_move_discard memflag
130638889Sjdp	  {
130738889Sjdp	    $$ = $1;
130838889Sjdp	    $$.memflags |= $2.on;
130938889Sjdp	    $$.memflags &=~ $2.off;
131038889Sjdp	  }
131138889Sjdp	;
131238889Sjdp
131338889Sjdp/* Memory flags.  This returns a struct with two integers, because we
131438889Sjdp   sometimes want to set bits and we sometimes want to clear them.  */
131538889Sjdp
131638889Sjdpmemflag:
131738889Sjdp	  MOVEABLE
131838889Sjdp	  {
131938889Sjdp	    $$.on = MEMFLAG_MOVEABLE;
132038889Sjdp	    $$.off = 0;
132138889Sjdp	  }
132238889Sjdp	| FIXED
132338889Sjdp	  {
132438889Sjdp	    $$.on = 0;
132538889Sjdp	    $$.off = MEMFLAG_MOVEABLE;
132638889Sjdp	  }
132738889Sjdp	| PURE
132838889Sjdp	  {
132938889Sjdp	    $$.on = MEMFLAG_PURE;
133038889Sjdp	    $$.off = 0;
133138889Sjdp	  }
133238889Sjdp	| IMPURE
133338889Sjdp	  {
133438889Sjdp	    $$.on = 0;
133538889Sjdp	    $$.off = MEMFLAG_PURE;
133638889Sjdp	  }
133738889Sjdp	| PRELOAD
133838889Sjdp	  {
133938889Sjdp	    $$.on = MEMFLAG_PRELOAD;
134038889Sjdp	    $$.off = 0;
134138889Sjdp	  }
134238889Sjdp	| LOADONCALL
134338889Sjdp	  {
134438889Sjdp	    $$.on = 0;
134538889Sjdp	    $$.off = MEMFLAG_PRELOAD;
134638889Sjdp	  }
134738889Sjdp	| DISCARDABLE
134838889Sjdp	  {
134938889Sjdp	    $$.on = MEMFLAG_DISCARDABLE;
135038889Sjdp	    $$.off = 0;
135138889Sjdp	  }
135238889Sjdp	;
135338889Sjdp
135438889Sjdp/* A file name.  */
135538889Sjdp
135638889Sjdpfile_name:
135738889Sjdp	  QUOTEDSTRING
135838889Sjdp	  {
135938889Sjdp	    $$ = $1;
136038889Sjdp	  }
136138889Sjdp	| STRING
136238889Sjdp	  {
136338889Sjdp	    $$ = $1;
136438889Sjdp	  }
136538889Sjdp	;
136638889Sjdp
136738889Sjdp/* A style expression.  This changes the static variable STYLE.  We do
136838889Sjdp   it this way because rc appears to permit a style to be set to
136938889Sjdp   something like
137038889Sjdp       WS_GROUP | NOT WS_TABSTOP
137138889Sjdp   to mean that a default of WS_TABSTOP should be removed.  Anything
137238889Sjdp   which wants to accept a style must first set STYLE to the default
137338889Sjdp   value.  The styleexpr nonterminal will change STYLE as specified by
137438889Sjdp   the user.  Note that we do not accept arbitrary expressions here,
137538889Sjdp   just numbers separated by '|'.  */
137638889Sjdp
137738889Sjdpstyleexpr:
137838889Sjdp	  parennumber
137938889Sjdp	  {
138038889Sjdp	    style |= $1;
138138889Sjdp	  }
138238889Sjdp	| NOT parennumber
138338889Sjdp	  {
138438889Sjdp	    style &=~ $2;
138538889Sjdp	  }
138638889Sjdp	| styleexpr '|' parennumber
138738889Sjdp	  {
138838889Sjdp	    style |= $3;
138938889Sjdp	  }
139038889Sjdp	| styleexpr '|' NOT parennumber
139138889Sjdp	  {
139238889Sjdp	    style &=~ $4;
139338889Sjdp	  }
139438889Sjdp	;
139538889Sjdp
139638889Sjdpparennumber:
139738889Sjdp	  NUMBER
139838889Sjdp	  {
139938889Sjdp	    $$ = $1.val;
140038889Sjdp	  }
140138889Sjdp	| '(' numexpr ')'
140238889Sjdp	  {
140338889Sjdp	    $$ = $2;
140438889Sjdp	  }
140538889Sjdp	;
140638889Sjdp
140738889Sjdp/* An optional expression with a leading comma.  */
140838889Sjdp
140938889Sjdpoptcnumexpr:
141038889Sjdp	  /* empty */
141138889Sjdp	  {
141238889Sjdp	    $$ = 0;
141338889Sjdp	  }
141438889Sjdp	| cnumexpr
141538889Sjdp	  {
141638889Sjdp	    $$ = $1;
141738889Sjdp	  }
141838889Sjdp	;
141938889Sjdp
142038889Sjdp/* An expression with a leading comma.  */
142138889Sjdp
142238889Sjdpcnumexpr:
142338889Sjdp	  ',' numexpr
142438889Sjdp	  {
142538889Sjdp	    $$ = $2;
142638889Sjdp	  }
142738889Sjdp	;
142838889Sjdp
142938889Sjdp/* A possibly negated numeric expression.  */
143038889Sjdp
143138889Sjdpnumexpr:
143238889Sjdp	  sizednumexpr
143338889Sjdp	  {
143438889Sjdp	    $$ = $1.val;
143538889Sjdp	  }
143638889Sjdp	;
143738889Sjdp
143838889Sjdp/* A possibly negated expression with a size.  */
143938889Sjdp
144038889Sjdpsizednumexpr:
144138889Sjdp	  NUMBER
144238889Sjdp	  {
144338889Sjdp	    $$ = $1;
144438889Sjdp	  }
144538889Sjdp	| '(' sizednumexpr ')'
144638889Sjdp	  {
144738889Sjdp	    $$ = $2;
144838889Sjdp	  }
144938889Sjdp	| '~' sizednumexpr %prec '~'
145038889Sjdp	  {
145138889Sjdp	    $$.val = ~ $2.val;
145238889Sjdp	    $$.dword = $2.dword;
145338889Sjdp	  }
145438889Sjdp	| '-' sizednumexpr %prec NEG
145538889Sjdp	  {
145638889Sjdp	    $$.val = - $2.val;
145738889Sjdp	    $$.dword = $2.dword;
145838889Sjdp	  }
145938889Sjdp	| sizednumexpr '*' sizednumexpr
146038889Sjdp	  {
146138889Sjdp	    $$.val = $1.val * $3.val;
146238889Sjdp	    $$.dword = $1.dword || $3.dword;
146338889Sjdp	  }
146438889Sjdp	| sizednumexpr '/' sizednumexpr
146538889Sjdp	  {
146638889Sjdp	    $$.val = $1.val / $3.val;
146738889Sjdp	    $$.dword = $1.dword || $3.dword;
146838889Sjdp	  }
146938889Sjdp	| sizednumexpr '%' sizednumexpr
147038889Sjdp	  {
147138889Sjdp	    $$.val = $1.val % $3.val;
147238889Sjdp	    $$.dword = $1.dword || $3.dword;
147338889Sjdp	  }
147438889Sjdp	| sizednumexpr '+' sizednumexpr
147538889Sjdp	  {
147638889Sjdp	    $$.val = $1.val + $3.val;
147738889Sjdp	    $$.dword = $1.dword || $3.dword;
147838889Sjdp	  }
147938889Sjdp	| sizednumexpr '-' sizednumexpr
148038889Sjdp	  {
148138889Sjdp	    $$.val = $1.val - $3.val;
148238889Sjdp	    $$.dword = $1.dword || $3.dword;
148338889Sjdp	  }
148438889Sjdp	| sizednumexpr '&' sizednumexpr
148538889Sjdp	  {
148638889Sjdp	    $$.val = $1.val & $3.val;
148738889Sjdp	    $$.dword = $1.dword || $3.dword;
148838889Sjdp	  }
148938889Sjdp	| sizednumexpr '^' sizednumexpr
149038889Sjdp	  {
149138889Sjdp	    $$.val = $1.val ^ $3.val;
149238889Sjdp	    $$.dword = $1.dword || $3.dword;
149338889Sjdp	  }
149438889Sjdp	| sizednumexpr '|' sizednumexpr
149538889Sjdp	  {
149638889Sjdp	    $$.val = $1.val | $3.val;
149738889Sjdp	    $$.dword = $1.dword || $3.dword;
149838889Sjdp	  }
149938889Sjdp	;
150038889Sjdp
150138889Sjdp/* An expression with a leading comma which does not use unary
150238889Sjdp   negation.  */
150338889Sjdp
150438889Sjdpcposnumexpr:
150538889Sjdp	  ',' posnumexpr
150638889Sjdp	  {
150738889Sjdp	    $$ = $2;
150838889Sjdp	  }
150938889Sjdp	;
151038889Sjdp
151138889Sjdp/* An expression which does not use unary negation.  */
151238889Sjdp
151338889Sjdpposnumexpr:
151438889Sjdp	  sizedposnumexpr
151538889Sjdp	  {
151638889Sjdp	    $$ = $1.val;
151738889Sjdp	  }
151838889Sjdp	;
151938889Sjdp
152038889Sjdp/* An expression which does not use unary negation.  We separate unary
152138889Sjdp   negation to avoid parsing conflicts when two numeric expressions
152238889Sjdp   appear consecutively.  */
152338889Sjdp
152438889Sjdpsizedposnumexpr:
152538889Sjdp	  NUMBER
152638889Sjdp	  {
152738889Sjdp	    $$ = $1;
152838889Sjdp	  }
152938889Sjdp	| '(' sizednumexpr ')'
153038889Sjdp	  {
153138889Sjdp	    $$ = $2;
153238889Sjdp	  }
153338889Sjdp	| '~' sizednumexpr %prec '~'
153438889Sjdp	  {
153538889Sjdp	    $$.val = ~ $2.val;
153638889Sjdp	    $$.dword = $2.dword;
153738889Sjdp	  }
153838889Sjdp	| sizedposnumexpr '*' sizednumexpr
153938889Sjdp	  {
154038889Sjdp	    $$.val = $1.val * $3.val;
154138889Sjdp	    $$.dword = $1.dword || $3.dword;
154238889Sjdp	  }
154338889Sjdp	| sizedposnumexpr '/' sizednumexpr
154438889Sjdp	  {
154538889Sjdp	    $$.val = $1.val / $3.val;
154638889Sjdp	    $$.dword = $1.dword || $3.dword;
154738889Sjdp	  }
154838889Sjdp	| sizedposnumexpr '%' sizednumexpr
154938889Sjdp	  {
155038889Sjdp	    $$.val = $1.val % $3.val;
155138889Sjdp	    $$.dword = $1.dword || $3.dword;
155238889Sjdp	  }
155338889Sjdp	| sizedposnumexpr '+' sizednumexpr
155438889Sjdp	  {
155538889Sjdp	    $$.val = $1.val + $3.val;
155638889Sjdp	    $$.dword = $1.dword || $3.dword;
155738889Sjdp	  }
155838889Sjdp	| sizedposnumexpr '-' sizednumexpr
155938889Sjdp	  {
156038889Sjdp	    $$.val = $1.val - $3.val;
156138889Sjdp	    $$.dword = $1.dword || $3.dword;
156238889Sjdp	  }
156338889Sjdp	| sizedposnumexpr '&' sizednumexpr
156438889Sjdp	  {
156538889Sjdp	    $$.val = $1.val & $3.val;
156638889Sjdp	    $$.dword = $1.dword || $3.dword;
156738889Sjdp	  }
156838889Sjdp	| sizedposnumexpr '^' sizednumexpr
156938889Sjdp	  {
157038889Sjdp	    $$.val = $1.val ^ $3.val;
157138889Sjdp	    $$.dword = $1.dword || $3.dword;
157238889Sjdp	  }
157338889Sjdp	| sizedposnumexpr '|' sizednumexpr
157438889Sjdp	  {
157538889Sjdp	    $$.val = $1.val | $3.val;
157638889Sjdp	    $$.dword = $1.dword || $3.dword;
157738889Sjdp	  }
157838889Sjdp	;
157938889Sjdp
158038889Sjdp%%
158138889Sjdp
158238889Sjdp/* Set the language from the command line.  */
158338889Sjdp
158438889Sjdpvoid
158538889Sjdprcparse_set_language (lang)
158638889Sjdp     int lang;
158738889Sjdp{
158838889Sjdp  language = lang;
158938889Sjdp}
1590