Home | History | Annotate | Line # | Download | only in binutils
rcparse.y revision 1.1
      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 (at) 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 
     37 static unsigned short language;
     38 
     39 /* The resource information during a sub statement.  */
     40 
     41 static rc_res_res_info sub_res_info;
     42 
     43 /* Dialog information.  This is built by the nonterminals styles and
     44    controls.  */
     45 
     46 static rc_dialog dialog;
     47 
     48 /* This is used when building a style.  It is modified by the
     49    nonterminal styleexpr.  */
     50 
     51 static unsigned long style;
     52 
     53 /* These are used when building a control.  They are set before using
     54    control_params.  */
     55 
     56 static rc_uint_type base_style;
     57 static rc_uint_type default_style;
     58 static rc_res_id class;
     59 static rc_res_id res_text_field;
     60 static unichar null_unichar;
     61 
     62 /* This is used for COMBOBOX, LISTBOX and EDITTEXT which
     63    do not allow resource 'text' field in control definition. */
     64 static 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 
    179 input:
    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 
    200 accelerator:
    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 
    210 acc_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 
    235 acc_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 
    252 acc_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 
    282 acc_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 
    298 acc_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 
    328 bitmap:
    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 
    340 cursor:
    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 
    352 dialog:
    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 
    435 exstyle:
    436 	  /* empty */
    437 	  {
    438 	    $$ = 0;
    439 	  }
    440 	| EXSTYLE '=' numexpr
    441 	  {
    442 	    $$ = $3;
    443 	  }
    444 	;
    445 
    446 styles:
    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 
    547 controls:
    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 
    559 control:
    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 
    873 control_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 
    907 cresid:
    908 	  ',' resid
    909 	  {
    910 	    if ($2.named)
    911 	      res_unistring_to_id (&$$, $2.u.n.name);
    912 	    else
    913 	      $$=$2;
    914 	  }
    915 	;
    916 
    917 optresidc:
    918 	  /* empty */
    919 	  {
    920 	    res_string_to_id (&$$, "");
    921 	  }
    922 	| resid ',' { $$=$1; }
    923 	;
    924 
    925 resid:
    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 
    939 opt_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 
    952 control_styleexpr:
    953 	  ','
    954 	  { style = WS_CHILD | WS_VISIBLE; }
    955 	  styleexpr
    956 	;
    957 
    958 icon_styleexpr:
    959 	  ','
    960 	  { style = SS_ICON | WS_CHILD | WS_VISIBLE; }
    961 	  styleexpr
    962 	;
    963 
    964 control_params_styleexpr:
    965 	  ','
    966 	  { style = base_style | WS_CHILD | WS_VISIBLE; }
    967 	  styleexpr
    968 	;
    969 
    970 /* Font resources.  */
    971 
    972 font:
    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 
    984 icon:
    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 
    997 language:
    998 	  LANGUAGE numexpr cnumexpr
    999 	  {
   1000 	    language = $2 | ($3 << SUBLANG_SHIFT);
   1001 	  }
   1002 	;
   1003 
   1004 /* Menu resources.  */
   1005 
   1006 menu:
   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 
   1016 menuitems:
   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 
   1037 menuitem:
   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 
   1052 menuitem_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 
   1067 menuitem_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 
   1096 menuex:
   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 
   1106 menuexitems:
   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 
   1127 menuexitem:
   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 
   1165 messagetable:
   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 
   1178 optrcdata_data:
   1179 	  {
   1180 	    rcparse_rcdata ();
   1181 	  }
   1182 	  optrcdata_data_int
   1183 	  {
   1184 	    rcparse_normal ();
   1185 	    $$ = $2;
   1186 	  }
   1187 	;
   1188 
   1189 optrcdata_data_int:
   1190 	  /* empty */
   1191 	  {
   1192 	    $$.first = NULL;
   1193 	    $$.last = NULL;
   1194 	  }
   1195 	| rcdata_data
   1196 	  {
   1197 	    $$ = $1;
   1198 	  }
   1199 	;
   1200 
   1201 rcdata_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 
   1261 stringtable:
   1262 	  STRINGTABLE suboptions BEG
   1263 	    { sub_res_info = $2; rcparse_rcdata (); }
   1264 	    string_data END { rcparse_normal (); }
   1265 	;
   1266 
   1267 string_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 
   1286 rcdata_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 
   1341 user:
   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 
   1358 toolbar:
   1359 	id TOOLBAR suboptions numexpr cnumexpr BEG toolbar_data END
   1360 	{
   1361 	  define_toolbar ($1, &$3, $4, $5, $7);
   1362 	}
   1363 	;
   1364 
   1365 toolbar_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 
   1409 versioninfo:
   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 
   1419 fixedverinfo:
   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 cnumexpr cnumexpr cnumexpr
   1427 	  {
   1428 	    $1->file_version_ms = ($3 << 16) | $4;
   1429 	    $1->file_version_ls = ($5 << 16) | $6;
   1430 	    $$ = $1;
   1431 	  }
   1432 	| fixedverinfo PRODUCTVERSION numexpr cnumexpr cnumexpr cnumexpr
   1433 	  {
   1434 	    $1->product_version_ms = ($3 << 16) | $4;
   1435 	    $1->product_version_ls = ($5 << 16) | $6;
   1436 	    $$ = $1;
   1437 	  }
   1438 	| fixedverinfo FILEFLAGSMASK numexpr
   1439 	  {
   1440 	    $1->file_flags_mask = $3;
   1441 	    $$ = $1;
   1442 	  }
   1443 	| fixedverinfo FILEFLAGS numexpr
   1444 	  {
   1445 	    $1->file_flags = $3;
   1446 	    $$ = $1;
   1447 	  }
   1448 	| fixedverinfo FILEOS numexpr
   1449 	  {
   1450 	    $1->file_os = $3;
   1451 	    $$ = $1;
   1452 	  }
   1453 	| fixedverinfo FILETYPE numexpr
   1454 	  {
   1455 	    $1->file_type = $3;
   1456 	    $$ = $1;
   1457 	  }
   1458 	| fixedverinfo FILESUBTYPE numexpr
   1459 	  {
   1460 	    $1->file_subtype = $3;
   1461 	    $$ = $1;
   1462 	  }
   1463 	;
   1464 
   1465 /* To handle verblocks successfully, the lexer handles BLOCK
   1466    specially.  A BLOCK "StringFileInfo" is returned as
   1467    BLOCKSTRINGFILEINFO.  A BLOCK "VarFileInfo" is returned as
   1468    BLOCKVARFILEINFO.  A BLOCK with some other string returns BLOCK
   1469    with the string as the value.  */
   1470 
   1471 verblocks:
   1472 	  /* empty */
   1473 	  {
   1474 	    $$ = NULL;
   1475 	  }
   1476 	| verblocks BLOCKSTRINGFILEINFO BEG verstringtables END
   1477 	  {
   1478 	    $$ = append_ver_stringfileinfo ($1, $4);
   1479 	  }
   1480 	| verblocks BLOCKVARFILEINFO BEG VALUE res_unicode_string_concat vertrans END
   1481 	  {
   1482 	    $$ = append_ver_varfileinfo ($1, $5, $6);
   1483 	  }
   1484 	;
   1485 
   1486 verstringtables:
   1487       /* empty */
   1488 	  {
   1489 	    $$ = NULL;
   1490 	  }
   1491 	| verstringtables BLOCK BEG vervals END
   1492 	  {
   1493 	    $$ = append_ver_stringtable ($1, $2, $4);
   1494 	  }
   1495 	;
   1496 
   1497 vervals:
   1498 	  /* empty */
   1499 	  {
   1500 	    $$ = NULL;
   1501 	  }
   1502 	| vervals VALUE res_unicode_string_concat ',' res_unicode_string_concat
   1503 	  {
   1504 	    $$ = append_verval ($1, $3, $5);
   1505 	  }
   1506 	;
   1507 
   1508 vertrans:
   1509 	  /* empty */
   1510 	  {
   1511 	    $$ = NULL;
   1512 	  }
   1513 	| vertrans cnumexpr cnumexpr
   1514 	  {
   1515 	    $$ = append_vertrans ($1, $2, $3);
   1516 	  }
   1517 	;
   1518 
   1519 /* A resource ID.  */
   1520 
   1521 id:
   1522 	  posnumexpr
   1523 	  {
   1524 	    $$.named = 0;
   1525 	    $$.u.id = $1;
   1526 	  }
   1527 	| resname
   1528 	  {
   1529 	    res_unistring_to_id (&$$, $1);
   1530 	  }
   1531 	;
   1532 
   1533 /* A resource reference.  */
   1534 
   1535 resname:
   1536 	  res_unicode_string
   1537 	  {
   1538 	    $$ = $1;
   1539 	  }
   1540 	| STRING
   1541 	  {
   1542 	    unichar *h = NULL;
   1543 	    unicode_from_ascii ((rc_uint_type *) NULL, &h, $1);
   1544 	    $$ = h;
   1545 	  }
   1546 	;
   1547 
   1548 
   1549 resref:
   1550 	  posnumexpr ','
   1551 	  {
   1552 	    $$.named = 0;
   1553 	    $$.u.id = $1;
   1554 	  }
   1555 	| resname
   1556 	  {
   1557 	    res_unistring_to_id (&$$, $1);
   1558 	  }
   1559 	| resname ','
   1560 	  {
   1561 	    res_unistring_to_id (&$$, $1);
   1562 	  }
   1563 	;
   1564 
   1565 /* Generic suboptions.  These may appear before the BEGIN in any
   1566    multiline statement.  */
   1567 
   1568 suboptions:
   1569 	  /* empty */
   1570 	  {
   1571 	    memset (&$$, 0, sizeof (rc_res_res_info));
   1572 	    $$.language = language;
   1573 	    /* FIXME: Is this the right default?  */
   1574 	    $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_PURE | MEMFLAG_DISCARDABLE;
   1575 	  }
   1576 	| suboptions memflag
   1577 	  {
   1578 	    $$ = $1;
   1579 	    $$.memflags |= $2.on;
   1580 	    $$.memflags &=~ $2.off;
   1581 	  }
   1582 	| suboptions CHARACTERISTICS numexpr
   1583 	  {
   1584 	    $$ = $1;
   1585 	    $$.characteristics = $3;
   1586 	  }
   1587 	| suboptions LANGUAGE numexpr cnumexpr
   1588 	  {
   1589 	    $$ = $1;
   1590 	    $$.language = $3 | ($4 << SUBLANG_SHIFT);
   1591 	  }
   1592 	| suboptions VERSIONK numexpr
   1593 	  {
   1594 	    $$ = $1;
   1595 	    $$.version = $3;
   1596 	  }
   1597 	;
   1598 
   1599 /* Memory flags which default to MOVEABLE and DISCARDABLE.  */
   1600 
   1601 memflags_move_discard:
   1602 	  /* empty */
   1603 	  {
   1604 	    memset (&$$, 0, sizeof (rc_res_res_info));
   1605 	    $$.language = language;
   1606 	    $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_DISCARDABLE;
   1607 	  }
   1608 	| memflags_move_discard memflag
   1609 	  {
   1610 	    $$ = $1;
   1611 	    $$.memflags |= $2.on;
   1612 	    $$.memflags &=~ $2.off;
   1613 	  }
   1614 	;
   1615 
   1616 /* Memory flags which default to MOVEABLE.  */
   1617 
   1618 memflags_move:
   1619 	  /* empty */
   1620 	  {
   1621 	    memset (&$$, 0, sizeof (rc_res_res_info));
   1622 	    $$.language = language;
   1623 	    $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_PURE | MEMFLAG_DISCARDABLE;
   1624 	  }
   1625 	| memflags_move memflag
   1626 	  {
   1627 	    $$ = $1;
   1628 	    $$.memflags |= $2.on;
   1629 	    $$.memflags &=~ $2.off;
   1630 	  }
   1631 	;
   1632 
   1633 /* Memory flags.  This returns a struct with two integers, because we
   1634    sometimes want to set bits and we sometimes want to clear them.  */
   1635 
   1636 memflag:
   1637 	  MOVEABLE
   1638 	  {
   1639 	    $$.on = MEMFLAG_MOVEABLE;
   1640 	    $$.off = 0;
   1641 	  }
   1642 	| FIXED
   1643 	  {
   1644 	    $$.on = 0;
   1645 	    $$.off = MEMFLAG_MOVEABLE;
   1646 	  }
   1647 	| PURE
   1648 	  {
   1649 	    $$.on = MEMFLAG_PURE;
   1650 	    $$.off = 0;
   1651 	  }
   1652 	| IMPURE
   1653 	  {
   1654 	    $$.on = 0;
   1655 	    $$.off = MEMFLAG_PURE;
   1656 	  }
   1657 	| PRELOAD
   1658 	  {
   1659 	    $$.on = MEMFLAG_PRELOAD;
   1660 	    $$.off = 0;
   1661 	  }
   1662 	| LOADONCALL
   1663 	  {
   1664 	    $$.on = 0;
   1665 	    $$.off = MEMFLAG_PRELOAD;
   1666 	  }
   1667 	| DISCARDABLE
   1668 	  {
   1669 	    $$.on = MEMFLAG_DISCARDABLE;
   1670 	    $$.off = 0;
   1671 	  }
   1672 	;
   1673 
   1674 /* A file name.  */
   1675 
   1676 file_name:
   1677 	  QUOTEDSTRING
   1678 	  {
   1679 	    $$ = $1;
   1680 	  }
   1681 	| STRING
   1682 	  {
   1683 	    $$ = $1;
   1684 	  }
   1685 	;
   1686 
   1687 /* Concat string */
   1688 res_unicode_string_concat:
   1689 	  res_unicode_string
   1690 	  {
   1691 	    $$ = $1;
   1692 	  }
   1693 	|
   1694 	  res_unicode_string_concat res_unicode_string
   1695 	  {
   1696 	    rc_uint_type l1 = unichar_len ($1);
   1697 	    rc_uint_type l2 = unichar_len ($2);
   1698 	    unichar *h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar));
   1699 	    if (l1 != 0)
   1700 	      memcpy (h, $1, l1 * sizeof (unichar));
   1701 	    if (l2 != 0)
   1702 	      memcpy (h + l1, $2, l2  * sizeof (unichar));
   1703 	    h[l1 + l2] = 0;
   1704 	    $$ = h;
   1705 	  }
   1706 	;
   1707 
   1708 res_unicode_string:
   1709 	  QUOTEDUNISTRING
   1710 	  {
   1711 	    $$ = unichar_dup ($1);
   1712 	  }
   1713 	| QUOTEDSTRING
   1714 	  {
   1715 	    unichar *h = NULL;
   1716 	    unicode_from_ascii ((rc_uint_type *) NULL, &h, $1);
   1717 	    $$ = h;
   1718 	  }
   1719 	;
   1720 
   1721 res_unicode_sizedstring:
   1722 	  sizedunistring
   1723 	  {
   1724 	    $$ = $1;
   1725 	  }
   1726 	| sizedstring
   1727 	  {
   1728 	    unichar *h = NULL;
   1729 	    rc_uint_type l = 0;
   1730 	    unicode_from_ascii_len (&l, &h, $1.s, $1.length);
   1731 	    $$.s = h;
   1732 	    $$.length = l;
   1733 	  }
   1734 	;
   1735 
   1736 /* Concat string */
   1737 res_unicode_sizedstring_concat:
   1738 	  res_unicode_sizedstring
   1739 	  {
   1740 	    $$ = $1;
   1741 	  }
   1742 	|
   1743 	  res_unicode_sizedstring_concat res_unicode_sizedstring
   1744 	  {
   1745 	    rc_uint_type l1 = $1.length;
   1746 	    rc_uint_type l2 = $2.length;
   1747 	    unichar *h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar));
   1748 	    if (l1 != 0)
   1749 	      memcpy (h, $1.s, l1 * sizeof (unichar));
   1750 	    if (l2 != 0)
   1751 	      memcpy (h + l1, $2.s, l2  * sizeof (unichar));
   1752 	    h[l1 + l2] = 0;
   1753 	    $$.length = l1 + l2;
   1754 	    $$.s = h;
   1755 	  }
   1756 	;
   1757 
   1758 sizedstring:
   1759 	  SIZEDSTRING
   1760 	  {
   1761 	    $$ = $1;
   1762 	  }
   1763 	| sizedstring SIZEDSTRING
   1764 	  {
   1765 	    rc_uint_type l = $1.length + $2.length;
   1766 	    char *h = (char *) res_alloc (l);
   1767 	    memcpy (h, $1.s, $1.length);
   1768 	    memcpy (h + $1.length, $2.s, $2.length);
   1769 	    $$.s = h;
   1770 	    $$.length = l;
   1771 	  }
   1772 	;
   1773 
   1774 sizedunistring:
   1775 	  SIZEDUNISTRING
   1776 	  {
   1777 	    $$ = $1;
   1778 	  }
   1779 	| sizedunistring SIZEDUNISTRING
   1780 	  {
   1781 	    rc_uint_type l = $1.length + $2.length;
   1782 	    unichar *h = (unichar *) res_alloc (l * sizeof (unichar));
   1783 	    memcpy (h, $1.s, $1.length * sizeof (unichar));
   1784 	    memcpy (h + $1.length, $2.s, $2.length  * sizeof (unichar));
   1785 	    $$.s = h;
   1786 	    $$.length = l;
   1787 	  }
   1788 	;
   1789 
   1790 /* A style expression.  This changes the static variable STYLE.  We do
   1791    it this way because rc appears to permit a style to be set to
   1792    something like
   1793        WS_GROUP | NOT WS_TABSTOP
   1794    to mean that a default of WS_TABSTOP should be removed.  Anything
   1795    which wants to accept a style must first set STYLE to the default
   1796    value.  The styleexpr nonterminal will change STYLE as specified by
   1797    the user.  Note that we do not accept arbitrary expressions here,
   1798    just numbers separated by '|'.  */
   1799 
   1800 styleexpr:
   1801 	  parennumber
   1802 	  {
   1803 	    style |= $1;
   1804 	  }
   1805 	| NOT parennumber
   1806 	  {
   1807 	    style &=~ $2;
   1808 	  }
   1809 	| styleexpr '|' parennumber
   1810 	  {
   1811 	    style |= $3;
   1812 	  }
   1813 	| styleexpr '|' NOT parennumber
   1814 	  {
   1815 	    style &=~ $4;
   1816 	  }
   1817 	;
   1818 
   1819 parennumber:
   1820 	  NUMBER
   1821 	  {
   1822 	    $$ = $1.val;
   1823 	  }
   1824 	| '(' numexpr ')'
   1825 	  {
   1826 	    $$ = $2;
   1827 	  }
   1828 	;
   1829 
   1830 /* An optional expression with a leading comma.  */
   1831 
   1832 optcnumexpr:
   1833 	  /* empty */
   1834 	  {
   1835 	    $$ = 0;
   1836 	  }
   1837 	| cnumexpr
   1838 	  {
   1839 	    $$ = $1;
   1840 	  }
   1841 	;
   1842 
   1843 /* An expression with a leading comma.  */
   1844 
   1845 cnumexpr:
   1846 	  ',' numexpr
   1847 	  {
   1848 	    $$ = $2;
   1849 	  }
   1850 	;
   1851 
   1852 /* A possibly negated numeric expression.  */
   1853 
   1854 numexpr:
   1855 	  sizednumexpr
   1856 	  {
   1857 	    $$ = $1.val;
   1858 	  }
   1859 	;
   1860 
   1861 /* A possibly negated expression with a size.  */
   1862 
   1863 sizednumexpr:
   1864 	  NUMBER
   1865 	  {
   1866 	    $$ = $1;
   1867 	  }
   1868 	| '(' sizednumexpr ')'
   1869 	  {
   1870 	    $$ = $2;
   1871 	  }
   1872 	| '~' sizednumexpr %prec '~'
   1873 	  {
   1874 	    $$.val = ~ $2.val;
   1875 	    $$.dword = $2.dword;
   1876 	  }
   1877 	| '-' sizednumexpr %prec NEG
   1878 	  {
   1879 	    $$.val = - $2.val;
   1880 	    $$.dword = $2.dword;
   1881 	  }
   1882 	| sizednumexpr '*' sizednumexpr
   1883 	  {
   1884 	    $$.val = $1.val * $3.val;
   1885 	    $$.dword = $1.dword || $3.dword;
   1886 	  }
   1887 	| sizednumexpr '/' sizednumexpr
   1888 	  {
   1889 	    $$.val = $1.val / $3.val;
   1890 	    $$.dword = $1.dword || $3.dword;
   1891 	  }
   1892 	| sizednumexpr '%' sizednumexpr
   1893 	  {
   1894 	    $$.val = $1.val % $3.val;
   1895 	    $$.dword = $1.dword || $3.dword;
   1896 	  }
   1897 	| sizednumexpr '+' sizednumexpr
   1898 	  {
   1899 	    $$.val = $1.val + $3.val;
   1900 	    $$.dword = $1.dword || $3.dword;
   1901 	  }
   1902 	| sizednumexpr '-' sizednumexpr
   1903 	  {
   1904 	    $$.val = $1.val - $3.val;
   1905 	    $$.dword = $1.dword || $3.dword;
   1906 	  }
   1907 	| sizednumexpr '&' sizednumexpr
   1908 	  {
   1909 	    $$.val = $1.val & $3.val;
   1910 	    $$.dword = $1.dword || $3.dword;
   1911 	  }
   1912 	| sizednumexpr '^' sizednumexpr
   1913 	  {
   1914 	    $$.val = $1.val ^ $3.val;
   1915 	    $$.dword = $1.dword || $3.dword;
   1916 	  }
   1917 	| sizednumexpr '|' sizednumexpr
   1918 	  {
   1919 	    $$.val = $1.val | $3.val;
   1920 	    $$.dword = $1.dword || $3.dword;
   1921 	  }
   1922 	;
   1923 
   1924 /* An expression with a leading comma which does not use unary
   1925    negation.  */
   1926 
   1927 cposnumexpr:
   1928 	  ',' posnumexpr
   1929 	  {
   1930 	    $$ = $2;
   1931 	  }
   1932 	;
   1933 
   1934 /* An expression which does not use unary negation.  */
   1935 
   1936 posnumexpr:
   1937 	  sizedposnumexpr
   1938 	  {
   1939 	    $$ = $1.val;
   1940 	  }
   1941 	;
   1942 
   1943 /* An expression which does not use unary negation.  We separate unary
   1944    negation to avoid parsing conflicts when two numeric expressions
   1945    appear consecutively.  */
   1946 
   1947 sizedposnumexpr:
   1948 	  NUMBER
   1949 	  {
   1950 	    $$ = $1;
   1951 	  }
   1952 	| '(' sizednumexpr ')'
   1953 	  {
   1954 	    $$ = $2;
   1955 	  }
   1956 	| '~' sizednumexpr %prec '~'
   1957 	  {
   1958 	    $$.val = ~ $2.val;
   1959 	    $$.dword = $2.dword;
   1960 	  }
   1961 	| sizedposnumexpr '*' sizednumexpr
   1962 	  {
   1963 	    $$.val = $1.val * $3.val;
   1964 	    $$.dword = $1.dword || $3.dword;
   1965 	  }
   1966 	| sizedposnumexpr '/' sizednumexpr
   1967 	  {
   1968 	    $$.val = $1.val / $3.val;
   1969 	    $$.dword = $1.dword || $3.dword;
   1970 	  }
   1971 	| sizedposnumexpr '%' sizednumexpr
   1972 	  {
   1973 	    $$.val = $1.val % $3.val;
   1974 	    $$.dword = $1.dword || $3.dword;
   1975 	  }
   1976 	| sizedposnumexpr '+' sizednumexpr
   1977 	  {
   1978 	    $$.val = $1.val + $3.val;
   1979 	    $$.dword = $1.dword || $3.dword;
   1980 	  }
   1981 	| sizedposnumexpr '-' sizednumexpr
   1982 	  {
   1983 	    $$.val = $1.val - $3.val;
   1984 	    $$.dword = $1.dword || $3.dword;
   1985 	  }
   1986 	| sizedposnumexpr '&' sizednumexpr
   1987 	  {
   1988 	    $$.val = $1.val & $3.val;
   1989 	    $$.dword = $1.dword || $3.dword;
   1990 	  }
   1991 	| sizedposnumexpr '^' sizednumexpr
   1992 	  {
   1993 	    $$.val = $1.val ^ $3.val;
   1994 	    $$.dword = $1.dword || $3.dword;
   1995 	  }
   1996 	| sizedposnumexpr '|' sizednumexpr
   1997 	  {
   1998 	    $$.val = $1.val | $3.val;
   1999 	    $$.dword = $1.dword || $3.dword;
   2000 	  }
   2001 	;
   2002 
   2003 %%
   2004 
   2005 /* Set the language from the command line.  */
   2006 
   2007 void
   2008 rcparse_set_language (int lang)
   2009 {
   2010   language = lang;
   2011 }
   2012