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