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 2 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
35static rc_uint_type mc_last_id = 0;
36static rc_uint_type mc_sefa_val = 0;
37static unichar *mc_last_symbol = NULL;
38static const mc_keyword *mc_cur_severity = NULL;
39static const mc_keyword *mc_cur_facility = NULL;
40static 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%%
67input:	  entities
68	;
69
70entities:
71	  /* empty */
72	| entities entity
73	;
74entity:	  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
84global_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
117severitymaps:
118	  severitymap
119	| severitymaps severitymap
120	| error { mc_fatal ("severity ident missing"); }
121;
122
123severitymap:
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
132facilitymaps:
133	  facilitymap
134	| facilitymaps facilitymap
135	| error { mc_fatal ("missing ident in FacilityNames"); }
136;
137
138facilitymap:
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
147langmaps:
148	  langmap
149	| langmaps langmap
150	| error { mc_fatal ("missing ident in LanguageNames"); }
151;
152
153langmap:
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
164alias_name:
165	  /* empty */
166	  {
167	    $$ = NULL;
168	  }
169	| ':' MCIDENT
170	  {
171	    $$ = $2;
172	  }
173	| ':' error { mc_fatal ("illegal token in identifier"); $$ = NULL; }
174;
175
176message:
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
190id:	  MCMESSAGEID '=' vid { $$ = $3; }
191	| MCMESSAGEID '=' error { mc_fatal ("missing number in MessageId"); $$ = 0; }
192	| MCMESSAGEID error { mc_fatal ("missing '=' for MessageId"); $$ = 0; }
193;
194
195vid:	  /* 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
210sefasy_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
239severity: 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
247facility: 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
255symbol: MCSYMBOLICNAME '=' MCIDENT
256	{
257	  mc_last_symbol = $3;
258	}
259;
260
261lang_entities:
262	  lang_entity
263	| lang_entities lang_entity
264;
265
266lang_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
277lines:	  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
297comments: 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
312lang:	  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
338token: 	MCIDENT { $$ = $1; }
339	|  MCTOKEN { $$ = $1->usz; }
340;
341
342lex_want_nl:
343	  /* Empty */	{ mclex_want_nl = 1; }
344;
345
346lex_want_line:
347	  /* Empty */	{ mclex_want_line = 1; }
348;
349
350lex_want_filename:
351	  /* Empty */	{ mclex_want_filename = 1; }
352;
353
354%%
355
356/* Something else.  */
357