gdb/testsuite: fix duplicate test names in gdb.base/index-cache.exp
[deliverable/binutils-gdb.git] / binutils / mclex.c
CommitLineData
692ed3e7 1/* mclex.c -- lexer for Windows mc files parser.
b3adc24a 2 Copyright (C) 2007-2020 Free Software Foundation, Inc.
692ed3e7
NC
3
4 Written by Kai Tietz, Onevision.
5
6 This file is part of GNU Binutils.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
32866df7 10 the Free Software Foundation; either version 3 of the License, or
692ed3e7
NC
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21 02110-1301, USA. */
22
23/* This is a lexer used by the Windows rc file parser.
24 It basically just recognized a bunch of keywords. */
25
26#include "sysdep.h"
27#include "bfd.h"
28#include "bucomm.h"
29#include "libiberty.h"
30#include "safe-ctype.h"
31#include "windmc.h"
32#include "mcparse.h"
33
34#include <assert.h>
35
36/* Exported globals. */
37bfd_boolean mclex_want_nl = FALSE;
38bfd_boolean mclex_want_line = FALSE;
39bfd_boolean mclex_want_filename = FALSE;
40
41/* Local globals. */
42static unichar *input_stream = NULL;
43static unichar *input_stream_pos = NULL;
44static int input_line = 1;
45static const char *input_filename = NULL;
46
47void
48mc_set_content (const unichar *src)
49{
50 if (!src)
51 return;
52 input_stream = input_stream_pos = unichar_dup (src);
53}
54
55void
56mc_set_inputfile (const char *name)
57{
58 if (! name || *name == 0)
59 input_filename = "-";
60 else
61 {
62 const char *s1 = strrchr (name, '/');
63 const char *s2 = strrchr (name, '\\');
64
65 if (! s1)
66 s1 = s2;
67 if (s1 && s2 && s1 < s2)
68 s1 = s2;
69 if (! s1)
70 s1 = name;
71 else
72 s1++;
73 s1 = xstrdup (s1);
74 input_filename = s1;
75 }
76}
77
78static void
79show_msg (const char *kind, const char *msg, va_list argp)
80{
81 fprintf (stderr, "In %s at line %d: %s: ", input_filename, input_line, kind);
82 vfprintf (stderr, msg, argp);
83 fprintf (stderr, ".\n");
84}
85
86void
87mc_warn (const char *s, ...)
88{
89 va_list argp;
90 va_start (argp, s);
91 show_msg ("warning", s, argp);
92 va_end (argp);
93}
94
95void
96mc_fatal (const char *s, ...)
97{
98 va_list argp;
99 va_start (argp, s);
100 show_msg ("fatal", s, argp);
101 va_end (argp);
102 xexit (1);
103}
104
105
106int
107yyerror (const char *s, ...)
108{
109 va_list argp;
110 va_start (argp, s);
111 show_msg ("parser", s, argp);
112 va_end (argp);
113 return 1;
114}
115
116static unichar *
117get_diff (unichar *end, unichar *start)
118{
119 unichar *ret;
120 unichar save = *end;
121
122 *end = 0;
123 ret = unichar_dup (start);
124 *end = save;
125 return ret;
126}
127
128static rc_uint_type
129parse_digit (unichar ch)
130{
131 rc_uint_type base = 10, v = 0, c;
132
133 if (ch == '0')
134 {
135 base = 8;
136 switch (input_stream_pos[0])
137 {
138 case 'x': case 'X': base = 16; input_stream_pos++; break;
139 case 'o': case 'O': base = 8; input_stream_pos++; break;
140 case 'b': case 'B': base = 2; input_stream_pos++; break;
141 }
142 }
143 else
144 v = (rc_uint_type) (ch - '0');
145
146 while ((ch = input_stream_pos[0]) != 0)
147 {
148 if (ch >= 'A' && ch <= 'F')
149 c = (rc_uint_type) (ch - 'A') + 10;
150 else if (ch >= 'a' && ch <= 'f')
151 c = (rc_uint_type) (ch - 'a') + 10;
152 else if (ch >= '0' && ch <= '9')
153 c = (rc_uint_type) (ch - '0');
154 else
155 break;
156 v *= base;
157 v += c;
158 ++input_stream_pos;
159 }
160 if (input_stream_pos[0] == 'U' || input_stream_pos[0] == 'u')
161 input_stream_pos++;
162 if (input_stream_pos[0] == 'L' || input_stream_pos[0] == 'l')
163 input_stream_pos++;
164 if (input_stream_pos[0] == 'L' || input_stream_pos[0] == 'l')
165 input_stream_pos++;
166 return v;
167}
168
169static mc_keyword *keyword_top = NULL;
170
171const mc_keyword *
172enum_facility (int e)
173{
174 mc_keyword *h = keyword_top;
175
176 while (h != NULL)
177 {
178 while (h && strcmp (h->group_name, "facility") != 0)
179 h = h->next;
180 if (e == 0)
181 return h;
182 --e;
183 if (h)
184 h = h->next;
185 }
186 return h;
187}
188
189const mc_keyword *
190enum_severity (int e)
191{
192 mc_keyword *h = keyword_top;
193
194 while (h != NULL)
195 {
196 while (h && strcmp (h->group_name, "severity") != 0)
197 h = h->next;
198 if (e == 0)
199 return h;
200 --e;
201 if (h)
202 h = h->next;
203 }
204 return h;
205}
206
207static void
208mc_add_keyword_ascii (const char *sz, int rid, const char *grp, rc_uint_type nv, const char *sv)
209{
210 unichar *usz, *usv = NULL;
211 rc_uint_type usz_len;
212
213 unicode_from_codepage (&usz_len, &usz, sz, CP_ACP);
214 if (sv)
215 unicode_from_codepage (&usz_len, &usv, sv, CP_ACP);
216 mc_add_keyword (usz, rid, grp, nv, usv);
217}
218
219void
220mc_add_keyword (unichar *usz, int rid, const char *grp, rc_uint_type nv, unichar *sv)
221{
222 mc_keyword *p, *c, *n;
223 size_t len = unichar_len (usz);
224
225 c = keyword_top;
226 p = NULL;
227 while (c != NULL)
228 {
229 if (c->len > len)
230 break;
231 if (c->len == len)
232 {
233 int e = memcmp (usz, c->usz, len * sizeof (unichar));
234
235 if (e < 0)
236 break;
237 if (! e)
238 {
239 if (! strcmp (grp, "keyword") || strcmp (c->group_name, grp) != 0)
240 fatal (_("Duplicate symbol entered into keyword list."));
241 c->rid = rid;
242 c->nval = nv;
243 c->sval = (!sv ? NULL : unichar_dup (sv));
244 if (! strcmp (grp, "language"))
245 {
246 const wind_language_t *lag = wind_find_language_by_id ((unsigned) nv);
247
248 if (lag == NULL)
249 fatal ("Language ident 0x%lx is not resolvable.\n", (long) nv);
250 memcpy (&c->lang_info, lag, sizeof (*lag));
251 }
252 return;
253 }
254 }
255 c = (p = c)->next;
256 }
257 n = xmalloc (sizeof (mc_keyword));
258 n->next = c;
259 n->len = len;
260 n->group_name = grp;
261 n->usz = usz;
262 n->rid = rid;
263 n->nval = nv;
264 n->sval = (!sv ? NULL : unichar_dup (sv));
265 if (! strcmp (grp, "language"))
266 {
267 const wind_language_t *lag = wind_find_language_by_id ((unsigned) nv);
268 if (lag == NULL)
269 fatal ("Language ident 0x%lx is not resolvable.\n", (long) nv);
270 memcpy (&n->lang_info, lag, sizeof (*lag));
271 }
272 if (! p)
273 keyword_top = n;
274 else
275 p->next = n;
276}
277
278static int
279mc_token (const unichar *t, size_t len)
280{
281 static int was_init = 0;
282 mc_keyword *k;
283
284 if (! was_init)
285 {
286 was_init = 1;
287 mc_add_keyword_ascii ("OutputBase", MCOUTPUTBASE, "keyword", 0, NULL);
288 mc_add_keyword_ascii ("MessageIdTypedef", MCMESSAGEIDTYPEDEF, "keyword", 0, NULL);
289 mc_add_keyword_ascii ("SeverityNames", MCSEVERITYNAMES, "keyword", 0, NULL);
290 mc_add_keyword_ascii ("FacilityNames", MCFACILITYNAMES, "keyword", 0, NULL);
291 mc_add_keyword_ascii ("LanguageNames", MCLANGUAGENAMES, "keyword", 0, NULL);
292 mc_add_keyword_ascii ("MessageId", MCMESSAGEID, "keyword", 0, NULL);
293 mc_add_keyword_ascii ("Severity", MCSEVERITY, "keyword", 0, NULL);
294 mc_add_keyword_ascii ("Facility", MCFACILITY, "keyword", 0, NULL);
295 mc_add_keyword_ascii ("SymbolicName", MCSYMBOLICNAME, "keyword", 0, NULL);
296 mc_add_keyword_ascii ("Language", MCLANGUAGE, "keyword", 0, NULL);
297 mc_add_keyword_ascii ("Success", MCTOKEN, "severity", 0, NULL);
298 mc_add_keyword_ascii ("Informational", MCTOKEN, "severity", 1, NULL);
299 mc_add_keyword_ascii ("Warning", MCTOKEN, "severity", 2, NULL);
300 mc_add_keyword_ascii ("Error", MCTOKEN, "severity", 3, NULL);
301 mc_add_keyword_ascii ("System", MCTOKEN, "facility", 0xff, NULL);
302 mc_add_keyword_ascii ("Application", MCTOKEN, "facility", 0xfff, NULL);
303 mc_add_keyword_ascii ("English", MCTOKEN, "language", 0x409, "MSG00001");
304 }
305 k = keyword_top;
306 if (!len || !t || *t == 0)
307 return -1;
308 while (k != NULL)
309 {
310 if (k->len > len)
311 break;
312 if (k->len == len)
313 {
314 if (! memcmp (k->usz, t, len * sizeof (unichar)))
315 {
316 if (k->rid == MCTOKEN)
317 yylval.tok = k;
318 return k->rid;
319 }
320 }
321 k = k->next;
322 }
323 return -1;
324}
325
326int
327yylex (void)
328{
329 unichar *start_token;
330 unichar ch;
331
332 if (! input_stream_pos)
333 {
334 fatal ("Input stream not setuped.\n");
335 return -1;
336 }
337 if (mclex_want_line)
338 {
339 start_token = input_stream_pos;
8affa48a
JA
340 if (input_stream_pos[0] == 0)
341 return -1;
692ed3e7
NC
342 if (input_stream_pos[0] == '.'
343 && (input_stream_pos[1] == '\n'
344 || (input_stream_pos[1] == '\r' && input_stream_pos[2] == '\n')))
8affa48a
JA
345 {
346 mclex_want_line = FALSE;
347 while (input_stream_pos[0] != 0 && input_stream_pos[0] != '\n')
348 ++input_stream_pos;
349 if (input_stream_pos[0] == '\n')
350 ++input_stream_pos;
351 return MCENDLINE;
352 }
692ed3e7
NC
353 while (input_stream_pos[0] != 0 && input_stream_pos[0] != '\n')
354 ++input_stream_pos;
355 if (input_stream_pos[0] == '\n')
356 ++input_stream_pos;
357 yylval.ustr = get_diff (input_stream_pos, start_token);
358 return MCLINE;
359 }
360 while ((ch = input_stream_pos[0]) <= 0x20)
361 {
362 if (ch == 0)
363 return -1;
364 ++input_stream_pos;
365 if (ch == '\n')
366 input_line += 1;
367 if (mclex_want_nl && ch == '\n')
368 {
369 mclex_want_nl = FALSE;
370 return NL;
371 }
372 }
373 start_token = input_stream_pos;
374 ++input_stream_pos;
375 if (mclex_want_filename)
376 {
377 mclex_want_filename = FALSE;
378 if (ch == '"')
379 {
380 start_token++;
381 while ((ch = input_stream_pos[0]) != 0)
382 {
383 if (ch == '"')
384 break;
385 ++input_stream_pos;
386 }
387 yylval.ustr = get_diff (input_stream_pos, start_token);
388 if (ch == '"')
389 ++input_stream_pos;
390 }
391 else
392 {
393 while ((ch = input_stream_pos[0]) != 0)
394 {
395 if (ch <= 0x20 || ch == ')')
396 break;
397 ++input_stream_pos;
398 }
399 yylval.ustr = get_diff (input_stream_pos, start_token);
400 }
401 return MCFILENAME;
402 }
403 switch (ch)
404 {
405 case ';':
406 ++start_token;
407 while (input_stream_pos[0] != '\n' && input_stream_pos[0] != 0)
408 ++input_stream_pos;
409 if (input_stream_pos[0] == '\n')
410 input_stream_pos++;
411 yylval.ustr = get_diff (input_stream_pos, start_token);
412 return MCCOMMENT;
413 case '=':
414 return '=';
415 case '(':
416 return '(';
417 case ')':
418 return ')';
419 case '+':
420 return '+';
421 case ':':
422 return ':';
423 case '0': case '1': case '2': case '3': case '4':
424 case '5': case '6': case '7': case '8': case '9':
425 yylval.ival = parse_digit (ch);
426 return MCNUMBER;
427 default:
428 if (ch >= 0x40)
429 {
430 int ret;
431 while (input_stream_pos[0] >= 0x40 || (input_stream_pos[0] >= '0' && input_stream_pos[0] <= '9'))
432 ++input_stream_pos;
433 ret = mc_token (start_token, (size_t) (input_stream_pos - start_token));
434 if (ret != -1)
435 return ret;
436 yylval.ustr = get_diff (input_stream_pos, start_token);
437 return MCIDENT;
438 }
439 yyerror ("illegal character 0x%x.", ch);
440 }
441 return -1;
442}
This page took 0.732372 seconds and 4 git commands to generate.