Commit | Line | Data |
---|---|---|
692ed3e7 NC |
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 | |
32866df7 | 12 | the Free Software Foundation; either version 3 of the License, or |
692ed3e7 NC |
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. */ |