gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / binutils / rcparse.y
index f2378c031594695d4b802f92600cb97d167b4e66..78ce917e233c5efdba82c409e2d913c949bba531 100644 (file)
@@ -1,12 +1,13 @@
 %{ /* rcparse.y -- parser for Windows rc files
 %{ /* rcparse.y -- parser for Windows rc files
-   Copyright 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997-2020 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support.
    Written by Ian Lance Taylor, Cygnus Support.
+   Extended by Kai Tietz, Onevision.
 
    This file is part of GNU Binutils.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
    This file is part of GNU Binutils.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
 
 /* This is a parser for Windows rc files.  It is based on the parser
    by Gunther Ebert <gunther.ebert@ixos-leipzig.de>.  */
 
 
 /* This is a parser for Windows rc files.  It is based on the parser
    by Gunther Ebert <gunther.ebert@ixos-leipzig.de>.  */
 
+#include "sysdep.h"
 #include "bfd.h"
 #include "bucomm.h"
 #include "libiberty.h"
 #include "windres.h"
 #include "bfd.h"
 #include "bucomm.h"
 #include "libiberty.h"
 #include "windres.h"
-
-#include <ctype.h>
+#include "safe-ctype.h"
 
 /* The current language.  */
 
 
 /* The current language.  */
 
@@ -35,12 +37,12 @@ static unsigned short language;
 
 /* The resource information during a sub statement.  */
 
 
 /* The resource information during a sub statement.  */
 
-static struct res_res_info sub_res_info;
+static rc_res_res_info sub_res_info;
 
 /* Dialog information.  This is built by the nonterminals styles and
    controls.  */
 
 
 /* Dialog information.  This is built by the nonterminals styles and
    controls.  */
 
-static struct dialog dialog;
+static rc_dialog dialog;
 
 /* This is used when building a style.  It is modified by the
    nonterminal styleexpr.  */
 
 /* This is used when building a style.  It is modified by the
    nonterminal styleexpr.  */
@@ -50,50 +52,63 @@ static unsigned long style;
 /* These are used when building a control.  They are set before using
    control_params.  */
 
 /* These are used when building a control.  They are set before using
    control_params.  */
 
-static unsigned long base_style;
-static unsigned long default_style;
-static unsigned long class;
+static rc_uint_type base_style;
+static rc_uint_type default_style;
+static rc_res_id class;
+static rc_res_id res_text_field;
+static unichar null_unichar;
+
+/* This is used for COMBOBOX, LISTBOX and EDITTEXT which
+   do not allow resource 'text' field in control definition. */
+static const rc_res_id res_null_text = { 1, {{0, &null_unichar}}};
 
 %}
 
 %union
 {
 
 %}
 
 %union
 {
-  struct accelerator acc;
-  struct accelerator *pacc;
-  struct dialog_control *dialog_control;
-  struct menuitem *menuitem;
+  rc_accelerator acc;
+  rc_accelerator *pacc;
+  rc_dialog_control *dialog_control;
+  rc_menuitem *menuitem;
   struct
   {
   struct
   {
-    struct rcdata_item *first;
-    struct rcdata_item *last;
+    rc_rcdata_item *first;
+    rc_rcdata_item *last;
   } rcdata;
   } rcdata;
-  struct rcdata_item *rcdata_item;
-  struct stringtable_data *stringtable;
-  struct fixed_versioninfo *fixver;
-  struct ver_info *verinfo;
-  struct ver_stringinfo *verstring;
-  struct ver_varinfo *vervar;
-  struct res_id id;
-  struct res_res_info res_info;
+  rc_rcdata_item *rcdata_item;
+  rc_fixed_versioninfo *fixver;
+  rc_ver_info *verinfo;
+  rc_ver_stringtable *verstringtable;
+  rc_ver_stringinfo *verstring;
+  rc_ver_varinfo *vervar;
+  rc_toolbar_item *toobar_item;
+  rc_res_id id;
+  rc_res_res_info res_info;
   struct
   {
   struct
   {
-    unsigned short on;
-    unsigned short off;
+    rc_uint_type on;
+    rc_uint_type off;
   } memflags;
   struct
   {
   } memflags;
   struct
   {
-    unsigned long val;
+    rc_uint_type val;
     /* Nonzero if this number was explicitly specified as long.  */
     int dword;
   } i;
     /* Nonzero if this number was explicitly specified as long.  */
     int dword;
   } i;
-  unsigned long il;
-  unsigned short is;
+  rc_uint_type il;
+  rc_uint_type is;
   const char *s;
   struct
   {
   const char *s;
   struct
   {
-    unsigned long length;
+    rc_uint_type length;
     const char *s;
   } ss;
     const char *s;
   } ss;
+  unichar *uni;
+  struct
+  {
+    rc_uint_type length;
+    const unichar *s;
+  } suni;
 };
 
 %token BEG END
 };
 
 %token BEG END
@@ -107,6 +122,7 @@ static unsigned long class;
 %token BEDIT HEDIT IEDIT
 %token FONT
 %token ICON
 %token BEDIT HEDIT IEDIT
 %token FONT
 %token ICON
+%token ANICURSOR ANIICON DLGINCLUDE DLGINIT FONTDIR HTML MANIFEST PLUGPLAY VXD TOOLBAR BUTTON
 %token LANGUAGE CHARACTERISTICS VERSIONK
 %token MENU MENUEX MENUITEM SEPARATOR POPUP CHECKED GRAYED HELP INACTIVE
 %token MENUBARBREAK MENUBREAK
 %token LANGUAGE CHARACTERISTICS VERSIONK
 %token MENU MENUEX MENUITEM SEPARATOR POPUP CHECKED GRAYED HELP INACTIVE
 %token MENUBARBREAK MENUBREAK
@@ -119,8 +135,10 @@ static unsigned long class;
 %token <s> BLOCK
 %token MOVEABLE FIXED PURE IMPURE PRELOAD LOADONCALL DISCARDABLE
 %token NOT
 %token <s> BLOCK
 %token MOVEABLE FIXED PURE IMPURE PRELOAD LOADONCALL DISCARDABLE
 %token NOT
+%token <uni> QUOTEDUNISTRING
 %token <s> QUOTEDSTRING STRING
 %token <i> NUMBER
 %token <s> QUOTEDSTRING STRING
 %token <i> NUMBER
+%token <suni> SIZEDUNISTRING
 %token <ss> SIZEDSTRING
 %token IGNORED_TOKEN
 
 %token <ss> SIZEDSTRING
 %token IGNORED_TOKEN
 
@@ -132,15 +150,20 @@ static unsigned long class;
 %type <rcdata_item> opt_control_data
 %type <fixver> fixedverinfo
 %type <verinfo> verblocks
 %type <rcdata_item> opt_control_data
 %type <fixver> fixedverinfo
 %type <verinfo> verblocks
+%type <verstringtable> verstringtables
 %type <verstring> vervals
 %type <vervar> vertrans
 %type <verstring> vervals
 %type <vervar> vertrans
+%type <toobar_item> toolbar_data
 %type <res_info> suboptions memflags_move_discard memflags_move
 %type <memflags> memflag
 %type <res_info> suboptions memflags_move_discard memflags_move
 %type <memflags> memflag
-%type <id> id resref
+%type <id> id rcdata_id optresidc resref resid cresid
 %type <il> exstyle parennumber
 %type <il> numexpr posnumexpr cnumexpr optcnumexpr cposnumexpr
 %type <is> acc_options acc_option menuitem_flags menuitem_flag
 %type <il> exstyle parennumber
 %type <il> numexpr posnumexpr cnumexpr optcnumexpr cposnumexpr
 %type <is> acc_options acc_option menuitem_flags menuitem_flag
-%type <s> optstringc file_name resname
+%type <s> file_name
+%type <uni> res_unicode_string resname res_unicode_string_concat
+%type <ss> sizedstring
+%type <suni> sizedunistring res_unicode_sizedstring res_unicode_sizedstring_concat
 %type <i> sizednumexpr sizedposnumexpr
 
 %left '|'
 %type <i> sizednumexpr sizedposnumexpr
 
 %left '|'
