1214571Sdim%{ /* mcparse.y -- parser for Windows mc files 2214571Sdim Copyright 2007 3214571Sdim Free Software Foundation, Inc. 4214571Sdim 5214571Sdim Parser for Windows mc files 6214571Sdim Written by Kai Tietz, Onevision. 7214571Sdim 8214571Sdim This file is part of GNU Binutils. 9214571Sdim 10214571Sdim This program is free software; you can redistribute it and/or modify 11214571Sdim it under the terms of the GNU General Public License as published by 12214571Sdim the Free Software Foundation; either version 2 of the License, or 13214571Sdim (at your option) any later version. 14214571Sdim 15214571Sdim This program is distributed in the hope that it will be useful, 16214571Sdim but WITHOUT ANY WARRANTY; without even the implied warranty of 17214571Sdim MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18214571Sdim GNU General Public License for more details. 19214571Sdim 20214571Sdim You should have received a copy of the GNU General Public License 21214571Sdim along with this program; if not, write to the Free Software 22214571Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 23214571Sdim 02110-1301, USA. */ 24214571Sdim 25214571Sdim/* This is a parser for Windows rc files. It is based on the parser 26214571Sdim by Gunther Ebert <gunther.ebert@ixos-leipzig.de>. */ 27214571Sdim 28214571Sdim#include "sysdep.h" 29214571Sdim#include "bfd.h" 30214571Sdim#include "bucomm.h" 31214571Sdim#include "libiberty.h" 32214571Sdim#include "windmc.h" 33214571Sdim#include "safe-ctype.h" 34214571Sdim 35214571Sdimstatic rc_uint_type mc_last_id = 0; 36214571Sdimstatic rc_uint_type mc_sefa_val = 0; 37214571Sdimstatic unichar *mc_last_symbol = NULL; 38214571Sdimstatic const mc_keyword *mc_cur_severity = NULL; 39214571Sdimstatic const mc_keyword *mc_cur_facility = NULL; 40214571Sdimstatic mc_node *cur_node = NULL; 41214571Sdim 42214571Sdim%} 43214571Sdim 44214571Sdim%union 45214571Sdim{ 46214571Sdim rc_uint_type ival; 47214571Sdim unichar *ustr; 48214571Sdim const mc_keyword *tok; 49214571Sdim mc_node *nod; 50214571Sdim}; 51214571Sdim 52214571Sdim%start input 53214571Sdim 54214571Sdim%token NL 55214571Sdim%token<ustr> MCIDENT MCFILENAME MCLINE MCCOMMENT 56214571Sdim%token<tok> MCTOKEN 57214571Sdim%token MCENDLINE 58214571Sdim%token MCLANGUAGENAMES MCFACILITYNAMES MCSEVERITYNAMES MCOUTPUTBASE MCMESSAGEIDTYPEDEF 59214571Sdim%token MCLANGUAGE MCMESSAGEID MCSEVERITY MCFACILITY MCSYMBOLICNAME 60214571Sdim%token <ival> MCNUMBER 61214571Sdim 62214571Sdim%type<ival> id vid sefasy_def 63214571Sdim%type<ustr> alias_name token lines comments 64214571Sdim%type<tok> lang 65214571Sdim 66214571Sdim%% 67214571Sdiminput: entities 68214571Sdim ; 69214571Sdim 70214571Sdimentities: 71214571Sdim /* empty */ 72214571Sdim | entities entity 73214571Sdim ; 74214571Sdimentity: global_section 75214571Sdim | message 76214571Sdim | comments 77214571Sdim { 78214571Sdim cur_node = mc_add_node (); 79214571Sdim cur_node->user_text = $1; 80214571Sdim } 81214571Sdim | error { mc_fatal ("syntax error"); } 82214571Sdim; 83214571Sdim 84214571Sdimglobal_section: 85214571Sdim MCSEVERITYNAMES '=' '(' severitymaps ')' 86214571Sdim | MCSEVERITYNAMES '=' '(' severitymaps error { mc_fatal ("missing ')' in SeverityNames"); } 87214571Sdim | MCSEVERITYNAMES '=' error { mc_fatal ("missing '(' in SeverityNames"); } 88214571Sdim | MCSEVERITYNAMES error { mc_fatal ("missing '=' for SeverityNames"); } 89214571Sdim | MCLANGUAGENAMES '=' '(' langmaps ')' 90214571Sdim | MCLANGUAGENAMES '=' '(' langmaps error { mc_fatal ("missing ')' in LanguageNames"); } 91214571Sdim | MCLANGUAGENAMES '=' error { mc_fatal ("missing '(' in LanguageNames"); } 92214571Sdim | MCLANGUAGENAMES error { mc_fatal ("missing '=' for LanguageNames"); } 93214571Sdim | MCFACILITYNAMES '=' '(' facilitymaps ')' 94214571Sdim | MCFACILITYNAMES '=' '(' facilitymaps error { mc_fatal ("missing ')' in FacilityNames"); } 95214571Sdim | MCFACILITYNAMES '=' error { mc_fatal ("missing '(' in FacilityNames"); } 96214571Sdim | MCFACILITYNAMES error { mc_fatal ("missing '=' for FacilityNames"); } 97214571Sdim | MCOUTPUTBASE '=' MCNUMBER 98214571Sdim { 99214571Sdim if ($3 != 10 && $3 != 16) 100214571Sdim mc_fatal ("OutputBase allows 10 or 16 as value"); 101214571Sdim mcset_out_values_are_decimal = ($3 == 10 ? 1 : 0); 102214571Sdim } 103214571Sdim | MCMESSAGEIDTYPEDEF '=' MCIDENT 104214571Sdim { 105214571Sdim mcset_msg_id_typedef = $3; 106214571Sdim } 107214571Sdim | MCMESSAGEIDTYPEDEF '=' error 108214571Sdim { 109214571Sdim mc_fatal ("MessageIdTypedef expects an identifier"); 110214571Sdim } 111214571Sdim | MCMESSAGEIDTYPEDEF error 112214571Sdim { 113214571Sdim mc_fatal ("missing '=' for MessageIdTypedef"); 114214571Sdim } 115214571Sdim; 116214571Sdim 117214571Sdimseveritymaps: 118214571Sdim severitymap 119214571Sdim | severitymaps severitymap 120214571Sdim | error { mc_fatal ("severity ident missing"); } 121214571Sdim; 122214571Sdim 123214571Sdimseveritymap: 124214571Sdim token '=' MCNUMBER alias_name 125214571Sdim { 126214571Sdim mc_add_keyword ($1, MCTOKEN, "severity", $3, $4); 127214571Sdim } 128214571Sdim | token '=' error { mc_fatal ("severity number missing"); } 129214571Sdim | token error { mc_fatal ("severity missing '='"); } 130214571Sdim; 131214571Sdim 132214571Sdimfacilitymaps: 133214571Sdim facilitymap 134214571Sdim | facilitymaps facilitymap 135214571Sdim | error { mc_fatal ("missing ident in FacilityNames"); } 136214571Sdim; 137214571Sdim 138214571Sdimfacilitymap: 139214571Sdim token '=' MCNUMBER alias_name 140214571Sdim { 141214571Sdim mc_add_keyword ($1, MCTOKEN, "facility", $3, $4); 142214571Sdim } 143214571Sdim | token '=' error { mc_fatal ("facility number missing"); } 144214571Sdim | token error { mc_fatal ("facility missing '='"); } 145214571Sdim; 146214571Sdim 147214571Sdimlangmaps: 148214571Sdim langmap 149214571Sdim | langmaps langmap 150214571Sdim | error { mc_fatal ("missing ident in LanguageNames"); } 151214571Sdim; 152214571Sdim 153214571Sdimlangmap: 154214571Sdim token '=' MCNUMBER lex_want_filename ':' MCFILENAME 155214571Sdim { 156214571Sdim mc_add_keyword ($1, MCTOKEN, "language", $3, $6); 157214571Sdim } 158214571Sdim | token '=' MCNUMBER lex_want_filename ':' error { mc_fatal ("missing filename in LanguageNames"); } 159214571Sdim | token '=' MCNUMBER error { mc_fatal ("missing ':' in LanguageNames"); } 160214571Sdim | token '=' error { mc_fatal ("missing language code in LanguageNames"); } 161214571Sdim | token error { mc_fatal ("missing '=' for LanguageNames"); } 162214571Sdim; 163214571Sdim 164214571Sdimalias_name: 165214571Sdim /* empty */ 166214571Sdim { 167214571Sdim $$ = NULL; 168214571Sdim } 169214571Sdim | ':' MCIDENT 170214571Sdim { 171214571Sdim $$ = $2; 172214571Sdim } 173214571Sdim | ':' error { mc_fatal ("illegal token in identifier"); $$ = NULL; } 174214571Sdim; 175214571Sdim 176214571Sdimmessage: 177214571Sdim id sefasy_def 178214571Sdim { 179214571Sdim cur_node = mc_add_node (); 180214571Sdim cur_node->symbol = mc_last_symbol; 181214571Sdim cur_node->facility = mc_cur_facility; 182214571Sdim cur_node->severity = mc_cur_severity; 183214571Sdim cur_node->id = ($1 & 0xffffUL); 184214571Sdim cur_node->vid = ($1 & 0xffffUL) | mc_sefa_val; 185214571Sdim mc_last_id = $1; 186214571Sdim } 187214571Sdim lang_entities 188214571Sdim; 189214571Sdim 190214571Sdimid: MCMESSAGEID '=' vid { $$ = $3; } 191214571Sdim | MCMESSAGEID '=' error { mc_fatal ("missing number in MessageId"); $$ = 0; } 192214571Sdim | MCMESSAGEID error { mc_fatal ("missing '=' for MessageId"); $$ = 0; } 193214571Sdim; 194214571Sdim 195214571Sdimvid: /* empty */ 196214571Sdim { 197214571Sdim $$ = ++mc_last_id; 198214571Sdim } 199214571Sdim | MCNUMBER 200214571Sdim { 201214571Sdim $$ = $1; 202214571Sdim } 203214571Sdim | '+' MCNUMBER 204214571Sdim { 205214571Sdim $$ = mc_last_id + $2; 206214571Sdim } 207214571Sdim | '+' error { mc_fatal ("missing number after MessageId '+'"); } 208214571Sdim; 209214571Sdim 210214571Sdimsefasy_def: 211214571Sdim /* empty */ 212214571Sdim { 213214571Sdim $$ = 0; 214214571Sdim mc_sefa_val = (mcset_custom_bit ? 1 : 0) << 29; 215214571Sdim mc_last_symbol = NULL; 216214571Sdim mc_cur_severity = NULL; 217214571Sdim mc_cur_facility = NULL; 218214571Sdim } 219214571Sdim | sefasy_def severity 220214571Sdim { 221214571Sdim if ($1 & 1) 222214571Sdim mc_warn (_("duplicate definition of Severity")); 223214571Sdim $$ = $1 | 1; 224214571Sdim } 225214571Sdim | sefasy_def facility 226214571Sdim { 227214571Sdim if ($1 & 2) 228214571Sdim mc_warn (_("duplicate definition of Facility")); 229214571Sdim $$ = $1 | 2; 230214571Sdim } 231214571Sdim | sefasy_def symbol 232214571Sdim { 233214571Sdim if ($1 & 4) 234214571Sdim mc_warn (_("duplicate definition of SymbolicName")); 235214571Sdim $$ = $1 | 4; 236214571Sdim } 237214571Sdim; 238214571Sdim 239214571Sdimseverity: MCSEVERITY '=' MCTOKEN 240214571Sdim { 241214571Sdim mc_sefa_val &= ~ (0x3UL << 30); 242214571Sdim mc_sefa_val |= (($3->nval & 0x3UL) << 30); 243214571Sdim mc_cur_severity = $3; 244214571Sdim } 245214571Sdim; 246214571Sdim 247214571Sdimfacility: MCFACILITY '=' MCTOKEN 248214571Sdim { 249214571Sdim mc_sefa_val &= ~ (0xfffUL << 16); 250214571Sdim mc_sefa_val |= (($3->nval & 0xfffUL) << 16); 251214571Sdim mc_cur_facility = $3; 252214571Sdim } 253214571Sdim; 254214571Sdim 255214571Sdimsymbol: MCSYMBOLICNAME '=' MCIDENT 256214571Sdim { 257214571Sdim mc_last_symbol = $3; 258214571Sdim } 259214571Sdim; 260214571Sdim 261214571Sdimlang_entities: 262214571Sdim lang_entity 263214571Sdim | lang_entities lang_entity 264214571Sdim; 265214571Sdim 266214571Sdimlang_entity: 267214571Sdim lang lex_want_line lines MCENDLINE 268214571Sdim { 269214571Sdim mc_node_lang *h; 270214571Sdim h = mc_add_node_lang (cur_node, $1, cur_node->vid); 271214571Sdim h->message = $3; 272214571Sdim if (mcset_max_message_length != 0 && unichar_len (h->message) > mcset_max_message_length) 273214571Sdim mc_warn ("message length to long"); 274214571Sdim } 275214571Sdim; 276214571Sdim 277214571Sdimlines: MCLINE 278214571Sdim { 279214571Sdim $$ = $1; 280214571Sdim } 281214571Sdim | lines MCLINE 282214571Sdim { 283214571Sdim unichar *h; 284214571Sdim rc_uint_type l1,l2; 285214571Sdim l1 = unichar_len ($1); 286214571Sdim l2 = unichar_len ($2); 287214571Sdim h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar)); 288214571Sdim if (l1) memcpy (h, $1, l1 * sizeof (unichar)); 289214571Sdim if (l2) memcpy (&h[l1], $2, l2 * sizeof (unichar)); 290214571Sdim h[l1 + l2] = 0; 291214571Sdim $$ = h; 292214571Sdim } 293214571Sdim | error { mc_fatal ("missing end of message text"); $$ = NULL; } 294214571Sdim | lines error { mc_fatal ("missing end of message text"); $$ = $1; } 295214571Sdim; 296214571Sdim 297214571Sdimcomments: MCCOMMENT { $$ = $1; } 298214571Sdim | comments MCCOMMENT 299214571Sdim { 300214571Sdim unichar *h; 301214571Sdim rc_uint_type l1,l2; 302214571Sdim l1 = unichar_len ($1); 303214571Sdim l2 = unichar_len ($2); 304214571Sdim h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar)); 305214571Sdim if (l1) memcpy (h, $1, l1 * sizeof (unichar)); 306214571Sdim if (l2) memcpy (&h[l1], $2, l2 * sizeof (unichar)); 307214571Sdim h[l1 + l2] = 0; 308214571Sdim $$ = h; 309214571Sdim } 310214571Sdim; 311214571Sdim 312214571Sdimlang: MCLANGUAGE lex_want_nl '=' MCTOKEN NL 313214571Sdim { 314214571Sdim $$ = $4; 315214571Sdim } 316214571Sdim | MCLANGUAGE lex_want_nl '=' MCIDENT NL 317214571Sdim { 318214571Sdim $$ = NULL; 319214571Sdim mc_fatal (_("undeclared language identifier")); 320214571Sdim } 321214571Sdim | MCLANGUAGE lex_want_nl '=' token error 322214571Sdim { 323214571Sdim $$ = NULL; 324214571Sdim mc_fatal ("missing newline after Language"); 325214571Sdim } 326214571Sdim | MCLANGUAGE lex_want_nl '=' error 327214571Sdim { 328214571Sdim $$ = NULL; 329214571Sdim mc_fatal ("missing ident for Language"); 330214571Sdim } 331214571Sdim | MCLANGUAGE error 332214571Sdim { 333214571Sdim $$ = NULL; 334214571Sdim mc_fatal ("missing '=' for Language"); 335214571Sdim } 336214571Sdim; 337214571Sdim 338214571Sdimtoken: MCIDENT { $$ = $1; } 339214571Sdim | MCTOKEN { $$ = $1->usz; } 340214571Sdim; 341214571Sdim 342214571Sdimlex_want_nl: 343214571Sdim /* Empty */ { mclex_want_nl = 1; } 344214571Sdim; 345214571Sdim 346214571Sdimlex_want_line: 347214571Sdim /* Empty */ { mclex_want_line = 1; } 348214571Sdim; 349214571Sdim 350214571Sdimlex_want_filename: 351214571Sdim /* Empty */ { mclex_want_filename = 1; } 352214571Sdim; 353214571Sdim 354214571Sdim%% 355214571Sdim 356214571Sdim/* Something else. */ 357