*** empty log message ***
[platform/upstream/binutils.git] / binutils / mcparse.y
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.  */