PageRenderTime 65ms CodeModel.GetById 45ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/binutils/rcparse.y

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