@@ -154,28 +177,21 @@ static unsigned long class;
 
 input:
          /* empty */
 
 input:
          /* empty */
-       | input newcmd accelerator
-       | input newcmd bitmap
-       | input newcmd cursor
-       | input newcmd dialog
-       | input newcmd font
-       | input newcmd icon
-       | input newcmd language
-       | input newcmd menu
-       | input newcmd menuex
-       | input newcmd messagetable
-       | input newcmd rcdata
-       | input newcmd stringtable
-       | input newcmd user
-       | input newcmd versioninfo
-       | input newcmd IGNORED_TOKEN
-       ;
-
-newcmd:
-         /* empty */
-         {
-           rcparse_discard_strings ();
-         }
+       | input accelerator
+       | input bitmap
+       | input cursor
+       | input dialog
+       | input font
+       | input icon
+       | input language
+       | input menu
+       | input menuex
+       | input messagetable
+       | input stringtable
+       | input toolbar
+       | input user
+       | input versioninfo
+       | input IGNORED_TOKEN
        ;
 
 /* Accelerator resources.  */
        ;
 
 /* Accelerator resources.  */
@@ -184,6 +200,9 @@ accelerator:
          id ACCELERATORS suboptions BEG acc_entries END
          {
            define_accelerator ($1, &$3, $5);
          id ACCELERATORS suboptions BEG acc_entries END
          {
            define_accelerator ($1, &$3, $5);
+           if (yychar != YYEMPTY)
+             YYERROR;
+           rcparse_discard_strings ();
          }
        ;
 
          }
        ;
 
@@ -194,15 +213,15 @@ acc_entries:
          }
        | acc_entries acc_entry
          {
          }
        | acc_entries acc_entry
          {
-           struct accelerator *a;
+           rc_accelerator *a;
 
 
-           a = (struct accelerator *) res_alloc (sizeof *a);
+           a = (rc_accelerator *) res_alloc (sizeof *a);
            *a = $2;
            if ($1 == NULL)
              $$ = a;
            else
              {
            *a = $2;
            if ($1 == NULL)
              $$ = a;
            else
              {
-               struct accelerator **pp;
+               rc_accelerator **pp;
 
                for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
                  ;
 
                for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
                  ;
@@ -224,7 +243,7 @@ acc_entry:
            $$.id = $2;
            $$.flags |= $4;
            if (($$.flags & ACC_VIRTKEY) == 0
            $$.id = $2;
            $$.flags |= $4;
            if (($$.flags & ACC_VIRTKEY) == 0
-               && ($$.flags & (ACC_SHIFT | ACC_CONTROL | ACC_ALT)) != 0)
+               && ($$.flags & (ACC_SHIFT | ACC_CONTROL)) != 0)
              rcparse_warning (_("inappropriate modifiers for non-VIRTKEY"));
          }
        ;
              rcparse_warning (_("inappropriate modifiers for non-VIRTKEY"));
          }
        ;
@@ -244,8 +263,7 @@ acc_event:
              {
                $$.flags = ACC_CONTROL | ACC_VIRTKEY;
                ++s;
              {
                $$.flags = ACC_CONTROL | ACC_VIRTKEY;
                ++s;
-               ch = *s;
-               ch = toupper ((unsigned char) ch);
+               ch = TOUPPER (s[0]);
              }
            $$.key = ch;
            if (s[1] != '\0')
              }
            $$.key = ch;
            if (s[1] != '\0')
@@ -310,6 +328,9 @@ bitmap:
          id BITMAP memflags_move file_name
          {
            define_bitmap ($1, &$3, $4);
          id BITMAP memflags_move file_name
          {
            define_bitmap ($1, &$3, $4);
+           if (yychar != YYEMPTY)
+             YYERROR;
+           rcparse_discard_strings ();
          }
        ;
 
          }
        ;
 
@@ -319,6 +340,9 @@ cursor:
          id CURSOR memflags_move_discard file_name
          {
            define_cursor ($1, &$3, $4);
          id CURSOR memflags_move_discard file_name
          {
            define_cursor ($1, &$3, $4);
+           if (yychar != YYEMPTY)
+             YYERROR;
+           rcparse_discard_strings ();
          }
        ;
 
          }
        ;
 
@@ -341,10 +365,14 @@ dialog:
              dialog.ex = NULL;
              dialog.controls = NULL;
              sub_res_info = $3;
              dialog.ex = NULL;
              dialog.controls = NULL;
              sub_res_info = $3;
+             style = 0;
            }
            styles BEG controls END
          {
            define_dialog ($1, &sub_res_info, &dialog);
            }
            styles BEG controls END
          {
            define_dialog ($1, &sub_res_info, &dialog);
+           if (yychar != YYEMPTY)
+             YYERROR;
+           rcparse_discard_strings ();
          }
        | id DIALOGEX memflags_move exstyle posnumexpr cnumexpr cnumexpr
            cnumexpr
          }
        | id DIALOGEX memflags_move exstyle posnumexpr cnumexpr cnumexpr
            cnumexpr
@@ -359,15 +387,19 @@ dialog:
              dialog.menu.named = 1;
              dialog.class.named = 1;
              dialog.font = NULL;
              dialog.menu.named = 1;
              dialog.class.named = 1;
              dialog.font = NULL;
-             dialog.ex = ((struct dialog_ex *)
-                          res_alloc (sizeof (struct dialog_ex)));
-             memset (dialog.ex, 0, sizeof (struct dialog_ex));
+             dialog.ex = ((rc_dialog_ex *)
+                          res_alloc (sizeof (rc_dialog_ex)));
+             memset (dialog.ex, 0, sizeof (rc_dialog_ex));
              dialog.controls = NULL;
              sub_res_info = $3;
              dialog.controls = NULL;
              sub_res_info = $3;
+             style = 0;
            }
            styles BEG controls END
          {
            define_dialog ($1, &sub_res_info, &dialog);
            }
            styles BEG controls END
          {
            define_dialog ($1, &sub_res_info, &dialog);
+           if (yychar != YYEMPTY)
+             YYERROR;
+           rcparse_discard_strings ();
          }
        | id DIALOGEX memflags_move exstyle posnumexpr cnumexpr cnumexpr
            cnumexpr cnumexpr
          }
        | id DIALOGEX memflags_move exstyle posnumexpr cnumexpr cnumexpr
            cnumexpr cnumexpr
@@ -382,16 +414,20 @@ dialog:
              dialog.menu.named = 1;
              dialog.class.named = 1;
              dialog.font = NULL;
              dialog.menu.named = 1;
              dialog.class.named = 1;
              dialog.font = NULL;
-             dialog.ex = ((struct dialog_ex *)
-                          res_alloc (sizeof (struct dialog_ex)));
-             memset (dialog.ex, 0, sizeof (struct dialog_ex));
+             dialog.ex = ((rc_dialog_ex *)
+                          res_alloc (sizeof (rc_dialog_ex)));
+             memset (dialog.ex, 0, sizeof (rc_dialog_ex));
              dialog.ex->help = $9;
              dialog.controls = NULL;
              sub_res_info = $3;
              dialog.ex->help = $9;
              dialog.controls = NULL;
              sub_res_info = $3;
+             style = 0;
            }
            styles BEG controls END
          {
            define_dialog ($1, &sub_res_info, &dialog);
            }
            styles BEG controls END
          {
            define_dialog ($1, &sub_res_info, &dialog);
+           if (yychar != YYEMPTY)
+             YYERROR;
+           rcparse_discard_strings ();
          }
        ;
 
          }
        ;
 
@@ -408,16 +444,17 @@ exstyle:
 
 styles:
          /* empty */
 
 styles:
          /* empty */
-       | styles CAPTION QUOTEDSTRING
+       | styles CAPTION res_unicode_string_concat
          {
          {
-           unicode_from_ascii ((int *) NULL, &dialog.caption, $3);
+           dialog.style |= WS_CAPTION;
+           style |= WS_CAPTION;
+           dialog.caption = $3;
          }
        | styles CLASS id
          {
            dialog.class = $3;
          }
        | styles STYLE
          }
        | styles CLASS id
          {
            dialog.class = $3;
          }
        | styles STYLE
