1 %{ /* mcparse.y -- parser for Windows mc files 2 Copyright (C) 2007-2014 Free Software Foundation, Inc. 3 4 Parser for Windows mc files 5 Written by Kai Tietz, Onevision. 6 7 This file is part of GNU Binutils. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 22 02110-1301, USA. */ 23 24 /* This is a parser for Windows rc files. It is based on the parser 25 by Gunther Ebert <gunther.ebert@ixos-leipzig.de>. */ 26 27 #include "sysdep.h" 28 #include "bfd.h" 29 #include "bucomm.h" 30 #include "libiberty.h" 31 #include "windmc.h" 32 #include "safe-ctype.h" 33 34 static rc_uint_type mc_last_id = 0; 35 static rc_uint_type mc_sefa_val = 0; 36 static unichar *mc_last_symbol = NULL; 37 static const mc_keyword *mc_cur_severity = NULL; 38 static const mc_keyword *mc_cur_facility = NULL; 39 static mc_node *cur_node = NULL; 40 41 %} 42 43 %union 44 { 45 rc_uint_type ival; 46 unichar *ustr; 47 const mc_keyword *tok; 48 mc_node *nod; 49 }; 50 51 %start input 52 53 %token NL 54 %token<ustr> MCIDENT MCFILENAME MCLINE MCCOMMENT 55 %token<tok> MCTOKEN 56 %token MCENDLINE 57 %token MCLANGUAGENAMES MCFACILITYNAMES MCSEVERITYNAMES MCOUTPUTBASE MCMESSAGEIDTYPEDEF 58 %token MCLANGUAGE MCMESSAGEID MCSEVERITY MCFACILITY MCSYMBOLICNAME 59 %token <ival> MCNUMBER 60 61 %type<ival> id vid sefasy_def 62 %type<ustr> alias_name token lines comments 63 %type<tok> lang 64 65 %% 66 input: entities 67 ; 68 69 entities: 70 /* empty */ 71 | entities entity 72 ; 73 entity: global_section 74 | message 75 | comments 76 { 77 cur_node = mc_add_node (); 78 cur_node->user_text = $1; 79 } 80 | error { mc_fatal ("syntax error"); } 81 ; 82 83 global_section: 84 MCSEVERITYNAMES '=' '(' severitymaps ')' 85 | MCSEVERITYNAMES '=' '(' severitymaps error { mc_fatal ("missing ')' in SeverityNames"); } 86 | MCSEVERITYNAMES '=' error { mc_fatal ("missing '(' in SeverityNames"); } 87 | MCSEVERITYNAMES error { mc_fatal ("missing '=' for SeverityNames"); } 88 | MCLANGUAGENAMES '=' '(' langmaps ')' 89 | MCLANGUAGENAMES '=' '(' langmaps error { mc_fatal ("missing ')' in LanguageNames"); } 90 | MCLANGUAGENAMES '=' error { mc_fatal ("missing '(' in LanguageNames"); } 91 | MCLANGUAGENAMES error { mc_fatal ("missing '=' for LanguageNames"); } 92 | MCFACILITYNAMES '=' '(' facilitymaps ')' 93 | MCFACILITYNAMES '=' '(' facilitymaps error { mc_fatal ("missing ')' in FacilityNames"); } 94 | MCFACILITYNAMES '=' error { mc_fatal ("missing '(' in FacilityNames"); } 95 | MCFACILITYNAMES error { mc_fatal ("missing '=' for FacilityNames"); } 96 | MCOUTPUTBASE '=' MCNUMBER 97 { 98 if ($3 != 10 && $3 != 16) 99 mc_fatal ("OutputBase allows 10 or 16 as value"); 100 mcset_out_values_are_decimal = ($3 == 10 ? 1 : 0); 101 } 102 | MCMESSAGEIDTYPEDEF '=' MCIDENT 103 { 104 mcset_msg_id_typedef = $3; 105 } 106 | MCMESSAGEIDTYPEDEF '=' error 107 { 108 mc_fatal ("MessageIdTypedef expects an identifier"); 109 } 110 | MCMESSAGEIDTYPEDEF error 111 { 112 mc_fatal ("missing '=' for MessageIdTypedef"); 113 } 114 ; 115 116 severitymaps: 117 severitymap 118 | severitymaps severitymap 119 | error { mc_fatal ("severity ident missing"); } 120 ; 121 122 severitymap: 123 token '=' MCNUMBER alias_name 124 { 125 mc_add_keyword ($1, MCTOKEN, "severity", $3, $4); 126 } 127 | token '=' error { mc_fatal ("severity number missing"); } 128 | token error { mc_fatal ("severity missing '='"); } 129 ; 130 131 facilitymaps: 132 facilitymap 133 | facilitymaps facilitymap 134 | error { mc_fatal ("missing ident in FacilityNames"); } 135 ; 136 137 facilitymap: 138 token '=' MCNUMBER alias_name 139 { 140 mc_add_keyword ($1, MCTOKEN, "facility", $3, $4); 141 } 142 | token '=' error { mc_fatal ("facility number missing"); } 143 | token error { mc_fatal ("facility missing '='"); } 144 ; 145 146 langmaps: 147 langmap 148 | langmaps langmap 149 | error { mc_fatal ("missing ident in LanguageNames"); } 150 ; 151 152 langmap: 153 token '=' MCNUMBER lex_want_filename ':' MCFILENAME 154 { 155 mc_add_keyword ($1, MCTOKEN, "language", $3, $6); 156 } 157 | token '=' MCNUMBER lex_want_filename ':' error { mc_fatal ("missing filename in LanguageNames"); } 158 | token '=' MCNUMBER error { mc_fatal ("missing ':' in LanguageNames"); } 159 | token '=' error { mc_fatal ("missing language code in LanguageNames"); } 160 | token error { mc_fatal ("missing '=' for LanguageNames"); } 161 ; 162 163 alias_name: 164 /* empty */ 165 { 166 $$ = NULL; 167 } 168 | ':' MCIDENT 169 { 170 $$ = $2; 171 } 172 | ':' error { mc_fatal ("illegal token in identifier"); $$ = NULL; } 173 ; 174 175 message: 176 id sefasy_def 177 { 178 cur_node = mc_add_node (); 179 cur_node->symbol = mc_last_symbol; 180 cur_node->facility = mc_cur_facility; 181 cur_node->severity = mc_cur_severity; 182 cur_node->id = ($1 & 0xffffUL); 183 cur_node->vid = ($1 & 0xffffUL) | mc_sefa_val; 184 mc_last_id = $1; 185 } 186 lang_entities 187 ; 188 189 id: MCMESSAGEID '=' vid { $$ = $3; } 190 | MCMESSAGEID '=' error { mc_fatal ("missing number in MessageId"); $$ = 0; } 191 | MCMESSAGEID error { mc_fatal ("missing '=' for MessageId"); $$ = 0; } 192 ; 193 194 vid: /* empty */ 195 { 196 $$ = ++mc_last_id; 197 } 198 | MCNUMBER 199 { 200 $$ = $1; 201 } 202 | '+' MCNUMBER 203 { 204 $$ = mc_last_id + $2; 205 } 206 | '+' error { mc_fatal ("missing number after MessageId '+'"); } 207 ; 208 209 sefasy_def: 210 /* empty */ 211 { 212 $$ = 0; 213 mc_sefa_val = (mcset_custom_bit ? 1 : 0) << 29; 214 mc_last_symbol = NULL; 215 mc_cur_severity = NULL; 216 mc_cur_facility = NULL; 217 } 218 | sefasy_def severity 219 { 220 if ($1 & 1) 221 mc_warn (_("duplicate definition of Severity")); 222 $$ = $1 | 1; 223 } 224 | sefasy_def facility 225 { 226 if ($1 & 2) 227 mc_warn (_("duplicate definition of Facility")); 228 $$ = $1 | 2; 229 } 230 | sefasy_def symbol 231 { 232 if ($1 & 4) 233 mc_warn (_("duplicate definition of SymbolicName")); 234 $$ = $1 | 4; 235 } 236 ; 237 238 severity: MCSEVERITY '=' MCTOKEN 239 { 240 mc_sefa_val &= ~ (0x3UL << 30); 241 mc_sefa_val |= (($3->nval & 0x3UL) << 30); 242 mc_cur_severity = $3; 243 } 244 ; 245 246 facility: MCFACILITY '=' MCTOKEN 247 { 248 mc_sefa_val &= ~ (0xfffUL << 16); 249 mc_sefa_val |= (($3->nval & 0xfffUL) << 16); 250 mc_cur_facility = $3; 251 } 252 ; 253 254 symbol: MCSYMBOLICNAME '=' MCIDENT 255 { 256 mc_last_symbol = $3; 257 } 258 ; 259 260 lang_entities: 261 lang_entity 262 | lang_entities lang_entity 263 ; 264 265 lang_entity: 266 lang lex_want_line lines MCENDLINE 267 { 268 mc_node_lang *h; 269 h = mc_add_node_lang (cur_node, $1, cur_node->vid); 270 h->message = $3; 271 if (mcset_max_message_length != 0 && unichar_len (h->message) > mcset_max_message_length) 272 mc_warn ("message length to long"); 273 } 274 ; 275 276 lines: MCLINE 277 { 278 $$ = $1; 279 } 280 | lines MCLINE 281 { 282 unichar *h; 283 rc_uint_type l1,l2; 284 l1 = unichar_len ($1); 285 l2 = unichar_len ($2); 286 h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar)); 287 if (l1) memcpy (h, $1, l1 * sizeof (unichar)); 288 if (l2) memcpy (&h[l1], $2, l2 * sizeof (unichar)); 289 h[l1 + l2] = 0; 290 $$ = h; 291 } 292 | error { mc_fatal ("missing end of message text"); $$ = NULL; } 293 | lines error { mc_fatal ("missing end of message text"); $$ = $1; } 294 ; 295 296 comments: MCCOMMENT { $$ = $1; } 297 | comments MCCOMMENT 298 { 299 unichar *h; 300 rc_uint_type l1,l2; 301 l1 = unichar_len ($1); 302 l2 = unichar_len ($2); 303 h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar)); 304 if (l1) memcpy (h, $1, l1 * sizeof (unichar)); 305 if (l2) memcpy (&h[l1], $2, l2 * sizeof (unichar)); 306 h[l1 + l2] = 0; 307 $$ = h; 308 } 309 ; 310 311 lang: MCLANGUAGE lex_want_nl '=' MCTOKEN NL 312 { 313 $$ = $4; 314 } 315 | MCLANGUAGE lex_want_nl '=' MCIDENT NL 316 { 317 $$ = NULL; 318 mc_fatal (_("undeclared language identifier")); 319 } 320 | MCLANGUAGE lex_want_nl '=' token error 321 { 322 $$ = NULL; 323 mc_fatal ("missing newline after Language"); 324 } 325 | MCLANGUAGE lex_want_nl '=' error 326 { 327 $$ = NULL; 328 mc_fatal ("missing ident for Language"); 329 } 330 | MCLANGUAGE error 331 { 332 $$ = NULL; 333 mc_fatal ("missing '=' for Language"); 334 } 335 ; 336 337 token: MCIDENT { $$ = $1; } 338 | MCTOKEN { $$ = $1->usz; } 339 ; 340 341 lex_want_nl: 342 /* Empty */ { mclex_want_nl = 1; } 343 ; 344 345 lex_want_line: 346 /* Empty */ { mclex_want_line = 1; } 347 ; 348 349 lex_want_filename: 350 /* Empty */ { mclex_want_filename = 1; } 351 ; 352 353 %% 354 355 /* Something else. */ 356