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