-           { style = dialog.style; }
            styleexpr
          {
            dialog.style = style;
            styleexpr
          {
            dialog.style = style;
@@ -426,23 +463,66 @@ styles:
          {
            dialog.exstyle = $3;
          }
          {
            dialog.exstyle = $3;
          }
-       | styles FONT numexpr ',' QUOTEDSTRING
+       | styles CLASS res_unicode_string_concat
+         {
+           res_unistring_to_id (& dialog.class, $3);
+         }
+       | styles FONT numexpr ',' res_unicode_string_concat
          {
            dialog.style |= DS_SETFONT;
          {
            dialog.style |= DS_SETFONT;
+           style |= DS_SETFONT;
            dialog.pointsize = $3;
            dialog.pointsize = $3;
-           unicode_from_ascii ((int *) NULL, &dialog.font, $5);
+           dialog.font = $5;
+           if (dialog.ex != NULL)
+             {
+               dialog.ex->weight = 0;
+               dialog.ex->italic = 0;
+               dialog.ex->charset = 1;
+             }
          }
          }
-       | styles FONT numexpr ',' QUOTEDSTRING cnumexpr cnumexpr
+       | styles FONT numexpr ',' res_unicode_string_concat cnumexpr
          {
            dialog.style |= DS_SETFONT;
          {
            dialog.style |= DS_SETFONT;
+           style |= DS_SETFONT;
            dialog.pointsize = $3;
            dialog.pointsize = $3;
-           unicode_from_ascii ((int *) NULL, &dialog.font, $5);
+           dialog.font = $5;
+           if (dialog.ex == NULL)
+             rcparse_warning (_("extended FONT requires DIALOGEX"));
+           else
+             {
+               dialog.ex->weight = $6;
+               dialog.ex->italic = 0;
+               dialog.ex->charset = 1;
+             }
+         }
+       | styles FONT numexpr ',' res_unicode_string_concat cnumexpr cnumexpr
+         {
+           dialog.style |= DS_SETFONT;
+           style |= DS_SETFONT;
+           dialog.pointsize = $3;
+           dialog.font = $5;
+           if (dialog.ex == NULL)
+             rcparse_warning (_("extended FONT requires DIALOGEX"));
+           else
+             {
+               dialog.ex->weight = $6;
+               dialog.ex->italic = $7;
+               dialog.ex->charset = 1;
+             }
+         }
+       | styles FONT numexpr ',' res_unicode_string_concat cnumexpr cnumexpr cnumexpr
+         {
+           dialog.style |= DS_SETFONT;
+           style |= DS_SETFONT;
+           dialog.pointsize = $3;
+           dialog.font = $5;
            if (dialog.ex == NULL)
              rcparse_warning (_("extended FONT requires DIALOGEX"));
            else
              {
                dialog.ex->weight = $6;
                dialog.ex->italic = $7;
            if (dialog.ex == NULL)
              rcparse_warning (_("extended FONT requires DIALOGEX"));
            else
              {
                dialog.ex->weight = $6;
                dialog.ex->italic = $7;
+               dialog.ex->charset = $8;
              }
          }
        | styles MENU id
              }
          }
        | styles MENU id
@@ -467,7 +547,7 @@ controls:
          /* empty */
        | controls control
          {
          /* empty */
        | controls control
          {
-           struct dialog_control **pp;
+           rc_dialog_control **pp;
 
            for (pp = &dialog.controls; *pp != NULL; pp = &(*pp)->next)
              ;
 
            for (pp = &dialog.controls; *pp != NULL; pp = &(*pp)->next)
              ;
@@ -476,70 +556,84 @@ controls:
        ;
 
 control:
        ;
 
 control:
-         AUTO3STATE
+         AUTO3STATE optresidc
            {
              default_style = BS_AUTO3STATE | WS_TABSTOP;
              base_style = BS_AUTO3STATE;
            {
              default_style = BS_AUTO3STATE | WS_TABSTOP;
              base_style = BS_AUTO3STATE;
-             class = CTL_BUTTON;
+             class.named = 0;
+             class.u.id = CTL_BUTTON;
+             res_text_field = $2;
            }
            control_params
          {
            }
            control_params
          {
-           $$ = $3;
+           $$ = $4;
          }
          }
-       | AUTOCHECKBOX
+       | AUTOCHECKBOX optresidc
            {
              default_style = BS_AUTOCHECKBOX | WS_TABSTOP;
              base_style = BS_AUTOCHECKBOX;
            {
              default_style = BS_AUTOCHECKBOX | WS_TABSTOP;
              base_style = BS_AUTOCHECKBOX;
-             class = CTL_BUTTON;
+             class.named = 0;
+             class.u.id = CTL_BUTTON;
+             res_text_field = $2;
            }
            control_params
          {
            }
            control_params
          {
-           $$ = $3;
+           $$ = $4;
          }
          }
-       | AUTORADIOBUTTON
+       | AUTORADIOBUTTON optresidc
            {
              default_style = BS_AUTORADIOBUTTON | WS_TABSTOP;
              base_style = BS_AUTORADIOBUTTON;
            {
              default_style = BS_AUTORADIOBUTTON | WS_TABSTOP;
              base_style = BS_AUTORADIOBUTTON;
-             class = CTL_BUTTON;
+             class.named = 0;
+             class.u.id = CTL_BUTTON;
+             res_text_field = $2;
            }
            control_params
          {
            }
            control_params
          {
-           $$ = $3;
+           $$ = $4;
          }
          }
-       | BEDIT
+       | BEDIT optresidc
            {
              default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
              base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
            {
              default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
              base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
-             class = CTL_EDIT;
+             class.named = 0;
+             class.u.id = CTL_EDIT;
+             res_text_field = $2;
            }
            control_params
          {
            }
            control_params
          {
-           $$ = $3;
+           $$ = $4;
            if (dialog.ex == NULL)
            if (dialog.ex == NULL)
-             rcparse_warning (_("IEDIT requires DIALOGEX"));
+             rcparse_warning (_("BEDIT requires DIALOGEX"));
            res_string_to_id (&$$->class, "BEDIT");
          }
            res_string_to_id (&$$->class, "BEDIT");
          }
-       | CHECKBOX
+       | CHECKBOX optresidc
            {
              default_style = BS_CHECKBOX | WS_TABSTOP;
              base_style = BS_CHECKBOX | WS_TABSTOP;
            {
              default_style = BS_CHECKBOX | WS_TABSTOP;
              base_style = BS_CHECKBOX | WS_TABSTOP;
-             class = CTL_BUTTON;
+             class.named = 0;
+             class.u.id = CTL_BUTTON;
+             res_text_field = $2;
            }
            control_params
          {
            }
            control_params
          {
-           $$ = $3;
+           $$ = $4;
          }
        | COMBOBOX
            {
          }
        | COMBOBOX
            {
+             /* This is as per MSDN documentation.  With some (???)
+                versions of MS rc.exe their is no default style.  */
              default_style = CBS_SIMPLE | WS_TABSTOP;
              base_style = 0;
              default_style = CBS_SIMPLE | WS_TABSTOP;
              base_style = 0;
-             class = CTL_COMBOBOX;
+             class.named = 0;
+             class.u.id = CTL_COMBOBOX;
+             res_text_field = res_null_text;
            }
            control_params
          {
            $$ = $3;
          }
            }
            control_params
          {
            $$ = $3;
          }
-       | CONTROL optstringc numexpr cnumexpr control_styleexpr cnumexpr
+       | CONTROL optresidc numexpr cresid control_styleexpr cnumexpr
            cnumexpr cnumexpr cnumexpr optcnumexpr opt_control_data
          {
            $$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10);
            cnumexpr cnumexpr cnumexpr optcnumexpr opt_control_data
          {
            $$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10);
@@ -550,7 +644,7 @@ control:
                $$->data = $11;
              }
          }
                $$->data = $11;
              }
          }
