Revert the value change of DT_ENCODING from 2003-01-17. Luckily (and
[deliverable/binutils-gdb.git] / binutils / rclex.l
CommitLineData
252b5132 1%{ /* rclex.l -- lexer for Windows rc files parser */
aef6203b
AM
2/* Copyright 1997, 1998, 1999, 2001, 2002, 2003, 2005
3 Free Software Foundation, Inc.
252b5132
RH
4 Written by Ian Lance Taylor, Cygnus Support.
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
10 the Free Software Foundation; either version 2 of the License, or
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
b43b5d5f
NC
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21 02110-1301, USA. */
252b5132
RH
22
23/* This is a lex input file which generates a lexer used by the
24 Windows rc file parser. It basically just recognized a bunch of
25 keywords. */
26
27#include "bfd.h"
28#include "bucomm.h"
29#include "libiberty.h"
3882b010 30#include "safe-ctype.h"
252b5132
RH
31#include "windres.h"
32#include "rcparse.h"
33
252b5132
RH
34#include <assert.h>
35
0af6db78
AM
36#define YY_NO_UNPUT
37
252b5132
RH
38/* Whether we are in rcdata mode, in which we returns the lengths of
39 strings. */
40
41static int rcdata_mode;
42
1a624788
DD
43/* Whether we are supressing lines from cpp (including windows.h or
44 headers from your C sources may bring in externs and typedefs).
45 When active, we return IGNORED_TOKEN, which lets us ignore these
46 outside of resource constructs. Thus, it isn't required to protect
47 all the non-preprocessor lines in your header files with #ifdef
48 RC_INVOKED. It also means your RC file can't include other RC
49 files if they're named "*.h". Sorry. Name them *.rch or whatever. */
50
51static int suppress_cpp_data;
52
53#define MAYBE_RETURN(x) return suppress_cpp_data ? IGNORED_TOKEN : (x)
54
55/* The first filename we detect in the cpp output. We use this to
56 tell included files from the original file. */
57
58static char *initial_fn;
59
252b5132
RH
60/* List of allocated strings. */
61
62struct alloc_string
63{
64 struct alloc_string *next;
65 char *s;
66};
67
68static struct alloc_string *strings;
69
70/* Local functions. */
71
2da42df6
AJ
72static void cpp_line (const char *);
73static char *handle_quotes (const char *, unsigned long *);
74static char *get_string (int);
252b5132
RH
75
76%}
77
78%%
79
1a624788
DD
80"BEGIN" { MAYBE_RETURN (BEG); }
81"{" { MAYBE_RETURN (BEG); }
82"END" { MAYBE_RETURN (END); }
83"}" { MAYBE_RETURN (END); }
84"ACCELERATORS" { MAYBE_RETURN (ACCELERATORS); }
85"VIRTKEY" { MAYBE_RETURN (VIRTKEY); }
86"ASCII" { MAYBE_RETURN (ASCII); }
87"NOINVERT" { MAYBE_RETURN (NOINVERT); }
88"SHIFT" { MAYBE_RETURN (SHIFT); }
89"CONTROL" { MAYBE_RETURN (CONTROL); }
90"ALT" { MAYBE_RETURN (ALT); }
91"BITMAP" { MAYBE_RETURN (BITMAP); }
92"CURSOR" { MAYBE_RETURN (CURSOR); }
93"DIALOG" { MAYBE_RETURN (DIALOG); }
94"DIALOGEX" { MAYBE_RETURN (DIALOGEX); }
95"EXSTYLE" { MAYBE_RETURN (EXSTYLE); }
96"CAPTION" { MAYBE_RETURN (CAPTION); }
97"CLASS" { MAYBE_RETURN (CLASS); }
98"STYLE" { MAYBE_RETURN (STYLE); }
99"AUTO3STATE" { MAYBE_RETURN (AUTO3STATE); }
100"AUTOCHECKBOX" { MAYBE_RETURN (AUTOCHECKBOX); }
101"AUTORADIOBUTTON" { MAYBE_RETURN (AUTORADIOBUTTON); }
102"CHECKBOX" { MAYBE_RETURN (CHECKBOX); }
103"COMBOBOX" { MAYBE_RETURN (COMBOBOX); }
104"CTEXT" { MAYBE_RETURN (CTEXT); }
105"DEFPUSHBUTTON" { MAYBE_RETURN (DEFPUSHBUTTON); }
106"EDITTEXT" { MAYBE_RETURN (EDITTEXT); }
107"GROUPBOX" { MAYBE_RETURN (GROUPBOX); }
108"LISTBOX" { MAYBE_RETURN (LISTBOX); }
109"LTEXT" { MAYBE_RETURN (LTEXT); }
110"PUSHBOX" { MAYBE_RETURN (PUSHBOX); }
111"PUSHBUTTON" { MAYBE_RETURN (PUSHBUTTON); }
112"RADIOBUTTON" { MAYBE_RETURN (RADIOBUTTON); }
113"RTEXT" { MAYBE_RETURN (RTEXT); }
114"SCROLLBAR" { MAYBE_RETURN (SCROLLBAR); }
115"STATE3" { MAYBE_RETURN (STATE3); }
116"USERBUTTON" { MAYBE_RETURN (USERBUTTON); }
117"BEDIT" { MAYBE_RETURN (BEDIT); }
118"HEDIT" { MAYBE_RETURN (HEDIT); }
119"IEDIT" { MAYBE_RETURN (IEDIT); }
120"FONT" { MAYBE_RETURN (FONT); }
121"ICON" { MAYBE_RETURN (ICON); }
122"LANGUAGE" { MAYBE_RETURN (LANGUAGE); }
123"CHARACTERISTICS" { MAYBE_RETURN (CHARACTERISTICS); }
124"VERSION" { MAYBE_RETURN (VERSIONK); }
125"MENU" { MAYBE_RETURN (MENU); }
126"MENUEX" { MAYBE_RETURN (MENUEX); }
127"MENUITEM" { MAYBE_RETURN (MENUITEM); }
128"SEPARATOR" { MAYBE_RETURN (SEPARATOR); }
129"POPUP" { MAYBE_RETURN (POPUP); }
130"CHECKED" { MAYBE_RETURN (CHECKED); }
131"GRAYED" { MAYBE_RETURN (GRAYED); }
132"HELP" { MAYBE_RETURN (HELP); }
133"INACTIVE" { MAYBE_RETURN (INACTIVE); }
134"MENUBARBREAK" { MAYBE_RETURN (MENUBARBREAK); }
135"MENUBREAK" { MAYBE_RETURN (MENUBREAK); }
136"MESSAGETABLE" { MAYBE_RETURN (MESSAGETABLE); }
137"RCDATA" { MAYBE_RETURN (RCDATA); }
138"STRINGTABLE" { MAYBE_RETURN (STRINGTABLE); }
139"VERSIONINFO" { MAYBE_RETURN (VERSIONINFO); }
140"FILEVERSION" { MAYBE_RETURN (FILEVERSION); }
141"PRODUCTVERSION" { MAYBE_RETURN (PRODUCTVERSION); }
142"FILEFLAGSMASK" { MAYBE_RETURN (FILEFLAGSMASK); }
143"FILEFLAGS" { MAYBE_RETURN (FILEFLAGS); }
144"FILEOS" { MAYBE_RETURN (FILEOS); }
145"FILETYPE" { MAYBE_RETURN (FILETYPE); }
146"FILESUBTYPE" { MAYBE_RETURN (FILESUBTYPE); }
147"VALUE" { MAYBE_RETURN (VALUE); }
148"MOVEABLE" { MAYBE_RETURN (MOVEABLE); }
149"FIXED" { MAYBE_RETURN (FIXED); }
150"PURE" { MAYBE_RETURN (PURE); }
151"IMPURE" { MAYBE_RETURN (IMPURE); }
152"PRELOAD" { MAYBE_RETURN (PRELOAD); }
153"LOADONCALL" { MAYBE_RETURN (LOADONCALL); }
154"DISCARDABLE" { MAYBE_RETURN (DISCARDABLE); }
155"NOT" { MAYBE_RETURN (NOT); }
252b5132
RH
156
157"BLOCK"[ \t\n]*"\""[^\#\n]*"\"" {
158 char *s, *send;
159
160 /* This is a hack to let us parse version
161 information easily. */
162
163 s = strchr (yytext, '"');
164 ++s;
165 send = strchr (s, '"');
166 if (strncmp (s, "StringFileInfo",
167 sizeof "StringFileInfo" - 1) == 0
168 && s + sizeof "StringFileInfo" - 1 == send)
1a624788 169 MAYBE_RETURN (BLOCKSTRINGFILEINFO);
252b5132
RH
170 else if (strncmp (s, "VarFileInfo",
171 sizeof "VarFileInfo" - 1) == 0
172 && s + sizeof "VarFileInfo" - 1 == send)
1a624788 173 MAYBE_RETURN (BLOCKVARFILEINFO);
252b5132
RH
174 else
175 {
176 char *r;
177
178 r = get_string (send - s + 1);
179 strncpy (r, s, send - s);
180 r[send - s] = '\0';
181 yylval.s = r;
1a624788 182 MAYBE_RETURN (BLOCK);
252b5132
RH
183 }
184 }
185
186"#"[^\n]* {
187 cpp_line (yytext);
188 }
189
190[0-9][x0-9A-Fa-f]*L {
191 yylval.i.val = strtoul (yytext, 0, 0);
192 yylval.i.dword = 1;
1a624788 193 MAYBE_RETURN (NUMBER);
252b5132
RH
194 }
195
196[0-9][x0-9A-Fa-f]* {
197 yylval.i.val = strtoul (yytext, 0, 0);
198 yylval.i.dword = 0;
1a624788 199 MAYBE_RETURN (NUMBER);
252b5132
RH
200 }
201
6e5f5201 202("\""[^\"\n]*"\""[ \t\n]*)+ {
252b5132
RH
203 char *s;
204 unsigned long length;
205
206 s = handle_quotes (yytext, &length);
207 if (! rcdata_mode)
208 {
209 yylval.s = s;
1a624788 210 MAYBE_RETURN (QUOTEDSTRING);
252b5132
RH
211 }
212 else
213 {
214 yylval.ss.length = length;
215 yylval.ss.s = s;
1a624788 216 MAYBE_RETURN (SIZEDSTRING);
252b5132
RH
217 }
218 }
219
c6e15d68 220[_A-Za-z][^ ,\t\r\n]* {
252b5132
RH
221 char *s;
222
223 /* I rejected comma in a string in order to
224 handle VIRTKEY, CONTROL in an accelerator
225 resource. This means that an unquoted
226 file name can not contain a comma. I
227 don't know what rc permits. */
228
229 s = get_string (strlen (yytext) + 1);
230 strcpy (s, yytext);
231 yylval.s = s;
1a624788 232 MAYBE_RETURN (STRING);
252b5132
RH
233 }
234
235[\n] { ++rc_lineno; }
236[ \t\r]+ { /* ignore whitespace */ }
1a624788 237. { MAYBE_RETURN (*yytext); }
252b5132
RH
238
239%%
240#ifndef yywrap
241/* This is needed for some versions of lex. */
2da42df6 242int yywrap (void)
252b5132
RH
243{
244 return 1;
245}
246#endif
247
248/* Handle a C preprocessor line. */
249
250static void
2da42df6 251cpp_line (const char *s)
252b5132
RH
252{
253 int line;
254 char *send, *fn;
255
256 ++s;
3882b010 257 while (ISSPACE (*s))
252b5132
RH
258 ++s;
259
260 line = strtol (s, &send, 0);
3882b010 261 if (*send != '\0' && ! ISSPACE (*send))
252b5132
RH
262 return;
263
264 /* Subtract 1 because we are about to count the newline. */
265 rc_lineno = line - 1;
266
267 s = send;
3882b010 268 while (ISSPACE (*s))
252b5132
RH
269 ++s;
270
271 if (*s != '"')
272 return;
273
274 ++s;
275 send = strchr (s, '"');
276 if (send == NULL)
277 return;
278
279 fn = (char *) xmalloc (send - s + 1);
280 strncpy (fn, s, send - s);
281 fn[send - s] = '\0';
282
283 free (rc_filename);
284 rc_filename = fn;
1a624788
DD
285
286 if (!initial_fn)
287 {
288 initial_fn = xmalloc (strlen (fn) + 1);
4c30641a 289 strcpy (initial_fn, fn);
1a624788
DD
290 }
291
292 /* Allow the initial file, regardless of name. Suppress all other
4c30641a 293 files if they end in ".h" (this allows included "*.rc"). */
1a624788
DD
294 if (strcmp (initial_fn, fn) == 0
295 || strcmp (fn + strlen (fn) - 2, ".h") != 0)
296 suppress_cpp_data = 0;
297 else
298 suppress_cpp_data = 1;
252b5132
RH
299}
300
301/* Handle a quoted string. The quotes are stripped. A pair of quotes
302 in a string are turned into a single quote. Adjacent strings are
303 merged separated by whitespace are merged, as in C. */
304
305static char *
2da42df6 306handle_quotes (const char *input, unsigned long *len)
252b5132
RH
307{
308 char *ret, *s;
309 const char *t;
310 int ch;
0851f043 311 int num_xdigits;
252b5132
RH
312
313 ret = get_string (strlen (input) + 1);
314
315 s = ret;
316 t = input;
317 if (*t == '"')
318 ++t;
319 while (*t != '\0')
320 {
321 if (*t == '\\')
322 {
323 ++t;
324 switch (*t)
325 {
326 case '\0':
327 rcparse_warning ("backslash at end of string");
328 break;
329
330 case '\"':
331 rcparse_warning ("use \"\" to put \" in a string");
332 break;
333
334 case 'a':
4d0b1625 335 *s++ = ESCAPE_B; /* Strange, but true... */
252b5132
RH
336 ++t;
337 break;
338
339 case 'b':
340 *s++ = ESCAPE_B;
341 ++t;
342 break;
343
344 case 'f':
345 *s++ = ESCAPE_F;
346 ++t;
347 break;
348
349 case 'n':
350 *s++ = ESCAPE_N;
351 ++t;
352 break;
353
354 case 'r':
355 *s++ = ESCAPE_R;
356 ++t;
357 break;
358
359 case 't':
360 *s++ = ESCAPE_T;
361 ++t;
362 break;
363
364 case 'v':
365 *s++ = ESCAPE_V;
366 ++t;
367 break;
368
369 case '\\':
370 *s++ = *t++;
371 break;
372
373 case '0': case '1': case '2': case '3':
374 case '4': case '5': case '6': case '7':
375 ch = *t - '0';
376 ++t;
377 if (*t >= '0' && *t <= '7')
378 {
379 ch = (ch << 3) | (*t - '0');
380 ++t;
381 if (*t >= '0' && *t <= '7')
382 {
383 ch = (ch << 3) | (*t - '0');
384 ++t;
385 }
386 }
387 *s++ = ch;
388 break;
389
390 case 'x':
391 ++t;
392 ch = 0;
0851f043
DS
393 /* We only handle single byte chars here. Make sure
394 we finish an escape sequence like "/xB0ABC" after
395 the first two digits. */
396 num_xdigits = 2;
397 while (num_xdigits--)
252b5132
RH
398 {
399 if (*t >= '0' && *t <= '9')
400 ch = (ch << 4) | (*t - '0');
401 else if (*t >= 'a' && *t <= 'f')
4c30641a 402 ch = (ch << 4) | (*t - 'a' + 10);
252b5132 403 else if (*t >= 'A' && *t <= 'F')
4c30641a 404 ch = (ch << 4) | (*t - 'A' + 10);
252b5132
RH
405 else
406 break;
407 ++t;
408 }
409 *s++ = ch;
410 break;
411
412 default:
413 rcparse_warning ("unrecognized escape sequence");
414 *s++ = '\\';
415 *s++ = *t++;
416 break;
417 }
418 }
419 else if (*t != '"')
420 *s++ = *t++;
421 else if (t[1] == '\0')
422 break;
423 else if (t[1] == '"')
424 {
425 *s++ = '"';
426 t += 2;
427 }
428 else
429 {
430 ++t;
3882b010
L
431 assert (ISSPACE (*t));
432 while (ISSPACE (*t))
0e11a9e9
CF
433 {
434 if ((*t) == '\n')
435 ++rc_lineno;
436 ++t;
437 }
252b5132
RH
438 if (*t == '\0')
439 break;
440 assert (*t == '"');
441 ++t;
442 }
443 }
444
445 *s = '\0';
446
447 *len = s - ret;
448
449 return ret;
450}
451
452/* Allocate a string of a given length. */
453
454static char *
2da42df6 455get_string (int len)
252b5132
RH
456{
457 struct alloc_string *as;
458
459 as = (struct alloc_string *) xmalloc (sizeof *as);
460 as->s = xmalloc (len);
461
462 as->next = strings;
405c98a4 463 strings = as;
252b5132
RH
464
465 return as->s;
466}
467
468/* Discard all the strings we have allocated. The parser calls this
469 when it no longer needs them. */
470
471void
2da42df6 472rcparse_discard_strings (void)
252b5132
RH
473{
474 struct alloc_string *as;
475
476 as = strings;
477 while (as != NULL)
478 {
479 struct alloc_string *n;
480
481 free (as->s);
482 n = as->next;
483 free (as);
484 as = n;
485 }
486
487 strings = NULL;
488}
489
490/* Enter rcdata mode. */
491
492void
2da42df6 493rcparse_rcdata (void)
252b5132
RH
494{
495 rcdata_mode = 1;
496}
497
498/* Go back to normal mode from rcdata mode. */
499
500void
2da42df6 501rcparse_normal (void)
252b5132
RH
502{
503 rcdata_mode = 0;
504}
This page took 1.136624 seconds and 4 git commands to generate.