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.
5 This file is part of GNU Binutils.
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.
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.
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
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
28 #include "libiberty.h"
35 /* Whether we are in rcdata mode, in which we returns the lengths of
38 static int rcdata_mode;
40 /* List of allocated strings. */
44 struct alloc_string *next;
48 static struct alloc_string *strings;
50 /* Local functions. */
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));
60 "BEGIN" { return BEG; }
64 "ACCELERATORS" { return ACCELERATORS; }
65 "VIRTKEY" { return VIRTKEY; }
66 "ASCII" { return ASCII; }
67 "NOINVERT" { return NOINVERT; }
68 "SHIFT" { return SHIFT; }
69 "CONTROL" { return CONTROL; }
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; }
137 "BLOCK"[ \t\n]*"\""[^\#\n]*"\"" {
140 /* This is a hack to let us parse version
141 information easily. */
143 s = strchr (yytext, '"');
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;
158 r = get_string (send - s + 1);
159 strncpy (r, s, send - s);
170 [0-9][x0-9A-Fa-f]*L {
171 yylval.i.val = strtoul (yytext, 0, 0);
177 yylval.i.val = strtoul (yytext, 0, 0);
182 ("\""[^\"\n]*"\""[ \t]*)+ {
184 unsigned long length;
186 s = handle_quotes (yytext, &length);
194 yylval.ss.length = length;
200 [A-Za-z][^ ,\t\r\n]* {
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. */
209 s = get_string (strlen (yytext) + 1);
215 [\n] { ++rc_lineno; }
216 [ \t\r]+ { /* ignore whitespace */ }
217 . { return *yytext; }
221 /* This is needed for some versions of lex. */
228 /* Handle a C preprocessor line. */
238 while (isspace ((unsigned char) *s))
241 line = strtol (s, &send, 0);
242 if (*send != '\0' && ! isspace ((unsigned char) *send))
245 /* Subtract 1 because we are about to count the newline. */
246 rc_lineno = line - 1;
249 while (isspace ((unsigned char) *s))
256 send = strchr (s, '"');
260 fn = (char *) xmalloc (send - s + 1);
261 strncpy (fn, s, send - s);
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. */
273 handle_quotes (input, len)
281 ret = get_string (strlen (input) + 1);
295 rcparse_warning ("backslash at end of string");
299 rcparse_warning ("use \"\" to put \" in a string");
341 case '0': case '1': case '2': case '3':
342 case '4': case '5': case '6': case '7':
345 if (*t >= '0' && *t <= '7')
347 ch = (ch << 3) | (*t - '0');
349 if (*t >= '0' && *t <= '7')
351 ch = (ch << 3) | (*t - '0');
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');
377 rcparse_warning ("unrecognized escape sequence");
385 else if (t[1] == '\0')
387 else if (t[1] == '"')
395 assert (isspace ((unsigned char) *t));
396 while (isspace ((unsigned char) *t))
412 /* Allocate a string of a given length. */
418 struct alloc_string *as;
420 as = (struct alloc_string *) xmalloc (sizeof *as);
421 as->s = xmalloc (len);
429 /* Discard all the strings we have allocated. The parser calls this
430 when it no longer needs them. */
433 rcparse_discard_strings ()
435 struct alloc_string *as;
440 struct alloc_string *n;
451 /* Enter rcdata mode. */
459 /* Go back to normal mode from rcdata mode. */