Add support for building simulator based on common simulator framework.
[deliverable/binutils-gdb.git] / binutils / rclex.l
1 %{ /* rclex.l -- lexer for Windows rc files parser */
2 /* Copyright 1997 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Cygnus Support.
4
5 This file is part of GNU Binutils.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
21
22 /* This is a lex input file which generates a lexer used by the
23 Windows rc file parser. It basically just recognized a bunch of
24 keywords. */
25
26 #include "bfd.h"
27 #include "bucomm.h"
28 #include "libiberty.h"
29 #include "windres.h"
30 #include "rcparse.h"
31
32 #include <ctype.h>
33 #include <assert.h>
34
35 /* Whether we are in rcdata mode, in which we returns the lengths of
36 strings. */
37
38 static int rcdata_mode;
39
40 /* List of allocated strings. */
41
42 struct alloc_string
43 {
44 struct alloc_string *next;
45 char *s;
46 };
47
48 static struct alloc_string *strings;
49
50 /* Local functions. */
51
52 static void cpp_line PARAMS ((const char *));
53 static char *handle_quotes PARAMS ((const char *, unsigned long *));
54 static char *get_string PARAMS ((int));
55
56 %}
57
58 %%
59
60 "BEGIN" { return BEG; }
61 "END" { return END; }
62 "ACCELERATORS" { return ACCELERATORS; }
63 "VIRTKEY" { return VIRTKEY; }
64 "ASCII" { return ASCII; }
65 "NOINVERT" { return NOINVERT; }
66 "SHIFT" { return SHIFT; }
67 "CONTROL" { return CONTROL; }
68 "ALT" { return ALT; }
69 "BITMAP" { return BITMAP; }
70 "CURSOR" { return CURSOR; }
71 "DIALOG" { return DIALOG; }
72 "DIALOGEX" { return DIALOGEX; }
73 "EXSTYLE" { return EXSTYLE; }
74 "CAPTION" { return CAPTION; }
75 "CLASS" { return CLASS; }
76 "STYLE" { return STYLE; }
77 "AUTO3STATE" { return AUTO3STATE; }
78 "AUTOCHECKBOX" { return AUTOCHECKBOX; }
79 "AUTORADIOBUTTON" { return AUTORADIOBUTTON; }
80 "CHECKBOX" { return CHECKBOX; }
81 "COMBOBOX" { return COMBOBOX; }
82 "CTEXT" { return CTEXT; }
83 "DEFPUSHBUTTON" { return DEFPUSHBUTTON; }
84 "EDITTEXT" { return EDITTEXT; }
85 "GROUPBOX" { return GROUPBOX; }
86 "LISTBOX" { return LISTBOX; }
87 "LTEXT" { return LTEXT; }
88 "PUSHBOX" { return PUSHBOX; }
89 "PUSHBUTTON" { return PUSHBUTTON; }
90 "RADIOBUTTON" { return RADIOBUTTON; }
91 "RTEXT" { return RTEXT; }
92 "SCROLLBAR" { return SCROLLBAR; }
93 "STATE3" { return STATE3; }
94 "USERBUTTON" { return USERBUTTON; }
95 "BEDIT" { return BEDIT; }
96 "HEDIT" { return HEDIT; }
97 "IEDIT" { return IEDIT; }
98 "FONT" { return FONT; }
99 "ICON" { return ICON; }
100 "LANGUAGE" { return LANGUAGE; }
101 "CHARACTERISTICS" { return CHARACTERISTICS; }
102 "VERSION" { return VERSIONK; }
103 "MENU" { return MENU; }
104 "MENUEX" { return MENUEX; }
105 "MENUITEM" { return MENUITEM; }
106 "SEPARATOR" { return SEPARATOR; }
107 "POPUP" { return POPUP; }
108 "CHECKED" { return CHECKED; }
109 "GRAYED" { return GRAYED; }
110 "HELP" { return HELP; }
111 "INACTIVE" { return INACTIVE; }
112 "MENUBARBREAK" { return MENUBARBREAK; }
113 "MENUBREAK" { return MENUBREAK; }
114 "MESSAGETABLE" { return MESSAGETABLE; }
115 "RCDATA" { return RCDATA; }
116 "STRINGTABLE" { return STRINGTABLE; }
117 "VERSIONINFO" { return VERSIONINFO; }
118 "FILEVERSION" { return FILEVERSION; }
119 "PRODUCTVERSION" { return PRODUCTVERSION; }
120 "FILEFLAGSMASK" { return FILEFLAGSMASK; }
121 "FILEFLAGS" { return FILEFLAGS; }
122 "FILEOS" { return FILEOS; }
123 "FILETYPE" { return FILETYPE; }
124 "FILESUBTYPE" { return FILESUBTYPE; }
125 "VALUE" { return VALUE; }
126 "MOVEABLE" { return MOVEABLE; }
127 "FIXED" { return FIXED; }
128 "PURE" { return PURE; }
129 "IMPURE" { return IMPURE; }
130 "PRELOAD" { return PRELOAD; }
131 "LOADONCALL" { return LOADONCALL; }
132 "DISCARDABLE" { return DISCARDABLE; }
133 "NOT" { return NOT; }
134
135 "BLOCK"[ \t\n]*"\""[^\#\n]*"\"" {
136 char *s, *send;
137
138 /* This is a hack to let us parse version
139 information easily. */
140
141 s = strchr (yytext, '"');
142 ++s;
143 send = strchr (s, '"');
144 if (strncmp (s, "StringFileInfo",
145 sizeof "StringFileInfo" - 1) == 0
146 && s + sizeof "StringFileInfo" - 1 == send)
147 return BLOCKSTRINGFILEINFO;
148 else if (strncmp (s, "VarFileInfo",
149 sizeof "VarFileInfo" - 1) == 0
150 && s + sizeof "VarFileInfo" - 1 == send)
151 return BLOCKVARFILEINFO;
152 else
153 {
154 char *r;
155
156 r = get_string (send - s + 1);
157 strncpy (r, s, send - s);
158 r[send - s] = '\0';
159 yylval.s = r;
160 return BLOCK;
161 }
162 }
163
164 "#"[^\n]* {
165 cpp_line (yytext);
166 }
167
168 [0-9][x0-9A-Fa-f]*L {
169 yylval.i.val = strtoul (yytext, 0, 0);
170 yylval.i.dword = 1;
171 return NUMBER;
172 }
173
174 [0-9][x0-9A-Fa-f]* {
175 yylval.i.val = strtoul (yytext, 0, 0);
176 yylval.i.dword = 0;
177 return NUMBER;
178 }
179
180 ("\""[^\"\n]*"\""[ \t]*)+ {
181 char *s;
182 unsigned long length;
183
184 s = handle_quotes (yytext, &length);
185 if (! rcdata_mode)
186 {
187 yylval.s = s;
188 return QUOTEDSTRING;
189 }
190 else
191 {
192 yylval.ss.length = length;
193 yylval.ss.s = s;
194 return SIZEDSTRING;
195 }
196 }
197
198 [A-Za-z][^ ,\t\r\n]* {
199 char *s;
200
201 /* I rejected comma in a string in order to
202 handle VIRTKEY, CONTROL in an accelerator
203 resource. This means that an unquoted
204 file name can not contain a comma. I
205 don't know what rc permits. */
206
207 s = get_string (strlen (yytext) + 1);
208 strcpy (s, yytext);
209 yylval.s = s;
210 return STRING;
211 }
212
213 [\n] { ++rc_lineno; }
214 [ \t\r]+ { /* ignore whitespace */ }
215 . { return *yytext; }
216
217 %%
218 #ifndef yywrap
219 /* This is needed for some versions of lex. */
220 int yywrap ()
221 {
222 return 1;
223 }
224 #endif
225
226 /* Handle a C preprocessor line. */
227
228 static void
229 cpp_line (s)
230 const char *s;
231 {
232 int line;
233 char *send, *fn;
234
235 ++s;
236 while (isspace (*s))
237 ++s;
238
239 line = strtol (s, &send, 0);
240 if (*send != '\0' && ! isspace (*send))
241 return;
242
243 /* Subtract 1 because we are about to count the newline. */
244 rc_lineno = line - 1;
245
246 s = send;
247 while (isspace (*s))
248 ++s;
249
250 if (*s != '"')
251 return;
252
253 ++s;
254 send = strchr (s, '"');
255 if (send == NULL)
256 return;
257
258 fn = (char *) xmalloc (send - s + 1);
259 strncpy (fn, s, send - s);
260 fn[send - s] = '\0';
261
262 free (rc_filename);
263 rc_filename = fn;
264 }
265
266 /* Handle a quoted string. The quotes are stripped. A pair of quotes
267 in a string are turned into a single quote. Adjacent strings are
268 merged separated by whitespace are merged, as in C. */
269
270 static char *
271 handle_quotes (input, len)
272 const char *input;
273 unsigned long *len;
274 {
275 char *ret, *s;
276 const char *t;
277 int ch;
278
279 ret = get_string (strlen (input) + 1);
280
281 s = ret;
282 t = input;
283 if (*t == '"')
284 ++t;
285 while (*t != '\0')
286 {
287 if (*t == '\\')
288 {
289 ++t;
290 switch (*t)
291 {
292 case '\0':
293 rcparse_warning ("backslash at end of string");
294 break;
295
296 case '\"':
297 rcparse_warning ("use \"\" to put \" in a string");
298 break;
299
300 case 'a':
301 *s++ = ESCAPE_A;
302 ++t;
303 break;
304
305 case 'b':
306 *s++ = ESCAPE_B;
307 ++t;
308 break;
309
310 case 'f':
311 *s++ = ESCAPE_F;
312 ++t;
313 break;
314
315 case 'n':
316 *s++ = ESCAPE_N;
317 ++t;
318 break;
319
320 case 'r':
321 *s++ = ESCAPE_R;
322 ++t;
323 break;
324
325 case 't':
326 *s++ = ESCAPE_T;
327 ++t;
328 break;
329
330 case 'v':
331 *s++ = ESCAPE_V;
332 ++t;
333 break;
334
335 case '\\':
336 *s++ = *t++;
337 break;
338
339 case '0': case '1': case '2': case '3':
340 case '4': case '5': case '6': case '7':
341 ch = *t - '0';
342 ++t;
343 if (*t >= '0' && *t <= '7')
344 {
345 ch = (ch << 3) | (*t - '0');
346 ++t;
347 if (*t >= '0' && *t <= '7')
348 {
349 ch = (ch << 3) | (*t - '0');
350 ++t;
351 }
352 }
353 *s++ = ch;
354 break;
355
356 case 'x':
357 ++t;
358 ch = 0;
359 while (1)
360 {
361 if (*t >= '0' && *t <= '9')
362 ch = (ch << 4) | (*t - '0');
363 else if (*t >= 'a' && *t <= 'f')
364 ch = (ch << 4) | (*t - 'a');
365 else if (*t >= 'A' && *t <= 'F')
366 ch = (ch << 4) | (*t - 'A');
367 else
368 break;
369 ++t;
370 }
371 *s++ = ch;
372 break;
373
374 default:
375 rcparse_warning ("unrecognized escape sequence");
376 *s++ = '\\';
377 *s++ = *t++;
378 break;
379 }
380 }
381 else if (*t != '"')
382 *s++ = *t++;
383 else if (t[1] == '\0')
384 break;
385 else if (t[1] == '"')
386 {
387 *s++ = '"';
388 t += 2;
389 }
390 else
391 {
392 ++t;
393 assert (isspace (*t));
394 while (isspace (*t))
395 ++t;
396 if (*t == '\0')
397 break;
398 assert (*t == '"');
399 ++t;
400 }
401 }
402
403 *s = '\0';
404
405 *len = s - ret;
406
407 return ret;
408 }
409
410 /* Allocate a string of a given length. */
411
412 static char *
413 get_string (len)
414 int len;
415 {
416 struct alloc_string *as;
417
418 as = (struct alloc_string *) xmalloc (sizeof *as);
419 as->s = xmalloc (len);
420
421 as->next = strings;
422 strings = as->next;
423
424 return as->s;
425 }
426
427 /* Discard all the strings we have allocated. The parser calls this
428 when it no longer needs them. */
429
430 void
431 rcparse_discard_strings ()
432 {
433 struct alloc_string *as;
434
435 as = strings;
436 while (as != NULL)
437 {
438 struct alloc_string *n;
439
440 free (as->s);
441 n = as->next;
442 free (as);
443 as = n;
444 }
445
446 strings = NULL;
447 }
448
449 /* Enter rcdata mode. */
450
451 void
452 rcparse_rcdata ()
453 {
454 rcdata_mode = 1;
455 }
456
457 /* Go back to normal mode from rcdata mode. */
458
459 void
460 rcparse_normal ()
461 {
462 rcdata_mode = 0;
463 }
This page took 0.039203 seconds and 4 git commands to generate.