-       | CONTROL optstringc numexpr cnumexpr control_styleexpr cnumexpr
+       | CONTROL optresidc numexpr cresid control_styleexpr cnumexpr
            cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data
          {
            $$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10);
            cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data
          {
            $$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10);
@@ -559,79 +653,65 @@ control:
            $$->help = $11;
            $$->data = $12;
          }
            $$->help = $11;
            $$->data = $12;
          }
-       | CONTROL optstringc numexpr ',' QUOTEDSTRING control_styleexpr
-           cnumexpr cnumexpr cnumexpr cnumexpr optcnumexpr opt_control_data
-         {
-           $$ = define_control ($2, $3, $7, $8, $9, $10, 0, style, $11);
-           if ($12 != NULL)
-             {
-               if (dialog.ex == NULL)
-                 rcparse_warning ("control data requires DIALOGEX");
-               $$->data = $12;
-             }
-           $$->class.named = 1;
-           unicode_from_ascii(&$$->class.u.n.length, &$$->class.u.n.name, $5);
-         }
-       | CONTROL optstringc numexpr ',' QUOTEDSTRING control_styleexpr
-           cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data
-         {
-           $$ = define_control ($2, $3, $7, $8, $9, $10, 0, style, $11);
-           if (dialog.ex == NULL)
-             rcparse_warning ("help ID requires DIALOGEX");
-           $$->help = $12;
-           $$->data = $13;
-           $$->class.named = 1;
-           unicode_from_ascii(&$$->class.u.n.length, &$$->class.u.n.name, $5);
-         }
-       | CTEXT
+       | CTEXT optresidc
            {
              default_style = SS_CENTER | WS_GROUP;
              base_style = SS_CENTER;
            {
              default_style = SS_CENTER | WS_GROUP;
              base_style = SS_CENTER;
-             class = CTL_STATIC;
+             class.named = 0;
+             class.u.id = CTL_STATIC;
+             res_text_field = $2;
            }
            control_params
          {
            }
            control_params
          {
-           $$ = $3;
+           $$ = $4;
          }
          }
-       | DEFPUSHBUTTON
+       | DEFPUSHBUTTON optresidc
            {
              default_style = BS_DEFPUSHBUTTON | WS_TABSTOP;
              base_style = BS_DEFPUSHBUTTON | WS_TABSTOP;
            {
              default_style = BS_DEFPUSHBUTTON | WS_TABSTOP;
              base_style = BS_DEFPUSHBUTTON | WS_TABSTOP;
-             class = CTL_BUTTON;
+             class.named = 0;
+             class.u.id = CTL_BUTTON;
+             res_text_field = $2;
            }
            control_params
          {
            }
            control_params
          {
-           $$ = $3;
+           $$ = $4;
          }
        | EDITTEXT
            {
              default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
              base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
          }
        | EDITTEXT
            {
              default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
              base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
-             class = CTL_EDIT;
+             class.named = 0;
+             class.u.id = CTL_EDIT;
+             res_text_field = res_null_text;
            }
            control_params
          {
            $$ = $3;
          }
            }
            control_params
          {
            $$ = $3;
          }
-       | GROUPBOX
+       | GROUPBOX optresidc
            {
              default_style = BS_GROUPBOX;
              base_style = BS_GROUPBOX;
            {
              default_style = BS_GROUPBOX;
              base_style = BS_GROUPBOX;
-             class = CTL_BUTTON;
+             class.named = 0;
+             class.u.id = CTL_BUTTON;
+             res_text_field = $2;
            }
            control_params
          {
            }
            control_params
          {
-           $$ = $3;
+           $$ = $4;
          }
          }
-       | HEDIT
+       | HEDIT optresidc
            {
              default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
              base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
            {
              default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
              base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
-             class = CTL_EDIT;
+             class.named = 0;
+             class.u.id = CTL_EDIT;
+             res_text_field = $2;
            }
            control_params
          {
            }
            control_params
          {
-           $$ = $3;
+           $$ = $4;
            if (dialog.ex == NULL)
              rcparse_warning (_("IEDIT requires DIALOGEX"));
            res_string_to_id (&$$->class, "HEDIT");
            if (dialog.ex == NULL)
              rcparse_warning (_("IEDIT requires DIALOGEX"));
            res_string_to_id (&$$->class, "HEDIT");
@@ -659,15 +739,17 @@ control:
            $$ = define_icon_control ($2, $3, $4, $5, style, $9, $10, $11,
                                      dialog.ex);
           }
            $$ = define_icon_control ($2, $3, $4, $5, style, $9, $10, $11,
                                      dialog.ex);
           }
