1 %{ /* mcparse.y -- parser for Windows mc files 2 Copyright (C) 2007-2022 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 cur_node->id_typecast = mcset_msg_id_typedef; 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