binutils-gdb/binutils/rcparse.y

2014 lines
40 KiB
Plaintext
Raw Normal View History

1999-05-03 09:29:11 +02:00
%{ /* rcparse.y -- parser for Windows rc files
Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007, 2008,
2011 Free Software Foundation, Inc.
1999-05-03 09:29:11 +02:00
Written by Ian Lance Taylor, Cygnus Support.
2007-05-23 10:48:29 +02:00
Extended by Kai Tietz, Onevision.
1999-05-03 09:29:11 +02:00
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
2007-07-05 18:54:46 +02:00
the Free Software Foundation; either version 3 of the License, or
1999-05-03 09:29:11 +02:00
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
2005-05-08 16:17:41 +02:00
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
02110-1301, USA. */
1999-05-03 09:29:11 +02:00
2007-07-05 18:54:46 +02:00
1999-05-03 09:29:11 +02:00
/* 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"
1999-05-03 09:29:11 +02:00
#include "bfd.h"
2007-05-23 10:48:29 +02:00
#include "bucomm.h"
1999-05-03 09:29:11 +02:00
#include "libiberty.h"
#include "windres.h"
#include "safe-ctype.h"
1999-05-03 09:29:11 +02:00
/* The current language. */
static unsigned short language;
/* The resource information during a sub statement. */
2007-05-23 10:48:29 +02:00
static rc_res_res_info sub_res_info;
1999-05-03 09:29:11 +02:00
/* Dialog information. This is built by the nonterminals styles and
controls. */
2007-05-23 10:48:29 +02:00
static rc_dialog dialog;
1999-05-03 09:29:11 +02:00
/* This is used when building a style. It is modified by the
nonterminal styleexpr. */
static unsigned long style;
/* These are used when building a control. They are set before using
control_params. */
2007-05-23 10:48:29 +02:00
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. */
2007-05-23 10:48:29 +02:00
static const rc_res_id res_null_text = { 1, {{0, &null_unichar}}};
1999-05-03 09:29:11 +02:00
%}
%union
{
2007-05-23 10:48:29 +02:00
rc_accelerator acc;
rc_accelerator *pacc;
rc_dialog_control *dialog_control;
rc_menuitem *menuitem;
1999-05-03 09:29:11 +02:00
struct
{
2007-05-23 10:48:29 +02:00
rc_rcdata_item *first;
rc_rcdata_item *last;
1999-05-03 09:29:11 +02:00
} rcdata;
2007-05-23 10:48:29 +02:00
rc_rcdata_item *rcdata_item;
rc_fixed_versioninfo *fixver;
rc_ver_info *verinfo;
rc_ver_stringtable *verstringtable;
2007-05-23 10:48:29 +02:00
rc_ver_stringinfo *verstring;
rc_ver_varinfo *vervar;
rc_toolbar_item *toobar_item;
rc_res_id id;
rc_res_res_info res_info;
1999-05-03 09:29:11 +02:00
struct
{
2007-05-23 10:48:29 +02:00
rc_uint_type on;
rc_uint_type off;
1999-05-03 09:29:11 +02:00
} memflags;
struct
{
2007-05-23 10:48:29 +02:00
rc_uint_type val;
1999-05-03 09:29:11 +02:00
/* Nonzero if this number was explicitly specified as long. */
int dword;
} i;
2007-05-23 10:48:29 +02:00
rc_uint_type il;
rc_uint_type is;
1999-05-03 09:29:11 +02:00
const char *s;
struct
{
2007-05-23 10:48:29 +02:00
rc_uint_type length;
1999-05-03 09:29:11 +02:00
const char *s;
} ss;
2007-05-23 10:48:29 +02:00
unichar *uni;
struct
{
rc_uint_type length;
const unichar *s;
} suni;
1999-05-03 09:29:11 +02:00
};
%token BEG END
%token ACCELERATORS VIRTKEY ASCII NOINVERT SHIFT CONTROL ALT
%token BITMAP
%token CURSOR
%token DIALOG DIALOGEX EXSTYLE CAPTION CLASS STYLE
%token AUTO3STATE AUTOCHECKBOX AUTORADIOBUTTON CHECKBOX COMBOBOX CTEXT
%token DEFPUSHBUTTON EDITTEXT GROUPBOX LISTBOX LTEXT PUSHBOX PUSHBUTTON
%token RADIOBUTTON RTEXT SCROLLBAR STATE3 USERBUTTON
%token BEDIT HEDIT IEDIT
%token FONT
%token ICON
2007-05-23 10:48:29 +02:00
%token ANICURSOR ANIICON DLGINCLUDE DLGINIT FONTDIR HTML MANIFEST PLUGPLAY VXD TOOLBAR BUTTON
1999-05-03 09:29:11 +02:00
%token LANGUAGE CHARACTERISTICS VERSIONK
%token MENU MENUEX MENUITEM SEPARATOR POPUP CHECKED GRAYED HELP INACTIVE
%token MENUBARBREAK MENUBREAK
%token MESSAGETABLE
%token RCDATA
%token STRINGTABLE
%token VERSIONINFO FILEVERSION PRODUCTVERSION FILEFLAGSMASK FILEFLAGS
%token FILEOS FILETYPE FILESUBTYPE BLOCKSTRINGFILEINFO BLOCKVARFILEINFO
%token VALUE
%token <s> BLOCK
%token MOVEABLE FIXED PURE IMPURE PRELOAD LOADONCALL DISCARDABLE
%token NOT
2007-05-23 10:48:29 +02:00
%token <uni> QUOTEDUNISTRING
1999-05-03 09:29:11 +02:00
%token <s> QUOTEDSTRING STRING
%token <i> NUMBER
2007-05-23 10:48:29 +02:00
%token <suni> SIZEDUNISTRING
1999-05-03 09:29:11 +02:00
%token <ss> SIZEDSTRING
%token IGNORED_TOKEN
1999-05-03 09:29:11 +02:00
%type <pacc> acc_entries
%type <acc> acc_entry acc_event
%type <dialog_control> control control_params
%type <menuitem> menuitems menuitem menuexitems menuexitem
%type <rcdata> optrcdata_data optrcdata_data_int rcdata_data
%type <rcdata_item> opt_control_data
%type <fixver> fixedverinfo
%type <verinfo> verblocks
%type <verstringtable> verstringtables
1999-05-03 09:29:11 +02:00
%type <verstring> vervals
%type <vervar> vertrans
2007-05-23 10:48:29 +02:00
%type <toobar_item> toolbar_data
1999-05-03 09:29:11 +02:00
%type <res_info> suboptions memflags_move_discard memflags_move
%type <memflags> memflag
2007-05-23 10:48:29 +02:00
%type <id> id rcdata_id optresidc resref resid cresid
1999-05-03 09:29:11 +02:00
%type <il> exstyle parennumber
%type <il> numexpr posnumexpr cnumexpr optcnumexpr cposnumexpr
%type <is> acc_options acc_option menuitem_flags menuitem_flag
2007-05-23 10:48:29 +02:00
%type <s> file_name
%type <uni> res_unicode_string resname res_unicode_string_concat
2007-05-23 10:48:29 +02:00
%type <ss> sizedstring
%type <suni> sizedunistring res_unicode_sizedstring res_unicode_sizedstring_concat
1999-05-03 09:29:11 +02:00
%type <i> sizednumexpr sizedposnumexpr
%left '|'
%left '^'
%left '&'
%left '+' '-'
%left '*' '/' '%'
%right '~' NEG
%%
input:
/* empty */
| input accelerator
| input bitmap
| input cursor
| input dialog
| input font
| input icon
| input language
| input menu
| input menuex
| input messagetable
| input stringtable
2007-05-23 10:48:29 +02:00
| input toolbar
| input user
| input versioninfo
| input IGNORED_TOKEN
1999-05-03 09:29:11 +02:00
;
/* Accelerator resources. */
accelerator:
id ACCELERATORS suboptions BEG acc_entries END
{
define_accelerator ($1, &$3, $5);
if (yychar != YYEMPTY)
YYERROR;
rcparse_discard_strings ();
1999-05-03 09:29:11 +02:00
}
;
acc_entries:
/* empty */
{
$$ = NULL;
}
| acc_entries acc_entry
{
2007-05-23 10:48:29 +02:00
rc_accelerator *a;
1999-05-03 09:29:11 +02:00
2007-05-23 10:48:29 +02:00
a = (rc_accelerator *) res_alloc (sizeof *a);
1999-05-03 09:29:11 +02:00
*a = $2;
if ($1 == NULL)
$$ = a;
else
{
2007-05-23 10:48:29 +02:00
rc_accelerator **pp;
1999-05-03 09:29:11 +02:00
for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
;
*pp = a;
$$ = $1;
}
}
;
acc_entry:
acc_event cposnumexpr
{
$$ = $1;
$$.id = $2;
}
| acc_event cposnumexpr ',' acc_options
{
$$ = $1;
$$.id = $2;
$$.flags |= $4;
if (($$.flags & ACC_VIRTKEY) == 0
&& ($$.flags & (ACC_SHIFT | ACC_CONTROL)) != 0)
1999-05-03 09:29:11 +02:00
rcparse_warning (_("inappropriate modifiers for non-VIRTKEY"));
}
;
acc_event:
QUOTEDSTRING
{
const char *s = $1;
char ch;
$$.next = NULL;
$$.id = 0;
ch = *s;
if (ch != '^')
$$.flags = 0;
else
{
$$.flags = ACC_CONTROL | ACC_VIRTKEY;
++s;
2007-05-23 10:48:29 +02:00
ch = TOUPPER (s[0]);
1999-05-03 09:29:11 +02:00
}
$$.key = ch;
if (s[1] != '\0')
rcparse_warning (_("accelerator should only be one character"));
}
| posnumexpr
{
$$.next = NULL;
$$.flags = 0;
$$.id = 0;
$$.key = $1;
}
;
acc_options:
acc_option
{
$$ = $1;
}
| acc_options ',' acc_option
{
$$ = $1 | $3;
}
/* I've had one report that the comma is optional. */
| acc_options acc_option
{
$$ = $1 | $2;
}
;
acc_option:
VIRTKEY
{
$$ = ACC_VIRTKEY;
}
| ASCII
{
/* This is just the absence of VIRTKEY. */
$$ = 0;
}
| NOINVERT
{
$$ = ACC_NOINVERT;
}
| SHIFT
{
$$ = ACC_SHIFT;
}
| CONTROL
{
$$ = ACC_CONTROL;
}
| ALT
{
$$ = ACC_ALT;
}
;
/* Bitmap resources. */
bitmap:
id BITMAP memflags_move file_name
{
define_bitmap ($1, &$3, $4);
if (yychar != YYEMPTY)
YYERROR;
rcparse_discard_strings ();
1999-05-03 09:29:11 +02:00
}
;
/* Cursor resources. */
cursor:
id CURSOR memflags_move_discard file_name
{
define_cursor ($1, &$3, $4);
if (yychar != YYEMPTY)
YYERROR;
rcparse_discard_strings ();
1999-05-03 09:29:11 +02:00
}
;
/* Dialog resources. */
dialog:
id DIALOG memflags_move exstyle posnumexpr cnumexpr cnumexpr
cnumexpr
{
memset (&dialog, 0, sizeof dialog);
dialog.x = $5;
dialog.y = $6;
dialog.width = $7;
dialog.height = $8;
dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU;
dialog.exstyle = $4;
dialog.menu.named = 1;
dialog.class.named = 1;
dialog.font = NULL;
dialog.ex = NULL;
dialog.controls = NULL;
sub_res_info = $3;
style = 0;
1999-05-03 09:29:11 +02:00
}
styles BEG controls END
{
define_dialog ($1, &sub_res_info, &dialog);
if (yychar != YYEMPTY)
YYERROR;
rcparse_discard_strings ();
1999-05-03 09:29:11 +02:00
}
| id DIALOGEX memflags_move exstyle posnumexpr cnumexpr cnumexpr
cnumexpr
{
memset (&dialog, 0, sizeof dialog);
dialog.x = $5;
dialog.y = $6;
dialog.width = $7;
dialog.height = $8;
dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU;
dialog.exstyle = $4;
dialog.menu.named = 1;
dialog.class.named = 1;
dialog.font = NULL;
2007-05-23 10:48:29 +02:00
dialog.ex = ((rc_dialog_ex *)
res_alloc (sizeof (rc_dialog_ex)));
memset (dialog.ex, 0, sizeof (rc_dialog_ex));
1999-05-03 09:29:11 +02:00
dialog.controls = NULL;
sub_res_info = $3;
style = 0;
1999-05-03 09:29:11 +02:00
}
styles BEG controls END
{
define_dialog ($1, &sub_res_info, &dialog);
if (yychar != YYEMPTY)
YYERROR;
rcparse_discard_strings ();
1999-05-03 09:29:11 +02:00
}
| id DIALOGEX memflags_move exstyle posnumexpr cnumexpr cnumexpr
cnumexpr cnumexpr
{
memset (&dialog, 0, sizeof dialog);
dialog.x = $5;
dialog.y = $6;
dialog.width = $7;
dialog.height = $8;
dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU;
dialog.exstyle = $4;
dialog.menu.named = 1;
dialog.class.named = 1;
dialog.font = NULL;
2007-05-23 10:48:29 +02:00
dialog.ex = ((rc_dialog_ex *)
res_alloc (sizeof (rc_dialog_ex)));
memset (dialog.ex, 0, sizeof (rc_dialog_ex));
1999-05-03 09:29:11 +02:00
dialog.ex->help = $9;
dialog.controls = NULL;
sub_res_info = $3;
style = 0;
1999-05-03 09:29:11 +02:00
}
styles BEG controls END
{
define_dialog ($1, &sub_res_info, &dialog);
if (yychar != YYEMPTY)
YYERROR;
rcparse_discard_strings ();
1999-05-03 09:29:11 +02:00
}
;
exstyle:
/* empty */
{
$$ = 0;
}
| EXSTYLE '=' numexpr
{
$$ = $3;
}
;
styles:
/* empty */
| styles CAPTION res_unicode_string_concat
1999-05-03 09:29:11 +02:00
{
dialog.style |= WS_CAPTION;
style |= WS_CAPTION;
2007-05-23 10:48:29 +02:00
dialog.caption = $3;
1999-05-03 09:29:11 +02:00
}
| styles CLASS id
{
dialog.class = $3;
}
| styles STYLE
styleexpr
{
dialog.style = style;
}
| styles EXSTYLE numexpr
{
dialog.exstyle = $3;
}
| styles CLASS res_unicode_string_concat
{
2007-05-23 10:48:29 +02:00
res_unistring_to_id (& dialog.class, $3);
}
| styles FONT numexpr ',' res_unicode_string_concat
1999-05-03 09:29:11 +02:00
{
dialog.style |= DS_SETFONT;
style |= DS_SETFONT;
1999-05-03 09:29:11 +02:00
dialog.pointsize = $3;
2007-05-23 10:48:29 +02:00
dialog.font = $5;
if (dialog.ex != NULL)
{
dialog.ex->weight = 0;
dialog.ex->italic = 0;
dialog.ex->charset = 1;
}
}
| styles FONT numexpr ',' res_unicode_string_concat cnumexpr
{
dialog.style |= DS_SETFONT;
style |= DS_SETFONT;
dialog.pointsize = $3;
2007-05-23 10:48:29 +02:00
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;
}
1999-05-03 09:29:11 +02:00
}
| styles FONT numexpr ',' res_unicode_string_concat cnumexpr cnumexpr
1999-05-03 09:29:11 +02:00
{
dialog.style |= DS_SETFONT;
style |= DS_SETFONT;
1999-05-03 09:29:11 +02:00
dialog.pointsize = $3;
2007-05-23 10:48:29 +02:00
dialog.font = $5;
1999-05-03 09:29:11 +02:00
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;
2007-05-23 10:48:29 +02:00
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 = $8;
1999-05-03 09:29:11 +02:00
}
}
| styles MENU id
{
dialog.menu = $3;
}
| styles CHARACTERISTICS numexpr
{
sub_res_info.characteristics = $3;
}
| styles LANGUAGE numexpr cnumexpr
{
sub_res_info.language = $3 | ($4 << SUBLANG_SHIFT);
1999-05-03 09:29:11 +02:00
}
| styles VERSIONK numexpr
{
sub_res_info.version = $3;
}
;
controls:
/* empty */
| controls control
{
2007-05-23 10:48:29 +02:00
rc_dialog_control **pp;
1999-05-03 09:29:11 +02:00
for (pp = &dialog.controls; *pp != NULL; pp = &(*pp)->next)
;
*pp = $2;
}
;
control:
AUTO3STATE optresidc
1999-05-03 09:29:11 +02:00
{
default_style = BS_AUTO3STATE | WS_TABSTOP;
base_style = BS_AUTO3STATE;
2007-05-23 10:48:29 +02:00
class.named = 0;
class.u.id = CTL_BUTTON;
res_text_field = $2;
1999-05-03 09:29:11 +02:00
}
control_params
{
$$ = $4;
1999-05-03 09:29:11 +02:00
}
| AUTOCHECKBOX optresidc
1999-05-03 09:29:11 +02:00
{
default_style = BS_AUTOCHECKBOX | WS_TABSTOP;
base_style = BS_AUTOCHECKBOX;
2007-05-23 10:48:29 +02:00
class.named = 0;
class.u.id = CTL_BUTTON;
res_text_field = $2;
1999-05-03 09:29:11 +02:00
}
control_params
{
$$ = $4;
1999-05-03 09:29:11 +02:00
}
| AUTORADIOBUTTON optresidc
1999-05-03 09:29:11 +02:00
{
default_style = BS_AUTORADIOBUTTON | WS_TABSTOP;
base_style = BS_AUTORADIOBUTTON;
2007-05-23 10:48:29 +02:00
class.named = 0;
class.u.id = CTL_BUTTON;
res_text_field = $2;
1999-05-03 09:29:11 +02:00
}
control_params
{
$$ = $4;
1999-05-03 09:29:11 +02:00
}
| BEDIT optresidc
1999-05-03 09:29:11 +02:00
{
default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
2007-05-23 10:48:29 +02:00
class.named = 0;
class.u.id = CTL_EDIT;
res_text_field = $2;
1999-05-03 09:29:11 +02:00
}
control_params
{
$$ = $4;
1999-05-03 09:29:11 +02:00
if (dialog.ex == NULL)
2002-04-09 17:23:38 +02:00
rcparse_warning (_("BEDIT requires DIALOGEX"));
1999-05-03 09:29:11 +02:00
res_string_to_id (&$$->class, "BEDIT");
}
| CHECKBOX optresidc
1999-05-03 09:29:11 +02:00
{
default_style = BS_CHECKBOX | WS_TABSTOP;
base_style = BS_CHECKBOX | WS_TABSTOP;
2007-05-23 10:48:29 +02:00
class.named = 0;
class.u.id = CTL_BUTTON;
res_text_field = $2;
1999-05-03 09:29:11 +02:00
}
control_params
{
$$ = $4;
1999-05-03 09:29:11 +02:00
}
| COMBOBOX
{
/* This is as per MSDN documentation. With some (???)
versions of MS rc.exe their is no default style. */
1999-05-03 09:29:11 +02:00
default_style = CBS_SIMPLE | WS_TABSTOP;
base_style = 0;
2007-05-23 10:48:29 +02:00
class.named = 0;
class.u.id = CTL_COMBOBOX;
res_text_field = res_null_text;
1999-05-03 09:29:11 +02:00
}
control_params
{
$$ = $3;
}
2007-05-23 10:48:29 +02:00
| CONTROL optresidc numexpr cresid control_styleexpr cnumexpr
1999-05-03 09:29:11 +02:00
cnumexpr cnumexpr cnumexpr optcnumexpr opt_control_data
{
$$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10);
if ($11 != NULL)
{
if (dialog.ex == NULL)
rcparse_warning (_("control data requires DIALOGEX"));
$$->data = $11;
}
}
2007-05-23 10:48:29 +02:00
| CONTROL optresidc numexpr cresid control_styleexpr cnumexpr
1999-05-03 09:29:11 +02:00
cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data
{
$$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10);
if (dialog.ex == NULL)
rcparse_warning (_("help ID requires DIALOGEX"));
$$->help = $11;
$$->data = $12;
}
| CTEXT optresidc
1999-05-03 09:29:11 +02:00
{
default_style = SS_CENTER | WS_GROUP;
base_style = SS_CENTER;
2007-05-23 10:48:29 +02:00
class.named = 0;
class.u.id = CTL_STATIC;
res_text_field = $2;
1999-05-03 09:29:11 +02:00
}
control_params
{
$$ = $4;
1999-05-03 09:29:11 +02:00
}
| DEFPUSHBUTTON optresidc
1999-05-03 09:29:11 +02:00
{
default_style = BS_DEFPUSHBUTTON | WS_TABSTOP;
base_style = BS_DEFPUSHBUTTON | WS_TABSTOP;
2007-05-23 10:48:29 +02:00
class.named = 0;
class.u.id = CTL_BUTTON;
res_text_field = $2;
1999-05-03 09:29:11 +02:00
}
control_params
{
$$ = $4;
1999-05-03 09:29:11 +02:00
}
| EDITTEXT
{
default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
2007-05-23 10:48:29 +02:00
class.named = 0;
class.u.id = CTL_EDIT;
res_text_field = res_null_text;
1999-05-03 09:29:11 +02:00
}
control_params
{
$$ = $3;
}
| GROUPBOX optresidc
1999-05-03 09:29:11 +02:00
{
default_style = BS_GROUPBOX;
base_style = BS_GROUPBOX;
2007-05-23 10:48:29 +02:00
class.named = 0;
class.u.id = CTL_BUTTON;
res_text_field = $2;
1999-05-03 09:29:11 +02:00
}
control_params
{
$$ = $4;
1999-05-03 09:29:11 +02:00
}
| HEDIT optresidc
1999-05-03 09:29:11 +02:00
{
default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
2007-05-23 10:48:29 +02:00
class.named = 0;
class.u.id = CTL_EDIT;
res_text_field = $2;
1999-05-03 09:29:11 +02:00
}
control_params
{
$$ = $4;
1999-05-03 09:29:11 +02:00
if (dialog.ex == NULL)
rcparse_warning (_("IEDIT requires DIALOGEX"));
res_string_to_id (&$$->class, "HEDIT");
}
| ICON resref numexpr cnumexpr cnumexpr opt_control_data
{
$$ = define_icon_control ($2, $3, $4, $5, 0, 0, 0, $6,
dialog.ex);
}
| ICON resref numexpr cnumexpr cnumexpr cnumexpr cnumexpr
opt_control_data
{
$$ = define_icon_control ($2, $3, $4, $5, 0, 0, 0, $8,
dialog.ex);
}
| ICON resref numexpr cnumexpr cnumexpr cnumexpr cnumexpr
1999-05-03 09:29:11 +02:00
icon_styleexpr optcnumexpr opt_control_data
{
$$ = define_icon_control ($2, $3, $4, $5, style, $9, 0, $10,
dialog.ex);
}
| ICON resref numexpr cnumexpr cnumexpr cnumexpr cnumexpr
1999-05-03 09:29:11 +02:00
icon_styleexpr cnumexpr cnumexpr opt_control_data
{
$$ = define_icon_control ($2, $3, $4, $5, style, $9, $10, $11,
dialog.ex);
}
| IEDIT optresidc
1999-05-03 09:29:11 +02:00
{
default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
2007-05-23 10:48:29 +02:00
class.named = 0;
class.u.id = CTL_EDIT;
res_text_field = $2;
1999-05-03 09:29:11 +02:00
}
control_params
{
$$ = $4;
1999-05-03 09:29:11 +02:00
if (dialog.ex == NULL)
rcparse_warning (_("IEDIT requires DIALOGEX"));
res_string_to_id (&$$->class, "IEDIT");
}
| LISTBOX
{
default_style = LBS_NOTIFY | WS_BORDER;
base_style = LBS_NOTIFY | WS_BORDER;
2007-05-23 10:48:29 +02:00
class.named = 0;
class.u.id = CTL_LISTBOX;
res_text_field = res_null_text;
1999-05-03 09:29:11 +02:00
}
control_params
{
$$ = $3;
}
| LTEXT optresidc
1999-05-03 09:29:11 +02:00
{
default_style = SS_LEFT | WS_GROUP;
base_style = SS_LEFT;
2007-05-23 10:48:29 +02:00
class.named = 0;
class.u.id = CTL_STATIC;
res_text_field = $2;
1999-05-03 09:29:11 +02:00
}
control_params
{
$$ = $4;
1999-05-03 09:29:11 +02:00
}
| PUSHBOX optresidc
1999-05-03 09:29:11 +02:00
{
default_style = BS_PUSHBOX | WS_TABSTOP;
base_style = BS_PUSHBOX;
2007-05-23 10:48:29 +02:00
class.named = 0;
class.u.id = CTL_BUTTON;
1999-05-03 09:29:11 +02:00
}
control_params
{
$$ = $4;
1999-05-03 09:29:11 +02:00
}
| PUSHBUTTON optresidc
1999-05-03 09:29:11 +02:00
{
default_style = BS_PUSHBUTTON | WS_TABSTOP;
base_style = BS_PUSHBUTTON | WS_TABSTOP;
2007-05-23 10:48:29 +02:00
class.named = 0;
class.u.id = CTL_BUTTON;
res_text_field = $2;
1999-05-03 09:29:11 +02:00
}
control_params
{
$$ = $4;
1999-05-03 09:29:11 +02:00
}
| RADIOBUTTON optresidc
1999-05-03 09:29:11 +02:00
{
default_style = BS_RADIOBUTTON | WS_TABSTOP;
base_style = BS_RADIOBUTTON;
2007-05-23 10:48:29 +02:00
class.named = 0;
class.u.id = CTL_BUTTON;
res_text_field = $2;
1999-05-03 09:29:11 +02:00
}
control_params
{
$$ = $4;
1999-05-03 09:29:11 +02:00
}
| RTEXT optresidc
1999-05-03 09:29:11 +02:00
{
default_style = SS_RIGHT | WS_GROUP;
base_style = SS_RIGHT;
2007-05-23 10:48:29 +02:00
class.named = 0;
class.u.id = CTL_STATIC;
res_text_field = $2;
1999-05-03 09:29:11 +02:00
}
control_params
{
$$ = $4;
1999-05-03 09:29:11 +02:00
}
| SCROLLBAR
{
default_style = SBS_HORZ;
base_style = 0;
2007-05-23 10:48:29 +02:00
class.named = 0;
class.u.id = CTL_SCROLLBAR;
res_text_field = res_null_text;
1999-05-03 09:29:11 +02:00
}
control_params
{
$$ = $3;
}
| STATE3 optresidc
1999-05-03 09:29:11 +02:00
{
default_style = BS_3STATE | WS_TABSTOP;
base_style = BS_3STATE;
2007-05-23 10:48:29 +02:00
class.named = 0;
class.u.id = CTL_BUTTON;
res_text_field = $2;
1999-05-03 09:29:11 +02:00
}
control_params
{
$$ = $4;
1999-05-03 09:29:11 +02:00
}
| USERBUTTON resref numexpr ',' numexpr ',' numexpr ','
1999-05-03 09:29:11 +02:00
numexpr ',' numexpr ','
{ style = WS_CHILD | WS_VISIBLE; }
styleexpr optcnumexpr
{
2007-05-23 10:48:29 +02:00
rc_res_id cid;
cid.named = 0;
cid.u.id = CTL_BUTTON;
$$ = define_control ($2, $3, $5, $7, $9, $11, cid,
style, $15);
1999-05-03 09:29:11 +02:00
}
;
/* Parameters for a control. The static variables DEFAULT_STYLE,
BASE_STYLE, and CLASS must be initialized before this nonterminal
is used. DEFAULT_STYLE is the style to use if no style expression
is specified. BASE_STYLE is the base style to use if a style
expression is specified; the style expression modifies the base
style. CLASS is the class of the control. */
control_params:
numexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data
1999-05-03 09:29:11 +02:00
{
$$ = define_control (res_text_field, $1, $2, $3, $4, $5, class,
1999-05-03 09:29:11 +02:00
default_style | WS_CHILD | WS_VISIBLE, 0);
if ($6 != NULL)
1999-05-03 09:29:11 +02:00
{
if (dialog.ex == NULL)
rcparse_warning (_("control data requires DIALOGEX"));
$$->data = $6;
1999-05-03 09:29:11 +02:00
}
}
| numexpr cnumexpr cnumexpr cnumexpr cnumexpr
1999-05-03 09:29:11 +02:00
control_params_styleexpr optcnumexpr opt_control_data
{
$$ = define_control (res_text_field, $1, $2, $3, $4, $5, class, style, $7);
if ($8 != NULL)
1999-05-03 09:29:11 +02:00
{
if (dialog.ex == NULL)
rcparse_warning (_("control data requires DIALOGEX"));
$$->data = $8;
1999-05-03 09:29:11 +02:00
}
}
| numexpr cnumexpr cnumexpr cnumexpr cnumexpr
1999-05-03 09:29:11 +02:00
control_params_styleexpr cnumexpr cnumexpr opt_control_data
{
$$ = define_control (res_text_field, $1, $2, $3, $4, $5, class, style, $7);
1999-05-03 09:29:11 +02:00
if (dialog.ex == NULL)
rcparse_warning (_("help ID requires DIALOGEX"));
$$->help = $8;
$$->data = $9;
1999-05-03 09:29:11 +02:00
}
;
2007-05-23 10:48:29 +02:00
cresid:
',' resid
{
if ($2.named)
res_unistring_to_id (&$$, $2.u.n.name);
else
$$=$2;
}
;
optresidc:
1999-05-03 09:29:11 +02:00
/* empty */
{
res_string_to_id (&$$, "");
}
2007-05-23 10:48:29 +02:00
| resid ',' { $$=$1; }
;
resid:
posnumexpr
{
$$.named = 0;
$$.u.id = $1;
1999-05-03 09:29:11 +02:00
}
| res_unicode_string_concat
{
2007-05-23 10:48:29 +02:00
$$.named = 1;
$$.u.n.name = $1;
$$.u.n.length = unichar_len ($1);
1999-05-03 09:29:11 +02:00
}
;
opt_control_data:
/* empty */
{
$$ = NULL;
}
| BEG optrcdata_data END
{
$$ = $2.first;
}
;
/* These only exist to parse a reduction out of a common case. */
control_styleexpr:
','
{ style = WS_CHILD | WS_VISIBLE; }
styleexpr
;
icon_styleexpr:
','
{ style = SS_ICON | WS_CHILD | WS_VISIBLE; }
styleexpr
;
control_params_styleexpr:
','
{ style = base_style | WS_CHILD | WS_VISIBLE; }
styleexpr
;
/* Font resources. */
font:
id FONT memflags_move_discard file_name
{
define_font ($1, &$3, $4);
if (yychar != YYEMPTY)
YYERROR;
rcparse_discard_strings ();
1999-05-03 09:29:11 +02:00
}
;
/* Icon resources. */
icon:
id ICON memflags_move_discard file_name
{
define_icon ($1, &$3, $4);
if (yychar != YYEMPTY)
YYERROR;
rcparse_discard_strings ();
1999-05-03 09:29:11 +02:00
}
;
/* Language command. This changes the static variable language, which
affects all subsequent resources. */
language:
LANGUAGE numexpr cnumexpr
{
language = $2 | ($3 << SUBLANG_SHIFT);
1999-05-03 09:29:11 +02:00
}
;
/* Menu resources. */
menu:
id MENU suboptions BEG menuitems END
{
define_menu ($1, &$3, $5);
if (yychar != YYEMPTY)
YYERROR;
rcparse_discard_strings ();
1999-05-03 09:29:11 +02:00
}
;
menuitems:
/* empty */
{
$$ = NULL;
}
| menuitems menuitem
{
if ($1 == NULL)
$$ = $2;
else
{
2007-05-23 10:48:29 +02:00
rc_menuitem **pp;
1999-05-03 09:29:11 +02:00
for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
;
*pp = $2;
$$ = $1;
}
}
;
menuitem:
MENUITEM res_unicode_string_concat cnumexpr menuitem_flags
1999-05-03 09:29:11 +02:00
{
$$ = define_menuitem ($2, $3, $4, 0, 0, NULL);
}
| MENUITEM SEPARATOR
{
$$ = define_menuitem (NULL, 0, 0, 0, 0, NULL);
}
| POPUP res_unicode_string_concat menuitem_flags BEG menuitems END
1999-05-03 09:29:11 +02:00
{
$$ = define_menuitem ($2, 0, $3, 0, 0, $5);
}
;
menuitem_flags:
/* empty */
{
$$ = 0;
}
| menuitem_flags ',' menuitem_flag
{
$$ = $1 | $3;
}
| menuitem_flags menuitem_flag
{
$$ = $1 | $2;
}
;
menuitem_flag:
CHECKED
{
$$ = MENUITEM_CHECKED;
}
| GRAYED
{
$$ = MENUITEM_GRAYED;
}
| HELP
{
$$ = MENUITEM_HELP;
}
| INACTIVE
{
$$ = MENUITEM_INACTIVE;
}
| MENUBARBREAK
{
$$ = MENUITEM_MENUBARBREAK;
}
| MENUBREAK
{
$$ = MENUITEM_MENUBREAK;
}
;
/* Menuex resources. */
menuex:
id MENUEX suboptions BEG menuexitems END
{
define_menu ($1, &$3, $5);
if (yychar != YYEMPTY)
YYERROR;
rcparse_discard_strings ();
1999-05-03 09:29:11 +02:00
}
;
menuexitems:
/* empty */
{
$$ = NULL;
}
| menuexitems menuexitem
{
if ($1 == NULL)
$$ = $2;
else
{
2007-05-23 10:48:29 +02:00
rc_menuitem **pp;
1999-05-03 09:29:11 +02:00
for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
;
*pp = $2;
$$ = $1;
}
}
;
menuexitem:
MENUITEM res_unicode_string_concat
1999-05-03 09:29:11 +02:00
{
$$ = define_menuitem ($2, 0, 0, 0, 0, NULL);
}
| MENUITEM res_unicode_string_concat cnumexpr
1999-05-03 09:29:11 +02:00
{
$$ = define_menuitem ($2, $3, 0, 0, 0, NULL);
}
| MENUITEM res_unicode_string_concat cnumexpr cnumexpr optcnumexpr
1999-05-03 09:29:11 +02:00
{
$$ = define_menuitem ($2, $3, $4, $5, 0, NULL);
}
| MENUITEM SEPARATOR
{
$$ = define_menuitem (NULL, 0, 0, 0, 0, NULL);
}
| POPUP res_unicode_string_concat BEG menuexitems END
1999-05-03 09:29:11 +02:00
{
$$ = define_menuitem ($2, 0, 0, 0, 0, $4);
}
| POPUP res_unicode_string_concat cnumexpr BEG menuexitems END
1999-05-03 09:29:11 +02:00
{
$$ = define_menuitem ($2, $3, 0, 0, 0, $5);
}
| POPUP res_unicode_string_concat cnumexpr cnumexpr BEG menuexitems END
1999-05-03 09:29:11 +02:00
{
$$ = define_menuitem ($2, $3, $4, 0, 0, $6);
}
| POPUP res_unicode_string_concat cnumexpr cnumexpr cnumexpr optcnumexpr
1999-05-03 09:29:11 +02:00
BEG menuexitems END
{
$$ = define_menuitem ($2, $3, $4, $5, $6, $8);
}
;
/* Messagetable resources. */
messagetable:
id MESSAGETABLE memflags_move file_name
{
define_messagetable ($1, &$3, $4);
if (yychar != YYEMPTY)
YYERROR;
rcparse_discard_strings ();
1999-05-03 09:29:11 +02:00
}
;
/* We use a different lexing algorithm, because rcdata strings may
contain embedded null bytes, and we need to know the length to use. */
optrcdata_data:
{
rcparse_rcdata ();
}
optrcdata_data_int
{
rcparse_normal ();
$$ = $2;
}
;
optrcdata_data_int:
/* empty */
{
$$.first = NULL;
$$.last = NULL;
}
| rcdata_data
{
$$ = $1;
}
;
rcdata_data:
2007-05-23 10:48:29 +02:00
sizedstring
1999-05-03 09:29:11 +02:00
{
2007-05-23 10:48:29 +02:00
rc_rcdata_item *ri;
1999-05-03 09:29:11 +02:00
ri = define_rcdata_string ($1.s, $1.length);
$$.first = ri;
$$.last = ri;
}
2007-05-23 10:48:29 +02:00
| sizedunistring
{
rc_rcdata_item *ri;
ri = define_rcdata_unistring ($1.s, $1.length);
$$.first = ri;
$$.last = ri;
}
1999-05-03 09:29:11 +02:00
| sizednumexpr
{
2007-05-23 10:48:29 +02:00
rc_rcdata_item *ri;
1999-05-03 09:29:11 +02:00
ri = define_rcdata_number ($1.val, $1.dword);
$$.first = ri;
$$.last = ri;
}
2007-05-23 10:48:29 +02:00
| rcdata_data ',' sizedstring
1999-05-03 09:29:11 +02:00
{
2007-05-23 10:48:29 +02:00
rc_rcdata_item *ri;
1999-05-03 09:29:11 +02:00
ri = define_rcdata_string ($3.s, $3.length);
$$.first = $1.first;
$1.last->next = ri;
$$.last = ri;
}
2007-05-23 10:48:29 +02:00
| rcdata_data ',' sizedunistring
{
rc_rcdata_item *ri;
ri = define_rcdata_unistring ($3.s, $3.length);
$$.first = $1.first;
$1.last->next = ri;
$$.last = ri;
}
1999-05-03 09:29:11 +02:00
| rcdata_data ',' sizednumexpr
{
2007-05-23 10:48:29 +02:00
rc_rcdata_item *ri;
1999-05-03 09:29:11 +02:00
ri = define_rcdata_number ($3.val, $3.dword);
$$.first = $1.first;
$1.last->next = ri;
$$.last = ri;
}
| rcdata_data ','
{
$$=$1;
}
1999-05-03 09:29:11 +02:00
;
/* Stringtable resources. */
stringtable:
STRINGTABLE suboptions BEG
{ sub_res_info = $2; rcparse_rcdata (); }
string_data END { rcparse_normal (); }
1999-05-03 09:29:11 +02:00
;
string_data:
/* empty */
| string_data numexpr res_unicode_sizedstring_concat
1999-05-03 09:29:11 +02:00
{
define_stringtable (&sub_res_info, $2, $3.s, $3.length);
rcparse_discard_strings ();
1999-05-03 09:29:11 +02:00
}
| string_data numexpr ',' res_unicode_sizedstring_concat
1999-05-03 09:29:11 +02:00
{
define_stringtable (&sub_res_info, $2, $4.s, $4.length);
rcparse_discard_strings ();
1999-05-03 09:29:11 +02:00
}
| string_data error
{
rcparse_warning (_("invalid stringtable resource."));
abort ();
}
1999-05-03 09:29:11 +02:00
;
2007-05-23 10:48:29 +02:00
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;
}
;
1999-05-03 09:29:11 +02:00
/* User defined resources. We accept general suboptions in the
file_name case to keep the parser happy. */
user:
2007-05-23 10:48:29 +02:00
id rcdata_id suboptions BEG optrcdata_data END
1999-05-03 09:29:11 +02:00
{
define_user_data ($1, $2, &$3, $5.first);
if (yychar != YYEMPTY)
YYERROR;
rcparse_discard_strings ();
1999-05-03 09:29:11 +02:00
}
2007-05-23 10:48:29 +02:00
| id rcdata_id suboptions file_name
1999-05-03 09:29:11 +02:00
{
define_user_file ($1, $2, &$3, $4);
if (yychar != YYEMPTY)
YYERROR;
rcparse_discard_strings ();
1999-05-03 09:29:11 +02:00
}
;
2007-05-23 10:48:29 +02:00
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;
}
;
1999-05-03 09:29:11 +02:00
/* Versioninfo resources. */
versioninfo:
id VERSIONINFO fixedverinfo BEG verblocks END
{
define_versioninfo ($1, language, $3, $5);
if (yychar != YYEMPTY)
YYERROR;
rcparse_discard_strings ();
1999-05-03 09:29:11 +02:00
}
;
fixedverinfo:
/* empty */
{
2007-05-23 10:48:29 +02:00
$$ = ((rc_fixed_versioninfo *)
res_alloc (sizeof (rc_fixed_versioninfo)));
memset ($$, 0, sizeof (rc_fixed_versioninfo));
1999-05-03 09:29:11 +02:00
}
| fixedverinfo FILEVERSION numexpr optcnumexpr optcnumexpr
optcnumexpr
1999-05-03 09:29:11 +02:00
{
$1->file_version_ms = ($3 << 16) | $4;
$1->file_version_ls = ($5 << 16) | $6;
$$ = $1;
}
| fixedverinfo PRODUCTVERSION numexpr optcnumexpr optcnumexpr
optcnumexpr
1999-05-03 09:29:11 +02:00
{
$1->product_version_ms = ($3 << 16) | $4;
$1->product_version_ls = ($5 << 16) | $6;
$$ = $1;
}
| fixedverinfo FILEFLAGSMASK numexpr
{
$1->file_flags_mask = $3;
$$ = $1;
}
| fixedverinfo FILEFLAGS numexpr
{
$1->file_flags = $3;
$$ = $1;
}
| fixedverinfo FILEOS numexpr
{
$1->file_os = $3;
$$ = $1;
}
| fixedverinfo FILETYPE numexpr
{
$1->file_type = $3;
$$ = $1;
}
| fixedverinfo FILESUBTYPE numexpr
{
$1->file_subtype = $3;
$$ = $1;
}
;
/* To handle verblocks successfully, the lexer handles BLOCK
specially. A BLOCK "StringFileInfo" is returned as
BLOCKSTRINGFILEINFO. A BLOCK "VarFileInfo" is returned as
BLOCKVARFILEINFO. A BLOCK with some other string returns BLOCK
with the string as the value. */
verblocks:
/* empty */
{
$$ = NULL;
}
| verblocks BLOCKSTRINGFILEINFO BEG verstringtables END
1999-05-03 09:29:11 +02:00
{
$$ = append_ver_stringfileinfo ($1, $4);
1999-05-03 09:29:11 +02:00
}
| verblocks BLOCKVARFILEINFO BEG VALUE res_unicode_string_concat vertrans END
1999-05-03 09:29:11 +02:00
{
$$ = append_ver_varfileinfo ($1, $5, $6);
}
;
verstringtables:
/* empty */
{
$$ = NULL;
}
| verstringtables BLOCK BEG vervals END
{
$$ = append_ver_stringtable ($1, $2, $4);
}
;
1999-05-03 09:29:11 +02:00
vervals:
/* empty */
{
$$ = NULL;
}
| vervals VALUE res_unicode_string_concat ',' res_unicode_string_concat
1999-05-03 09:29:11 +02:00
{
$$ = append_verval ($1, $3, $5);
}
;
vertrans:
/* empty */
{
$$ = NULL;
}
| vertrans cnumexpr cnumexpr
{
$$ = append_vertrans ($1, $2, $3);
}
;
/* A resource ID. */
id:
posnumexpr
{
$$.named = 0;
$$.u.id = $1;
}
2007-05-23 10:48:29 +02:00
| resname
{
res_unistring_to_id (&$$, $1);
1999-05-03 09:29:11 +02:00
}
;
/* A resource reference. */
resname:
2007-05-23 10:48:29 +02:00
res_unicode_string
{
$$ = $1;
}
2007-05-23 10:48:29 +02:00
| STRING
{
2007-05-23 10:48:29 +02:00
unichar *h = NULL;
unicode_from_ascii ((rc_uint_type *) NULL, &h, $1);
$$ = h;
}
;
resref:
posnumexpr ','
{
$$.named = 0;
$$.u.id = $1;
}
| resname
{
2007-05-23 10:48:29 +02:00
res_unistring_to_id (&$$, $1);
}
| resname ','
{
res_unistring_to_id (&$$, $1);
}
;
1999-05-03 09:29:11 +02:00
/* Generic suboptions. These may appear before the BEGIN in any
multiline statement. */
suboptions:
/* empty */
{
2007-05-23 10:48:29 +02:00
memset (&$$, 0, sizeof (rc_res_res_info));
1999-05-03 09:29:11 +02:00
$$.language = language;
/* FIXME: Is this the right default? */
$$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_PURE | MEMFLAG_DISCARDABLE;
1999-05-03 09:29:11 +02:00
}
| suboptions memflag
{
$$ = $1;
$$.memflags |= $2.on;
$$.memflags &=~ $2.off;
}
| suboptions CHARACTERISTICS numexpr
{
$$ = $1;
$$.characteristics = $3;
}
| suboptions LANGUAGE numexpr cnumexpr
{
$$ = $1;
$$.language = $3 | ($4 << SUBLANG_SHIFT);
1999-05-03 09:29:11 +02:00
}
| suboptions VERSIONK numexpr
{
$$ = $1;
$$.version = $3;
}
;
/* Memory flags which default to MOVEABLE and DISCARDABLE. */
memflags_move_discard:
/* empty */
{
2007-05-23 10:48:29 +02:00
memset (&$$, 0, sizeof (rc_res_res_info));
1999-05-03 09:29:11 +02:00
$$.language = language;
$$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_DISCARDABLE;
}
| memflags_move_discard memflag
{
$$ = $1;
$$.memflags |= $2.on;
$$.memflags &=~ $2.off;
}
;
/* Memory flags which default to MOVEABLE. */
memflags_move:
/* empty */
{
2007-05-23 10:48:29 +02:00
memset (&$$, 0, sizeof (rc_res_res_info));
1999-05-03 09:29:11 +02:00
$$.language = language;
$$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_PURE | MEMFLAG_DISCARDABLE;
1999-05-03 09:29:11 +02:00
}
| memflags_move memflag
{
$$ = $1;
$$.memflags |= $2.on;
$$.memflags &=~ $2.off;
}
;
/* Memory flags. This returns a struct with two integers, because we
sometimes want to set bits and we sometimes want to clear them. */
memflag:
MOVEABLE
{
$$.on = MEMFLAG_MOVEABLE;
$$.off = 0;
}
| FIXED
{
$$.on = 0;
$$.off = MEMFLAG_MOVEABLE;
}
| PURE
{
$$.on = MEMFLAG_PURE;
$$.off = 0;
}
| IMPURE
{
$$.on = 0;
$$.off = MEMFLAG_PURE;
}
| PRELOAD
{
$$.on = MEMFLAG_PRELOAD;
$$.off = 0;
}
| LOADONCALL
{
$$.on = 0;
$$.off = MEMFLAG_PRELOAD;
}
| DISCARDABLE
{
$$.on = MEMFLAG_DISCARDABLE;
$$.off = 0;
}
;
/* A file name. */
file_name:
QUOTEDSTRING
{
$$ = $1;
}
| STRING
{
$$ = $1;
}
;
/* 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;
}
;
2007-05-23 10:48:29 +02:00
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;
}
;
2007-05-23 10:48:29 +02:00
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;
}
;
1999-05-03 09:29:11 +02:00
/* 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
WS_GROUP | NOT WS_TABSTOP
to mean that a default of WS_TABSTOP should be removed. Anything
which wants to accept a style must first set STYLE to the default
value. The styleexpr nonterminal will change STYLE as specified by
the user. Note that we do not accept arbitrary expressions here,
just numbers separated by '|'. */
styleexpr:
parennumber
{
style |= $1;
}
| NOT parennumber
{
style &=~ $2;
}
| styleexpr '|' parennumber
{
style |= $3;
}
| styleexpr '|' NOT parennumber
{
style &=~ $4;
}
;
parennumber:
NUMBER
{
$$ = $1.val;
}
| '(' numexpr ')'
{
$$ = $2;
}
;
/* An optional expression with a leading comma. */
optcnumexpr:
/* empty */
{
$$ = 0;
}
| cnumexpr
{
$$ = $1;
}
;
/* An expression with a leading comma. */
cnumexpr:
',' numexpr
{
$$ = $2;
}
;
/* A possibly negated numeric expression. */
numexpr:
sizednumexpr
{
$$ = $1.val;
}
;
/* A possibly negated expression with a size. */
sizednumexpr:
NUMBER
{
$$ = $1;
}
| '(' sizednumexpr ')'
{
$$ = $2;
}
| '~' sizednumexpr %prec '~'
{
$$.val = ~ $2.val;
$$.dword = $2.dword;
}
| '-' sizednumexpr %prec NEG
{
$$.val = - $2.val;
$$.dword = $2.dword;
}
| sizednumexpr '*' sizednumexpr
{
$$.val = $1.val * $3.val;
$$.dword = $1.dword || $3.dword;
}
| sizednumexpr '/' sizednumexpr
{
$$.val = $1.val / $3.val;
$$.dword = $1.dword || $3.dword;
}
| sizednumexpr '%' sizednumexpr
{
$$.val = $1.val % $3.val;
$$.dword = $1.dword || $3.dword;
}
| sizednumexpr '+' sizednumexpr
{
$$.val = $1.val + $3.val;
$$.dword = $1.dword || $3.dword;
}
| sizednumexpr '-' sizednumexpr
{
$$.val = $1.val - $3.val;
$$.dword = $1.dword || $3.dword;
}
| sizednumexpr '&' sizednumexpr
{
$$.val = $1.val & $3.val;
$$.dword = $1.dword || $3.dword;
}
| sizednumexpr '^' sizednumexpr
{
$$.val = $1.val ^ $3.val;
$$.dword = $1.dword || $3.dword;
}
| sizednumexpr '|' sizednumexpr
{
$$.val = $1.val | $3.val;
$$.dword = $1.dword || $3.dword;
}
;
/* An expression with a leading comma which does not use unary
negation. */
cposnumexpr:
',' posnumexpr
{
$$ = $2;
}
;
/* An expression which does not use unary negation. */
posnumexpr:
sizedposnumexpr
{
$$ = $1.val;
}
;
/* An expression which does not use unary negation. We separate unary
negation to avoid parsing conflicts when two numeric expressions
appear consecutively. */
sizedposnumexpr:
NUMBER
{
$$ = $1;
}
| '(' sizednumexpr ')'
{
$$ = $2;
}
| '~' sizednumexpr %prec '~'
{
$$.val = ~ $2.val;
$$.dword = $2.dword;
}
| sizedposnumexpr '*' sizednumexpr
{
$$.val = $1.val * $3.val;
$$.dword = $1.dword || $3.dword;
}
| sizedposnumexpr '/' sizednumexpr
{
$$.val = $1.val / $3.val;
$$.dword = $1.dword || $3.dword;
}
| sizedposnumexpr '%' sizednumexpr
{
$$.val = $1.val % $3.val;
$$.dword = $1.dword || $3.dword;
}
| sizedposnumexpr '+' sizednumexpr
{
$$.val = $1.val + $3.val;
$$.dword = $1.dword || $3.dword;
}
| sizedposnumexpr '-' sizednumexpr
{
$$.val = $1.val - $3.val;
$$.dword = $1.dword || $3.dword;
}
| sizedposnumexpr '&' sizednumexpr
{
$$.val = $1.val & $3.val;
$$.dword = $1.dword || $3.dword;
}
| sizedposnumexpr '^' sizednumexpr
{
$$.val = $1.val ^ $3.val;
$$.dword = $1.dword || $3.dword;
}
| sizedposnumexpr '|' sizednumexpr
{
$$.val = $1.val | $3.val;
$$.dword = $1.dword || $3.dword;
}
;
%%
/* Set the language from the command line. */
void
rcparse_set_language (int lang)
1999-05-03 09:29:11 +02:00
{
language = lang;
}