1%{ /* mcparse.y -- parser for Windows mc files
2  Copyright (C) 2007-2017 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
34static rc_uint_type mc_last_id = 0;
35static rc_uint_type mc_sefa_val = 0;
36static unichar *mc_last_symbol = NULL;
37static const mc_keyword *mc_cur_severity = NULL;
38static const mc_keyword *mc_cur_facility = NULL;
39static 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%%
66input:	  entities
67	;
68
69entities:
70	  /* empty */
71	| entities entity
72	;
73entity:	  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
83global_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
116severitymaps:
117	  severitymap
118	| severitymaps severitymap
119	| error { mc_fatal ("severity ident missing"); }
120;
121
122severitymap:
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
131facilitymaps:
132	  facilitymap
133	| facilitymaps facilitymap
134	| error { mc_fatal ("missing ident in FacilityNames"); }
135;
136
137facilitymap:
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
146langmaps:
147	  langmap
148	| langmaps langmap
149	| error { mc_fatal ("missing ident in LanguageNames"); }
150;
151
152langmap:
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
163alias_name:
164	  /* empty */
165	  {
166	    $$ = NULL;
167	  }
168	| ':' MCIDENT
169	  {
170	    $$ = $2;
171	  }
172	| ':' error { mc_fatal ("illegal token in identifier"); $$ = NULL; }
173;
174
175message:
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	    mc_last_id = $1;
185	  }
186	  lang_entities
187;
188
189id:	  MCMESSAGEID '=' vid { $$ = $3; }
190	| MCMESSAGEID '=' error { mc_fatal ("missing number in MessageId"); $$ = 0; }
191	| MCMESSAGEID error { mc_fatal ("missing '=' for MessageId"); $$ = 0; }
192;
193
194vid:	  /* empty */
195	  {
196	    $$ = ++mc_last_id;
197	  }
198	| MCNUMBER
199	  {
200	    $$ = $1;
201	  }
202	| '+' MCNUMBER
203	  {
204	    $$ = mc_last_id + $2;
205	  }
206	| '+' error { mc_fatal ("missing number after MessageId '+'"); }
207;
208
209sefasy_def:
210	  /* empty */
211	  {
212	    $$ = 0;
213	    mc_sefa_val = (mcset_custom_bit ? 1 : 0) << 29;
214	    mc_last_symbol = NULL;
215	    mc_cur_severity = NULL;
216	    mc_cur_facility = NULL;
217	  }
218	| sefasy_def severity
219	  {
220	    if ($1 & 1)
221	      mc_warn (_("duplicate definition of Severity"));
222	    $$ = $1 | 1;
223	  }
224	| sefasy_def facility
225	  {
226	    if ($1 & 2)
227	      mc_warn (_("duplicate definition of Facility"));
228	    $$ = $1 | 2;
229	  }
230	| sefasy_def symbol
231	  {
232	    if ($1 & 4)
233	      mc_warn (_("duplicate definition of SymbolicName"));
234	    $$ = $1 | 4;
235	  }
236;
237
238severity: MCSEVERITY '=' MCTOKEN
239	  {
240	    mc_sefa_val &= ~ (0x3UL << 30);
241	    mc_sefa_val |= (($3->nval & 0x3UL) << 30);
242	    mc_cur_severity = $3;
243	  }
244;
245
246facility: MCFACILITY '=' MCTOKEN
247	  {
248	    mc_sefa_val &= ~ (0xfffUL << 16);
249	    mc_sefa_val |= (($3->nval & 0xfffUL) << 16);
250	    mc_cur_facility = $3;
251	  }
252;
253
254symbol: MCSYMBOLICNAME '=' MCIDENT
255	{
256	  mc_last_symbol = $3;
257	}
258;
259
260lang_entities:
261	  lang_entity
262	| lang_entities lang_entity
263;
264
265lang_entity:
266	  lang lex_want_line lines MCENDLINE
267	  {
268	    mc_node_lang *h;
269	    h = mc_add_node_lang (cur_node, $1, cur_node->vid);
270	    h->message = $3;
271	    if (mcset_max_message_length != 0 && unichar_len (h->message) > mcset_max_message_length)
272	      mc_warn ("message length to long");
273	  }
274;
275
276lines:	  MCLINE
277	  {
278	    $$ = $1;
279	  }
280	| lines MCLINE
281	  {
282	    unichar *h;
283	    rc_uint_type l1,l2;
284	    l1 = unichar_len ($1);
285	    l2 = unichar_len ($2);
286	    h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar));
287	    if (l1) memcpy (h, $1, l1 * sizeof (unichar));
288	    if (l2) memcpy (&h[l1], $2, l2 * sizeof (unichar));
289	    h[l1 + l2] = 0;
290	    $$ = h;
291	  }
292	| error { mc_fatal ("missing end of message text"); $$ = NULL; }
293	| lines error { mc_fatal ("missing end of message text"); $$ = $1; }
294;
295
296comments: MCCOMMENT { $$ = $1; }
297	| comments MCCOMMENT
298	  {
299	    unichar *h;
300	    rc_uint_type l1,l2;
301	    l1 = unichar_len ($1);
302	    l2 = unichar_len ($2);
303	    h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar));
304	    if (l1) memcpy (h, $1, l1 * sizeof (unichar));
305	    if (l2) memcpy (&h[l1], $2, l2 * sizeof (unichar));
306	    h[l1 + l2] = 0;
307	    $$ = h;
308	  }
309;
310
311lang:	  MCLANGUAGE lex_want_nl '=' MCTOKEN NL
312	  {
313	    $$ = $4;
314	  }
315	| MCLANGUAGE lex_want_nl '=' MCIDENT NL
316	  {
317	    $$ = NULL;
318	    mc_fatal (_("undeclared language identifier"));
319	  }
320	| MCLANGUAGE lex_want_nl '=' token error
321	  {
322	    $$ = NULL;
323	    mc_fatal ("missing newline after Language");
324	  }
325	| MCLANGUAGE lex_want_nl '=' error
326	  {
327	    $$ = NULL;
328	    mc_fatal ("missing ident for Language");
329	  }
330	| MCLANGUAGE error
331	  {
332	    $$ = NULL;
333	    mc_fatal ("missing '=' for Language");
334	  }
335;
336
337token: 	MCIDENT { $$ = $1; }
338	|  MCTOKEN { $$ = $1->usz; }
339;
340
341lex_want_nl:
342	  /* Empty */	{ mclex_want_nl = 1; }
343;
344
345lex_want_line:
346	  /* Empty */	{ mclex_want_line = 1; }
347;
348
349lex_want_filename:
350	  /* Empty */	{ mclex_want_filename = 1; }
351;
352
353%%
354
355/* Something else.  */
356