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