]> Git Repo - binutils.git/blob - binutils/rclex.l
First stab at Windows resource compiler:
[binutils.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 static void cpp_line PARAMS ((const char *));
36 static char *handle_quotes PARAMS ((const char *));
37
38 %}
39
40 %%
41
42 "BEGIN"                 { return BEG; }
43 "END"                   { return END; }
44 "ACCELERATORS"          { return ACCELERATORS; }
45 "VIRTKEY"               { return VIRTKEY; }
46 "ASCII"                 { return ASCII; }
47 "NOINVERT"              { return NOINVERT; }
48 "SHIFT"                 { return SHIFT; }
49 "CONTROL"               { return CONTROL; }
50 "ALT"                   { return ALT; }
51 "BITMAP"                { return BITMAP; }
52 "CURSOR"                { return CURSOR; }
53 "DIALOG"                { return DIALOG; }
54 "DIALOGEX"              { return DIALOGEX; }
55 "EXSTYLE"               { return EXSTYLE; }
56 "CAPTION"               { return CAPTION; }
57 "CLASS"                 { return CLASS; }
58 "STYLE"                 { return STYLE; }
59 "AUTO3STATE"            { return AUTO3STATE; }
60 "AUTOCHECKBOX"          { return AUTOCHECKBOX; }
61 "AUTORADIOBUTTON"       { return AUTORADIOBUTTON; }
62 "CHECKBOX"              { return CHECKBOX; }
63 "COMBOBOX"              { return COMBOBOX; }
64 "CTEXT"                 { return CTEXT; }
65 "DEFPUSHBUTTON"         { return DEFPUSHBUTTON; }
66 "EDITTEXT"              { return EDITTEXT; }
67 "GROUPBOX"              { return GROUPBOX; }
68 "LISTBOX"               { return LISTBOX; }
69 "LTEXT"                 { return LTEXT; }
70 "PUSHBOX"               { return PUSHBOX; }
71 "PUSHBUTTON"            { return PUSHBUTTON; }
72 "RADIOBUTTON"           { return RADIOBUTTON; }
73 "RTEXT"                 { return RTEXT; }
74 "SCROLLBAR"             { return SCROLLBAR; }
75 "STATE3"                { return STATE3; }
76 "USERBUTTON"            { return USERBUTTON; }
77 "BEDIT"                 { return BEDIT; }
78 "HEDIT"                 { return HEDIT; }
79 "IEDIT"                 { return IEDIT; }
80 "FONT"                  { return FONT; }
81 "ICON"                  { return ICON; }
82 "LANGUAGE"              { return LANGUAGE; }
83 "CHARACTERISTICS"       { return CHARACTERISTICS; }
84 "VERSION"               { return VERSION; }
85 "MENU"                  { return MENU; }
86 "MENUEX"                { return MENUEX; }
87 "MENUITEM"              { return MENUITEM; }
88 "SEPARATOR"             { return SEPARATOR; }
89 "POPUP"                 { return POPUP; }
90 "CHECKED"               { return CHECKED; }
91 "GRAYED"                { return GRAYED; }
92 "HELP"                  { return HELP; }
93 "INACTIVE"              { return INACTIVE; }
94 "MENUBARBREAK"          { return MENUBARBREAK; }
95 "MENUBREAK"             { return MENUBREAK; }
96 "MESSAGETABLE"          { return MESSAGETABLE; }
97 "RCDATA"                { return RCDATA; }
98 "STRINGTABLE"           { return STRINGTABLE; }
99 "VERSIONINFO"           { return VERSIONINFO; }
100 "FILEVERSION"           { return FILEVERSION; }
101 "PRODUCTVERSION"        { return PRODUCTVERSION; }
102 "FILEFLAGSMASK"         { return FILEFLAGSMASK; }
103 "FILEFLAGS"             { return FILEFLAGS; }
104 "FILEOS"                { return FILEOS; }
105 "FILETYPE"              { return FILETYPE; }
106 "FILESUBTYPE"           { return FILESUBTYPE; }
107 "VALUE"                 { return VALUE; }
108 "MOVEABLE"              { return MOVEABLE; }
109 "FIXED"                 { return FIXED; }
110 "PURE"                  { return PURE; }
111 "IMPURE"                { return IMPURE; }
112 "PRELOAD"               { return PRELOAD; }
113 "LOADONCALL"            { return LOADONCALL; }
114 "DISCARDABLE"           { return DISCARDABLE; }
115 "NOT"                   { return NOT; }
116
117 "BLOCK"[ \t\n]*"\""[^\#\n]*"\"" {
118                           char *s, *send;
119
120                           /* This is a hack to let us parse version
121                              information easily.  */
122
123                           s = strchr (yytext, '"');
124                           ++s;
125                           send = strchr (s, '"');
126                           if (strncmp (s, "StringFileInfo",
127                                        sizeof "StringFileInfo" - 1) == 0
128                               && s + sizeof "StringFileInfo" - 1 == send)
129                             return BLOCKSTRINGFILEINFO;
130                           else if (strncmp (s, "VarFileInfo",
131                                             sizeof "VarFileInfo" - 1) == 0
132                                    && s + sizeof "VarFileInfo" - 1 == send)
133                             return BLOCKVARFILEINFO;
134                           else
135                             {
136                               yylval.s = (char *) xmalloc (send - s + 1);
137                               strncpy (yylval.s, s, send - s);
138                               yylval.s[send - s] = '\0';
139                               return BLOCK;
140                             }
141                         }
142
143 "#"[^\n]*               {
144                           cpp_line (yytext);
145                         }
146
147 [0-9][x0-9A-Fa-f]*L     {
148                           yylval.i.val = strtoul (yytext, 0, 0);
149                           yylval.i.dword = 1;
150                           return NUMBER;
151                         }
152
153 [0-9][x0-9A-Fa-f]*      {
154                           yylval.i.val = strtoul (yytext, 0, 0);
155                           yylval.i.dword = 0;
156                           return NUMBER;
157                         }
158
159 ("\""[^\"\n]*"\""[ \t]*)+ {
160                           yylval.s = handle_quotes (yytext);
161                           return QUOTEDSTRING;
162                         }
163
164 [A-Za-z][^ \t\r\n]*     {
165                           yylval.s = xstrdup (yytext);
166                           return STRING;
167                         }
168
169 [\n]                    { ++rc_lineno; }
170 [ \t\r]+                { /* ignore whitespace */ }
171 .                       { return *yytext; }
172
173 %%
174 #ifndef yywrap
175 /* This is needed for some versions of lex.  */
176 int yywrap ()
177 {
178   return 1;
179 }
180 #endif
181
182 /* Handle a C preprocessor line.  */
183
184 static void
185 cpp_line (s)
186      const char *s;
187 {
188   int line;
189   char *send, *fn;
190
191   ++s;
192   while (isspace (*s))
193     ++s;
194   
195   line = strtol (s, &send, 0);
196   if (*send != '\0' && ! isspace (*send))
197     return;
198
199   /* Subtract 1 because we are about to count the newline.  */
200   rc_lineno = line - 1;
201
202   s = send;
203   while (isspace (*s))
204     ++s;
205
206   if (*s != '"')
207     return;
208
209   ++s;
210   send = strchr (s, '"');
211   if (send == NULL)
212     return;
213
214   fn = (char *) xmalloc (send - s + 1);
215   strncpy (fn, s, send - s);
216   fn[send - s] = '\0';
217
218   free (rc_filename);
219   rc_filename = fn;
220 }
221
222 /* Handle a quoted string.  The quotes are stripped.  A pair of quotes
223    in a string are turned into a single quote.  Adjacent strings are
224    merged separated by whitespace are merged, as in C.  */
225
226 static char *
227 handle_quotes (input)
228      const char *input;
229 {
230   char *ret, *s;
231   const char *t;
232   int ch;
233
234   ret = (char *) xmalloc (strlen (input) + 1);
235
236   s = ret;
237   t = input;
238   if (*t == '"')
239     ++t;
240   while (*t != '\0')
241     {
242       if (*t == '\\')
243         {
244           ++t;
245           switch (*t)
246             {
247             case '\0':
248               rcparse_warning ("backslash at end of string");
249               break;
250
251             case '\"':
252               rcparse_warning ("use \"\" to put \" in a string");
253               break;
254
255             case '\\':
256               *s++ = *t++;
257               break;
258
259             case '0': case '1': case '2': case '3':
260             case '4': case '5': case '6': case '7':
261               ch = *t - '0';
262               ++t;
263               if (*t >= '0' && *t <= '7')
264                 {
265                   ch = (ch << 3) | (*t - '0');
266                   ++t;
267                   if (*t >= '0' && *t <= '7')
268                     {
269                       ch = (ch << 3) | (*t - '0');
270                       ++t;
271                     }
272                 }
273               *s++ = ch;
274               break;
275
276             case 'x':
277               ++t;
278               ch = 0;
279               while (1)
280                 {
281                   if (*t >= '0' && *t <= '9')
282                     ch = (ch << 4) | (*t - '0');
283                   else if (*t >= 'a' && *t <= 'f')
284                     ch = (ch << 4) | (*t - 'a');
285                   else if (*t >= 'A' && *t <= 'F')
286                     ch = (ch << 4) | (*t - 'A');
287                   else
288                     break;
289                   ++t;
290                 }
291               *s++ = ch;
292               break;
293             }
294         }
295       else if (*t != '"')
296         *s++ = *t++;
297       else if (t[1] == '\0')
298         break;
299       else if (t[1] == '"')
300         {
301           *s++ = '"';
302           t += 2;
303         }
304       else
305         {
306           ++t;
307           assert (isspace (*t));
308           while (isspace (*t))
309             ++t;
310           if (*t == '\0')
311             break;
312           assert (*t == '"');
313           ++t;
314         }
315     }
316
317   *s = '\0';
318
319   return ret;
320 }
This page took 0.044607 seconds and 4 git commands to generate.