Release 2.33.1
[external/binutils.git] / binutils / mcparse.y
1 %{ /* mcparse.y -- parser for Windows mc files
2   Copyright (C) 2007-2019 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.  */