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