
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. */