Commit | Line | Data |
---|---|---|
692ed3e7 | 1 | %{ /* mcparse.y -- parser for Windows mc files |
6f2750fe | 2 | Copyright (C) 2007-2016 Free Software Foundation, Inc. |
3aade688 | 3 | |
692ed3e7 NC |
4 | Parser for Windows mc files |
5 | Written by Kai Tietz, Onevision. | |
3aade688 | 6 | |
692ed3e7 | 7 | This file is part of GNU Binutils. |
3aade688 | 8 | |
692ed3e7 NC |
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 | |
32866df7 | 11 | the Free Software Foundation; either version 3 of the License, or |
692ed3e7 | 12 | (at your option) any later version. |
3aade688 | 13 | |
692ed3e7 NC |
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. | |
3aade688 | 18 | |
692ed3e7 NC |
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. */ |