• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 %{ /* mcparse.y -- parser for Windows mc files
2   Copyright (C) 2007-2014 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 
34 static rc_uint_type mc_last_id = 0;
35 static rc_uint_type mc_sefa_val = 0;
36 static unichar *mc_last_symbol = NULL;
37 static const mc_keyword *mc_cur_severity = NULL;
38 static const mc_keyword *mc_cur_facility = NULL;
39 static 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 %%
66 input:	  entities
67 	;
68 
69 entities:
70 	  /* empty */
71 	| entities entity
72 	;
73 entity:	  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 
83 global_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 
116 severitymaps:
117 	  severitymap
118 	| severitymaps severitymap
119 	| error { mc_fatal ("severity ident missing"); }
120 ;
121 
122 severitymap:
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 
131 facilitymaps:
132 	  facilitymap
133 	| facilitymaps facilitymap
134 	| error { mc_fatal ("missing ident in FacilityNames"); }
135 ;
136 
137 facilitymap:
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 
146 langmaps:
147 	  langmap
148 	| langmaps langmap
149 	| error { mc_fatal ("missing ident in LanguageNames"); }
150 ;
151 
152 langmap:
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 
163 alias_name:
164 	  /* empty */
165 	  {
166 	    $$ = NULL;
167 	  }
168 	| ':' MCIDENT
169 	  {
170 	    $$ = $2;
171 	  }
172 	| ':' error { mc_fatal ("illegal token in identifier"); $$ = NULL; }
173 ;
174 
175 message:
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 
189 id:	  MCMESSAGEID '=' vid { $$ = $3; }
190 	| MCMESSAGEID '=' error { mc_fatal ("missing number in MessageId"); $$ = 0; }
191 	| MCMESSAGEID error { mc_fatal ("missing '=' for MessageId"); $$ = 0; }
192 ;
193 
194 vid:	  /* 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 
209 sefasy_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 
238 severity: 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 
246 facility: 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 
254 symbol: MCSYMBOLICNAME '=' MCIDENT
255 	{
256 	  mc_last_symbol = $3;
257 	}
258 ;
259 
260 lang_entities:
261 	  lang_entity
262 	| lang_entities lang_entity
263 ;
264 
265 lang_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 
276 lines:	  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 
296 comments: 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 
311 lang:	  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 
337 token: 	MCIDENT { $$ = $1; }
338 	|  MCTOKEN { $$ = $1->usz; }
339 ;
340 
341 lex_want_nl:
342 	  /* Empty */	{ mclex_want_nl = 1; }
343 ;
344 
345 lex_want_line:
346 	  /* Empty */	{ mclex_want_line = 1; }
347 ;
348 
349 lex_want_filename:
350 	  /* Empty */	{ mclex_want_filename = 1; }
351 ;
352 
353 %%
354 
355 /* Something else.  */
356