-       | IEDIT
+       | IEDIT optresidc
            {
              default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
              base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
            {
              default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
              base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
-             class = CTL_EDIT;
+             class.named = 0;
+             class.u.id = CTL_EDIT;
+             res_text_field = $2;
            }
            control_params
          {
            }
            control_params
          {
-           $$ = $3;
+           $$ = $4;
            if (dialog.ex == NULL)
              rcparse_warning (_("IEDIT requires DIALOGEX"));
            res_string_to_id (&$$->class, "IEDIT");
            if (dialog.ex == NULL)
              rcparse_warning (_("IEDIT requires DIALOGEX"));
            res_string_to_id (&$$->class, "IEDIT");
@@ -676,89 +758,107 @@ control:
            {
              default_style = LBS_NOTIFY | WS_BORDER;
              base_style = LBS_NOTIFY | WS_BORDER;
            {
              default_style = LBS_NOTIFY | WS_BORDER;
              base_style = LBS_NOTIFY | WS_BORDER;
-             class = CTL_LISTBOX;
+             class.named = 0;
+             class.u.id = CTL_LISTBOX;
+             res_text_field = res_null_text;
            }
            control_params
          {
            $$ = $3;
          }
            }
            control_params
          {
            $$ = $3;
          }
-       | LTEXT
+       | LTEXT optresidc
            {
              default_style = SS_LEFT | WS_GROUP;
              base_style = SS_LEFT;
            {
              default_style = SS_LEFT | WS_GROUP;
              base_style = SS_LEFT;
-             class = CTL_STATIC;
+             class.named = 0;
+             class.u.id = CTL_STATIC;
+             res_text_field = $2;
            }
            control_params
          {
            }
            control_params
          {
-           $$ = $3;
+           $$ = $4;
          }
          }
-       | PUSHBOX
+       | PUSHBOX optresidc
            {
              default_style = BS_PUSHBOX | WS_TABSTOP;
              base_style = BS_PUSHBOX;
            {
              default_style = BS_PUSHBOX | WS_TABSTOP;
              base_style = BS_PUSHBOX;
-             class = CTL_BUTTON;
+             class.named = 0;
+             class.u.id = CTL_BUTTON;
            }
            control_params
          {
            }
            control_params
          {
-           $$ = $3;
+           $$ = $4;
          }
          }
-       | PUSHBUTTON
+       | PUSHBUTTON optresidc
            {
              default_style = BS_PUSHBUTTON | WS_TABSTOP;
              base_style = BS_PUSHBUTTON | WS_TABSTOP;
            {
              default_style = BS_PUSHBUTTON | WS_TABSTOP;
              base_style = BS_PUSHBUTTON | WS_TABSTOP;
-             class = CTL_BUTTON;
+             class.named = 0;
+             class.u.id = CTL_BUTTON;
+             res_text_field = $2;
            }
            control_params
          {
            }
            control_params
          {
-           $$ = $3;
+           $$ = $4;
          }
          }
-       | RADIOBUTTON
+       | RADIOBUTTON optresidc
            {
              default_style = BS_RADIOBUTTON | WS_TABSTOP;
              base_style = BS_RADIOBUTTON;
            {
              default_style = BS_RADIOBUTTON | WS_TABSTOP;
              base_style = BS_RADIOBUTTON;
-             class = CTL_BUTTON;
+             class.named = 0;
+             class.u.id = CTL_BUTTON;
+             res_text_field = $2;
            }
            control_params
          {
            }
            control_params
          {
-           $$ = $3;
+           $$ = $4;
          }
          }
-       | RTEXT
+       | RTEXT optresidc
            {
              default_style = SS_RIGHT | WS_GROUP;
              base_style = SS_RIGHT;
            {
              default_style = SS_RIGHT | WS_GROUP;
              base_style = SS_RIGHT;
-             class = CTL_STATIC;
+             class.named = 0;
+             class.u.id = CTL_STATIC;
+             res_text_field = $2;
            }
            control_params
          {
            }
            control_params
          {
-           $$ = $3;
+           $$ = $4;
          }
        | SCROLLBAR
            {
              default_style = SBS_HORZ;
              base_style = 0;
          }
        | SCROLLBAR
            {
              default_style = SBS_HORZ;
              base_style = 0;
-             class = CTL_SCROLLBAR;
+             class.named = 0;
+             class.u.id = CTL_SCROLLBAR;
+             res_text_field = res_null_text;
            }
            control_params
          {
            $$ = $3;
          }
            }
            control_params
          {
            $$ = $3;
          }
-       | STATE3
+       | STATE3 optresidc
            {
              default_style = BS_3STATE | WS_TABSTOP;
              base_style = BS_3STATE;
            {
              default_style = BS_3STATE | WS_TABSTOP;
              base_style = BS_3STATE;
-             class = CTL_BUTTON;
+             class.named = 0;
+             class.u.id = CTL_BUTTON;
+             res_text_field = $2;
            }
            control_params
          {
            }
            control_params
          {
-           $$ = $3;
+           $$ = $4;
          }
          }
-       | USERBUTTON QUOTEDSTRING ',' numexpr ',' numexpr ',' numexpr ','
-           numexpr ',' numexpr ',' 
+       | USERBUTTON resref numexpr ',' numexpr ',' numexpr ','
+           numexpr ',' numexpr ','
            { style = WS_CHILD | WS_VISIBLE; }
            styleexpr optcnumexpr
          {
            { style = WS_CHILD | WS_VISIBLE; }
            styleexpr optcnumexpr
          {
-           $$ = define_control ($2, $4, $6, $8, $10, $12, CTL_BUTTON,
-                                style, $16);
+           rc_res_id cid;
+           cid.named = 0;
+           cid.u.id = CTL_BUTTON;
+           $$ = define_control ($2, $3, $5, $7, $9, $11, cid,
+                                style, $15);
          }
        ;
 
          }
        ;
 
@@ -770,52 +870,68 @@ control:
    style.  CLASS is the class of the control.  */
 
 control_params:
    style.  CLASS is the class of the control.  */
 
 control_params:
-         optstringc numexpr cnumexpr cnumexpr cnumexpr cnumexpr
-           opt_control_data
+         numexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data
          {
          {
-           $$ = define_control ($1, $2, $3, $4, $5, $6, class,
+           $$ = define_control (res_text_field, $1, $2, $3, $4, $5, class,
                                 default_style | WS_CHILD | WS_VISIBLE, 0);
                                 default_style | WS_CHILD | WS_VISIBLE, 0);
-           if ($7 != NULL)
+           if ($6 != NULL)
              {
                if (dialog.ex == NULL)
                  rcparse_warning (_("control data requires DIALOGEX"));
              {
                if (dialog.ex == NULL)
                  rcparse_warning (_("control data requires DIALOGEX"));
-               $$->data = $7;
+               $$->data = $6;
              }
          }
              }
          }
-       | optstringc numexpr cnumexpr cnumexpr cnumexpr cnumexpr
+       | numexpr cnumexpr cnumexpr cnumexpr cnumexpr
            control_params_styleexpr optcnumexpr opt_control_data
          {
            control_params_styleexpr optcnumexpr opt_control_data
          {
-           $$ = define_control ($1, $2, $3, $4, $5, $6, class, style, $8);
-           if ($9 != NULL)
+           $$ = define_control (res_text_field, $1, $2, $3, $4, $5, class, style, $7);
+           if ($8 != NULL)
              {
                if (dialog.ex == NULL)
                  rcparse_warning (_("control data requires DIALOGEX"));
              {
                if (dialog.ex == NULL)
                  rcparse_warning (_("control data requires DIALOGEX"));
-               $$->data = $9;
+               $$->data = $8;
              }
          }
              }
          }
-       | optstringc numexpr cnumexpr cnumexpr cnumexpr cnumexpr
+       | numexpr cnumexpr cnumexpr cnumexpr cnumexpr
            control_params_styleexpr cnumexpr cnumexpr opt_control_data
          {
            control_params_styleexpr cnumexpr cnumexpr opt_control_data
          {
-           $$ = define_control ($1, $2, $3, $4, $5, $6, class, style, $8);
+           $$ = define_control (res_text_field, $1, $2, $3, $4, $5, class, style, $7);
            if (dialog.ex == NULL)
              rcparse_warning (_("help ID requires DIALOGEX"));
            if (dialog.ex == NULL)
              rcparse_warning (_("help ID requires DIALOGEX"));
-           $$->help = $9;
-           $$->data = $10;
+           $$->help = $8;
+           $$->data = $9;
          }
        ;
 
          }
        ;
 
-optstringc:
+cresid:
+         ',' resid
+         {
+           if ($2.named)
+             res_unistring_to_id (&$$, $2.u.n.name);
+           else
+             $$=$2;
+         }
+       ;
+
+optresidc:
          /* empty */
          {
          /* empty */
          {
-           $$ = NULL;
+           res_string_to_id (&$$, "");
          }
          }
-       | QUOTEDSTRING
+       | resid ',' { $$=$1; }
+       ;
+
+resid:
+         posnumexpr
          {
          {
-           $$ = $1;
+           $$.named = 0;
+           $$.u.id = $1;
          }
          }
-       | QUOTEDSTRING ','
+       | res_unicode_string_concat
          {
          {
-           $$ = $1;
+           $$.named = 1;
+           $$.u.n.name = $1;
+           $$.u.n.length = unichar_len ($1);
          }
        ;
 
          }
        ;
 
@@ -856,6 +972,9 @@ font:
          id FONT memflags_move_discard file_name
          {
            define_font ($1, &$3, $4);
          id FONT memflags_move_discard file_name
          {
            define_font ($1, &$3, $4);
+           if (yychar != YYEMPTY)
+             YYERROR;
+           rcparse_discard_strings ();
          }
        ;
 
          }
        ;
 
@@ -865,6 +984,9 @@ icon:
          id ICON memflags_move_discard file_name
          {
            define_icon ($1, &$3, $4);
          id ICON memflags_move_discard file_name
          {
            define_icon ($1, &$3, $4);
+           if (yychar != YYEMPTY)
+             YYERROR;
+           rcparse_discard_strings ();
          }
        ;
 
          }
        ;
 
@@ -884,6 +1006,9 @@ menu:
          id MENU suboptions BEG menuitems END
          {
            define_menu ($1, &$3, $5);
          id MENU suboptions BEG menuitems END
          {
            define_menu ($1, &$3, $5);
+           if (yychar != YYEMPTY)
+             YYERROR;
+           rcparse_discard_strings ();
          }
        ;
 
          }
        ;
 
@@ -898,7 +1023,7 @@ menuitems:
              $$ = $2;
            else
              {
              $$ = $2;
            else
              {
-               struct menuitem **pp;
+               rc_menuitem **pp;
 
                for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
                  ;
 
                for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
                  ;
@@ -909,7 +1034,7 @@ menuitems:
        ;
 
 menuitem:
        ;
 
 menuitem:
-         MENUITEM QUOTEDSTRING cnumexpr menuitem_flags
+         MENUITEM res_unicode_string_concat cnumexpr menuitem_flags
          {
            $$ = define_menuitem ($2, $3, $4, 0, 0, NULL);
          }
          {
            $$ = define_menuitem ($2, $3, $4, 0, 0, NULL);
          }
@@ -917,7 +1042,7 @@ menuitem:
          {
            $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL);
          }
          {
            $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL);
          }
-       | POPUP QUOTEDSTRING menuitem_flags BEG menuitems END
+       | POPUP res_unicode_string_concat menuitem_flags BEG menuitems END
          {
            $$ = define_menuitem ($2, 0, $3, 0, 0, $5);
          }
          {
            $$ = define_menuitem ($2, 0, $3, 0, 0, $5);
          }
@@ -971,6 +1096,9 @@ menuex:
          id MENUEX suboptions BEG menuexitems END
          {
            define_menu ($1, &$3, $5);
          id MENUEX suboptions BEG menuexitems END
          {
            define_menu ($1, &$3, $5);
+           if (yychar != YYEMPTY)
+             YYERROR;
+           rcparse_discard_strings ();
          }
        ;
 
          }
        ;
 
@@ -985,7 +1113,7 @@ menuexitems:
              $$ = $2;
            else
              {
              $$ = $2;
            else
              {
-               struct menuitem **pp;
+               rc_menuitem **pp;
 
                for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
                  ;
 
                for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
                  ;
@@ -996,15 +1124,15 @@ menuexitems:
        ;
 
 menuexitem:
        ;
 
 menuexitem:
-         MENUITEM QUOTEDSTRING
+         MENUITEM res_unicode_string_concat
          {
            $$ = define_menuitem ($2, 0, 0, 0, 0, NULL);
          }
          {
            $$ = define_menuitem ($2, 0, 0, 0, 0, NULL);
          }
-       | MENUITEM QUOTEDSTRING cnumexpr
+       | MENUITEM res_unicode_string_concat cnumexpr
          {
            $$ = define_menuitem ($2, $3, 0, 0, 0, NULL);
          }
          {
            $$ = define_menuitem ($2, $3, 0, 0, 0, NULL);
          }
-       | MENUITEM QUOTEDSTRING cnumexpr cnumexpr optcnumexpr
+       | MENUITEM res_unicode_string_concat cnumexpr cnumexpr optcnumexpr
          {
            $$ = define_menuitem ($2, $3, $4, $5, 0, NULL);
          }
          {
            $$ = define_menuitem ($2, $3, $4, $5, 0, NULL);
          }
@@ -1012,19 +1140,19 @@ menuexitem:
          {
            $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL);
          }
          {
            $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL);
          }
-       | POPUP QUOTEDSTRING BEG menuexitems END
+       | POPUP res_unicode_string_concat BEG menuexitems END
          {
            $$ = define_menuitem ($2, 0, 0, 0, 0, $4);
          }
          {
            $$ = define_menuitem ($2, 0, 0, 0, 0, $4);
          }
-       | POPUP QUOTEDSTRING cnumexpr BEG menuexitems END
+       | POPUP res_unicode_string_concat cnumexpr BEG menuexitems END
          {
            $$ = define_menuitem ($2, $3, 0, 0, 0, $5);
          }
          {
            $$ = define_menuitem ($2, $3, 0, 0, 0, $5);
          }
-       | POPUP QUOTEDSTRING cnumexpr cnumexpr BEG menuexitems END
+       | POPUP res_unicode_string_concat cnumexpr cnumexpr BEG menuexitems END
          {
            $$ = define_menuitem ($2, $3, $4, 0, 0, $6);
          }
          {
            $$ = define_menuitem ($2, $3, $4, 0, 0, $6);
          }
-       | POPUP QUOTEDSTRING cnumexpr cnumexpr cnumexpr optcnumexpr
+       | POPUP res_unicode_string_concat cnumexpr cnumexpr cnumexpr optcnumexpr
            BEG menuexitems END
          {
            $$ = define_menuitem ($2, $3, $4, $5, $6, $8);
            BEG menuexitems END
          {
            $$ = define_menuitem ($2, $3, $4, $5, $6, $8);
@@ -1037,15 +1165,9 @@ messagetable:
          id MESSAGETABLE memflags_move file_name
          {
            define_messagetable ($1, &$3, $4);
          id MESSAGETABLE memflags_move file_name
          {
            define_messagetable ($1, &$3, $4);
-         }
-       ;
-
-/* Rcdata resources.  */
-
-rcdata:
-         id RCDATA suboptions BEG optrcdata_data END
-         {
-           define_rcdata ($1, &$3, $5.first);
+           if (yychar != YYEMPTY)
+             YYERROR;
+           rcparse_discard_strings ();
          }
        ;
 
          }
        ;
 
@@ -1076,102 +1198,242 @@ optrcdata_data_int:
        ;
 
 rcdata_data:
        ;
 
 rcdata_data:
-         SIZEDSTRING
+         sizedstring
          {
          {
-           struct rcdata_item *ri;
+           rc_rcdata_item *ri;
 
            ri = define_rcdata_string ($1.s, $1.length);
            $$.first = ri;
            $$.last = ri;
          }
 
            ri = define_rcdata_string ($1.s, $1.length);
            $$.first = ri;
            $$.last = ri;
          }
+       | sizedunistring
+         {
+           rc_rcdata_item *ri;
+
+           ri = define_rcdata_unistring ($1.s, $1.length);
+           $$.first = ri;
+           $$.last = ri;
+         }
        | sizednumexpr
          {
        | sizednumexpr
          {
-           struct rcdata_item *ri;
+           rc_rcdata_item *ri;
 
            ri = define_rcdata_number ($1.val, $1.dword);
            $$.first = ri;
            $$.last = ri;
          }
 
            ri = define_rcdata_number ($1.val, $1.dword);
            $$.first = ri;
            $$.last = ri;
          }
-       | rcdata_data ',' SIZEDSTRING
+       | rcdata_data ',' sizedstring
          {
          {
-           struct rcdata_item *ri;
+           rc_rcdata_item *ri;
 
            ri = define_rcdata_string ($3.s, $3.length);
            $$.first = $1.first;
            $1.last->next = ri;
            $$.last = ri;
          }
 
            ri = define_rcdata_string ($3.s, $3.length);
            $$.first = $1.first;
            $1.last->next = ri;
            $$.last = ri;
          }
+       | rcdata_data ',' sizedunistring
+         {
+           rc_rcdata_item *ri;
+
+           ri = define_rcdata_unistring ($3.s, $3.length);
+           $$.first = $1.first;
+           $1.last->next = ri;
+           $$.last = ri;
+         }
        | rcdata_data ',' sizednumexpr
          {
        | rcdata_data ',' sizednumexpr
          {
-           struct rcdata_item *ri;
+           rc_rcdata_item *ri;
 
            ri = define_rcdata_number ($3.val, $3.dword);
            $$.first = $1.first;
            $1.last->next = ri;
            $$.last = ri;
          }
 
            ri = define_rcdata_number ($3.val, $3.dword);
            $$.first = $1.first;
            $1.last->next = ri;
            $$.last = ri;
          }
+       | rcdata_data ','
+         {
+           $$=$1;
+         }
        ;
 
 /* Stringtable resources.  */
 
 stringtable:
        ;
 
 /* Stringtable resources.  */
 
 stringtable:
-         STRINGTABLE suboptions BEG 
-           { sub_res_info = $2; }
-           string_data END
+         STRINGTABLE suboptions BEG
+           { sub_res_info = $2; rcparse_rcdata (); }
+           string_data END { rcparse_normal (); }
        ;
 
 string_data:
          /* empty */
        ;
 
 string_data:
          /* empty */
-       | string_data numexpr QUOTEDSTRING
+       | string_data numexpr res_unicode_sizedstring_concat
+         {
+           define_stringtable (&sub_res_info, $2, $3.s, $3.length);
+           rcparse_discard_strings ();
+         }
+       | string_data numexpr ',' res_unicode_sizedstring_concat
          {
          {
-           define_stringtable (&sub_res_info, $2, $3);
+           define_stringtable (&sub_res_info, $2, $4.s, $4.length);
+           rcparse_discard_strings ();
          }
          }
-       | string_data numexpr ',' QUOTEDSTRING
+       | string_data error
          {
          {
-           define_stringtable (&sub_res_info, $2, $4);
+           rcparse_warning (_("invalid stringtable resource."));
+           abort ();
          }
        ;
 
          }
        ;
 
+rcdata_id:
+       id
+         {
+           $$=$1;
+         }
+      | HTML
+       {
+         $$.named = 0;
+         $$.u.id = 23;
+       }
+      | RCDATA
+        {
+          $$.named = 0;
+          $$.u.id = RT_RCDATA;
+        }
+      | MANIFEST
+        {
+          $$.named = 0;
+          $$.u.id = RT_MANIFEST;
+        }
+      | PLUGPLAY
+        {
+          $$.named = 0;
+          $$.u.id = RT_PLUGPLAY;
+        }
+      | VXD
+        {
+          $$.named = 0;
+          $$.u.id = RT_VXD;
+        }
+      | DLGINCLUDE
+        {
+          $$.named = 0;
+          $$.u.id = RT_DLGINCLUDE;
+        }
+      | DLGINIT
+        {
+          $$.named = 0;
+          $$.u.id = RT_DLGINIT;
+        }
+      | ANICURSOR
+        {
+          $$.named = 0;
+          $$.u.id = RT_ANICURSOR;
+        }
+      | ANIICON
+        {
+          $$.named = 0;
+          $$.u.id = RT_ANIICON;
+        }
+      ;
+
 /* User defined resources.  We accept general suboptions in the
    file_name case to keep the parser happy.  */
 
 user:
 /* User defined resources.  We accept general suboptions in the
    file_name case to keep the parser happy.  */
 
 user:
-         id id suboptions BEG optrcdata_data END
+         id rcdata_id suboptions BEG optrcdata_data END
          {
            define_user_data ($1, $2, &$3, $5.first);
          {
            define_user_data ($1, $2, &$3, $5.first);
+           if (yychar != YYEMPTY)
+             YYERROR;
+           rcparse_discard_strings ();
          }
          }
-       | id id suboptions file_name
+       | id rcdata_id suboptions file_name
          {
            define_user_file ($1, $2, &$3, $4);
          {
            define_user_file ($1, $2, &$3, $4);
+           if (yychar != YYEMPTY)
+             YYERROR;
+           rcparse_discard_strings ();
          }
        ;
 
          }
        ;
 
+toolbar:
+       id TOOLBAR suboptions numexpr cnumexpr BEG toolbar_data END
+       {
+         define_toolbar ($1, &$3, $4, $5, $7);
+       }
+       ;
+
+toolbar_data: /* empty */ { $$= NULL; }
+       | toolbar_data BUTTON id
+       {
+         rc_toolbar_item *c,*n;
+         c = $1;
+         n= (rc_toolbar_item *)
+             res_alloc (sizeof (rc_toolbar_item));
+         if (c != NULL)
+           while (c->next != NULL)
+             c = c->next;
+         n->prev = c;
+         n->next = NULL;
+         if (c != NULL)
+           c->next = n;
+         n->id = $3;
+         if ($1 == NULL)
+           $$ = n;
+         else
+           $$ = $1;
+       }
+       | toolbar_data SEPARATOR
+       {
+         rc_toolbar_item *c,*n;
+         c = $1;
+         n= (rc_toolbar_item *)
+             res_alloc (sizeof (rc_toolbar_item));
+         if (c != NULL)
+           while (c->next != NULL)
+             c = c->next;
+         n->prev = c;
+         n->next = NULL;
+         if (c != NULL)
+           c->next = n;
+         n->id.named = 0;
+         n->id.u.id = 0;
+         if ($1 == NULL)
+           $$ = n;
+         else
+           $$ = $1;
+       }
+       ;
+
 /* Versioninfo resources.  */
 
 versioninfo:
          id VERSIONINFO fixedverinfo BEG verblocks END
          {
            define_versioninfo ($1, language, $3, $5);
 /* Versioninfo resources.  */
 
 versioninfo:
          id VERSIONINFO fixedverinfo BEG verblocks END
          {
            define_versioninfo ($1, language, $3, $5);
+           if (yychar != YYEMPTY)
+             YYERROR;
+           rcparse_discard_strings ();
          }
        ;
 
 fixedverinfo:
          /* empty */
          {
          }
        ;
 
 fixedverinfo:
          /* empty */
          {
-           $$ = ((struct fixed_versioninfo *)
-                 res_alloc (sizeof (struct fixed_versioninfo)));
-           memset ($$, 0, sizeof (struct fixed_versioninfo));
+           $$ = ((rc_fixed_versioninfo *)
+                 res_alloc (sizeof (rc_fixed_versioninfo)));
+           memset ($$, 0, sizeof (rc_fixed_versioninfo));
          }
          }
-       | fixedverinfo FILEVERSION numexpr cnumexpr cnumexpr cnumexpr
+       | fixedverinfo FILEVERSION numexpr optcnumexpr optcnumexpr
+         optcnumexpr
          {
          {
-           $1->file_version_ms = ($3 << 16) | $4;
-           $1->file_version_ls = ($5 << 16) | $6;
+           $1->file_version_ms = ($3 << 16) | ($4 & 0xffff);
+           $1->file_version_ls = ($5 << 16) | ($6 & 0xffff);
            $$ = $1;
          }
            $$ = $1;
          }
-       | fixedverinfo PRODUCTVERSION numexpr cnumexpr cnumexpr cnumexpr
+       | fixedverinfo PRODUCTVERSION numexpr optcnumexpr optcnumexpr
+         optcnumexpr
          {
          {
-           $1->product_version_ms = ($3 << 16) | $4;
-           $1->product_version_ls = ($5 << 16) | $6;
+           $1->product_version_ms = ($3 << 16) | ($4 & 0xffff);
+           $1->product_version_ls = ($5 << 16) | ($6 & 0xffff);
            $$ = $1;
          }
        | fixedverinfo FILEFLAGSMASK numexpr
            $$ = $1;
          }
        | fixedverinfo FILEFLAGSMASK numexpr
@@ -1212,22 +1474,33 @@ verblocks:
          {
            $$ = NULL;
          }
          {
            $$ = NULL;
          }
-       | verblocks BLOCKSTRINGFILEINFO BEG BLOCK BEG vervals END END
+       | verblocks BLOCKSTRINGFILEINFO BEG verstringtables END
          {
          {
-           $$ = append_ver_stringfileinfo ($1, $4, $6);
+           $$ = append_ver_stringfileinfo ($1, $4);
          }
          }
-       | verblocks BLOCKVARFILEINFO BEG VALUE QUOTEDSTRING vertrans END
+       | verblocks BLOCKVARFILEINFO BEG VALUE res_unicode_string_concat vertrans END
          {
            $$ = append_ver_varfileinfo ($1, $5, $6);
          }
        ;
 
          {
            $$ = append_ver_varfileinfo ($1, $5, $6);
          }
        ;
 
+verstringtables:
+      /* empty */
+         {
+           $$ = NULL;
+         }
+       | verstringtables BLOCK BEG vervals END
+         {
+           $$ = append_ver_stringtable ($1, $2, $4);
+         }
+       ;
+
 vervals:
          /* empty */
          {
            $$ = NULL;
          }
 vervals:
          /* empty */
          {
            $$ = NULL;
          }
-       | vervals VALUE QUOTEDSTRING ',' QUOTEDSTRING
+       | vervals VALUE res_unicode_string_concat ',' res_unicode_string_concat
          {
            $$ = append_verval ($1, $3, $5);
          }
          {
            $$ = append_verval ($1, $3, $5);
          }
@@ -1252,34 +1525,24 @@ id:
            $$.named = 0;
            $$.u.id = $1;
          }
            $$.named = 0;
            $$.u.id = $1;
          }
-       | STRING
+       | resname
          {
          {
-           char *copy, *s;
-
-           /* It seems that resource ID's are forced to upper case.  */
-           copy = xstrdup ($1);
-           for (s = copy; *s != '\0'; s++)
-             if (islower ((unsigned char) *s))
-               *s = toupper ((unsigned char) *s);
-           res_string_to_id (&$$, copy);
-           free (copy);
+           res_unistring_to_id (&$$, $1);
          }
        ;
 
 /* A resource reference.  */
 
 resname:
          }
        ;
 
 /* A resource reference.  */
 
 resname:
-         QUOTEDSTRING
+         res_unicode_string
          {
            $$ = $1;
          }
          {
            $$ = $1;
          }
-       | QUOTEDSTRING ','
-         {
-           $$ = $1;
-         }
-       | STRING ','
+       | STRING
          {
          {
-           $$ = $1;
+           unichar *h = NULL;
+           unicode_from_ascii ((rc_uint_type *) NULL, &h, $1);
+           $$ = h;
          }
        ;
 
          }
        ;
 
@@ -1292,15 +1555,11 @@ resref:
          }
        | resname
          {
          }
        | resname
          {
-           char *copy, *s;
-
-           /* It seems that resource ID's are forced to upper case.  */
-           copy = xstrdup ($1);
-           for (s = copy; *s != '\0'; s++)
-             if (islower ((unsigned char) *s))
-               *s = toupper ((unsigned char) *s);
-           res_string_to_id (&$$, copy);
-           free (copy);
+           res_unistring_to_id (&$$, $1);
+         }
+       | resname ','
+         {
+           res_unistring_to_id (&$$, $1);
          }
        ;
 
          }
        ;
 
