summaryrefslogtreecommitdiff
path: root/binutils/mcparse.y
diff options
context:
space:
mode:
Diffstat (limited to 'binutils/mcparse.y')
-rw-r--r--binutils/mcparse.y356
1 files changed, 356 insertions, 0 deletions
diff --git a/binutils/mcparse.y b/binutils/mcparse.y
new file mode 100644
index 00000000000..9aaba9b8d41
--- /dev/null
+++ b/binutils/mcparse.y
@@ -0,0 +1,356 @@
+%{ /* mcparse.y -- parser for Windows mc files
+ Copyright 2007
+ Free Software Foundation, Inc.
+
+ Parser for Windows mc files
+ Written 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
+ the Free Software Foundation; either version 2 of the License, or
+ (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
+ 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>. */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "windmc.h"
+#include "safe-ctype.h"
+
+static rc_uint_type mc_last_id = 0;
+static rc_uint_type mc_sefa_val = 0;
+static unichar *mc_last_symbol = NULL;
+static const mc_keyword *mc_cur_severity = NULL;
+static const mc_keyword *mc_cur_facility = NULL;
+static mc_node *cur_node = NULL;
+
+%}
+
+%union
+{
+ rc_uint_type ival;
+ unichar *ustr;
+ const mc_keyword *tok;
+ mc_node *nod;
+};
+
+%start input
+
+%token NL
+%token<ustr> MCIDENT MCFILENAME MCLINE MCCOMMENT
+%token<tok> MCTOKEN
+%token MCENDLINE
+%token MCLANGUAGENAMES MCFACILITYNAMES MCSEVERITYNAMES MCOUTPUTBASE MCMESSAGEIDTYPEDEF
+%token MCLANGUAGE MCMESSAGEID MCSEVERITY MCFACILITY MCSYMBOLICNAME
+%token <ival> MCNUMBER
+
+%type<ival> id vid sefasy_def
+%type<ustr> alias_name token lines comments
+%type<tok> lang
+
+%%
+input: entities
+ ;
+
+entities:
+ /* empty */
+ | entities entity
+ ;
+entity: global_section
+ | message
+ | comments
+ {
+ cur_node = mc_add_node ();
+ cur_node->user_text = $1;
+ }
+ | error { mc_fatal ("syntax error"); }
+;
+
+global_section:
+ MCSEVERITYNAMES '=' '(' severitymaps ')'
+ | MCSEVERITYNAMES '=' '(' severitymaps error { mc_fatal ("missing ')' in SeverityNames"); }
+ | MCSEVERITYNAMES '=' error { mc_fatal ("missing '(' in SeverityNames"); }
+ | MCSEVERITYNAMES error { mc_fatal ("missing '=' for SeverityNames"); }
+ | MCLANGUAGENAMES '=' '(' langmaps ')'
+ | MCLANGUAGENAMES '=' '(' langmaps error { mc_fatal ("missing ')' in LanguageNames"); }
+ | MCLANGUAGENAMES '=' error { mc_fatal ("missing '(' in LanguageNames"); }
+ | MCLANGUAGENAMES error { mc_fatal ("missing '=' for LanguageNames"); }
+ | MCFACILITYNAMES '=' '(' facilitymaps ')'
+ | MCFACILITYNAMES '=' '(' facilitymaps error { mc_fatal ("missing ')' in FacilityNames"); }
+ | MCFACILITYNAMES '=' error { mc_fatal ("missing '(' in FacilityNames"); }
+ | MCFACILITYNAMES error { mc_fatal ("missing '=' for FacilityNames"); }
+ | MCOUTPUTBASE '=' MCNUMBER
+ {
+ if ($3 != 10 && $3 != 16)
+ mc_fatal ("OutputBase allows 10 or 16 as value");
+ mcset_out_values_are_decimal = ($3 == 10 ? 1 : 0);
+ }
+ | MCMESSAGEIDTYPEDEF '=' MCIDENT
+ {
+ mcset_msg_id_typedef = $3;
+ }
+ | MCMESSAGEIDTYPEDEF '=' error
+ {
+ mc_fatal ("MessageIdTypedef expects an identifier");
+ }
+ | MCMESSAGEIDTYPEDEF error
+ {
+ mc_fatal ("missing '=' for MessageIdTypedef");
+ }
+;
+
+severitymaps:
+ severitymap
+ | severitymaps severitymap
+ | error { mc_fatal ("severity ident missing"); }
+;
+
+severitymap:
+ token '=' MCNUMBER alias_name
+ {
+ mc_add_keyword ($1, MCTOKEN, "severity", $3, $4);
+ }
+ | token '=' error { mc_fatal ("severity number missing"); }
+ | token error { mc_fatal ("severity missing '='"); }
+;
+
+facilitymaps:
+ facilitymap
+ | facilitymaps facilitymap
+ | error { mc_fatal ("missing ident in FacilityNames"); }
+;
+
+facilitymap:
+ token '=' MCNUMBER alias_name
+ {
+ mc_add_keyword ($1, MCTOKEN, "facility", $3, $4);
+ }
+ | token '=' error { mc_fatal ("facility number missing"); }
+ | token error { mc_fatal ("facility missing '='"); }
+;
+
+langmaps:
+ langmap
+ | langmaps langmap
+ | error { mc_fatal ("missing ident in LanguageNames"); }
+;
+
+langmap:
+ token '=' MCNUMBER lex_want_filename ':' MCFILENAME
+ {
+ mc_add_keyword ($1, MCTOKEN, "language", $3, $6);
+ }
+ | token '=' MCNUMBER lex_want_filename ':' error { mc_fatal ("missing filename in LanguageNames"); }
+ | token '=' MCNUMBER error { mc_fatal ("missing ':' in LanguageNames"); }
+ | token '=' error { mc_fatal ("missing language code in LanguageNames"); }
+ | token error { mc_fatal ("missing '=' for LanguageNames"); }
+;
+
+alias_name:
+ /* empty */
+ {
+ $$ = NULL;
+ }
+ | ':' MCIDENT
+ {
+ $$ = $2;
+ }
+ | ':' error { mc_fatal ("illegal token in identifier"); $$ = NULL; }
+;
+
+message:
+ id sefasy_def
+ {
+ cur_node = mc_add_node ();
+ cur_node->symbol = mc_last_symbol;
+ cur_node->facility = mc_cur_facility;
+ cur_node->severity = mc_cur_severity;
+ cur_node->id = ($1 & 0xffffUL);
+ cur_node->vid = ($1 & 0xffffUL) | mc_sefa_val;
+ mc_last_id = $1;
+ }
+ lang_entities
+;
+
+id: MCMESSAGEID '=' vid { $$ = $3; }
+ | MCMESSAGEID '=' error { mc_fatal ("missing number in MessageId"); $$ = 0; }
+ | MCMESSAGEID error { mc_fatal ("missing '=' for MessageId"); $$ = 0; }
+;
+
+vid: /* empty */
+ {
+ $$ = ++mc_last_id;
+ }
+ | MCNUMBER
+ {
+ $$ = $1;
+ }
+ | '+' MCNUMBER
+ {
+ $$ = mc_last_id + $2;
+ }
+ | '+' error { mc_fatal ("missing number after MessageId '+'"); }
+;
+
+sefasy_def:
+ /* empty */
+ {
+ $$ = 0;
+ mc_sefa_val = (mcset_custom_bit ? 1 : 0) << 29;
+ mc_last_symbol = NULL;
+ mc_cur_severity = NULL;
+ mc_cur_facility = NULL;
+ }
+ | sefasy_def severity
+ {
+ if ($1 & 1)
+ mc_warn (_("duplicate definition of Severity"));
+ $$ = $1 | 1;
+ }
+ | sefasy_def facility
+ {
+ if ($1 & 2)
+ mc_warn (_("duplicate definition of Facility"));
+ $$ = $1 | 2;
+ }
+ | sefasy_def symbol
+ {
+ if ($1 & 4)
+ mc_warn (_("duplicate definition of SymbolicName"));
+ $$ = $1 | 4;
+ }
+;
+
+severity: MCSEVERITY '=' MCTOKEN
+ {
+ mc_sefa_val &= ~ (0x3UL << 30);
+ mc_sefa_val |= (($3->nval & 0x3UL) << 30);
+ mc_cur_severity = $3;
+ }
+;
+
+facility: MCFACILITY '=' MCTOKEN
+ {
+ mc_sefa_val &= ~ (0xfffUL << 16);
+ mc_sefa_val |= (($3->nval & 0xfffUL) << 16);
+ mc_cur_facility = $3;
+ }
+;
+
+symbol: MCSYMBOLICNAME '=' MCIDENT
+ {
+ mc_last_symbol = $3;
+ }
+;
+
+lang_entities:
+ lang_entity
+ | lang_entities lang_entity
+;
+
+lang_entity:
+ lang lex_want_line lines MCENDLINE
+ {
+ mc_node_lang *h;
+ h = mc_add_node_lang (cur_node, $1, cur_node->vid);
+ h->message = $3;
+ if (mcset_max_message_length != 0 && unichar_len (h->message) > mcset_max_message_length)
+ mc_warn ("message length to long");
+ }
+;
+
+lines: MCLINE
+ {
+ $$ = $1;
+ }
+ | lines MCLINE
+ {
+ unichar *h;
+ rc_uint_type l1,l2;
+ l1 = unichar_len ($1);
+ l2 = unichar_len ($2);
+ h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar));
+ if (l1) memcpy (h, $1, l1 * sizeof (unichar));
+ if (l2) memcpy (&h[l1], $2, l2 * sizeof (unichar));
+ h[l1 + l2] = 0;
+ $$ = h;
+ }
+ | error { mc_fatal ("missing end of message text"); $$ = NULL; }
+ | lines error { mc_fatal ("missing end of message text"); $$ = $1; }
+;
+
+comments: MCCOMMENT { $$ = $1; }
+ | comments MCCOMMENT
+ {
+ unichar *h;
+ rc_uint_type l1,l2;
+ l1 = unichar_len ($1);
+ l2 = unichar_len ($2);
+ h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar));
+ if (l1) memcpy (h, $1, l1 * sizeof (unichar));
+ if (l2) memcpy (&h[l1], $2, l2 * sizeof (unichar));
+ h[l1 + l2] = 0;
+ $$ = h;
+ }
+;
+
+lang: MCLANGUAGE lex_want_nl '=' MCTOKEN NL
+ {
+ $$ = $4;
+ }
+ | MCLANGUAGE lex_want_nl '=' MCIDENT NL
+ {
+ $$ = NULL;
+ mc_fatal (_("undeclared language identifier"));
+ }
+ | MCLANGUAGE lex_want_nl '=' token error
+ {
+ $$ = NULL;
+ mc_fatal ("missing newline after Language");
+ }
+ | MCLANGUAGE lex_want_nl '=' error
+ {
+ $$ = NULL;
+ mc_fatal ("missing ident for Language");
+ }
+ | MCLANGUAGE error
+ {
+ $$ = NULL;
+ mc_fatal ("missing '=' for Language");
+ }
+;
+
+token: MCIDENT { $$ = $1; }
+ | MCTOKEN { $$ = $1->usz; }
+;
+
+lex_want_nl:
+ /* Empty */ { mclex_want_nl = 1; }
+;
+
+lex_want_line:
+ /* Empty */ { mclex_want_line = 1; }
+;
+
+lex_want_filename:
+ /* Empty */ { mclex_want_filename = 1; }
+;
+
+%%
+
+/* Something else. */