diff options
author | Ian Lance Taylor <ian@airs.com> | 1997-06-22 21:35:35 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1997-06-22 21:35:35 +0000 |
commit | 1d371d35ee4269aea572319c41143a2c0b75bda1 (patch) | |
tree | 7bf9595c48d9b7654603b5da647c323060d0e443 /binutils/rclex.l | |
parent | 677a92a07d3eac1a6a484ba34784f53cbee51a74 (diff) | |
download | gdb-1d371d35ee4269aea572319c41143a2c0b75bda1.zip gdb-1d371d35ee4269aea572319c41143a2c0b75bda1.tar.gz gdb-1d371d35ee4269aea572319c41143a2c0b75bda1.tar.bz2 |
First stab at Windows resource compiler:
* windres.h: New file.
* windres.c: New file.
* resrc.c: New file.
* rcparse.y: New file.
* rclex.l: New file.
* configure.in: Define and substitute BUILD_WINDRES.
* configure: Rebuild.
* Makefile.in: Rebuild dependencies.
(WINDRES_PROG): New variable.
(PROGS): Add @BUILD_WINDRES@.
(HFILES): Add dlltool.h and windres.h.
(CFILES): Add windres.c and resrc.c.
(GENERATED_CFILES): Add rcparse.c and rclex.c.
(WINDRES_OBJS): New variable.
$(WINDRES_PROG): New target.
(rcparse.c, rcparse.h, rclex.c): New targets.
Snapshot. windres can parse and print rc files.
Diffstat (limited to 'binutils/rclex.l')
-rw-r--r-- | binutils/rclex.l | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/binutils/rclex.l b/binutils/rclex.l new file mode 100644 index 0000000..eb36bf6 --- /dev/null +++ b/binutils/rclex.l @@ -0,0 +1,320 @@ +%{ /* rclex.l -- lexer for Windows rc files parser */ +/* Copyright 1997 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Cygnus Support. + + This file is part of GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* This is a lex input file which generates a lexer used by the + Windows rc file parser. It basically just recognized a bunch of + keywords. */ + +#include "bfd.h" +#include "bucomm.h" +#include "libiberty.h" +#include "windres.h" +#include "rcparse.h" + +#include <ctype.h> +#include <assert.h> + +static void cpp_line PARAMS ((const char *)); +static char *handle_quotes PARAMS ((const char *)); + +%} + +%% + +"BEGIN" { return BEG; } +"END" { return END; } +"ACCELERATORS" { return ACCELERATORS; } +"VIRTKEY" { return VIRTKEY; } +"ASCII" { return ASCII; } +"NOINVERT" { return NOINVERT; } +"SHIFT" { return SHIFT; } +"CONTROL" { return CONTROL; } +"ALT" { return ALT; } +"BITMAP" { return BITMAP; } +"CURSOR" { return CURSOR; } +"DIALOG" { return DIALOG; } +"DIALOGEX" { return DIALOGEX; } +"EXSTYLE" { return EXSTYLE; } +"CAPTION" { return CAPTION; } +"CLASS" { return CLASS; } +"STYLE" { return STYLE; } +"AUTO3STATE" { return AUTO3STATE; } +"AUTOCHECKBOX" { return AUTOCHECKBOX; } +"AUTORADIOBUTTON" { return AUTORADIOBUTTON; } +"CHECKBOX" { return CHECKBOX; } +"COMBOBOX" { return COMBOBOX; } +"CTEXT" { return CTEXT; } +"DEFPUSHBUTTON" { return DEFPUSHBUTTON; } +"EDITTEXT" { return EDITTEXT; } +"GROUPBOX" { return GROUPBOX; } +"LISTBOX" { return LISTBOX; } +"LTEXT" { return LTEXT; } +"PUSHBOX" { return PUSHBOX; } +"PUSHBUTTON" { return PUSHBUTTON; } +"RADIOBUTTON" { return RADIOBUTTON; } +"RTEXT" { return RTEXT; } +"SCROLLBAR" { return SCROLLBAR; } +"STATE3" { return STATE3; } +"USERBUTTON" { return USERBUTTON; } +"BEDIT" { return BEDIT; } +"HEDIT" { return HEDIT; } +"IEDIT" { return IEDIT; } +"FONT" { return FONT; } +"ICON" { return ICON; } +"LANGUAGE" { return LANGUAGE; } +"CHARACTERISTICS" { return CHARACTERISTICS; } +"VERSION" { return VERSION; } +"MENU" { return MENU; } +"MENUEX" { return MENUEX; } +"MENUITEM" { return MENUITEM; } +"SEPARATOR" { return SEPARATOR; } +"POPUP" { return POPUP; } +"CHECKED" { return CHECKED; } +"GRAYED" { return GRAYED; } +"HELP" { return HELP; } +"INACTIVE" { return INACTIVE; } +"MENUBARBREAK" { return MENUBARBREAK; } +"MENUBREAK" { return MENUBREAK; } +"MESSAGETABLE" { return MESSAGETABLE; } +"RCDATA" { return RCDATA; } +"STRINGTABLE" { return STRINGTABLE; } +"VERSIONINFO" { return VERSIONINFO; } +"FILEVERSION" { return FILEVERSION; } +"PRODUCTVERSION" { return PRODUCTVERSION; } +"FILEFLAGSMASK" { return FILEFLAGSMASK; } +"FILEFLAGS" { return FILEFLAGS; } +"FILEOS" { return FILEOS; } +"FILETYPE" { return FILETYPE; } +"FILESUBTYPE" { return FILESUBTYPE; } +"VALUE" { return VALUE; } +"MOVEABLE" { return MOVEABLE; } +"FIXED" { return FIXED; } +"PURE" { return PURE; } +"IMPURE" { return IMPURE; } +"PRELOAD" { return PRELOAD; } +"LOADONCALL" { return LOADONCALL; } +"DISCARDABLE" { return DISCARDABLE; } +"NOT" { return NOT; } + +"BLOCK"[ \t\n]*"\""[^\#\n]*"\"" { + char *s, *send; + + /* This is a hack to let us parse version + information easily. */ + + s = strchr (yytext, '"'); + ++s; + send = strchr (s, '"'); + if (strncmp (s, "StringFileInfo", + sizeof "StringFileInfo" - 1) == 0 + && s + sizeof "StringFileInfo" - 1 == send) + return BLOCKSTRINGFILEINFO; + else if (strncmp (s, "VarFileInfo", + sizeof "VarFileInfo" - 1) == 0 + && s + sizeof "VarFileInfo" - 1 == send) + return BLOCKVARFILEINFO; + else + { + yylval.s = (char *) xmalloc (send - s + 1); + strncpy (yylval.s, s, send - s); + yylval.s[send - s] = '\0'; + return BLOCK; + } + } + +"#"[^\n]* { + cpp_line (yytext); + } + +[0-9][x0-9A-Fa-f]*L { + yylval.i.val = strtoul (yytext, 0, 0); + yylval.i.dword = 1; + return NUMBER; + } + +[0-9][x0-9A-Fa-f]* { + yylval.i.val = strtoul (yytext, 0, 0); + yylval.i.dword = 0; + return NUMBER; + } + +("\""[^\"\n]*"\""[ \t]*)+ { + yylval.s = handle_quotes (yytext); + return QUOTEDSTRING; + } + +[A-Za-z][^ \t\r\n]* { + yylval.s = xstrdup (yytext); + return STRING; + } + +[\n] { ++rc_lineno; } +[ \t\r]+ { /* ignore whitespace */ } +. { return *yytext; } + +%% +#ifndef yywrap +/* This is needed for some versions of lex. */ +int yywrap () +{ + return 1; +} +#endif + +/* Handle a C preprocessor line. */ + +static void +cpp_line (s) + const char *s; +{ + int line; + char *send, *fn; + + ++s; + while (isspace (*s)) + ++s; + + line = strtol (s, &send, 0); + if (*send != '\0' && ! isspace (*send)) + return; + + /* Subtract 1 because we are about to count the newline. */ + rc_lineno = line - 1; + + s = send; + while (isspace (*s)) + ++s; + + if (*s != '"') + return; + + ++s; + send = strchr (s, '"'); + if (send == NULL) + return; + + fn = (char *) xmalloc (send - s + 1); + strncpy (fn, s, send - s); + fn[send - s] = '\0'; + + free (rc_filename); + rc_filename = fn; +} + +/* Handle a quoted string. The quotes are stripped. A pair of quotes + in a string are turned into a single quote. Adjacent strings are + merged separated by whitespace are merged, as in C. */ + +static char * +handle_quotes (input) + const char *input; +{ + char *ret, *s; + const char *t; + int ch; + + ret = (char *) xmalloc (strlen (input) + 1); + + s = ret; + t = input; + if (*t == '"') + ++t; + while (*t != '\0') + { + if (*t == '\\') + { + ++t; + switch (*t) + { + case '\0': + rcparse_warning ("backslash at end of string"); + break; + + case '\"': + rcparse_warning ("use \"\" to put \" in a string"); + break; + + case '\\': + *s++ = *t++; + break; + + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + ch = *t - '0'; + ++t; + if (*t >= '0' && *t <= '7') + { + ch = (ch << 3) | (*t - '0'); + ++t; + if (*t >= '0' && *t <= '7') + { + ch = (ch << 3) | (*t - '0'); + ++t; + } + } + *s++ = ch; + break; + + case 'x': + ++t; + ch = 0; + while (1) + { + if (*t >= '0' && *t <= '9') + ch = (ch << 4) | (*t - '0'); + else if (*t >= 'a' && *t <= 'f') + ch = (ch << 4) | (*t - 'a'); + else if (*t >= 'A' && *t <= 'F') + ch = (ch << 4) | (*t - 'A'); + else + break; + ++t; + } + *s++ = ch; + break; + } + } + else if (*t != '"') + *s++ = *t++; + else if (t[1] == '\0') + break; + else if (t[1] == '"') + { + *s++ = '"'; + t += 2; + } + else + { + ++t; + assert (isspace (*t)); + while (isspace (*t)) + ++t; + if (*t == '\0') + break; + assert (*t == '"'); + ++t; + } + } + + *s = '\0'; + + return ret; +} |