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