12a6b7db3Sskrll %{ /* mcparse.y -- parser for Windows mc files 2*f22f0ef4Schristos Copyright (C) 2007-2022 Free Software Foundation, Inc. 32a6b7db3Sskrll 42a6b7db3Sskrll Parser for Windows mc files 52a6b7db3Sskrll Written by Kai Tietz, Onevision. 62a6b7db3Sskrll 72a6b7db3Sskrll This file is part of GNU Binutils. 82a6b7db3Sskrll 92a6b7db3Sskrll This program is free software; you can redistribute it and/or modify 102a6b7db3Sskrll it under the terms of the GNU General Public License as published by 112a6b7db3Sskrll the Free Software Foundation; either version 3 of the License, or 122a6b7db3Sskrll (at your option) any later version. 132a6b7db3Sskrll 142a6b7db3Sskrll This program is distributed in the hope that it will be useful, 152a6b7db3Sskrll but WITHOUT ANY WARRANTY; without even the implied warranty of 162a6b7db3Sskrll MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 172a6b7db3Sskrll GNU General Public License for more details. 182a6b7db3Sskrll 192a6b7db3Sskrll You should have received a copy of the GNU General Public License 202a6b7db3Sskrll along with this program; if not, write to the Free Software 212a6b7db3Sskrll Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 222a6b7db3Sskrll 02110-1301, USA. */ 232a6b7db3Sskrll 242a6b7db3Sskrll /* This is a parser for Windows rc files. It is based on the parser 252a6b7db3Sskrll by Gunther Ebert <gunther.ebert@ixos-leipzig.de>. */ 262a6b7db3Sskrll 272a6b7db3Sskrll #include "sysdep.h" 282a6b7db3Sskrll #include "bfd.h" 292a6b7db3Sskrll #include "bucomm.h" 302a6b7db3Sskrll #include "libiberty.h" 312a6b7db3Sskrll #include "windmc.h" 322a6b7db3Sskrll #include "safe-ctype.h" 332a6b7db3Sskrll 342a6b7db3Sskrll static rc_uint_type mc_last_id = 0; 352a6b7db3Sskrll static rc_uint_type mc_sefa_val = 0; 362a6b7db3Sskrll static unichar *mc_last_symbol = NULL; 372a6b7db3Sskrll static const mc_keyword *mc_cur_severity = NULL; 382a6b7db3Sskrll static const mc_keyword *mc_cur_facility = NULL; 392a6b7db3Sskrll static mc_node *cur_node = NULL; 402a6b7db3Sskrll 412a6b7db3Sskrll %} 422a6b7db3Sskrll 432a6b7db3Sskrll %union 442a6b7db3Sskrll { 452a6b7db3Sskrll rc_uint_type ival; 462a6b7db3Sskrll unichar *ustr; 472a6b7db3Sskrll const mc_keyword *tok; 482a6b7db3Sskrll mc_node *nod; 492a6b7db3Sskrll }; 502a6b7db3Sskrll 512a6b7db3Sskrll %start input 522a6b7db3Sskrll 532a6b7db3Sskrll %token NL 542a6b7db3Sskrll %token<ustr> MCIDENT MCFILENAME MCLINE MCCOMMENT 552a6b7db3Sskrll %token<tok> MCTOKEN 562a6b7db3Sskrll %token MCENDLINE 572a6b7db3Sskrll %token MCLANGUAGENAMES MCFACILITYNAMES MCSEVERITYNAMES MCOUTPUTBASE MCMESSAGEIDTYPEDEF 582a6b7db3Sskrll %token MCLANGUAGE MCMESSAGEID MCSEVERITY MCFACILITY MCSYMBOLICNAME 592a6b7db3Sskrll %token <ival> MCNUMBER 602a6b7db3Sskrll 612a6b7db3Sskrll %type<ival> id vid sefasy_def 622a6b7db3Sskrll %type<ustr> alias_name token lines comments 632a6b7db3Sskrll %type<tok> lang 642a6b7db3Sskrll 652a6b7db3Sskrll %% 662a6b7db3Sskrll input: entities 672a6b7db3Sskrll ; 682a6b7db3Sskrll 692a6b7db3Sskrll entities: 702a6b7db3Sskrll /* empty */ 712a6b7db3Sskrll | entities entity 722a6b7db3Sskrll ; 732a6b7db3Sskrll entity: global_section 742a6b7db3Sskrll | message 752a6b7db3Sskrll | comments 762a6b7db3Sskrll { 772a6b7db3Sskrll cur_node = mc_add_node (); 782a6b7db3Sskrll cur_node->user_text = $1; 792a6b7db3Sskrll } 802a6b7db3Sskrll | error { mc_fatal ("syntax error"); } 812a6b7db3Sskrll ; 822a6b7db3Sskrll 832a6b7db3Sskrll global_section: 842a6b7db3Sskrll MCSEVERITYNAMES '=' '(' severitymaps ')' 852a6b7db3Sskrll | MCSEVERITYNAMES '=' '(' severitymaps error { mc_fatal ("missing ')' in SeverityNames"); } 862a6b7db3Sskrll | MCSEVERITYNAMES '=' error { mc_fatal ("missing '(' in SeverityNames"); } 872a6b7db3Sskrll | MCSEVERITYNAMES error { mc_fatal ("missing '=' for SeverityNames"); } 882a6b7db3Sskrll | MCLANGUAGENAMES '=' '(' langmaps ')' 892a6b7db3Sskrll | MCLANGUAGENAMES '=' '(' langmaps error { mc_fatal ("missing ')' in LanguageNames"); } 902a6b7db3Sskrll | MCLANGUAGENAMES '=' error { mc_fatal ("missing '(' in LanguageNames"); } 912a6b7db3Sskrll | MCLANGUAGENAMES error { mc_fatal ("missing '=' for LanguageNames"); } 922a6b7db3Sskrll | MCFACILITYNAMES '=' '(' facilitymaps ')' 932a6b7db3Sskrll | MCFACILITYNAMES '=' '(' facilitymaps error { mc_fatal ("missing ')' in FacilityNames"); } 942a6b7db3Sskrll | MCFACILITYNAMES '=' error { mc_fatal ("missing '(' in FacilityNames"); } 952a6b7db3Sskrll | MCFACILITYNAMES error { mc_fatal ("missing '=' for FacilityNames"); } 962a6b7db3Sskrll | MCOUTPUTBASE '=' MCNUMBER 972a6b7db3Sskrll { 982a6b7db3Sskrll if ($3 != 10 && $3 != 16) 992a6b7db3Sskrll mc_fatal ("OutputBase allows 10 or 16 as value"); 1002a6b7db3Sskrll mcset_out_values_are_decimal = ($3 == 10 ? 1 : 0); 1012a6b7db3Sskrll } 1022a6b7db3Sskrll | MCMESSAGEIDTYPEDEF '=' MCIDENT 1032a6b7db3Sskrll { 1042a6b7db3Sskrll mcset_msg_id_typedef = $3; 1052a6b7db3Sskrll } 1062a6b7db3Sskrll | MCMESSAGEIDTYPEDEF '=' error 1072a6b7db3Sskrll { 1082a6b7db3Sskrll mc_fatal ("MessageIdTypedef expects an identifier"); 1092a6b7db3Sskrll } 1102a6b7db3Sskrll | MCMESSAGEIDTYPEDEF error 1112a6b7db3Sskrll { 1122a6b7db3Sskrll mc_fatal ("missing '=' for MessageIdTypedef"); 1132a6b7db3Sskrll } 1142a6b7db3Sskrll ; 1152a6b7db3Sskrll 1162a6b7db3Sskrll severitymaps: 1172a6b7db3Sskrll severitymap 1182a6b7db3Sskrll | severitymaps severitymap 1192a6b7db3Sskrll | error { mc_fatal ("severity ident missing"); } 1202a6b7db3Sskrll ; 1212a6b7db3Sskrll 1222a6b7db3Sskrll severitymap: 1232a6b7db3Sskrll token '=' MCNUMBER alias_name 1242a6b7db3Sskrll { 1252a6b7db3Sskrll mc_add_keyword ($1, MCTOKEN, "severity", $3, $4); 1262a6b7db3Sskrll } 1272a6b7db3Sskrll | token '=' error { mc_fatal ("severity number missing"); } 1282a6b7db3Sskrll | token error { mc_fatal ("severity missing '='"); } 1292a6b7db3Sskrll ; 1302a6b7db3Sskrll 1312a6b7db3Sskrll facilitymaps: 1322a6b7db3Sskrll facilitymap 1332a6b7db3Sskrll | facilitymaps facilitymap 1342a6b7db3Sskrll | error { mc_fatal ("missing ident in FacilityNames"); } 1352a6b7db3Sskrll ; 1362a6b7db3Sskrll 1372a6b7db3Sskrll facilitymap: 1382a6b7db3Sskrll token '=' MCNUMBER alias_name 1392a6b7db3Sskrll { 1402a6b7db3Sskrll mc_add_keyword ($1, MCTOKEN, "facility", $3, $4); 1412a6b7db3Sskrll } 1422a6b7db3Sskrll | token '=' error { mc_fatal ("facility number missing"); } 1432a6b7db3Sskrll | token error { mc_fatal ("facility missing '='"); } 1442a6b7db3Sskrll ; 1452a6b7db3Sskrll 1462a6b7db3Sskrll langmaps: 1472a6b7db3Sskrll langmap 1482a6b7db3Sskrll | langmaps langmap 1492a6b7db3Sskrll | error { mc_fatal ("missing ident in LanguageNames"); } 1502a6b7db3Sskrll ; 1512a6b7db3Sskrll 1522a6b7db3Sskrll langmap: 1532a6b7db3Sskrll token '=' MCNUMBER lex_want_filename ':' MCFILENAME 1542a6b7db3Sskrll { 1552a6b7db3Sskrll mc_add_keyword ($1, MCTOKEN, "language", $3, $6); 1562a6b7db3Sskrll } 1572a6b7db3Sskrll | token '=' MCNUMBER lex_want_filename ':' error { mc_fatal ("missing filename in LanguageNames"); } 1582a6b7db3Sskrll | token '=' MCNUMBER error { mc_fatal ("missing ':' in LanguageNames"); } 1592a6b7db3Sskrll | token '=' error { mc_fatal ("missing language code in LanguageNames"); } 1602a6b7db3Sskrll | token error { mc_fatal ("missing '=' for LanguageNames"); } 1612a6b7db3Sskrll ; 1622a6b7db3Sskrll 1632a6b7db3Sskrll alias_name: 1642a6b7db3Sskrll /* empty */ 1652a6b7db3Sskrll { 1662a6b7db3Sskrll $$ = NULL; 1672a6b7db3Sskrll } 1682a6b7db3Sskrll | ':' MCIDENT 1692a6b7db3Sskrll { 1702a6b7db3Sskrll $$ = $2; 1712a6b7db3Sskrll } 1722a6b7db3Sskrll | ':' error { mc_fatal ("illegal token in identifier"); $$ = NULL; } 1732a6b7db3Sskrll ; 1742a6b7db3Sskrll 1752a6b7db3Sskrll message: 1762a6b7db3Sskrll id sefasy_def 1772a6b7db3Sskrll { 1782a6b7db3Sskrll cur_node = mc_add_node (); 1792a6b7db3Sskrll cur_node->symbol = mc_last_symbol; 1802a6b7db3Sskrll cur_node->facility = mc_cur_facility; 1812a6b7db3Sskrll cur_node->severity = mc_cur_severity; 1822a6b7db3Sskrll cur_node->id = ($1 & 0xffffUL); 1832a6b7db3Sskrll cur_node->vid = ($1 & 0xffffUL) | mc_sefa_val; 184*f22f0ef4Schristos cur_node->id_typecast = mcset_msg_id_typedef; 1852a6b7db3Sskrll mc_last_id = $1; 1862a6b7db3Sskrll } 1872a6b7db3Sskrll lang_entities 1882a6b7db3Sskrll ; 1892a6b7db3Sskrll 1902a6b7db3Sskrll id: MCMESSAGEID '=' vid { $$ = $3; } 1912a6b7db3Sskrll | MCMESSAGEID '=' error { mc_fatal ("missing number in MessageId"); $$ = 0; } 1922a6b7db3Sskrll | MCMESSAGEID error { mc_fatal ("missing '=' for MessageId"); $$ = 0; } 1932a6b7db3Sskrll ; 1942a6b7db3Sskrll 1952a6b7db3Sskrll vid: /* empty */ 1962a6b7db3Sskrll { 1972a6b7db3Sskrll $$ = ++mc_last_id; 1982a6b7db3Sskrll } 1992a6b7db3Sskrll | MCNUMBER 2002a6b7db3Sskrll { 2012a6b7db3Sskrll $$ = $1; 2022a6b7db3Sskrll } 2032a6b7db3Sskrll | '+' MCNUMBER 2042a6b7db3Sskrll { 2052a6b7db3Sskrll $$ = mc_last_id + $2; 2062a6b7db3Sskrll } 2072a6b7db3Sskrll | '+' error { mc_fatal ("missing number after MessageId '+'"); } 2082a6b7db3Sskrll ; 2092a6b7db3Sskrll 2102a6b7db3Sskrll sefasy_def: 2112a6b7db3Sskrll /* empty */ 2122a6b7db3Sskrll { 2132a6b7db3Sskrll $$ = 0; 2142a6b7db3Sskrll mc_sefa_val = (mcset_custom_bit ? 1 : 0) << 29; 2152a6b7db3Sskrll mc_last_symbol = NULL; 2162a6b7db3Sskrll mc_cur_severity = NULL; 2172a6b7db3Sskrll mc_cur_facility = NULL; 2182a6b7db3Sskrll } 2192a6b7db3Sskrll | sefasy_def severity 2202a6b7db3Sskrll { 2212a6b7db3Sskrll if ($1 & 1) 2222a6b7db3Sskrll mc_warn (_("duplicate definition of Severity")); 2232a6b7db3Sskrll $$ = $1 | 1; 2242a6b7db3Sskrll } 2252a6b7db3Sskrll | sefasy_def facility 2262a6b7db3Sskrll { 2272a6b7db3Sskrll if ($1 & 2) 2282a6b7db3Sskrll mc_warn (_("duplicate definition of Facility")); 2292a6b7db3Sskrll $$ = $1 | 2; 2302a6b7db3Sskrll } 2312a6b7db3Sskrll | sefasy_def symbol 2322a6b7db3Sskrll { 2332a6b7db3Sskrll if ($1 & 4) 2342a6b7db3Sskrll mc_warn (_("duplicate definition of SymbolicName")); 2352a6b7db3Sskrll $$ = $1 | 4; 2362a6b7db3Sskrll } 2372a6b7db3Sskrll ; 2382a6b7db3Sskrll 2392a6b7db3Sskrll severity: MCSEVERITY '=' MCTOKEN 2402a6b7db3Sskrll { 2412a6b7db3Sskrll mc_sefa_val &= ~ (0x3UL << 30); 2422a6b7db3Sskrll mc_sefa_val |= (($3->nval & 0x3UL) << 30); 2432a6b7db3Sskrll mc_cur_severity = $3; 2442a6b7db3Sskrll } 2452a6b7db3Sskrll ; 2462a6b7db3Sskrll 2472a6b7db3Sskrll facility: MCFACILITY '=' MCTOKEN 2482a6b7db3Sskrll { 2492a6b7db3Sskrll mc_sefa_val &= ~ (0xfffUL << 16); 2502a6b7db3Sskrll mc_sefa_val |= (($3->nval & 0xfffUL) << 16); 2512a6b7db3Sskrll mc_cur_facility = $3; 2522a6b7db3Sskrll } 2532a6b7db3Sskrll ; 2542a6b7db3Sskrll 2552a6b7db3Sskrll symbol: MCSYMBOLICNAME '=' MCIDENT 2562a6b7db3Sskrll { 2572a6b7db3Sskrll mc_last_symbol = $3; 2582a6b7db3Sskrll } 2592a6b7db3Sskrll ; 2602a6b7db3Sskrll 2612a6b7db3Sskrll lang_entities: 2622a6b7db3Sskrll lang_entity 2632a6b7db3Sskrll | lang_entities lang_entity 2642a6b7db3Sskrll ; 2652a6b7db3Sskrll 2662a6b7db3Sskrll lang_entity: 2672a6b7db3Sskrll lang lex_want_line lines MCENDLINE 2682a6b7db3Sskrll { 2692a6b7db3Sskrll mc_node_lang *h; 2702a6b7db3Sskrll h = mc_add_node_lang (cur_node, $1, cur_node->vid); 2712a6b7db3Sskrll h->message = $3; 2722a6b7db3Sskrll if (mcset_max_message_length != 0 && unichar_len (h->message) > mcset_max_message_length) 2732a6b7db3Sskrll mc_warn ("message length to long"); 2742a6b7db3Sskrll } 2752a6b7db3Sskrll ; 2762a6b7db3Sskrll 2772a6b7db3Sskrll lines: MCLINE 2782a6b7db3Sskrll { 2792a6b7db3Sskrll $$ = $1; 2802a6b7db3Sskrll } 2812a6b7db3Sskrll | lines MCLINE 2822a6b7db3Sskrll { 2832a6b7db3Sskrll unichar *h; 2842a6b7db3Sskrll rc_uint_type l1,l2; 2852a6b7db3Sskrll l1 = unichar_len ($1); 2862a6b7db3Sskrll l2 = unichar_len ($2); 2872a6b7db3Sskrll h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar)); 2882a6b7db3Sskrll if (l1) memcpy (h, $1, l1 * sizeof (unichar)); 2892a6b7db3Sskrll if (l2) memcpy (&h[l1], $2, l2 * sizeof (unichar)); 2902a6b7db3Sskrll h[l1 + l2] = 0; 2912a6b7db3Sskrll $$ = h; 2922a6b7db3Sskrll } 2932a6b7db3Sskrll | error { mc_fatal ("missing end of message text"); $$ = NULL; } 2942a6b7db3Sskrll | lines error { mc_fatal ("missing end of message text"); $$ = $1; } 2952a6b7db3Sskrll ; 2962a6b7db3Sskrll 2972a6b7db3Sskrll comments: MCCOMMENT { $$ = $1; } 2982a6b7db3Sskrll | comments MCCOMMENT 2992a6b7db3Sskrll { 3002a6b7db3Sskrll unichar *h; 3012a6b7db3Sskrll rc_uint_type l1,l2; 3022a6b7db3Sskrll l1 = unichar_len ($1); 3032a6b7db3Sskrll l2 = unichar_len ($2); 3042a6b7db3Sskrll h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar)); 3052a6b7db3Sskrll if (l1) memcpy (h, $1, l1 * sizeof (unichar)); 3062a6b7db3Sskrll if (l2) memcpy (&h[l1], $2, l2 * sizeof (unichar)); 3072a6b7db3Sskrll h[l1 + l2] = 0; 3082a6b7db3Sskrll $$ = h; 3092a6b7db3Sskrll } 3102a6b7db3Sskrll ; 3112a6b7db3Sskrll 3122a6b7db3Sskrll lang: MCLANGUAGE lex_want_nl '=' MCTOKEN NL 3132a6b7db3Sskrll { 3142a6b7db3Sskrll $$ = $4; 3152a6b7db3Sskrll } 3162a6b7db3Sskrll | MCLANGUAGE lex_want_nl '=' MCIDENT NL 3172a6b7db3Sskrll { 3182a6b7db3Sskrll $$ = NULL; 3192a6b7db3Sskrll mc_fatal (_("undeclared language identifier")); 3202a6b7db3Sskrll } 3212a6b7db3Sskrll | MCLANGUAGE lex_want_nl '=' token error 3222a6b7db3Sskrll { 3232a6b7db3Sskrll $$ = NULL; 3242a6b7db3Sskrll mc_fatal ("missing newline after Language"); 3252a6b7db3Sskrll } 3262a6b7db3Sskrll | MCLANGUAGE lex_want_nl '=' error 3272a6b7db3Sskrll { 3282a6b7db3Sskrll $$ = NULL; 3292a6b7db3Sskrll mc_fatal ("missing ident for Language"); 3302a6b7db3Sskrll } 3312a6b7db3Sskrll | MCLANGUAGE error 3322a6b7db3Sskrll { 3332a6b7db3Sskrll $$ = NULL; 3342a6b7db3Sskrll mc_fatal ("missing '=' for Language"); 3352a6b7db3Sskrll } 3362a6b7db3Sskrll ; 3372a6b7db3Sskrll 3382a6b7db3Sskrll token: MCIDENT { $$ = $1; } 3392a6b7db3Sskrll | MCTOKEN { $$ = $1->usz; } 3402a6b7db3Sskrll ; 3412a6b7db3Sskrll 3422a6b7db3Sskrll lex_want_nl: 3432a6b7db3Sskrll /* Empty */ { mclex_want_nl = 1; } 3442a6b7db3Sskrll ; 3452a6b7db3Sskrll 3462a6b7db3Sskrll lex_want_line: 3472a6b7db3Sskrll /* Empty */ { mclex_want_line = 1; } 3482a6b7db3Sskrll ; 3492a6b7db3Sskrll 3502a6b7db3Sskrll lex_want_filename: 3512a6b7db3Sskrll /* Empty */ { mclex_want_filename = 1; } 3522a6b7db3Sskrll ; 3532a6b7db3Sskrll 3542a6b7db3Sskrll %% 3552a6b7db3Sskrll 3562a6b7db3Sskrll /* Something else. */ 357