1 %{ /* rclex.l -- lexer for Windows rc files parser */
2 /* Copyright 1997, 1998, 1999, 2001, 2002, 2003, 2005
3 Free Software Foundation, Inc.
4 Written by Ian Lance Taylor, Cygnus Support.
6 This file is part of GNU Binutils.
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA
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
29 #include "libiberty.h"
30 #include "safe-ctype.h"
38 /* Whether we are in rcdata mode, in which we returns the lengths of
41 static int rcdata_mode;
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. */
51 static int suppress_cpp_data;
53 #define MAYBE_RETURN(x) return suppress_cpp_data ? IGNORED_TOKEN : (x)
55 /* The first filename we detect in the cpp output. We use this to
56 tell included files from the original file. */
58 static char *initial_fn;
60 /* List of allocated strings. */
64 struct alloc_string *next;
68 static struct alloc_string *strings;
70 /* Local functions. */
72 static void cpp_line (const char *);
73 static char *handle_quotes (const char *, unsigned long *);
74 static char *get_string (int);
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); }
157 "BLOCK"[ \t\n]*"\""[^\#\n]*"\"" {
160 /* This is a hack to let us parse version
161 information easily. */
163 s = strchr (yytext, '"');
165 send = strchr (s, '"');
166 if (strncmp (s, "StringFileInfo",
167 sizeof "StringFileInfo" - 1) == 0
168 && s + sizeof "StringFileInfo" - 1 == send)
169 MAYBE_RETURN (BLOCKSTRINGFILEINFO);
170 else if (strncmp (s, "VarFileInfo",
171 sizeof "VarFileInfo" - 1) == 0
172 && s + sizeof "VarFileInfo" - 1 == send)
173 MAYBE_RETURN (BLOCKVARFILEINFO);
178 r = get_string (send - s + 1);
179 strncpy (r, s, send - s);
182 MAYBE_RETURN (BLOCK);
190 [0-9][x0-9A-Fa-f]*L {
191 yylval.i.val = strtoul (yytext, 0, 0);
193 MAYBE_RETURN (NUMBER);
197 yylval.i.val = strtoul (yytext, 0, 0);
199 MAYBE_RETURN (NUMBER);
202 ("\""[^\"\n]*"\""[ \t\n]*)+ {
204 unsigned long length;
206 s = handle_quotes (yytext, &length);
210 MAYBE_RETURN (QUOTEDSTRING);
214 yylval.ss.length = length;
216 MAYBE_RETURN (SIZEDSTRING);
220 [A-Za-z][^ ,\t\r\n]* {
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. */
229 s = get_string (strlen (yytext) + 1);
232 MAYBE_RETURN (STRING);
235 [\n] { ++rc_lineno; }
236 [ \t\r]+ { /* ignore whitespace */ }
237 . { MAYBE_RETURN (*yytext); }
241 /* This is needed for some versions of lex. */
248 /* Handle a C preprocessor line. */
251 cpp_line (const char *s)
260 line = strtol (s, &send, 0);
261 if (*send != '\0' && ! ISSPACE (*send))
264 /* Subtract 1 because we are about to count the newline. */
265 rc_lineno = line - 1;
275 send = strchr (s, '"');
279 fn = (char *) xmalloc (send - s + 1);
280 strncpy (fn, s, send - s);
288 initial_fn = xmalloc (strlen (fn) + 1);
289 strcpy (initial_fn, fn);
292 /* Allow the initial file, regardless of name. Suppress all other
293 files if they end in ".h" (this allows included "*.rc"). */
294 if (strcmp (initial_fn, fn) == 0
295 || strcmp (fn + strlen (fn) - 2, ".h") != 0)
296 suppress_cpp_data = 0;
298 suppress_cpp_data = 1;
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. */
306 handle_quotes (const char *input, unsigned long *len)
312 ret = get_string (strlen (input) + 1);
326 rcparse_warning ("backslash at end of string");
330 rcparse_warning ("use \"\" to put \" in a string");
334 *s++ = ESCAPE_B; /* Strange, but true... */
372 case '0': case '1': case '2': case '3':
373 case '4': case '5': case '6': case '7':
376 if (*t >= '0' && *t <= '7')
378 ch = (ch << 3) | (*t - '0');
380 if (*t >= '0' && *t <= '7')
382 ch = (ch << 3) | (*t - '0');
394 if (*t >= '0' && *t <= '9')
395 ch = (ch << 4) | (*t - '0');
396 else if (*t >= 'a' && *t <= 'f')
397 ch = (ch << 4) | (*t - 'a' + 10);
398 else if (*t >= 'A' && *t <= 'F')
399 ch = (ch << 4) | (*t - 'A' + 10);
408 rcparse_warning ("unrecognized escape sequence");
416 else if (t[1] == '\0')
418 else if (t[1] == '"')
426 assert (ISSPACE (*t));
447 /* Allocate a string of a given length. */
452 struct alloc_string *as;
454 as = (struct alloc_string *) xmalloc (sizeof *as);
455 as->s = xmalloc (len);
463 /* Discard all the strings we have allocated. The parser calls this
464 when it no longer needs them. */
467 rcparse_discard_strings (void)
469 struct alloc_string *as;
474 struct alloc_string *n;
485 /* Enter rcdata mode. */
488 rcparse_rcdata (void)
493 /* Go back to normal mode from rcdata mode. */
496 rcparse_normal (void)