@@ -1310,10 +1569,10 @@ resref:
 suboptions:
          /* empty */
          {
 suboptions:
          /* empty */
          {
-           memset (&$$, 0, sizeof (struct res_res_info));
+           memset (&$$, 0, sizeof (rc_res_res_info));
            $$.language = language;
            /* FIXME: Is this the right default?  */
            $$.language = language;
            /* FIXME: Is this the right default?  */
-           $$.memflags = MEMFLAG_MOVEABLE;
+           $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_PURE | MEMFLAG_DISCARDABLE;
          }
        | suboptions memflag
          {
          }
        | suboptions memflag
          {
@@ -1343,7 +1602,7 @@ suboptions:
 memflags_move_discard:
          /* empty */
          {
 memflags_move_discard:
          /* empty */
          {
-           memset (&$$, 0, sizeof (struct res_res_info));
+           memset (&$$, 0, sizeof (rc_res_res_info));
            $$.language = language;
            $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_DISCARDABLE;
          }
            $$.language = language;
            $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_DISCARDABLE;
          }
@@ -1360,9 +1619,9 @@ memflags_move_discard:
 memflags_move:
          /* empty */
          {
 memflags_move:
          /* empty */
          {
-           memset (&$$, 0, sizeof (struct res_res_info));
+           memset (&$$, 0, sizeof (rc_res_res_info));
            $$.language = language;
            $$.language = language;
-           $$.memflags = MEMFLAG_MOVEABLE;
+           $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_PURE | MEMFLAG_DISCARDABLE;
          }
        | memflags_move memflag
          {
          }
        | memflags_move memflag
          {
@@ -1426,6 +1685,109 @@ file_name:
          }
        ;
 
          }
        ;
 
+/* Concat string */
+res_unicode_string_concat:
+         res_unicode_string
+         {
+           $$ = $1;
+         }
+       |
+         res_unicode_string_concat res_unicode_string
+         {
+           rc_uint_type l1 = unichar_len ($1);
+           rc_uint_type l2 = unichar_len ($2);
+           unichar *h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar));
+           if (l1 != 0)
+             memcpy (h, $1, l1 * sizeof (unichar));
+           if (l2 != 0)
+             memcpy (h + l1, $2, l2  * sizeof (unichar));
+           h[l1 + l2] = 0;
+           $$ = h;
+         }
+       ;
+
+res_unicode_string:
+         QUOTEDUNISTRING
+         {
+           $$ = unichar_dup ($1);
+         }
+       | QUOTEDSTRING
+         {
+           unichar *h = NULL;
+           unicode_from_ascii ((rc_uint_type *) NULL, &h, $1);
+           $$ = h;
+         }
+       ;
+
+res_unicode_sizedstring:
+         sizedunistring
+         {
+           $$ = $1;
+         }
+       | sizedstring
+         {
+           unichar *h = NULL;
+           rc_uint_type l = 0;
+           unicode_from_ascii_len (&l, &h, $1.s, $1.length);
+           $$.s = h;
+           $$.length = l;
+         }
+       ;
+
+/* Concat string */
+res_unicode_sizedstring_concat:
+         res_unicode_sizedstring
+         {
+           $$ = $1;
+         }
+       |
+         res_unicode_sizedstring_concat res_unicode_sizedstring
+         {
+           rc_uint_type l1 = $1.length;
+           rc_uint_type l2 = $2.length;
+           unichar *h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar));
+           if (l1 != 0)
+             memcpy (h, $1.s, l1 * sizeof (unichar));
+           if (l2 != 0)
+             memcpy (h + l1, $2.s, l2  * sizeof (unichar));
+           h[l1 + l2] = 0;
+           $$.length = l1 + l2;
+           $$.s = h;
+         }
+       ;
+
+sizedstring:
+         SIZEDSTRING
+         {
+           $$ = $1;
+         }
+       | sizedstring SIZEDSTRING
+         {
+           rc_uint_type l = $1.length + $2.length;
+           char *h = (char *) res_alloc (l);
+           memcpy (h, $1.s, $1.length);
+           memcpy (h + $1.length, $2.s, $2.length);
+           $$.s = h;
+           $$.length = l;
+         }
+       ;
+
+sizedunistring:
+         SIZEDUNISTRING
+         {
+           $$ = $1;
+         }
+       | sizedunistring SIZEDUNISTRING
+         {
+           rc_uint_type l = $1.length + $2.length;
+           unichar *h = (unichar *) res_alloc (l * sizeof (unichar));
+           memcpy (h, $1.s, $1.length * sizeof (unichar));
+           memcpy (h + $1.length, $2.s, $2.length  * sizeof (unichar));
+           $$.s = h;
+           $$.length = l;
+         }
+       ;
+
 /* A style expression.  This changes the static variable STYLE.  We do
    it this way because rc appears to permit a style to be set to
    something like
 /* A style expression.  This changes the static variable STYLE.  We do
    it this way because rc appears to permit a style to be set to
    something like
@@ -1525,12 +1887,12 @@ sizednumexpr:
          }
        | sizednumexpr '/' sizednumexpr
          {
          }
        | sizednumexpr '/' sizednumexpr
          {
-           $$.val = $1.val / $3.val;
+           $$.val = $1.val / ($3.val ? $3.val : 1);
            $$.dword = $1.dword || $3.dword;
          }
        | sizednumexpr '%' sizednumexpr
          {
            $$.dword = $1.dword || $3.dword;
          }
        | sizednumexpr '%' sizednumexpr
          {
-           $$.val = $1.val % $3.val;
+           $$.val = $1.val % ($3.val ? $3.val : 1);
            $$.dword = $1.dword || $3.dword;
          }
        | sizednumexpr '+' sizednumexpr
            $$.dword = $1.dword || $3.dword;
          }
        | sizednumexpr '+' sizednumexpr
@@ -1604,12 +1966,13 @@ sizedposnumexpr:
          }
        | sizedposnumexpr '/' sizednumexpr
          {
          }
        | sizedposnumexpr '/' sizednumexpr
          {
-           $$.val = $1.val / $3.val;
+           $$.val = $1.val / ($3.val ? $3.val : 1);
            $$.dword = $1.dword || $3.dword;
          }
        | sizedposnumexpr '%' sizednumexpr
          {
            $$.dword = $1.dword || $3.dword;
          }
        | sizedposnumexpr '%' sizednumexpr
          {
-           $$.val = $1.val % $3.val;
+           /* PR 17512: file: 89105a25.  */
+           $$.val = $1.val % ($3.val ? $3.val : 1);
            $$.dword = $1.dword || $3.dword;
          }
        | sizedposnumexpr '+' sizednumexpr
            $$.dword = $1.dword || $3.dword;
          }
        | sizedposnumexpr '+' sizednumexpr
@@ -1644,8 +2007,7 @@ sizedposnumexpr:
 /* Set the language from the command line.  */
 
 void
 /* Set the language from the command line.  */
 
 void
-rcparse_set_language (lang)
-     int lang;
+rcparse_set_language (int lang)
 {
   language = lang;
 }
 {
   language = lang;
 }
This page took 0.044973 seconds and 4 git commands to generate.