Updated windres tool

This commit is contained in:
Nick Clifton 2007-05-23 08:48:29 +00:00
parent 950c3b7d2c
commit 4a594fce16
28 changed files with 5799 additions and 3573 deletions

View File

@ -1,3 +1,34 @@
2007-05-23 Kai Tietz <Kai.Tietz@onevision.com>
* rclex.c: New file replacing rclex.l.
* rclex.l: Removed.
* windint.h: New file holding common structure and type
definitions.
* Makefile.am: Added new header windint.h and exchanged rclex.l by
rclex.c.
* Makefile.in: Regenerate.
* rcparse.y: Renamed some structures.
Use in internal representation always bfd_vma instead of long or
int.
Removed from %union unused stringtable.
Added to %union suni structure for unicode strings.
Added new tokens for ANICURSOR, ANIICON, DLGINCLUDE,
DLGINIT, FONTDIR, HTML, MANIFEST, PLUGPLAY, VXD,
TOOLBAR, BUTTON, QUOTEDUNISTRING, and SIZEDUNISTRING.
Added support for these new rc file tokens.
* resbin.c: Rewrote using bfd and binary structures, and support
new resource types.
* rescoff.c: Likewise.
* resres.c: Likewise.
* resrc.c: Likewise. Dumps as RC are now recompilable.
* windres.c: As above. Using bfd for res and provide target
specific endianess support.
* windres.h: Use windint.h as include. Additionally removed K&R
syntax.
* winduni.c: New printing and unichar support routines.
* winduni.h: Prototypes for new unichar helpers.
* windint.h: New file.
2007-05-22 Paul Brook <paul@codesourcery.com>
* objdump.c (find_symbol_for_address): Merge section and target

View File

@ -79,7 +79,7 @@ INCLUDES = -D_GNU_SOURCE \
HFILES = \
arsup.h binemul.h bucomm.h budbg.h \
coffgrok.h debug.h dlltool.h nlmconv.h \
windres.h winduni.h
windres.h winduni.h windint.h
GENERATED_HFILES = arparse.h sysroff.h sysinfo.h defparse.h rcparse.h
@ -91,14 +91,14 @@ CFILES = \
ieee.c is-ranlib.c is-strip.c maybe-ranlib.c maybe-strip.c \
nlmconv.c nm.c not-ranlib.c not-strip.c \
objcopy.c objdump.c prdbg.c \
rdcoff.c rddbg.c readelf.c rename.c \
rclex.c rdcoff.c rddbg.c readelf.c rename.c \
resbin.c rescoff.c resrc.c resres.c \
size.c srconv.c stabs.c strings.c sysdump.c version.c \
windres.c winduni.c wrstabs.c
GENERATED_CFILES = \
arparse.c arlex.c sysroff.c sysinfo.c syslex.c \
defparse.c deflex.c nlmheader.c rcparse.c rclex.c
defparse.c deflex.c nlmheader.c rcparse.c
DEBUG_SRCS = rddbg.c debug.c stabs.c ieee.c rdcoff.c
WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c
@ -333,7 +333,7 @@ nlmconv.o: nlmconv.c $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h
nlmconv_SOURCES = nlmconv.c nlmheader.y $(BULIBS)
windres_SOURCES = windres.c resrc.c rescoff.c resbin.c rcparse.y rclex.l \
windres_SOURCES = windres.c resrc.c rescoff.c resbin.c rcparse.y rclex.c \
winduni.c resres.c $(BULIBS)
windres_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(LIBINTL)
@ -342,7 +342,7 @@ dllwrap_LDADD = $(LIBIBERTY) $(LIBINTL)
EXTRA_DIST = arparse.c arparse.h arlex.c nlmheader.c sysinfo.c sysinfo.h \
syslex.c deflex.c defparse.h defparse.c rclex.c rcparse.h rcparse.c
syslex.c deflex.c defparse.h defparse.c rcparse.h rcparse.c
diststuff: $(EXTRA_DIST) info
all: info
@ -579,20 +579,20 @@ rename.o: rename.c sysdep.h $(INCDIR)/ansidecl.h ../bfd/bfdver.h \
resbin.o: resbin.c sysdep.h $(INCDIR)/ansidecl.h ../bfd/bfdver.h \
config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h $(INCDIR)/ansidecl.h \
$(INCDIR)/symcat.h $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \
bucomm.h windres.h winduni.h
bucomm.h windres.h winduni.h windint.h
rescoff.o: rescoff.c sysdep.h $(INCDIR)/ansidecl.h \
../bfd/bfdver.h config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h \
$(INCDIR)/ansidecl.h $(INCDIR)/symcat.h $(INCDIR)/libiberty.h \
$(INCDIR)/ansidecl.h bucomm.h windres.h winduni.h $(INCDIR)/coff/internal.h \
$(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
$(INCDIR)/ansidecl.h bucomm.h windres.h winduni.h windint.h \
$(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
resrc.o: resrc.c sysdep.h $(INCDIR)/ansidecl.h ../bfd/bfdver.h \
config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h $(INCDIR)/ansidecl.h \
$(INCDIR)/symcat.h $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \
$(INCDIR)/safe-ctype.h bucomm.h windres.h winduni.h
$(INCDIR)/safe-ctype.h bucomm.h windres.h winduni.h windint.h
resres.o: resres.c sysdep.h $(INCDIR)/ansidecl.h ../bfd/bfdver.h \
config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h $(INCDIR)/ansidecl.h \
$(INCDIR)/symcat.h $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \
bucomm.h windres.h winduni.h
bucomm.h windres.h winduni.h windint.h
size.o: size.c sysdep.h $(INCDIR)/ansidecl.h ../bfd/bfdver.h \
config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h $(INCDIR)/ansidecl.h \
$(INCDIR)/symcat.h $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \
@ -624,7 +624,7 @@ windres.o: windres.c sysdep.h $(INCDIR)/ansidecl.h \
../bfd/bfdver.h config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h \
$(INCDIR)/ansidecl.h $(INCDIR)/symcat.h $(INCDIR)/libiberty.h \
$(INCDIR)/ansidecl.h $(INCDIR)/safe-ctype.h $(INCDIR)/obstack.h \
bucomm.h windres.h winduni.h
bucomm.h windres.h winduni.h windint.h
winduni.o: winduni.c sysdep.h $(INCDIR)/ansidecl.h \
../bfd/bfdver.h config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h \
$(INCDIR)/ansidecl.h $(INCDIR)/symcat.h winduni.h $(INCDIR)/safe-ctype.h
@ -656,9 +656,10 @@ nlmheader.o: nlmheader.c sysdep.h $(INCDIR)/ansidecl.h \
rcparse.o: rcparse.c sysdep.h $(INCDIR)/ansidecl.h \
../bfd/bfdver.h config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h \
$(INCDIR)/ansidecl.h $(INCDIR)/symcat.h $(INCDIR)/libiberty.h \
$(INCDIR)/ansidecl.h windres.h winduni.h $(INCDIR)/safe-ctype.h
$(INCDIR)/ansidecl.h windres.h winduni.h windint.h \
$(INCDIR)/safe-ctype.h
rclex.o: rclex.c sysdep.h $(INCDIR)/ansidecl.h ../bfd/bfdver.h \
config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h $(INCDIR)/ansidecl.h \
$(INCDIR)/symcat.h $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \
$(INCDIR)/safe-ctype.h windres.h winduni.h rcparse.h
$(INCDIR)/safe-ctype.h windres.h winduni.h windint.h rcparse.h
# IF YOU PUT ANYTHING HERE IT WILL GO AWAY

View File

@ -52,7 +52,7 @@ DIST_COMMON = $(srcdir)/../config.guess $(srcdir)/../config.sub NEWS \
$(srcdir)/config.in $(srcdir)/../mkinstalldirs \
$(top_srcdir)/po/Make-in arparse.h arparse.c arlex.c \
defparse.h defparse.c deflex.c nlmheader.h nlmheader.c \
arparse.h arparse.c arlex.c rcparse.h rcparse.c rclex.c \
arparse.h arparse.c arlex.c rcparse.h rcparse.c \
$(srcdir)/../ylwrap $(srcdir)/../ltmain.sh \
$(srcdir)/../config.guess $(srcdir)/../config.sub
subdir = .
@ -379,7 +379,7 @@ INCLUDES = -D_GNU_SOURCE \
HFILES = \
arsup.h binemul.h bucomm.h budbg.h \
coffgrok.h debug.h dlltool.h nlmconv.h \
windres.h winduni.h
windres.h winduni.h windint.h
GENERATED_HFILES = arparse.h sysroff.h sysinfo.h defparse.h rcparse.h
CFILES = \
@ -390,14 +390,14 @@ CFILES = \
ieee.c is-ranlib.c is-strip.c maybe-ranlib.c maybe-strip.c \
nlmconv.c nm.c not-ranlib.c not-strip.c \
objcopy.c objdump.c prdbg.c \
rdcoff.c rddbg.c readelf.c rename.c \
rclex.c rdcoff.c rddbg.c readelf.c rename.c \
resbin.c rescoff.c resrc.c resres.c \
size.c srconv.c stabs.c strings.c sysdump.c version.c \
windres.c winduni.c wrstabs.c
GENERATED_CFILES = \
arparse.c arlex.c sysroff.c sysinfo.c syslex.c \
defparse.c deflex.c nlmheader.c rcparse.c rclex.c
defparse.c deflex.c nlmheader.c rcparse.c
DEBUG_SRCS = rddbg.c debug.c stabs.c ieee.c rdcoff.c
WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c
@ -473,14 +473,14 @@ dlltool_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(LIBINTL)
coffdump_SOURCES = coffdump.c coffgrok.c $(BULIBS)
sysdump_SOURCES = sysdump.c $(BULIBS)
nlmconv_SOURCES = nlmconv.c nlmheader.y $(BULIBS)
windres_SOURCES = windres.c resrc.c rescoff.c resbin.c rcparse.y rclex.l \
windres_SOURCES = windres.c resrc.c rescoff.c resbin.c rcparse.y rclex.c \
winduni.c resres.c $(BULIBS)
windres_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(LIBINTL)
dllwrap_SOURCES = dllwrap.c version.c
dllwrap_LDADD = $(LIBIBERTY) $(LIBINTL)
EXTRA_DIST = arparse.c arparse.h arlex.c nlmheader.c sysinfo.c sysinfo.h \
syslex.c deflex.c defparse.h defparse.c rclex.c rcparse.h rcparse.c
syslex.c deflex.c defparse.h defparse.c rcparse.h rcparse.c
DISTCLEANFILES = sysroff.c sysroff.h site.exp site.bak
@ -865,7 +865,6 @@ maintainer-clean-generic:
-rm -f defparse.h
-rm -f nlmheader.c
-rm -f nlmheader.h
-rm -f rclex.c
-rm -f rcparse.c
-rm -f rcparse.h
clean: clean-recursive
@ -1304,20 +1303,20 @@ rename.o: rename.c sysdep.h $(INCDIR)/ansidecl.h ../bfd/bfdver.h \
resbin.o: resbin.c sysdep.h $(INCDIR)/ansidecl.h ../bfd/bfdver.h \
config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h $(INCDIR)/ansidecl.h \
$(INCDIR)/symcat.h $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \
bucomm.h windres.h winduni.h
bucomm.h windres.h winduni.h windint.h
rescoff.o: rescoff.c sysdep.h $(INCDIR)/ansidecl.h \
../bfd/bfdver.h config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h \
$(INCDIR)/ansidecl.h $(INCDIR)/symcat.h $(INCDIR)/libiberty.h \
$(INCDIR)/ansidecl.h bucomm.h windres.h winduni.h $(INCDIR)/coff/internal.h \
$(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
$(INCDIR)/ansidecl.h bucomm.h windres.h winduni.h windint.h \
$(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
resrc.o: resrc.c sysdep.h $(INCDIR)/ansidecl.h ../bfd/bfdver.h \
config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h $(INCDIR)/ansidecl.h \
$(INCDIR)/symcat.h $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \
$(INCDIR)/safe-ctype.h bucomm.h windres.h winduni.h
$(INCDIR)/safe-ctype.h bucomm.h windres.h winduni.h windint.h
resres.o: resres.c sysdep.h $(INCDIR)/ansidecl.h ../bfd/bfdver.h \
config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h $(INCDIR)/ansidecl.h \
$(INCDIR)/symcat.h $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \
bucomm.h windres.h winduni.h
bucomm.h windres.h winduni.h windint.h
size.o: size.c sysdep.h $(INCDIR)/ansidecl.h ../bfd/bfdver.h \
config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h $(INCDIR)/ansidecl.h \
$(INCDIR)/symcat.h $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \
@ -1349,7 +1348,7 @@ windres.o: windres.c sysdep.h $(INCDIR)/ansidecl.h \
../bfd/bfdver.h config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h \
$(INCDIR)/ansidecl.h $(INCDIR)/symcat.h $(INCDIR)/libiberty.h \
$(INCDIR)/ansidecl.h $(INCDIR)/safe-ctype.h $(INCDIR)/obstack.h \
bucomm.h windres.h winduni.h
bucomm.h windres.h winduni.h windint.h
winduni.o: winduni.c sysdep.h $(INCDIR)/ansidecl.h \
../bfd/bfdver.h config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h \
$(INCDIR)/ansidecl.h $(INCDIR)/symcat.h winduni.h $(INCDIR)/safe-ctype.h
@ -1381,11 +1380,12 @@ nlmheader.o: nlmheader.c sysdep.h $(INCDIR)/ansidecl.h \
rcparse.o: rcparse.c sysdep.h $(INCDIR)/ansidecl.h \
../bfd/bfdver.h config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h \
$(INCDIR)/ansidecl.h $(INCDIR)/symcat.h $(INCDIR)/libiberty.h \
$(INCDIR)/ansidecl.h windres.h winduni.h $(INCDIR)/safe-ctype.h
$(INCDIR)/ansidecl.h windres.h winduni.h windint.h \
$(INCDIR)/safe-ctype.h
rclex.o: rclex.c sysdep.h $(INCDIR)/ansidecl.h ../bfd/bfdver.h \
config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h $(INCDIR)/ansidecl.h \
$(INCDIR)/symcat.h $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \
$(INCDIR)/safe-ctype.h windres.h winduni.h rcparse.h
$(INCDIR)/safe-ctype.h windres.h winduni.h windint.h rcparse.h
# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.

835
binutils/rclex.c Normal file
View File

@ -0,0 +1,835 @@
/* rclex.c -- lexer for Windows rc files parser */
/* Copyright 1997, 1998, 1999, 2001, 2002, 2003, 2005, 2006, 2007
Free Software Foundation, Inc.
Written by Kai Tietz, Onevision.
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., 51 Franklin Street - Fifth Floor, Boston, MA
02110-1301, USA. */
/* This is a lexer used by the Windows rc file parser. It basically
just recognized a bunch of keywords. */
#include "sysdep.h"
#include "bfd.h"
#include "bucomm.h"
#include "libiberty.h"
#include "safe-ctype.h"
#include "windres.h"
#include "rcparse.h"
#include <assert.h>
/* Whether we are in rcdata mode, in which we returns the lengths of
strings. */
static int rcdata_mode;
/* Whether we are supressing lines from cpp (including windows.h or
headers from your C sources may bring in externs and typedefs).
When active, we return IGNORED_TOKEN, which lets us ignore these
outside of resource constructs. Thus, it isn't required to protect
all the non-preprocessor lines in your header files with #ifdef
RC_INVOKED. It also means your RC file can't include other RC
files if they're named "*.h". Sorry. Name them *.rch or whatever. */
static int suppress_cpp_data;
#define IGNORE_CPP(x) (suppress_cpp_data ? IGNORED_TOKEN : (x))
/* The first filename we detect in the cpp output. We use this to
tell included files from the original file. */
static char *initial_fn;
/* List of allocated strings. */
struct alloc_string
{
struct alloc_string *next;
char *s;
};
static struct alloc_string *strings;
struct rclex_keywords
{
const char *name;
int tok;
};
#define K(KEY) { #KEY, KEY }
#define KRT(KEY) { #KEY, RT_##KEY }
static const struct rclex_keywords keywds[] =
{
K(ACCELERATORS), K(ALT), K(ANICURSOR), K(ANIICON), K(ASCII),
K(AUTO3STATE), K(AUTOCHECKBOX), K(AUTORADIOBUTTON),
K(BEDIT), { "BEGIN", BEG }, K(BITMAP), K(BLOCK), K(BUTTON),
K(CAPTION), K(CHARACTERISTICS), K(CHECKBOX), K(CHECKED),
K(CLASS), K(COMBOBOX), K(CONTROL), K(CTEXT), K(CURSOR),
K(DEFPUSHBUTTON), K(DIALOG), K(DIALOGEX), K(DISCARDABLE),
K(DLGINCLUDE), K(DLGINIT),
K(EDITTEXT), K(END), K(EXSTYLE),
K(FILEFLAGS), K(FILEFLAGSMASK), K(FILEOS), K(FILESUBTYPE),
K(FILETYPE), K(FILEVERSION), K(FIXED), K(FONT), K(FONTDIR),
K(GRAYED), KRT(GROUP_CURSOR), KRT(GROUP_ICON), K(GROUPBOX),
K(HEDIT), K(HELP), K(HTML),
K(ICON), K(IEDIT), K(IMPURE), K(INACTIVE),
K(LANGUAGE), K(LISTBOX), K(LOADONCALL), K(LTEXT),
K(MANIFEST), K(MENU), K(MENUBARBREAK), K(MENUBREAK),
K(MENUEX), K(MENUITEM), K(MESSAGETABLE), K(MOVEABLE),
K(NOINVERT), K(NOT),
K(PLUGPLAY), K(POPUP), K(PRELOAD), K(PRODUCTVERSION),
K(PURE), K(PUSHBOX), K(PUSHBUTTON),
K(RADIOBUTTON), K(RCDATA), K(RTEXT),
K(SCROLLBAR), K(SEPARATOR), K(SHIFT), K(STATE3),
K(STRINGTABLE), K(STYLE),
K(TOOLBAR),
K(USERBUTTON),
K(VALUE), { "VERSION", VERSIONK }, K(VERSIONINFO),
K(VIRTKEY), K(VXD),
{ NULL, 0 },
};
/* External input stream from resrc */
extern FILE *cpp_pipe;
/* Lexical scanner helpers. */
static int rclex_lastch = -1;
static size_t rclex_tok_max = 0;
static size_t rclex_tok_pos = 0;
static char *rclex_tok = NULL;
static int
rclex_translatekeyword (const char *key)
{
if (key && ISUPPER (key[0]))
{
const struct rclex_keywords *kw = &keywds[0];
do
{
if (! strcmp (kw->name, key))
return kw->tok;
++kw;
}
while (kw->name != NULL);
}
return STRING;
}
/* Handle a C preprocessor line. */
static void
cpp_line (void)
{
const char *s = rclex_tok;
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 = xmalloc (send - s + 1);
strncpy (fn, s, send - s);
fn[send - s] = '\0';
free (rc_filename);
rc_filename = fn;
if (! initial_fn)
{
initial_fn = xmalloc (strlen (fn) + 1);
strcpy (initial_fn, fn);
}
/* Allow the initial file, regardless of name. Suppress all other
files if they end in ".h" (this allows included "*.rc"). */
if (strcmp (initial_fn, fn) == 0
|| strcmp (fn + strlen (fn) - 2, ".h") != 0)
suppress_cpp_data = 0;
else
suppress_cpp_data = 1;
}
/* Allocate a string of a given length. */
static char *
get_string (int len)
{
struct alloc_string *as;
as = xmalloc (sizeof *as);
as->s = xmalloc (len);
as->next = strings;
strings = as;
return as->s;
}
/* 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 (rc_uint_type *len)
{
const char *input = rclex_tok;
char *ret, *s;
const char *t;
int ch;
int num_xdigits;
ret = get_string (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");
*s++ = '"';
++t;
break;
case 'a':
*s++ = ESCAPE_B; /* Strange, but true... */
++t;
break;
case 'b':
*s++ = ESCAPE_B;
++t;
break;
case 'f':
*s++ = ESCAPE_F;
++t;
break;
case 'n':
*s++ = ESCAPE_N;
++t;
break;
case 'r':
*s++ = ESCAPE_R;
++t;
break;
case 't':
*s++ = ESCAPE_T;
++t;
break;
case 'v':
*s++ = ESCAPE_V;
++t;
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': case 'X':
++t;
ch = 0;
/* We only handle single byte chars here. Make sure
we finish an escape sequence like "/xB0ABC" after
the first two digits. */
num_xdigits = 2;
while (num_xdigits--)
{
if (*t >= '0' && *t <= '9')
ch = (ch << 4) | (*t - '0');
else if (*t >= 'a' && *t <= 'f')
ch = (ch << 4) | (*t - 'a' + 10);
else if (*t >= 'A' && *t <= 'F')
ch = (ch << 4) | (*t - 'A' + 10);
else
break;
++t;
}
*s++ = ch;
break;
default:
rcparse_warning ("unrecognized escape sequence");
*s++ = '\\';
*s++ = *t++;
break;
}
}
else if (*t != '"')
*s++ = *t++;
else if (t[1] == '\0')
break;
else if (t[1] == '"')
{
*s++ = '"';
t += 2;
}
else
{
rcparse_warning ("unexpected character after '\"'");
++t;
assert (ISSPACE (*t));
while (ISSPACE (*t))
{
if ((*t) == '\n')
++rc_lineno;
++t;
}
if (*t == '\0')
break;
assert (*t == '"');
++t;
}
}
*s = '\0';
*len = s - ret;
return ret;
}
/* Allocate a unicode string of a given length. */
static unichar *
get_unistring (int len)
{
return (unichar *) get_string (len * sizeof (unichar));
}
/* Handle a quoted unicode 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 unichar *
handle_uniquotes (rc_uint_type *len)
{
const char *input = rclex_tok;
unichar *ret, *s;
const char *t;
int ch;
int num_xdigits;
ret = get_unistring (strlen (input) + 1);
s = ret;
t = input;
if ((*t == 'L' || *t == 'l') && t[1] == '"')
t += 2;
else 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 'a':
*s++ = ESCAPE_B; /* Strange, but true... */
++t;
break;
case 'b':
*s++ = ESCAPE_B;
++t;
break;
case 'f':
*s++ = ESCAPE_F;
++t;
break;
case 'n':
*s++ = ESCAPE_N;
++t;
break;
case 'r':
*s++ = ESCAPE_R;
++t;
break;
case 't':
*s++ = ESCAPE_T;
++t;
break;
case 'v':
*s++ = ESCAPE_V;
++t;
break;
case '\\':
*s++ = (unichar) *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++ = (unichar) ch;
break;
case 'x': case 'X':
++t;
ch = 0;
/* We only handle two byte chars here. Make sure
we finish an escape sequence like "/xB0ABC" after
the first two digits. */
num_xdigits = 4;
while (num_xdigits--)
{
if (*t >= '0' && *t <= '9')
ch = (ch << 4) | (*t - '0');
else if (*t >= 'a' && *t <= 'f')
ch = (ch << 4) | (*t - 'a' + 10);
else if (*t >= 'A' && *t <= 'F')
ch = (ch << 4) | (*t - 'A' + 10);
else
break;
++t;
}
*s++ = (unichar) ch;
break;
default:
rcparse_warning ("unrecognized escape sequence");
*s++ = '\\';
*s++ = (unichar) *t++;
break;
}
}
else if (*t != '"')
*s++ = (unichar) *t++;
else if (t[1] == '\0')
break;
else if (t[1] == '"')
{
*s++ = '"';
t += 2;
}
else
{
++t;
assert (ISSPACE (*t));
while (ISSPACE (*t))
{
if ((*t) == '\n')
++rc_lineno;
++t;
}
if (*t == '\0')
break;
assert (*t == '"');
++t;
}
}
*s = '\0';
*len = s - ret;
return ret;
}
/* Discard all the strings we have allocated. The parser calls this
when it no longer needs them. */
void
rcparse_discard_strings (void)
{
struct alloc_string *as;
as = strings;
while (as != NULL)
{
struct alloc_string *n;
free (as->s);
n = as->next;
free (as);
as = n;
}
strings = NULL;
}
/* Enter rcdata mode. */
void
rcparse_rcdata (void)
{
rcdata_mode = 1;
}
/* Go back to normal mode from rcdata mode. */
void
rcparse_normal (void)
{
rcdata_mode = 0;
}
static void
rclex_tok_add_char (int ch)
{
if (! rclex_tok || rclex_tok_max <= rclex_tok_pos)
{
char *h = xmalloc (rclex_tok_max + 9);
if (! h)
abort ();
if (rclex_tok)
{
memcpy (h, rclex_tok, rclex_tok_pos + 1);
free (rclex_tok);
}
else
rclex_tok_pos = 0;
rclex_tok_max += 8;
rclex_tok = h;
}
if (ch != -1)
rclex_tok[rclex_tok_pos++] = (char) ch;
rclex_tok[rclex_tok_pos] = 0;
}
static int
rclex_readch (void)
{
int r = -1;
if ((r = rclex_lastch) != -1)
rclex_lastch = -1;
else
{
char ch;
do
{
if (! cpp_pipe || feof (cpp_pipe)
|| fread (&ch, 1, 1,cpp_pipe) != 1)
break;
r = ((int) ch) & 0xff;
}
while (r == 0 || r == '\r');
}
rclex_tok_add_char (r);
return r;
}
static int
rclex_peekch (void)
{
int r;
if ((r = rclex_lastch) == -1)
{
if ((r = rclex_readch ()) != -1)
{
rclex_lastch = r;
if (rclex_tok_pos > 0)
rclex_tok[--rclex_tok_pos] = 0;
}
}
return r;
}
static void
rclex_string (void)
{
int c;
while ((c = rclex_peekch ()) != -1)
{
if (c == '\n')
break;
if (c == '\\')
{
rclex_readch ();
if ((c = rclex_peekch ()) == -1 || c == '\n')
break;
rclex_readch ();
}
else if (rclex_readch () == '"')
{
if (rclex_peekch () == '"')
rclex_readch ();
else
break;
}
}
}
static rc_uint_type
read_digit (int ch)
{
rc_uint_type base = 10;
rc_uint_type ret, val;
int warned = 0;
ret = 0;
if (ch == '0')
{
base = 8;
switch (rclex_peekch ())
{
case 'o': case 'O':
rclex_readch ();
base = 8;
break;
case 'x': case 'X':
rclex_readch ();
base = 16;
break;
}
}
else
ret = (rc_uint_type) (ch - '0');
while ((ch = rclex_peekch ()) != -1)
{
if (ISDIGIT (ch))
val = (rc_uint_type) (ch - '0');
else if (ch >= 'a' && ch <= 'f')
val = (rc_uint_type) ((ch - 'a') + 10);
else if (ch >= 'A' && ch <= 'F')
val = (rc_uint_type) ((ch - 'A') + 10);
else
break;
rclex_readch ();
if (! warned && val >= base)
{
warned = 1;
rcparse_warning ("digit exceeds base");
}
ret *= base;
ret += val;
}
return ret;
}
/* yyparser entry method. */
int
yylex (void)
{
char *s;
unichar *us;
rc_uint_type length;
int ch;
/* Make sure that rclex_tok is initialized. */
if (! rclex_tok)
rclex_tok_add_char (-1);
do
{
do
{
/* Clear token. */
rclex_tok_pos = 0;
rclex_tok[0] = 0;
if ((ch = rclex_readch ()) == -1)
return -1;
if (ch == '\n')
++rc_lineno;
}
while (ch <= 0x20);
switch (ch)
{
case '#':
while ((ch = rclex_peekch ()) != -1 && ch != '\n')
rclex_readch ();
cpp_line ();
ch = IGNORED_TOKEN;
break;
case '{':
ch = IGNORE_CPP (BEG);
break;
case '}':
ch = IGNORE_CPP (END);
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
yylval.i.val = read_digit (ch);
yylval.i.dword = 0;
switch (rclex_peekch ())
{
case 'l': case 'L':
rclex_readch ();
yylval.i.dword = 1;
break;
}
ch = IGNORE_CPP (NUMBER);
break;
case '"':
rclex_string ();
ch = IGNORE_CPP ((! rcdata_mode ? QUOTEDSTRING : SIZEDSTRING));
if (ch == IGNORED_TOKEN)
break;
s = handle_quotes (&length);
if (! rcdata_mode)
yylval.s = s;
else
{
yylval.ss.length = length;
yylval.ss.s = s;
}
break;
case 'L': case 'l':
if (rclex_peekch () == '"')
{
rclex_readch ();
rclex_string ();
ch = IGNORE_CPP ((! rcdata_mode ? QUOTEDUNISTRING : SIZEDUNISTRING));
if (ch == IGNORED_TOKEN)
break;
us = handle_uniquotes (&length);
if (! rcdata_mode)
yylval.uni = us;
else
{
yylval.suni.length = length;
yylval.suni.s = us;
}
break;
}
/* Fall through. */
default:
if (ISIDST (ch) || ch=='$')
{
while ((ch = rclex_peekch ()) != -1 && (ISIDNUM (ch) || ch == '$' || ch == '.'))
rclex_readch ();
ch = IGNORE_CPP (rclex_translatekeyword (rclex_tok));
if (ch == STRING)
{
s = get_string (strlen (rclex_tok) + 1);
strcpy (s, rclex_tok);
yylval.s = s;
}
else if (ch == BLOCK)
{
const char *hs = NULL;
switch (yylex ())
{
case STRING:
case QUOTEDSTRING:
hs = yylval.s;
break;
case SIZEDSTRING:
hs = yylval.s = yylval.ss.s;
break;
}
if (! hs)
{
rcparse_warning ("BLOCK expects a string as argument.");
ch = IGNORED_TOKEN;
}
else if (! strcmp (hs, "StringFileInfo"))
ch = BLOCKSTRINGFILEINFO;
else if (! strcmp (hs, "VarFileInfo"))
ch = BLOCKVARFILEINFO;
}
break;
}
ch = IGNORE_CPP (ch);
break;
}
}
while (ch == IGNORED_TOKEN);
return ch;
}

View File

@ -1,504 +0,0 @@
%{ /* rclex.l -- lexer for Windows rc files parser */
/* Copyright 1997, 1998, 1999, 2001, 2002, 2003, 2005, 2007
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., 51 Franklin Street - Fifth Floor, Boston, MA
02110-1301, 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 "sysdep.h"
#include "bfd.h"
#include "libiberty.h"
#include "safe-ctype.h"
#include "windres.h"
#include "rcparse.h"
#include <assert.h>
#define YY_NO_UNPUT
/* Whether we are in rcdata mode, in which we returns the lengths of
strings. */
static int rcdata_mode;
/* Whether we are supressing lines from cpp (including windows.h or
headers from your C sources may bring in externs and typedefs).
When active, we return IGNORED_TOKEN, which lets us ignore these
outside of resource constructs. Thus, it isn't required to protect
all the non-preprocessor lines in your header files with #ifdef
RC_INVOKED. It also means your RC file can't include other RC
files if they're named "*.h". Sorry. Name them *.rch or whatever. */
static int suppress_cpp_data;
#define MAYBE_RETURN(x) return suppress_cpp_data ? IGNORED_TOKEN : (x)
/* The first filename we detect in the cpp output. We use this to
tell included files from the original file. */
static char *initial_fn;
/* List of allocated strings. */
struct alloc_string
{
struct alloc_string *next;
char *s;
};
static struct alloc_string *strings;
/* Local functions. */
static void cpp_line (const char *);
static char *handle_quotes (const char *, unsigned long *);
static char *get_string (int);
%}
%%
"BEGIN" { MAYBE_RETURN (BEG); }
"{" { MAYBE_RETURN (BEG); }
"END" { MAYBE_RETURN (END); }
"}" { MAYBE_RETURN (END); }
"ACCELERATORS" { MAYBE_RETURN (ACCELERATORS); }
"VIRTKEY" { MAYBE_RETURN (VIRTKEY); }
"ASCII" { MAYBE_RETURN (ASCII); }
"NOINVERT" { MAYBE_RETURN (NOINVERT); }
"SHIFT" { MAYBE_RETURN (SHIFT); }
"CONTROL" { MAYBE_RETURN (CONTROL); }
"ALT" { MAYBE_RETURN (ALT); }
"BITMAP" { MAYBE_RETURN (BITMAP); }
"CURSOR" { MAYBE_RETURN (CURSOR); }
"DIALOG" { MAYBE_RETURN (DIALOG); }
"DIALOGEX" { MAYBE_RETURN (DIALOGEX); }
"EXSTYLE" { MAYBE_RETURN (EXSTYLE); }
"CAPTION" { MAYBE_RETURN (CAPTION); }
"CLASS" { MAYBE_RETURN (CLASS); }
"STYLE" { MAYBE_RETURN (STYLE); }
"AUTO3STATE" { MAYBE_RETURN (AUTO3STATE); }
"AUTOCHECKBOX" { MAYBE_RETURN (AUTOCHECKBOX); }
"AUTORADIOBUTTON" { MAYBE_RETURN (AUTORADIOBUTTON); }
"CHECKBOX" { MAYBE_RETURN (CHECKBOX); }
"COMBOBOX" { MAYBE_RETURN (COMBOBOX); }
"CTEXT" { MAYBE_RETURN (CTEXT); }
"DEFPUSHBUTTON" { MAYBE_RETURN (DEFPUSHBUTTON); }
"EDITTEXT" { MAYBE_RETURN (EDITTEXT); }
"GROUPBOX" { MAYBE_RETURN (GROUPBOX); }
"LISTBOX" { MAYBE_RETURN (LISTBOX); }
"LTEXT" { MAYBE_RETURN (LTEXT); }
"PUSHBOX" { MAYBE_RETURN (PUSHBOX); }
"PUSHBUTTON" { MAYBE_RETURN (PUSHBUTTON); }
"RADIOBUTTON" { MAYBE_RETURN (RADIOBUTTON); }
"RTEXT" { MAYBE_RETURN (RTEXT); }
"SCROLLBAR" { MAYBE_RETURN (SCROLLBAR); }
"STATE3" { MAYBE_RETURN (STATE3); }
"USERBUTTON" { MAYBE_RETURN (USERBUTTON); }
"BEDIT" { MAYBE_RETURN (BEDIT); }
"HEDIT" { MAYBE_RETURN (HEDIT); }
"IEDIT" { MAYBE_RETURN (IEDIT); }
"FONT" { MAYBE_RETURN (FONT); }
"ICON" { MAYBE_RETURN (ICON); }
"LANGUAGE" { MAYBE_RETURN (LANGUAGE); }
"CHARACTERISTICS" { MAYBE_RETURN (CHARACTERISTICS); }
"VERSION" { MAYBE_RETURN (VERSIONK); }
"MENU" { MAYBE_RETURN (MENU); }
"MENUEX" { MAYBE_RETURN (MENUEX); }
"MENUITEM" { MAYBE_RETURN (MENUITEM); }
"SEPARATOR" { MAYBE_RETURN (SEPARATOR); }
"POPUP" { MAYBE_RETURN (POPUP); }
"CHECKED" { MAYBE_RETURN (CHECKED); }
"GRAYED" { MAYBE_RETURN (GRAYED); }
"HELP" { MAYBE_RETURN (HELP); }
"INACTIVE" { MAYBE_RETURN (INACTIVE); }
"MENUBARBREAK" { MAYBE_RETURN (MENUBARBREAK); }
"MENUBREAK" { MAYBE_RETURN (MENUBREAK); }
"MESSAGETABLE" { MAYBE_RETURN (MESSAGETABLE); }
"RCDATA" { MAYBE_RETURN (RCDATA); }
"STRINGTABLE" { MAYBE_RETURN (STRINGTABLE); }
"VERSIONINFO" { MAYBE_RETURN (VERSIONINFO); }
"FILEVERSION" { MAYBE_RETURN (FILEVERSION); }
"PRODUCTVERSION" { MAYBE_RETURN (PRODUCTVERSION); }
"FILEFLAGSMASK" { MAYBE_RETURN (FILEFLAGSMASK); }
"FILEFLAGS" { MAYBE_RETURN (FILEFLAGS); }
"FILEOS" { MAYBE_RETURN (FILEOS); }
"FILETYPE" { MAYBE_RETURN (FILETYPE); }
"FILESUBTYPE" { MAYBE_RETURN (FILESUBTYPE); }
"VALUE" { MAYBE_RETURN (VALUE); }
"MOVEABLE" { MAYBE_RETURN (MOVEABLE); }
"FIXED" { MAYBE_RETURN (FIXED); }
"PURE" { MAYBE_RETURN (PURE); }
"IMPURE" { MAYBE_RETURN (IMPURE); }
"PRELOAD" { MAYBE_RETURN (PRELOAD); }
"LOADONCALL" { MAYBE_RETURN (LOADONCALL); }
"DISCARDABLE" { MAYBE_RETURN (DISCARDABLE); }
"NOT" { MAYBE_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)
MAYBE_RETURN (BLOCKSTRINGFILEINFO);
else if (strncmp (s, "VarFileInfo",
sizeof "VarFileInfo" - 1) == 0
&& s + sizeof "VarFileInfo" - 1 == send)
MAYBE_RETURN (BLOCKVARFILEINFO);
else
{
char *r;
r = get_string (send - s + 1);
strncpy (r, s, send - s);
r[send - s] = '\0';
yylval.s = r;
MAYBE_RETURN (BLOCK);
}
}
"#"[^\n]* {
cpp_line (yytext);
}
[0-9][x0-9A-Fa-f]*L {
yylval.i.val = strtoul (yytext, 0, 0);
yylval.i.dword = 1;
MAYBE_RETURN (NUMBER);
}
[0-9][x0-9A-Fa-f]* {
yylval.i.val = strtoul (yytext, 0, 0);
yylval.i.dword = 0;
MAYBE_RETURN (NUMBER);
}
("\""[^\"\n]*"\""[ \t\n]*)+ {
char *s;
unsigned long length;
s = handle_quotes (yytext, &length);
if (! rcdata_mode)
{
yylval.s = s;
MAYBE_RETURN (QUOTEDSTRING);
}
else
{
yylval.ss.length = length;
yylval.ss.s = s;
MAYBE_RETURN (SIZEDSTRING);
}
}
[_A-Za-z][^ ,\t\r\n]* {
char *s;
/* I rejected comma in a string in order to
handle VIRTKEY, CONTROL in an accelerator
resource. This means that an unquoted
file name can not contain a comma. I
don't know what rc permits. */
s = get_string (strlen (yytext) + 1);
strcpy (s, yytext);
yylval.s = s;
MAYBE_RETURN (STRING);
}
[\n] { ++rc_lineno; }
[ \t\r]+ { /* ignore whitespace */ }
. { MAYBE_RETURN (*yytext); }
%%
#ifndef yywrap
/* This is needed for some versions of lex. */
int yywrap (void)
{
return 1;
}
#endif
/* Handle a C preprocessor line. */
static void
cpp_line (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;
if (!initial_fn)
{
initial_fn = xmalloc (strlen (fn) + 1);
strcpy (initial_fn, fn);
}
/* Allow the initial file, regardless of name. Suppress all other
files if they end in ".h" (this allows included "*.rc"). */
if (strcmp (initial_fn, fn) == 0
|| strcmp (fn + strlen (fn) - 2, ".h") != 0)
suppress_cpp_data = 0;
else
suppress_cpp_data = 1;
}
/* 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 (const char *input, unsigned long *len)
{
char *ret, *s;
const char *t;
int ch;
int num_xdigits;
ret = get_string (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 'a':
*s++ = ESCAPE_B; /* Strange, but true... */
++t;
break;
case 'b':
*s++ = ESCAPE_B;
++t;
break;
case 'f':
*s++ = ESCAPE_F;
++t;
break;
case 'n':
*s++ = ESCAPE_N;
++t;
break;
case 'r':
*s++ = ESCAPE_R;
++t;
break;
case 't':
*s++ = ESCAPE_T;
++t;
break;
case 'v':
*s++ = ESCAPE_V;
++t;
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;
/* We only handle single byte chars here. Make sure
we finish an escape sequence like "/xB0ABC" after
the first two digits. */
num_xdigits = 2;
while (num_xdigits--)
{
if (*t >= '0' && *t <= '9')
ch = (ch << 4) | (*t - '0');
else if (*t >= 'a' && *t <= 'f')
ch = (ch << 4) | (*t - 'a' + 10);
else if (*t >= 'A' && *t <= 'F')
ch = (ch << 4) | (*t - 'A' + 10);
else
break;
++t;
}
*s++ = ch;
break;
default:
rcparse_warning ("unrecognized escape sequence");
*s++ = '\\';
*s++ = *t++;
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))
{
if ((*t) == '\n')
++rc_lineno;
++t;
}
if (*t == '\0')
break;
assert (*t == '"');
++t;
}
}
*s = '\0';
*len = s - ret;
return ret;
}
/* Allocate a string of a given length. */
static char *
get_string (int len)
{
struct alloc_string *as;
as = (struct alloc_string *) xmalloc (sizeof *as);
as->s = xmalloc (len);
as->next = strings;
strings = as;
return as->s;
}
/* Discard all the strings we have allocated. The parser calls this
when it no longer needs them. */
void
rcparse_discard_strings (void)
{
struct alloc_string *as;
as = strings;
while (as != NULL)
{
struct alloc_string *n;
free (as->s);
n = as->next;
free (as);
as = n;
}
strings = NULL;
}
/* Enter rcdata mode. */
void
rcparse_rcdata (void)
{
rcdata_mode = 1;
}
/* Go back to normal mode from rcdata mode. */
void
rcparse_normal (void)
{
rcdata_mode = 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
Copyright 1997, 1998, 1999, 2000, 2003, 2007
Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
Rewritten by Kai Tietz, Onevision.
This file is part of GNU Binutils.
@ -25,8 +26,8 @@
#include "sysdep.h"
#include "bfd.h"
#include "libiberty.h"
#include "bucomm.h"
#include "libiberty.h"
#include "windres.h"
#include <assert.h>
@ -49,14 +50,12 @@ struct coff_file_info
/* End of data read from file. */
const bfd_byte *data_end;
/* Address of the resource section minus the image base of the file. */
bfd_vma secaddr;
/* Non-zero if the file is big endian. */
int big_endian;
rc_uint_type secaddr;
};
/* A resource directory table in a COFF file. */
struct extern_res_directory
struct __attribute__ ((__packed__)) extern_res_directory
{
/* Characteristics. */
bfd_byte characteristics[4];
@ -97,26 +96,24 @@ struct extern_res_data
bfd_byte reserved[4];
};
/* Macros to swap in values. */
#define getfi_16(fi, s) ((fi)->big_endian ? bfd_getb16 (s) : bfd_getl16 (s))
#define getfi_32(fi, s) ((fi)->big_endian ? bfd_getb32 (s) : bfd_getl32 (s))
/* Local functions. */
static void overrun (const struct coff_file_info *, const char *);
static struct res_directory *read_coff_res_dir
(const bfd_byte *, const struct coff_file_info *,
const struct res_id *, int);
static struct res_resource *read_coff_data_entry
(const bfd_byte *, const struct coff_file_info *, const struct res_id *);
static rc_res_directory *read_coff_res_dir (windres_bfd *, const bfd_byte *,
const struct coff_file_info *,
const rc_res_id *, int);
static rc_res_resource *read_coff_data_entry (windres_bfd *, const bfd_byte *,
const struct coff_file_info *,
const rc_res_id *);
/* Read the resources in a COFF file. */
struct res_directory *
rc_res_directory *
read_coff_rsrc (const char *filename, const char *target)
{
rc_res_directory *ret;
bfd *abfd;
windres_bfd wrbfd;
char **matching;
asection *sec;
bfd_size_type size;
@ -144,27 +141,28 @@ read_coff_rsrc (const char *filename, const char *target)
fatal (_("%s: no resource section"), filename);
}
set_windres_bfd (&wrbfd, abfd, sec, WR_KIND_BFD);
size = bfd_section_size (abfd, sec);
data = (bfd_byte *) res_alloc (size);
if (! bfd_get_section_contents (abfd, sec, data, 0, size))
bfd_fatal (_("can't read resource section"));
get_windres_bfd_content (&wrbfd, data, 0, size);
finfo.filename = filename;
finfo.data = data;
finfo.data_end = data + size;
finfo.secaddr = (bfd_get_section_vma (abfd, sec)
- pe_data (abfd)->pe_opthdr.ImageBase);
finfo.big_endian = bfd_big_endian (abfd);
bfd_close (abfd);
/* Now just read in the top level resource directory. Note that we
don't free data, since we create resource entries that point into
it. If we ever want to free up the resource information we read,
this will have to be cleaned up. */
return read_coff_res_dir (data, &finfo, (const struct res_id *) NULL, 0);
ret = read_coff_res_dir (&wrbfd, data, &finfo, (const rc_res_id *) NULL, 0);
bfd_close (abfd);
return ret;
}
/* Give an error if we are out of bounds. */
@ -177,14 +175,15 @@ overrun (const struct coff_file_info *finfo, const char *msg)
/* Read a resource directory. */
static struct res_directory *
read_coff_res_dir (const bfd_byte *data, const struct coff_file_info *finfo,
const struct res_id *type, int level)
static rc_res_directory *
read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data,
const struct coff_file_info *finfo,
const rc_res_id *type, int level)
{
const struct extern_res_directory *erd;
struct res_directory *rd;
rc_res_directory *rd;
int name_count, id_count, i;
struct res_entry **pp;
rc_res_entry **pp;
const struct extern_res_entry *ere;
if ((size_t) (finfo->data_end - data) < sizeof (struct extern_res_directory))
@ -192,15 +191,15 @@ read_coff_res_dir (const bfd_byte *data, const struct coff_file_info *finfo,
erd = (const struct extern_res_directory *) data;
rd = (struct res_directory *) res_alloc (sizeof *rd);
rd->characteristics = getfi_32 (finfo, erd->characteristics);
rd->time = getfi_32 (finfo, erd->time);
rd->major = getfi_16 (finfo, erd->major);
rd->minor = getfi_16 (finfo, erd->minor);
rd = (rc_res_directory *) res_alloc (sizeof (rc_res_directory));
rd->characteristics = windres_get_32 (wrbfd, erd->characteristics, 4);
rd->time = windres_get_32 (wrbfd, erd->time, 4);
rd->major = windres_get_16 (wrbfd, erd->major, 2);
rd->minor = windres_get_16 (wrbfd, erd->minor, 2);
rd->entries = NULL;
name_count = getfi_16 (finfo, erd->name_count);
id_count = getfi_16 (finfo, erd->id_count);
name_count = windres_get_16 (wrbfd, erd->name_count, 2);
id_count = windres_get_16 (wrbfd, erd->id_count, 2);
pp = &rd->entries;
@ -210,33 +209,33 @@ read_coff_res_dir (const bfd_byte *data, const struct coff_file_info *finfo,
for (i = 0; i < name_count; i++, ere++)
{
unsigned long name, rva;
struct res_entry *re;
rc_uint_type name, rva;
rc_res_entry *re;
const bfd_byte *ers;
int length, j;
if ((const bfd_byte *) ere >= finfo->data_end)
overrun (finfo, _("named directory entry"));
name = getfi_32 (finfo, ere->name);
rva = getfi_32 (finfo, ere->rva);
name = windres_get_32 (wrbfd, ere->name, 4);
rva = windres_get_32 (wrbfd, ere->rva, 4);
/* For some reason the high bit in NAME is set. */
name &=~ 0x80000000;
if (name > (size_t) (finfo->data_end - finfo->data))
if (name > (rc_uint_type) (finfo->data_end - finfo->data))
overrun (finfo, _("directory entry name"));
ers = finfo->data + name;
re = (struct res_entry *) res_alloc (sizeof *re);
re = (rc_res_entry *) res_alloc (sizeof *re);
re->next = NULL;
re->id.named = 1;
length = getfi_16 (finfo, ers);
length = windres_get_16 (wrbfd, ers, 2);
re->id.u.n.length = length;
re->id.u.n.name = (unichar *) res_alloc (length * sizeof (unichar));
for (j = 0; j < length; j++)
re->id.u.n.name[j] = getfi_16 (finfo, ers + j * 2 + 2);
re->id.u.n.name[j] = windres_get_16 (wrbfd, ers + j * 2 + 2, 2);
if (level == 0)
type = &re->id;
@ -244,18 +243,18 @@ read_coff_res_dir (const bfd_byte *data, const struct coff_file_info *finfo,
if ((rva & 0x80000000) != 0)
{
rva &=~ 0x80000000;
if (rva >= (size_t) (finfo->data_end - finfo->data))
if (rva >= (rc_uint_type) (finfo->data_end - finfo->data))
overrun (finfo, _("named subdirectory"));
re->subdir = 1;
re->u.dir = read_coff_res_dir (finfo->data + rva, finfo, type,
re->u.dir = read_coff_res_dir (wrbfd, finfo->data + rva, finfo, type,
level + 1);
}
else
{
if (rva >= (size_t) (finfo->data_end - finfo->data))
if (rva >= (rc_uint_type) (finfo->data_end - finfo->data))
overrun (finfo, _("named resource"));
re->subdir = 0;
re->u.res = read_coff_data_entry (finfo->data + rva, finfo, type);
re->u.res = read_coff_data_entry (wrbfd, finfo->data + rva, finfo, type);
}
*pp = re;
@ -265,15 +264,15 @@ read_coff_res_dir (const bfd_byte *data, const struct coff_file_info *finfo,
for (i = 0; i < id_count; i++, ere++)
{
unsigned long name, rva;
struct res_entry *re;
rc_res_entry *re;
if ((const bfd_byte *) ere >= finfo->data_end)
overrun (finfo, _("ID directory entry"));
name = getfi_32 (finfo, ere->name);
rva = getfi_32 (finfo, ere->rva);
name = windres_get_32 (wrbfd, ere->name, 4);
rva = windres_get_32 (wrbfd, ere->rva, 4);
re = (struct res_entry *) res_alloc (sizeof *re);
re = (rc_res_entry *) res_alloc (sizeof *re);
re->next = NULL;
re->id.named = 0;
re->id.u.id = name;
@ -284,18 +283,18 @@ read_coff_res_dir (const bfd_byte *data, const struct coff_file_info *finfo,
if ((rva & 0x80000000) != 0)
{
rva &=~ 0x80000000;
if (rva >= (size_t) (finfo->data_end - finfo->data))
if (rva >= (rc_uint_type) (finfo->data_end - finfo->data))
overrun (finfo, _("ID subdirectory"));
re->subdir = 1;
re->u.dir = read_coff_res_dir (finfo->data + rva, finfo, type,
re->u.dir = read_coff_res_dir (wrbfd, finfo->data + rva, finfo, type,
level + 1);
}
else
{
if (rva >= (size_t) (finfo->data_end - finfo->data))
if (rva >= (rc_uint_type) (finfo->data_end - finfo->data))
overrun (finfo, _("ID resource"));
re->subdir = 0;
re->u.res = read_coff_data_entry (finfo->data + rva, finfo, type);
re->u.res = read_coff_data_entry (wrbfd, finfo->data + rva, finfo, type);
}
*pp = re;
@ -307,12 +306,14 @@ read_coff_res_dir (const bfd_byte *data, const struct coff_file_info *finfo,
/* Read a resource data entry. */
static struct res_resource *
read_coff_data_entry (const bfd_byte *data, const struct coff_file_info *finfo, const struct res_id *type)
static rc_res_resource *
read_coff_data_entry (windres_bfd *wrbfd, const bfd_byte *data,
const struct coff_file_info *finfo,
const rc_res_id *type)
{
const struct extern_res_data *erd;
struct res_resource *r;
unsigned long size, rva;
rc_res_resource *r;
rc_uint_type size, rva;
const bfd_byte *resdata;
if (type == NULL)
@ -323,22 +324,22 @@ read_coff_data_entry (const bfd_byte *data, const struct coff_file_info *finfo,
erd = (const struct extern_res_data *) data;
size = getfi_32 (finfo, erd->size);
rva = getfi_32 (finfo, erd->rva);
size = windres_get_32 (wrbfd, erd->size, 4);
rva = windres_get_32 (wrbfd, erd->rva, 4);
if (rva < finfo->secaddr
|| rva - finfo->secaddr >= (size_t) (finfo->data_end - finfo->data))
|| rva - finfo->secaddr >= (rc_uint_type) (finfo->data_end - finfo->data))
overrun (finfo, _("resource data"));
resdata = finfo->data + (rva - finfo->secaddr);
if (size > (size_t) (finfo->data_end - resdata))
if (size > (rc_uint_type) (finfo->data_end - resdata))
overrun (finfo, _("resource data size"));
r = bin_to_res (*type, resdata, size, finfo->big_endian);
r = bin_to_res (wrbfd, *type, resdata, size);
memset (&r->res_info, 0, sizeof (struct res_res_info));
r->coff_info.codepage = getfi_32 (finfo, erd->codepage);
r->coff_info.reserved = getfi_32 (finfo, erd->reserved);
memset (&r->res_info, 0, sizeof (rc_res_res_info));
r->coff_info.codepage = windres_get_32 (wrbfd, erd->codepage, 4);
r->coff_info.reserved = windres_get_32 (wrbfd, erd->reserved, 4);
return r;
}
@ -348,9 +349,19 @@ read_coff_data_entry (const bfd_byte *data, const struct coff_file_info *finfo,
struct bindata_build
{
/* The data. */
struct bindata *d;
bindata *d;
/* The last structure we have added to the list. */
struct bindata *last;
bindata *last;
/* The size of the list as a whole. */
unsigned long length;
};
struct coff_res_data_build
{
/* The data. */
coff_res_data *d;
/* The last structure we have added to the list. */
coff_res_data *last;
/* The size of the list as a whole. */
unsigned long length;
};
@ -362,9 +373,7 @@ struct coff_write_info
{
/* These fields are based on the BFD. */
/* The BFD itself. */
bfd *abfd;
/* Non-zero if the file is big endian. */
int big_endian;
windres_bfd *wrbfd;
/* Pointer to section symbol used to build RVA relocs. */
asymbol **sympp;
@ -384,27 +393,19 @@ struct coff_write_info
/* Resource data entries. */
struct bindata_build dataents;
/* Actual resource data. */
struct bindata_build resources;
struct coff_res_data_build resources;
/* Relocations. */
arelent **relocs;
/* Number of relocations. */
unsigned int reloc_count;
};
/* Macros to swap out values. */
#define putcwi_16(cwi, v, s) \
((cwi->big_endian) ? bfd_putb16 ((v), (s)) : bfd_putl16 ((v), (s)))
#define putcwi_32(cwi, v, s) \
((cwi->big_endian) ? bfd_putb32 ((v), (s)) : bfd_putl32 ((v), (s)))
static void coff_bin_sizes
(const struct res_directory *, struct coff_write_info *);
static unsigned char *coff_alloc (struct bindata_build *, size_t);
static void coff_bin_sizes (const rc_res_directory *, struct coff_write_info *);
static bfd_byte *coff_alloc (struct bindata_build *, rc_uint_type);
static void coff_to_bin
(const struct res_directory *, struct coff_write_info *);
(const rc_res_directory *, struct coff_write_info *);
static void coff_res_to_bin
(const struct res_resource *, struct coff_write_info *);
(const rc_res_resource *, struct coff_write_info *);
/* Write resources to a COFF file. RESOURCES should already be
sorted.
@ -416,12 +417,14 @@ static void coff_res_to_bin
void
write_coff_file (const char *filename, const char *target,
const struct res_directory *resources)
const rc_res_directory *resources)
{
bfd *abfd;
asection *sec;
struct coff_write_info cwi;
struct bindata *d;
windres_bfd wrbfd;
bindata *d;
coff_res_data *rd;
unsigned long length, offset;
if (filename == NULL)
@ -475,8 +478,9 @@ write_coff_file (const char *filename, const char *target,
We build these different types of data in different lists. */
cwi.abfd = abfd;
cwi.big_endian = bfd_big_endian (abfd);
set_windres_bfd (&wrbfd, abfd, sec, WR_KIND_BFD);
cwi.wrbfd = &wrbfd;
cwi.sympp = sec->symbol_ptr_ptr;
cwi.dirsize = 0;
cwi.dirstrsize = 0;
@ -511,7 +515,7 @@ write_coff_file (const char *filename, const char *target,
alignment. */
if ((cwi.dirstrs.length & 3) != 0)
{
unsigned char *ex;
bfd_byte *ex;
ex = coff_alloc (&cwi.dirstrs, 2);
ex[0] = 0;
@ -543,21 +547,18 @@ write_coff_file (const char *filename, const char *target,
}
for (d = cwi.dirstrs.d; d != NULL; d = d->next)
{
if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length))
bfd_fatal ("bfd_set_section_contents");
set_windres_bfd_content (&wrbfd, d->data, offset, d->length);
offset += d->length;
}
for (d = cwi.dataents.d; d != NULL; d = d->next)
{
if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length))
bfd_fatal ("bfd_set_section_contents");
set_windres_bfd_content (&wrbfd, d->data, offset, d->length);
offset += d->length;
}
for (d = cwi.resources.d; d != NULL; d = d->next)
for (rd = cwi.resources.d; rd != NULL; rd = rd->next)
{
if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length))
bfd_fatal ("bfd_set_section_contents");
offset += d->length;
res_to_bin (cwi.wrbfd, (rc_uint_type) offset, rd->res);
offset += rd->length;
}
assert (offset == length);
@ -573,10 +574,10 @@ write_coff_file (const char *filename, const char *target,
entries. This updates fields in CWI. */
static void
coff_bin_sizes (const struct res_directory *resdir,
coff_bin_sizes (const rc_res_directory *resdir,
struct coff_write_info *cwi)
{
const struct res_entry *re;
const rc_res_entry *re;
cwi->dirsize += sizeof (struct extern_res_directory);
@ -596,15 +597,15 @@ coff_bin_sizes (const struct res_directory *resdir,
/* Allocate data for a particular list. */
static unsigned char *
coff_alloc (struct bindata_build *bb, size_t size)
static bfd_byte *
coff_alloc (struct bindata_build *bb, rc_uint_type size)
{
struct bindata *d;
bindata *d;
d = (struct bindata *) reswr_alloc (sizeof *d);
d = (bindata *) reswr_alloc (sizeof (bindata));
d->next = NULL;
d->data = (unsigned char *) reswr_alloc (size);
d->data = (bfd_byte *) reswr_alloc (size);
d->length = size;
if (bb->d == NULL)
@ -620,11 +621,11 @@ coff_alloc (struct bindata_build *bb, size_t size)
/* Convert the resource directory RESDIR to binary. */
static void
coff_to_bin (const struct res_directory *resdir, struct coff_write_info *cwi)
coff_to_bin (const rc_res_directory *resdir, struct coff_write_info *cwi)
{
struct extern_res_directory *erd;
int ci, cn;
const struct res_entry *e;
const rc_res_entry *e;
struct extern_res_entry *ere;
/* Write out the directory table. */
@ -632,10 +633,10 @@ coff_to_bin (const struct res_directory *resdir, struct coff_write_info *cwi)
erd = ((struct extern_res_directory *)
coff_alloc (&cwi->dirs, sizeof (*erd)));
putcwi_32 (cwi, resdir->characteristics, erd->characteristics);
putcwi_32 (cwi, resdir->time, erd->time);
putcwi_16 (cwi, resdir->major, erd->major);
putcwi_16 (cwi, resdir->minor, erd->minor);
windres_put_32 (cwi->wrbfd, erd->characteristics, resdir->characteristics);
windres_put_32 (cwi->wrbfd, erd->time, resdir->time);
windres_put_16 (cwi->wrbfd, erd->major, resdir->major);
windres_put_16 (cwi->wrbfd, erd->minor, resdir->minor);
ci = 0;
cn = 0;
@ -647,8 +648,8 @@ coff_to_bin (const struct res_directory *resdir, struct coff_write_info *cwi)
++ci;
}
putcwi_16 (cwi, cn, erd->name_count);
putcwi_16 (cwi, ci, erd->id_count);
windres_put_16 (cwi->wrbfd, erd->name_count, cn);
windres_put_16 (cwi->wrbfd, erd->id_count, ci);
/* Write out the data entries. Note that we allocate space for all
the entries before writing them out. That permits a recursive
@ -659,35 +660,33 @@ coff_to_bin (const struct res_directory *resdir, struct coff_write_info *cwi)
for (e = resdir->entries; e != NULL; e = e->next, ere++)
{
if (! e->id.named)
putcwi_32 (cwi, e->id.u.id, ere->name);
windres_put_32 (cwi->wrbfd, ere->name, e->id.u.id);
else
{
unsigned char *str;
int i;
bfd_byte *str;
rc_uint_type i;
/* For some reason existing files seem to have the high bit
set on the address of the name, although that is not
documented. */
putcwi_32 (cwi,
0x80000000 | (cwi->dirsize + cwi->dirstrs.length),
ere->name);
windres_put_32 (cwi->wrbfd, ere->name,
0x80000000 | (cwi->dirsize + cwi->dirstrs.length));
str = coff_alloc (&cwi->dirstrs, e->id.u.n.length * 2 + 2);
putcwi_16 (cwi, e->id.u.n.length, str);
windres_put_16 (cwi->wrbfd, str, e->id.u.n.length);
for (i = 0; i < e->id.u.n.length; i++)
putcwi_16 (cwi, e->id.u.n.name[i], str + i * 2 + 2);
windres_put_16 (cwi->wrbfd, str + (i + 1) * sizeof (unichar), e->id.u.n.name[i]);
}
if (e->subdir)
{
putcwi_32 (cwi, 0x80000000 | cwi->dirs.length, ere->rva);
windres_put_32 (cwi->wrbfd, ere->rva, 0x80000000 | cwi->dirs.length);
coff_to_bin (e->u.dir, cwi);
}
else
{
putcwi_32 (cwi,
cwi->dirsize + cwi->dirstrsize + cwi->dataents.length,
ere->rva);
windres_put_32 (cwi->wrbfd, ere->rva,
cwi->dirsize + cwi->dirstrsize + cwi->dataents.length);
coff_res_to_bin (e->u.res, cwi);
}
@ -697,12 +696,11 @@ coff_to_bin (const struct res_directory *resdir, struct coff_write_info *cwi)
/* Convert the resource RES to binary. */
static void
coff_res_to_bin (const struct res_resource *res, struct coff_write_info *cwi)
coff_res_to_bin (const rc_res_resource *res, struct coff_write_info *cwi)
{
arelent *r;
struct extern_res_data *erd;
struct bindata *d;
unsigned long length;
coff_res_data *d;
/* For some reason, although every other address is a section
offset, the address of the resource data itself is an RVA. That
@ -715,7 +713,7 @@ coff_res_to_bin (const struct res_resource *res, struct coff_write_info *cwi)
r->sym_ptr_ptr = cwi->sympp;
r->address = cwi->dirsize + cwi->dirstrsize + cwi->dataents.length;
r->addend = 0;
r->howto = bfd_reloc_type_lookup (cwi->abfd, BFD_RELOC_RVA);
r->howto = bfd_reloc_type_lookup (WR_BFD (cwi->wrbfd), BFD_RELOC_RVA);
if (r->howto == NULL)
bfd_fatal (_("can't get BFD_RELOC_RVA relocation type"));
@ -727,41 +725,29 @@ coff_res_to_bin (const struct res_resource *res, struct coff_write_info *cwi)
erd = (struct extern_res_data *) coff_alloc (&cwi->dataents, sizeof (*erd));
putcwi_32 (cwi,
windres_put_32 (cwi->wrbfd, erd->rva,
(cwi->dirsize
+ cwi->dirstrsize
+ cwi->dataentsize
+ cwi->resources.length),
erd->rva);
putcwi_32 (cwi, res->coff_info.codepage, erd->codepage);
putcwi_32 (cwi, res->coff_info.reserved, erd->reserved);
+ cwi->resources.length));
windres_put_32 (cwi->wrbfd, erd->codepage, res->coff_info.codepage);
windres_put_32 (cwi->wrbfd, erd->reserved, res->coff_info.reserved);
d = res_to_bin (res, cwi->big_endian);
d = (coff_res_data *) reswr_alloc (sizeof (coff_res_data));
d->length = res_to_bin (NULL, (rc_uint_type) 0, res);
d->res = res;
d->next = NULL;
if (cwi->resources.d == NULL)
cwi->resources.d = d;
else
cwi->resources.last->next = d;
length = 0;
for (; d->next != NULL; d = d->next)
length += d->length;
length += d->length;
cwi->resources.last = d;
cwi->resources.length += length;
cwi->resources.length += (d->length + 3) & ~3;
putcwi_32 (cwi, length, erd->size);
windres_put_32 (cwi->wrbfd, erd->size, d->length);
/* Force the next resource to have 32 bit alignment. */
if ((length & 3) != 0)
{
int add;
unsigned char *ex;
add = 4 - (length & 3);
ex = coff_alloc (&cwi->resources, add);
memset (ex, 0, add);
}
d->length = (d->length + 3) & ~3;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,8 @@
/* resres.c: read_res_file and write_res_file implementation for windres.
Copyright 1998, 1999, 2001, 2002, 2007 Free Software Foundation, Inc.
Copyright 1998, 1999, 2001, 2002, 2007
Free Software Foundation, Inc.
Written by Anders Norlander <anorland@hem2.passagen.se>.
Rewritten by Kai Tietz, Onevision.
This file is part of GNU Binutils.
@ -25,161 +27,186 @@
#include "sysdep.h"
#include "bfd.h"
#include "libiberty.h"
#include "bucomm.h"
#include "libiberty.h"
#include "windres.h"
#include <assert.h>
#include <time.h>
struct res_hdr
{
unsigned long data_size;
unsigned long header_size;
};
static rc_uint_type write_res_directory (windres_bfd *, rc_uint_type,
const rc_res_directory *, const rc_res_id *,
const rc_res_id *, rc_uint_type *, int);
static rc_uint_type write_res_resource (windres_bfd *, rc_uint_type,const rc_res_id *,
const rc_res_id *, const rc_res_resource *,
rc_uint_type *);
static rc_uint_type write_res_bin (windres_bfd *, rc_uint_type, const rc_res_resource *,
const rc_res_id *, const rc_res_id *,
const rc_res_res_info *);
static void write_res_directory
PARAMS ((const struct res_directory *,
const struct res_id *, const struct res_id *,
int *, int));
static void write_res_resource
PARAMS ((const struct res_id *, const struct res_id *,
const struct res_resource *, int *));
static void write_res_bin
PARAMS ((const struct res_resource *, const struct res_id *,
const struct res_id *, const struct res_res_info *));
static rc_uint_type write_res_id (windres_bfd *, rc_uint_type, const rc_res_id *);
static rc_uint_type write_res_info (windres_bfd *, rc_uint_type, const rc_res_res_info *);
static rc_uint_type write_res_data_hdr (windres_bfd *, rc_uint_type, res_hdr *);
static void write_res_id PARAMS ((const struct res_id *));
static void write_res_info PARAMS ((const struct res_res_info *));
static void write_res_data PARAMS ((const void *, size_t, int));
static void write_res_header
PARAMS ((unsigned long, const struct res_id *, const struct res_id *,
const struct res_res_info *));
static rc_uint_type write_res_header (windres_bfd *, rc_uint_type, rc_uint_type,
const rc_res_id *, const rc_res_id *,
const rc_res_res_info *);
static int read_resource_entry PARAMS ((void));
static void read_res_data PARAMS ((void *, size_t, int));
static void read_res_id PARAMS ((struct res_id *));
static unichar *read_unistring PARAMS ((int *));
static void skip_null_resource PARAMS ((void));
static int read_resource_entry (windres_bfd *, rc_uint_type *, rc_uint_type);
static void read_res_data (windres_bfd *, rc_uint_type *, rc_uint_type, void *,
rc_uint_type);
static void read_res_data_hdr (windres_bfd *, rc_uint_type *, rc_uint_type, res_hdr *);
static void read_res_id (windres_bfd *, rc_uint_type *, rc_uint_type, rc_res_id *);
static unichar *read_unistring (windres_bfd *, rc_uint_type *, rc_uint_type, rc_uint_type *);
static void skip_null_resource (windres_bfd *, rc_uint_type *, rc_uint_type);
static int probe_binary (windres_bfd *wrbfd, rc_uint_type);
static unsigned long get_id_size PARAMS ((const struct res_id *));
static void res_align_file PARAMS ((void));
static unsigned long get_id_size (const rc_res_id *);
static void
res_add_resource
PARAMS ((struct res_resource *, const struct res_id *,
const struct res_id *, int, int));
static void res_add_resource (rc_res_resource *, const rc_res_id *,
const rc_res_id *, rc_uint_type, int);
void
res_append_resource
PARAMS ((struct res_directory **, struct res_resource *,
int, const struct res_id *, int));
static void res_append_resource (rc_res_directory **, rc_res_resource *,
int, const rc_res_id *, int);
static struct res_directory *resources = NULL;
static rc_res_directory *resources = NULL;
static FILE *fres;
static const char *filename;
extern char *program_name;
/* Read resource file */
struct res_directory *
read_res_file (fn)
const char *fn;
rc_res_directory *
read_res_file (const char *fn)
{
rc_uint_type off, flen;
windres_bfd wrbfd;
bfd *abfd;
asection *sec;
filename = fn;
fres = fopen (filename, "rb");
if (fres == NULL)
fatal ("can't open `%s' for output: %s", filename, strerror (errno));
skip_null_resource ();
flen = (rc_uint_type) get_file_size (filename);
if (! flen)
fatal ("can't open '%s' for input.", filename);
abfd = windres_open_as_binary (filename, 1);
sec = bfd_get_section_by_name (abfd, ".data");
if (sec == NULL)
bfd_fatal ("bfd_get_section_by_name");
set_windres_bfd (&wrbfd, abfd, sec,
(target_is_bigendian ? WR_KIND_BFD_BIN_B
: WR_KIND_BFD_BIN_L));
off = 0;
while (read_resource_entry ())
if (! probe_binary (&wrbfd, flen))
set_windres_bfd_endianess (&wrbfd, ! target_is_bigendian);
skip_null_resource (&wrbfd, &off, flen);
while (read_resource_entry (&wrbfd, &off, flen))
;
fclose (fres);
bfd_close (abfd);
return resources;
}
/* Write resource file */
void
write_res_file (fn, resdir)
const char *fn;
const struct res_directory *resdir;
write_res_file (const char *fn,const rc_res_directory *resdir)
{
int language;
static const unsigned char sign[] =
asection *sec;
rc_uint_type language;
bfd *abfd;
windres_bfd wrbfd;
unsigned long sec_length = 0,sec_length_wrote;
static const bfd_byte sign[] =
{0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
long fpos;
filename = fn;
fres = fopen (filename, "wb");
if (fres == NULL)
fatal ("can't open `%s' for output: %s", filename, strerror (errno));
abfd = windres_open_as_binary (filename, 0);
sec = bfd_make_section (abfd, ".data");
if (sec == NULL)
bfd_fatal ("bfd_make_section");
if (! bfd_set_section_flags (abfd, sec,
(SEC_HAS_CONTENTS | SEC_ALLOC
| SEC_LOAD | SEC_DATA)))
bfd_fatal ("bfd_set_section_flags");
/* Requiring this is probably a bug in BFD. */
sec->output_section = sec;
/* Write 32 bit resource signature */
write_res_data (sign, sizeof (sign), 1);
/* write resources */
set_windres_bfd (&wrbfd, abfd, sec,
(target_is_bigendian ? WR_KIND_BFD_BIN_B
: WR_KIND_BFD_BIN_L));
language = -1;
write_res_directory (resdir, (const struct res_id *) NULL,
(const struct res_id *) NULL, &language, 1);
sec_length = write_res_directory ((windres_bfd *) NULL, 0x20UL, resdir,
(const rc_res_id *) NULL,
(const rc_res_id *) NULL, &language, 1);
if (! bfd_set_section_size (abfd, sec, (sec_length + 3) & ~3))
bfd_fatal ("bfd_set_section_size");
if ((sec_length & 3) != 0)
set_windres_bfd_content (&wrbfd, sign, sec_length, 4-(sec_length & 3));
set_windres_bfd_content (&wrbfd, sign, 0, sizeof (sign));
language = -1;
sec_length_wrote = write_res_directory (&wrbfd, 0x20UL, resdir,
(const rc_res_id *) NULL,
(const rc_res_id *) NULL,
&language, 1);
if (sec_length != sec_length_wrote)
fatal ("res write failed with different sizes (%lu/%lu).", (long) sec_length,
(long) sec_length_wrote);
/* end file on DWORD boundary */
fpos = ftell (fres);
if (fpos % 4)
write_res_data (sign, fpos % 4, 1);
fclose (fres);
bfd_close (abfd);
return;
}
/* Read a resource entry, returns 0 when all resources are read */
static int
read_resource_entry (void)
read_resource_entry (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax)
{
struct res_id type;
struct res_id name;
struct res_res_info resinfo;
struct res_hdr reshdr;
long version;
rc_res_id type;
rc_res_id name;
rc_res_res_info resinfo;
res_hdr reshdr;
void *buff;
struct res_resource *r;
rc_res_resource *r;
struct bin_res_info l;
res_align_file ();
off[0] = (off[0] + 3) & ~3;
/* Read header */
if (fread (&reshdr, sizeof (reshdr), 1, fres) != 1)
if ((off[0] + 8) > omax)
return 0;
read_res_data_hdr (wrbfd, off, omax, &reshdr);
/* read resource type */
read_res_id (&type);
read_res_id (wrbfd, off, omax, &type);
/* read resource id */
read_res_id (&name);
read_res_id (wrbfd, off, omax, &name);
res_align_file ();
off[0] = (off[0] + 3) & ~3;
/* Read additional resource header */
read_res_data (&resinfo.version, sizeof (resinfo.version), 1);
read_res_data (&resinfo.memflags, sizeof (resinfo.memflags), 1);
read_res_data (&resinfo.language, sizeof (resinfo.language), 1);
read_res_data (&version, sizeof (version), 1);
read_res_data (&resinfo.characteristics, sizeof (resinfo.characteristics), 1);
read_res_data (wrbfd, off, omax, &l, BIN_RES_INFO_SIZE);
resinfo.version = windres_get_32 (wrbfd, l.version, 4);
resinfo.memflags = windres_get_16 (wrbfd, l.memflags, 2);
resinfo.language = windres_get_16 (wrbfd, l.language, 2);
/* resinfo.version2 = windres_get_32 (wrbfd, l.version2, 4); */
resinfo.characteristics = windres_get_32 (wrbfd, l.characteristics, 4);
res_align_file ();
off[0] = (off[0] + 3) & ~3;
/* Allocate buffer for data */
buff = res_alloc (reshdr.data_size);
/* Read data */
read_res_data (buff, reshdr.data_size, 1);
read_res_data (wrbfd, off, omax, buff, reshdr.data_size);
/* Convert binary data to resource */
r = bin_to_res (type, buff, reshdr.data_size, 0);
r = bin_to_res (wrbfd, type, buff, reshdr.data_size);
r->res_info = resinfo;
/* Add resource to resource directory */
res_add_resource (r, &type, &name, resinfo.language, 0);
@ -188,15 +215,12 @@ read_resource_entry (void)
}
/* write resource directory to binary resource file */
static void
write_res_directory (rd, type, name, language, level)
const struct res_directory *rd;
const struct res_id *type;
const struct res_id *name;
int *language;
int level;
static rc_uint_type
write_res_directory (windres_bfd *wrbfd, rc_uint_type off, const rc_res_directory *rd,
const rc_res_id *type, const rc_res_id *name, rc_uint_type *language,
int level)
{
const struct res_entry *re;
const rc_res_entry *re;
for (re = rd->entries; re != NULL; re = re->next)
{
@ -219,7 +243,7 @@ write_res_directory (rd, type, name, language, level)
case 3:
/* If we're at level 3, then this key represents a language.
Use it to update the current language. */
if (!re->id.named
if (! re->id.named
&& re->id.u.id != (unsigned long) *language
&& (re->id.u.id & 0xffff) == re->id.u.id)
{
@ -232,7 +256,8 @@ write_res_directory (rd, type, name, language, level)
}
if (re->subdir)
write_res_directory (re->u.dir, type, name, language, level + 1);
off = write_res_directory (wrbfd, off, re->u.dir, type, name, language,
level + 1);
else
{
if (level == 3)
@ -242,25 +267,25 @@ write_res_directory (rd, type, name, language, level)
2, and represents the name to use. We probably just
set LANGUAGE, and it will probably match what the
resource itself records if anything. */
write_res_resource (type, name, re->u.res, language);
off = write_res_resource (wrbfd, off, type, name, re->u.res,
language);
}
else
{
fprintf (stderr, "// Resource at unexpected level %d\n", level);
write_res_resource (type, (struct res_id *) NULL, re->u.res,
language);
off = write_res_resource (wrbfd, off, type, (rc_res_id *) NULL,
re->u.res, language);
}
}
}
return off;
}
static void
write_res_resource (type, name, res, language)
const struct res_id *type;
const struct res_id *name;
const struct res_resource *res;
int *language ATTRIBUTE_UNUSED;
static rc_uint_type
write_res_resource (windres_bfd *wrbfd, rc_uint_type off, const rc_res_id *type,
const rc_res_id *name, const rc_res_resource *res,
rc_uint_type *language ATTRIBUTE_UNUSED)
{
int rt;
@ -328,6 +353,10 @@ write_res_resource (type, name, res, language)
case RES_TYPE_VERSIONINFO:
rt = RT_VERSION;
break;
case RES_TYPE_TOOLBAR:
rt = RT_TOOLBAR;
break;
}
if (rt != 0
@ -340,35 +369,29 @@ write_res_resource (type, name, res, language)
abort ();
}
write_res_bin (res, type, name, &res->res_info);
return;
return write_res_bin (wrbfd, off, res, type, name, &res->res_info);
}
/* Write a resource in binary resource format */
static void
write_res_bin (res, type, name, resinfo)
const struct res_resource *res;
const struct res_id *type;
const struct res_id *name;
const struct res_res_info *resinfo;
static rc_uint_type
write_res_bin (windres_bfd *wrbfd, rc_uint_type off, const rc_res_resource *res,
const rc_res_id *type, const rc_res_id *name,
const rc_res_res_info *resinfo)
{
unsigned long datasize = 0;
const struct bindata *bin_rep, *data;
rc_uint_type noff;
rc_uint_type datasize = 0;
bin_rep = res_to_bin (res, 0);
for (data = bin_rep; data != NULL; data = data->next)
datasize += data->length;
noff = res_to_bin ((windres_bfd *) NULL, off, res);
datasize = noff - off;
write_res_header (datasize, type, name, resinfo);
for (data = bin_rep; data != NULL; data = data->next)
write_res_data (data->data, data->length, 1);
off = write_res_header (wrbfd, off, datasize, type, name, resinfo);
return res_to_bin (wrbfd, off, res);
}
/* Get number of bytes needed to store an id in binary format */
static unsigned long
get_id_size (id)
const struct res_id *id;
const rc_res_id *id;
{
if (id->named)
return sizeof (unichar) * (id->u.n.length + 1);
@ -377,108 +400,142 @@ get_id_size (id)
}
/* Write a resource header */
static void
write_res_header (datasize, type, name, resinfo)
unsigned long datasize;
const struct res_id *type;
const struct res_id *name;
const struct res_res_info *resinfo;
static rc_uint_type
write_res_header (windres_bfd *wrbfd, rc_uint_type off, rc_uint_type datasize,
const rc_res_id *type, const rc_res_id *name,
const rc_res_res_info *resinfo)
{
struct res_hdr reshdr;
res_hdr reshdr;
reshdr.data_size = datasize;
reshdr.header_size = 24 + get_id_size (type) + get_id_size (name);
reshdr.header_size = (reshdr.header_size + 3) & ~3;
res_align_file ();
write_res_data (&reshdr, sizeof (reshdr), 1);
write_res_id (type);
write_res_id (name);
off = (off + 3) & ~3;
res_align_file ();
off = write_res_data_hdr (wrbfd, off, &reshdr);
off = write_res_id (wrbfd, off, type);
off = write_res_id (wrbfd, off, name);
write_res_info (resinfo);
res_align_file ();
off = (off + 3) & ~3;
off = write_res_info (wrbfd, off, resinfo);
off = (off + 3) & ~3;
return off;
}
/* Write data to file, abort on failure */
static void
write_res_data (data, size, count)
const void *data;
size_t size;
int count;
static rc_uint_type
write_res_data_hdr (windres_bfd *wrbfd, rc_uint_type off, res_hdr *hdr)
{
if ((size_t) fwrite (data, size, count, fres) != (size_t) count)
fatal ("%s: could not write to file", filename);
if (wrbfd)
{
struct bin_res_hdr brh;
windres_put_32 (wrbfd, brh.data_size, hdr->data_size);
windres_put_32 (wrbfd, brh.header_size, hdr->header_size);
set_windres_bfd_content (wrbfd, &brh, off, BIN_RES_HDR_SIZE);
}
return off + BIN_RES_HDR_SIZE;
}
static void
read_res_data_hdr (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax,
res_hdr *reshdr)
{
struct bin_res_hdr brh;
if ((off[0] + BIN_RES_HDR_SIZE) > omax)
fatal ("%s: unexpected end of file %ld/%ld", filename,(long) off[0], (long) omax);
get_windres_bfd_content (wrbfd, &brh, off[0], BIN_RES_HDR_SIZE);
reshdr->data_size = windres_get_32 (wrbfd, brh.data_size, 4);
reshdr->header_size = windres_get_32 (wrbfd, brh.header_size, 4);
off[0] += BIN_RES_HDR_SIZE;
}
/* Read data from file, abort on failure */
static void
read_res_data (data, size, count)
void *data;
size_t size;
int count;
read_res_data (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax, void *data,
rc_uint_type size)
{
if (fread (data, size, count, fres) != (size_t) count)
fatal ("%s: unexpected end of file", filename);
if ((off[0] + size) > omax)
fatal ("%s: unexpected end of file %ld/%ld %ld", filename,(long) off[0],
(long) omax, (long) size);
get_windres_bfd_content (wrbfd, data, off[0], size);
off[0] += size;
}
/* Write a resource id */
static void
write_res_id (id)
const struct res_id *id;
static rc_uint_type
write_res_id (windres_bfd *wrbfd, rc_uint_type off, const rc_res_id *id)
{
if (id->named)
{
unsigned long len = id->u.n.length;
unichar null_term = 0;
write_res_data (id->u.n.name, len * sizeof (unichar), 1);
write_res_data (&null_term, sizeof (null_term), 1);
rc_uint_type len = (((bfd_signed_vma) id->u.n.length < 0 ? 0 : id->u.n.length) + 1);
if (wrbfd)
{
rc_uint_type i;
bfd_byte *d = (bfd_byte *) xmalloc (len * sizeof (unichar));
for (i = 0; i < (len - 1); i++)
windres_put_16 (wrbfd, d + (i * sizeof (unichar)), id->u.n.name[i]);
windres_put_16 (wrbfd, d + (i * sizeof (unichar)), 0);
set_windres_bfd_content (wrbfd, d, off, (len * sizeof (unichar)));
}
off += (len * sizeof (unichar));
}
else
{
unsigned short i = 0xFFFF;
write_res_data (&i, sizeof (i), 1);
i = id->u.id;
write_res_data (&i, sizeof (i), 1);
if (wrbfd)
{
struct bin_res_id bid;
windres_put_16 (wrbfd, bid.sig, 0xffff);
windres_put_16 (wrbfd, bid.id, id->u.id);
set_windres_bfd_content (wrbfd, &bid, off, BIN_RES_ID);
}
off += BIN_RES_ID;
}
return off;
}
/* Write resource info */
static void
write_res_info (info)
const struct res_res_info *info;
static rc_uint_type
write_res_info (windres_bfd *wrbfd, rc_uint_type off, const rc_res_res_info *info)
{
write_res_data (&info->version, sizeof (info->version), 1);
write_res_data (&info->memflags, sizeof (info->memflags), 1);
write_res_data (&info->language, sizeof (info->language), 1);
write_res_data (&info->version, sizeof (info->version), 1);
write_res_data (&info->characteristics, sizeof (info->characteristics), 1);
if (wrbfd)
{
struct bin_res_info l;
windres_put_32 (wrbfd, l.version, info->version);
windres_put_16 (wrbfd, l.memflags, info->memflags);
windres_put_16 (wrbfd, l.language, info->language);
windres_put_32 (wrbfd, l.version2, info->version);
windres_put_32 (wrbfd, l.characteristics, info->characteristics);
set_windres_bfd_content (wrbfd, &l, off, BIN_RES_INFO_SIZE);
}
return off + BIN_RES_INFO_SIZE;
}
/* read a resource identifier */
void
read_res_id (id)
struct res_id *id;
static void
read_res_id (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax, rc_res_id *id)
{
struct bin_res_id bid;
unsigned short ord;
unichar *id_s = NULL;
int len;
rc_uint_type len;
read_res_data (&ord, sizeof (ord), 1);
read_res_data (wrbfd, off, omax, &bid, BIN_RES_ID - 2);
ord = (unsigned short) windres_get_16 (wrbfd, bid.sig, 2);
if (ord == 0xFFFF) /* an ordinal id */
{
read_res_data (&ord, sizeof (ord), 1);
read_res_data (wrbfd, off, omax, bid.id, BIN_RES_ID - 2);
id->named = 0;
id->u.id = ord;
id->u.id = windres_get_16 (wrbfd, bid.id, 2);
}
else
/* named id */
{
if (fseek (fres, -sizeof (ord), SEEK_CUR) != 0)
fatal ("%s: %s: could not seek in file", program_name, filename);
id_s = read_unistring (&len);
off[0] -= 2;
id_s = read_unistring (wrbfd, off, omax, &len);
id->named = 1;
id->u.n.length = len;
id->u.n.name = id_s;
@ -487,39 +544,57 @@ read_res_id (id)
/* Read a null terminated UNICODE string */
static unichar *
read_unistring (len)
int *len;
read_unistring (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax,
rc_uint_type *len)
{
unichar *s;
bfd_byte d[2];
unichar c;
unichar *p;
int l;
rc_uint_type l;
rc_uint_type soff = off[0];
*len = 0;
l = 0;
do {
read_res_data (wrbfd, &soff, omax, d, sizeof (unichar));
c = windres_get_16 (wrbfd, d, 2);
} while (c != 0);
l = ((soff - off[0]) / sizeof (unichar));
/* there are hardly any names longer than 256 characters */
p = s = (unichar *) xmalloc (sizeof (unichar) * 256);
/* there are hardly any names longer than 256 characters, but anyway. */
p = s = (unichar *) xmalloc (sizeof (unichar) * l);
do
{
read_res_data (&c, sizeof (c), 1);
read_res_data (wrbfd, off, omax, d, sizeof (unichar));
c = windres_get_16 (wrbfd, d, 2);
*p++ = c;
if (c != 0)
l++;
}
while (c != 0);
*len = l;
*len = l - 1;
return s;
}
/* align file on DWORD boundary */
static void
res_align_file (void)
static int
probe_binary (windres_bfd *wrbfd, rc_uint_type omax)
{
int pos = ftell (fres);
int skip = ((pos + 3) & ~3) - pos;
if (fseek (fres, skip, SEEK_CUR) != 0)
fatal ("%s: %s: unable to align file", program_name, filename);
rc_uint_type off;
res_hdr reshdr;
off = 0;
read_res_data_hdr (wrbfd, &off, omax, &reshdr);
if (reshdr.data_size != 0)
return 1;
if ((reshdr.header_size != 0x20 && ! target_is_bigendian)
|| (reshdr.header_size != 0x20000000 && target_is_bigendian))
return 1;
/* Subtract size of HeaderSize. DataSize has to be zero. */
off += 0x20 - BIN_RES_HDR_SIZE;
if ((off + BIN_RES_HDR_SIZE) >= omax)
return 1;
read_res_data_hdr (wrbfd, &off, omax, &reshdr);
if ((off + reshdr.data_size + reshdr.header_size) > omax)
return 0;
return 1;
}
/* Check if file is a win32 binary resource file, if so
@ -527,16 +602,19 @@ res_align_file (void)
error.
*/
static void
skip_null_resource (void)
skip_null_resource (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax)
{
struct res_hdr reshdr =
{0, 0};
read_res_data (&reshdr, sizeof (reshdr), 1);
if ((reshdr.data_size != 0) || (reshdr.header_size != 0x20))
res_hdr reshdr;
read_res_data_hdr (wrbfd, off, omax, &reshdr);
if (reshdr.data_size != 0)
goto skip_err;
if ((reshdr.header_size != 0x20 && ! target_is_bigendian)
|| (reshdr.header_size != 0x20000000 && target_is_bigendian))
goto skip_err;
/* Subtract size of HeaderSize and DataSize */
if (fseek (fres, reshdr.header_size - 8, SEEK_CUR) != 0)
/* Subtract size of HeaderSize. DataSize has to be zero. */
off[0] += 0x20 - BIN_RES_HDR_SIZE;
if (off[0] >= omax)
goto skip_err;
return;
@ -548,15 +626,11 @@ skip_err:
}
/* Add a resource to resource directory */
void
res_add_resource (r, type, id, language, dupok)
struct res_resource *r;
const struct res_id *type;
const struct res_id *id;
int language;
int dupok;
static void
res_add_resource (rc_res_resource *r, const rc_res_id *type, const rc_res_id *id,
rc_uint_type language, int dupok)
{
struct res_id a[3];
rc_res_id a[3];
a[0] = *type;
a[1] = *id;
@ -569,21 +643,17 @@ res_add_resource (r, type, id, language, dupok)
This is just copied from define_resource
and modified to add an existing resource.
*/
void
res_append_resource (resources, resource, cids, ids, dupok)
struct res_directory **resources;
struct res_resource *resource;
int cids;
const struct res_id *ids;
int dupok;
static void
res_append_resource (rc_res_directory **resources, rc_res_resource *resource,
int cids, const rc_res_id *ids, int dupok)
{
struct res_entry *re = NULL;
rc_res_entry *re = NULL;
int i;
assert (cids > 0);
for (i = 0; i < cids; i++)
{
struct res_entry **pp;
rc_res_entry **pp;
if (*resources == NULL)
{
@ -594,8 +664,8 @@ res_append_resource (resources, resource, cids, ids, dupok)
if (timeval == 0)
timeval = time (NULL);
*resources = ((struct res_directory *)
res_alloc (sizeof **resources));
*resources = ((rc_res_directory *)
res_alloc (sizeof (rc_res_directory)));
(*resources)->characteristics = 0;
(*resources)->time = timeval;
(*resources)->major = 0;
@ -611,7 +681,7 @@ res_append_resource (resources, resource, cids, ids, dupok)
re = *pp;
else
{
re = (struct res_entry *) res_alloc (sizeof *re);
re = (rc_res_entry *) res_alloc (sizeof (rc_res_entry));
re->next = NULL;
re->id = ids[i];
if ((i + 1) < cids)
@ -630,7 +700,7 @@ res_append_resource (resources, resource, cids, ids, dupok)
if ((i + 1) < cids)
{
if (!re->subdir)
if (! re->subdir)
{
fprintf (stderr, "%s: ", program_name);
res_ids_print (stderr, i, ids);

View File

@ -1,3 +1,18 @@
2007-05-23 Kai Tietz <Kai.Tietz@onevision.com>
* binutils-all/windres/html.rc: New.
* binutils-all/windres/html.rsd: New.
* binutils-all/windres/html1.hm: New.
* binutils-all/windres/html2.hm: New.
* binutils-all/windres/messagetable.rc: New.
* binutils-all/windres/messagetable.rsd: New.
* binutils-all/windres/MSG00001.bin: New.
* binutils-all/windres/strtab2.rc: New.
* binutils-all/windres/strtab2.rsd: New.
* binutils-all/windres/version.rc: New.
* binutils-all/windres/version.rsd: New.
* binutils-all/windres/dialog.rsd: Fix expected results.
2007-05-17 Joseph Myers <joseph@codesourcery.com>
* binutils-all/strip-3.d: Strip .pdr section.

Binary file not shown.

View File

@ -9,10 +9,10 @@ Contents of section .data:
0040 0100ffff 00000000 00000000 00008880 ................
0050 02000000 0000c800 c8000000 00000000 ................
0060 00000000 00000000 4d000050 0b000b00 ........M..P....
0070 5300a200 ffff0000 63006c00 61007300 S.......c.l.a.s.
0080 73006e00 61006d00 65000000 ffff6c00 s.n.a.m.e.....l.
0070 5300a200 ffffffff 43004c00 41005300 S.......C.L.A.S.
0080 53004e00 41004d00 45000000 ffff6c00 S.N.A.M.E.....l.
0090 00000000 00000000 00000000 0e120050 ...............P
00a0 05000500 0a000a00 66000000 63006c00 ........f...c.l.
00b0 61007300 73006e00 61006d00 65000000 a.s.s.n.a.m.e...
00a0 05000500 0a000a00 66000000 43004c00 ........f...C.L.
00b0 41005300 53004e00 41004d00 45000000 A.S.S.N.A.M.E...
00c0 73007400 72006900 6e006700 69006400 s.t.r.i.n.g.i.d.
00d0 00000000 ....

View File

@ -0,0 +1,7 @@
//#xfail x86_64-*-mingw*
#include "windows.h"
LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
129 HTML "html1.hm"
130 HTML "html2.hm"

View File

@ -0,0 +1,45 @@
html.res: file format binary
Contents of section .data:
0000 00000000 20000000 ffff0000 ffff0000 .... ...........
0010 00000000 00000000 00000000 00000000 ................
0020 0d010000 20000000 ffff1700 ffff8100 .... ...........
0030 00000000 30100704 00000000 00000000 ....0...........
0040 3c21444f 43545950 4520646f 63747970 <!DOCTYPE doctyp
0050 65205055 424c4943 20222d2f 2f773363 e PUBLIC "-//w3c
0060 2f2f6474 64206874 6d6c2034 2e302074 //dtd html 4.0 t
0070 72616e73 6974696f 6e616c2f 2f656e22 ransitional//en"
0080 3e0d0a3c 68746d6c 3e0d0a3c 68656164 >..<html>..<head
0090 3e0d0a20 203c6d65 74612063 6f6e7465 >.. <meta conte
00a0 6e743d22 74657874 2f68746d 6c3b2063 nt="text/html; c
00b0 68617273 65743d69 736f2d38 3835392d harset=iso-8859-
00c0 31222020 68747470 2d657175 69763d22 1" http-equiv="
00d0 436f6e74 656e742d 54797065 223e0d0a Content-Type">..
00e0 20203c74 69746c65 3e57696e 64726573 <title>Windres
00f0 3c2f7469 746c653e 0d0a3c2f 68656164 </title>..</head
0100 3e0d0a0d 0a3c626f 64793e0d 0a546869 >....<body>..Thi
0110 73206973 20612074 65737420 70616765 s is a test page
0120 20666f72 2077696e 64726573 2048544d for windres HTM
0130 4c207265 736f7572 63652e0d 0a3c2f62 L resource...</b
0140 6f64793e 0d0a3c2f 68746d6c 3e000000 ody>..</html>...
0150 14010000 20000000 ffff1700 ffff8200 .... ...........
0160 00000000 30100704 00000000 00000000 ....0...........
0170 3c21444f 43545950 4520646f 63747970 <!DOCTYPE doctyp
0180 65205055 424c4943 20222d2f 2f773363 e PUBLIC "-//w3c
0190 2f2f6474 64206874 6d6c2034 2e302074 //dtd html 4.0 t
01a0 72616e73 6974696f 6e616c2f 2f656e22 ransitional//en"
01b0 3e0d0a3c 68746d6c 3e0d0a3c 68656164 >..<html>..<head
01c0 3e0d0a20 203c6d65 74612063 6f6e7465 >.. <meta conte
01d0 6e743d22 74657874 2f68746d 6c3b2063 nt="text/html; c
01e0 68617273 65743d69 736f2d38 3835392d harset=iso-8859-
01f0 31222020 68747470 2d657175 69763d22 1" http-equiv="
0200 436f6e74 656e742d 54797065 223e0d0a Content-Type">..
0210 20203c74 69746c65 3e57696e 64726573 <title>Windres
0220 3c2f7469 746c653e 0d0a3c2f 68656164 </title>..</head
0230 3e0d0a0d 0a3c626f 64793e0d 0a546869 >....<body>..Thi
0240 73206973 20612073 65636f6e 64207465 s is a second te
0250 73742070 61676520 666f7220 77696e64 st page for wind
0260 72657320 48544d4c 20726573 6f757263 res HTML resourc
0270 652e0d0a 3c2f626f 64793e0d 0a3c2f68 e...</body>..</h
0280 746d6c3e tml>

View File

@ -0,0 +1,11 @@
<!DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type">
<title>Windres</title>
</head>
<body>
This is a test page for windres HTML resource.
</body>
</html>

View File

@ -0,0 +1,11 @@
<!DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type">
<title>Windres</title>
</head>
<body>
This is a second test page for windres HTML resource.
</body>
</html>

View File

@ -0,0 +1,6 @@
//#xfail x86_64-*-mingw*
#include "windows.h"
LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
888 MESSAGETABLE MSG00001.bin

View File

@ -0,0 +1,15 @@
messagetable.res: file format binary
Contents of section .data:
0000 00000000 20000000 ffff0000 ffff0000 .... ...........
0010 00000000 00000000 00000000 00000000 ................
0020 70000000 20000000 ffff0b00 ffff7803 p... .........x.
0030 00000000 30100704 00000000 00000000 ....0...........
0040 01000000 00000000 05000000 10000000 ................
0050 14000000 4e6f7469 63653a20 25310d0a ....Notice: %1..
0060 00000000 0c000000 25310d0a 00000000 ........%1......
0070 10000000 5761726e 3a202531 0d0a0000 ....Warn: %1....
0080 10000000 4572726f 723a2025 310d0a00 ....Error: %1...
0090 10000000 46617461 6c3a2025 310d0a00 ....Fatal: %1...
00a0 10000000 25310d0a 25320d0a 00000000 ....%1..%2......

View File

@ -0,0 +1,9 @@
//#xfail x86_64-*-mingw*
#include "windows.h"
LANGUAGE 0, 0
STRINGTABLE MOVEABLE PURE DISCARDABLE
BEGIN
1 L"hello, world"
END

View File

@ -0,0 +1,8 @@
0000 00000000 20000000 ffff0000 ffff0000 .... ...........
0010 00000000 00000000 00000000 00000000 ................
0020 38000000 20000000 ffff0600 ffff0100 8... ...........
0030 00000000 30100000 00000000 00000000 ....0...........
0040 00000c00 68006500 6c006c00 6f002c00 ....h.e.l.l.o.,.
0050 20007700 6f007200 6c006400 00000000 .w.o.r.l.d.....
0060 00000000 00000000 00000000 00000000 ................
0070 00000000 00000000 ........

View File

@ -0,0 +1,33 @@
//#xfail x86_64-*-mingw*
#include "windows.h"
LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x3fL
FILEFLAGS 0x0L
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040704e4"
BEGIN
VALUE L"CompanyName", L"binutil\x0073"
VALUE "FileDescription", "RC compiler."
VALUE "FileVersion", "1.0.0.1"
VALUE "InternalName", "windres.exe"
VALUE "LegalCopyright", "(c) FSF. All rights are reserved."
VALUE "OriginalFilename", "windres.exe"
VALUE "ProductName", "windows resource compiler"
VALUE "ProductVersion", "1.0.0.1"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x407, 1252
END
END

View File

@ -0,0 +1,55 @@
version.res: file format binary
Contents of section .data:
0000 00000000 20000000 ffff0000 ffff0000 .... ...........
0010 00000000 00000000 00000000 00000000 ................
0020 ec020000 20000000 ffff1000 ffff0100 .... ...........
0030 00000000 00000704 00000000 00000000 ................
0040 ec023400 00005600 53005f00 56004500 ..4...V.S._.V.E.
0050 52005300 49004f00 4e005f00 49004e00 R.S.I.O.N._.I.N.
0060 46004f00 00000000 bd04effe 00000100 F.O.............
0070 00000100 01000000 00000100 01000000 ................
0080 3f000000 00000000 04000000 01000000 ?...............
0090 00000000 00000000 00000000 4c020000 ............L...
00a0 00005300 74007200 69006e00 67004600 ..S.t.r.i.n.g.F.
00b0 69006c00 65004900 6e006600 6f000000 i.l.e.I.n.f.o...
00c0 28020000 00003000 34003000 37003000 (.....0.4.0.7.0.
00d0 34006500 34000000 32000900 01004300 4.e.4...2.....C.
00e0 6f006d00 70006100 6e007900 4e006100 o.m.p.a.n.y.N.a.
00f0 6d006500 00000000 62006900 6e007500 m.e.....b.i.n.u.
0100 74006900 6c007300 00000000 42000d00 t.i.l.s.....B...
0110 01004600 69006c00 65004400 65007300 ..F.i.l.e.D.e.s.
0120 63007200 69007000 74006900 6f006e00 c.r.i.p.t.i.o.n.
0130 00000000 52004300 20006300 6f006d00 ....R.C. .c.o.m.
0140 70006900 6c006500 72002e00 00000000 p.i.l.e.r.......
0150 30000800 01004600 69006c00 65005600 0.....F.i.l.e.V.
0160 65007200 73006900 6f006e00 00000000 e.r.s.i.o.n.....
0170 31002e00 30002e00 30002e00 31000000 1...0...0...1...
0180 38000c00 01004900 6e007400 65007200 8.....I.n.t.e.r.
0190 6e006100 6c004e00 61006d00 65000000 n.a.l.N.a.m.e...
01a0 77006900 6e006400 72006500 73002e00 w.i.n.d.r.e.s...
01b0 65007800 65000000 68002200 01004c00 e.x.e...h."...L.
01c0 65006700 61006c00 43006f00 70007900 e.g.a.l.C.o.p.y.
01d0 72006900 67006800 74000000 28006300 r.i.g.h.t...(.c.
01e0 29002000 46005300 46002e00 20004100 ). .F.S.F... .A.
01f0 6c006c00 20007200 69006700 68007400 l.l. .r.i.g.h.t.
0200 73002000 61007200 65002000 72006500 s. .a.r.e. .r.e.
0210 73006500 72007600 65006400 2e000000 s.e.r.v.e.d.....
0220 40000c00 01004f00 72006900 67006900 @.....O.r.i.g.i.
0230 6e006100 6c004600 69006c00 65006e00 n.a.l.F.i.l.e.n.
0240 61006d00 65000000 77006900 6e006400 a.m.e...w.i.n.d.
0250 72006500 73002e00 65007800 65000000 r.e.s...e.x.e...
0260 54001a00 01005000 72006f00 64007500 T.....P.r.o.d.u.
0270 63007400 4e006100 6d006500 00000000 c.t.N.a.m.e.....
0280 77006900 6e006400 6f007700 73002000 w.i.n.d.o.w.s. .
0290 72006500 73006f00 75007200 63006500 r.e.s.o.u.r.c.e.
02a0 20006300 6f006d00 70006900 6c006500 .c.o.m.p.i.l.e.
02b0 72000000 34000800 01005000 72006f00 r...4.....P.r.o.
02c0 64007500 63007400 56006500 72007300 d.u.c.t.V.e.r.s.
02d0 69006f00 6e000000 31002e00 30002e00 i.o.n...1...0...
02e0 30002e00 31000000 44000000 00005600 0...1...D.....V.
02f0 61007200 46006900 6c006500 49006e00 a.r.F.i.l.e.I.n.
0300 66006f00 00000000 24000400 00005400 f.o.....$.....T.
0310 72006100 6e007300 6c006100 74006900 r.a.n.s.l.a.t.i.
0320 6f006e00 00000000 0704e404 o.n.........

1088
binutils/windint.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
Rewritten by Kai Tietz, Onevision.
This file is part of GNU Binutils.
@ -39,16 +40,26 @@
#include <time.h>
#include "bfd.h"
#include "getopt.h"
#include "bucomm.h"
#include "libiberty.h"
#include "safe-ctype.h"
#include "obstack.h"
#include "bucomm.h"
#include "windres.h"
/* Defined in bfd/binary.c. Used to set architecture and machine of input
binary files. */
extern enum bfd_architecture bfd_external_binary_architecture;
extern unsigned long bfd_external_machine;
/* Used by resrc.c at least. */
int verbose = 0;
int target_is_bigendian = 0;
const char *def_target_arch;
static void set_endianess (bfd *, const char *);
/* An enumeration of format types. */
enum res_format
@ -106,14 +117,22 @@ static struct include_dir *include_dirs;
/* Static functions. */
static void res_init (void);
static int extended_menuitems (const struct menuitem *);
static int extended_menuitems (const rc_menuitem *);
static enum res_format format_from_name (const char *, int);
static enum res_format format_from_filename (const char *, int);
static void usage (FILE *, int);
static int cmp_res_entry (const void *, const void *);
static struct res_directory *sort_resources (struct res_directory *);
static rc_res_directory *sort_resources (rc_res_directory *);
static void reswr_init (void);
static const char * quot (const char *);
static rc_uint_type target_get_8 (const void *, rc_uint_type);
static void target_put_8 (void *, rc_uint_type);
static rc_uint_type target_get_16 (const void *, rc_uint_type);
static void target_put_16 (void *, rc_uint_type);
static rc_uint_type target_get_32 (const void *, rc_uint_type);
static void target_put_32 (void *, rc_uint_type);
/* When we are building a resource tree, we allocate everything onto
an obstack, so that we can free it all at once if we want. */
@ -136,9 +155,9 @@ res_init (void)
/* Allocate space on the resource building obstack. */
void *
res_alloc (size_t bytes)
res_alloc (rc_uint_type bytes)
{
return (void *) obstack_alloc (&res_obstack, bytes);
return (void *) obstack_alloc (&res_obstack, (size_t) bytes);
}
/* We also use an obstack to save memory used while writing out a set
@ -157,9 +176,9 @@ reswr_init (void)
/* Allocate space on the resource writing obstack. */
void *
reswr_alloc (size_t bytes)
reswr_alloc (rc_uint_type bytes)
{
return (void *) obstack_alloc (&reswr_obstack, bytes);
return (void *) obstack_alloc (&reswr_obstack, (size_t) bytes);
}
/* Open a file using the include directory search list. */
@ -209,7 +228,7 @@ open_file_search (const char *filename, const char *mode, const char *errmsg,
section. */
int
res_id_cmp (struct res_id a, struct res_id b)
res_id_cmp (rc_res_id a, rc_res_id b)
{
if (! a.named)
{
@ -257,24 +276,23 @@ res_id_cmp (struct res_id a, struct res_id b)
/* Print a resource ID. */
void
res_id_print (FILE *stream, struct res_id id, int quote)
res_id_print (FILE *stream, rc_res_id id, int quote)
{
if (! id.named)
fprintf (stream, "%lu", id.u.id);
fprintf (stream, "%u", (int) id.u.id);
else
{
if (quote)
putc ('"', stream);
unicode_print_quoted (stream, id.u.n.name, id.u.n.length);
else
unicode_print (stream, id.u.n.name, id.u.n.length);
if (quote)
putc ('"', stream);
}
}
/* Print a list of resource ID's. */
void
res_ids_print (FILE *stream, int cids, const struct res_id *ids)
res_ids_print (FILE *stream, int cids, const rc_res_id *ids)
{
int i;
@ -289,43 +307,52 @@ res_ids_print (FILE *stream, int cids, const struct res_id *ids)
/* Convert an ASCII string to a resource ID. */
void
res_string_to_id (struct res_id *res_id, const char *string)
res_string_to_id (rc_res_id *res_id, const char *string)
{
res_id->named = 1;
unicode_from_ascii (&res_id->u.n.length, &res_id->u.n.name, string);
}
/* Convert an unicode string to a resource ID. */
void
res_unistring_to_id (rc_res_id *res_id, const unichar *u)
{
res_id->named = 1;
res_id->u.n.length = unichar_len (u);
res_id->u.n.name = unichar_dup_uppercase (u);
}
/* Define a resource. The arguments are the resource tree, RESOURCES,
and the location at which to put it in the tree, CIDS and IDS.
This returns a newly allocated res_resource structure, which the
This returns a newly allocated rc_res_resource structure, which the
caller is expected to initialize. If DUPOK is non-zero, then if a
resource with this ID exists, it is returned. Otherwise, a warning
is issued, and a new resource is created replacing the existing
one. */
struct res_resource *
define_resource (struct res_directory **resources, int cids,
const struct res_id *ids, int dupok)
rc_res_resource *
define_resource (rc_res_directory **resources, int cids,
const rc_res_id *ids, int dupok)
{
struct res_entry *re = NULL;
rc_res_entry *re = NULL;
int i;
assert (cids > 0);
for (i = 0; i < cids; i++)
{
struct res_entry **pp;
rc_res_entry **pp;
if (*resources == NULL)
{
static unsigned long timeval;
static unsigned int timeval;
/* Use the same timestamp for every resource created in a
single run. */
if (timeval == 0)
timeval = time (NULL);
*resources = ((struct res_directory *)
res_alloc (sizeof **resources));
*resources = ((rc_res_directory *)
res_alloc (sizeof (rc_res_directory)));
(*resources)->characteristics = 0;
(*resources)->time = timeval;
(*resources)->major = 0;
@ -341,7 +368,7 @@ define_resource (struct res_directory **resources, int cids,
re = *pp;
else
{
re = (struct res_entry *) res_alloc (sizeof *re);
re = (rc_res_entry *) res_alloc (sizeof (rc_res_entry));
re->next = NULL;
re->id = ids[i];
if ((i + 1) < cids)
@ -390,9 +417,9 @@ define_resource (struct res_directory **resources, int cids,
fprintf (stderr, _(": duplicate value\n"));
}
re->u.res = ((struct res_resource *)
res_alloc (sizeof (struct res_resource)));
memset (re->u.res, 0, sizeof (struct res_resource));
re->u.res = ((rc_res_resource *)
res_alloc (sizeof (rc_res_resource)));
memset (re->u.res, 0, sizeof (rc_res_resource));
re->u.res->type = RES_TYPE_UNINITIALIZED;
return re->u.res;
@ -401,11 +428,11 @@ define_resource (struct res_directory **resources, int cids,
/* Define a standard resource. This is a version of define_resource
that just takes type, name, and language arguments. */
struct res_resource *
define_standard_resource (struct res_directory **resources, int type,
struct res_id name, int language, int dupok)
rc_res_resource *
define_standard_resource (rc_res_directory **resources, int type,
rc_res_id name, rc_uint_type language, int dupok)
{
struct res_id a[3];
rc_res_id a[3];
a[0].named = 0;
a[0].u.id = type;
@ -420,21 +447,21 @@ define_standard_resource (struct res_directory **resources, int type,
static int
cmp_res_entry (const void *p1, const void *p2)
{
const struct res_entry **re1, **re2;
const rc_res_entry **re1, **re2;
re1 = (const struct res_entry **) p1;
re2 = (const struct res_entry **) p2;
re1 = (const rc_res_entry **) p1;
re2 = (const rc_res_entry **) p2;
return res_id_cmp ((*re1)->id, (*re2)->id);
}
/* Sort the resources. */
static struct res_directory *
sort_resources (struct res_directory *resdir)
static rc_res_directory *
sort_resources (rc_res_directory *resdir)
{
int c, i;
struct res_entry *re;
struct res_entry **a;
rc_res_entry *re;
rc_res_entry **a;
if (resdir->entries == NULL)
return resdir;
@ -445,12 +472,12 @@ sort_resources (struct res_directory *resdir)
/* This is a recursive routine, so using xmalloc is probably better
than alloca. */
a = (struct res_entry **) xmalloc (c * sizeof (struct res_entry *));
a = (rc_res_entry **) xmalloc (c * sizeof (rc_res_entry *));
for (i = 0, re = resdir->entries; re != NULL; re = re->next, i++)
a[i] = re;
qsort (a, c, sizeof (struct res_entry *), cmp_res_entry);
qsort (a, c, sizeof (rc_res_entry *), cmp_res_entry);
resdir->entries = a[0];
for (i = 0; i < c - 1; i++)
@ -472,9 +499,9 @@ sort_resources (struct res_directory *resdir)
DIALOGEX. */
int
extended_dialog (const struct dialog *dialog)
extended_dialog (const rc_dialog *dialog)
{
const struct dialog_control *c;
const rc_dialog_control *c;
if (dialog->ex != NULL)
return 1;
@ -489,15 +516,15 @@ extended_dialog (const struct dialog *dialog)
/* Return whether MENUITEMS are a MENU or a MENUEX. */
int
extended_menu (const struct menu *menu)
extended_menu (const rc_menu *menu)
{
return extended_menuitems (menu->items);
}
static int
extended_menuitems (const struct menuitem *menuitems)
extended_menuitems (const rc_menuitem *menuitems)
{
const struct menuitem *mi;
const rc_menuitem *mi;
for (mi = menuitems; mi != NULL; mi = mi->next)
{
@ -556,7 +583,7 @@ format_from_filename (const char *filename, int input)
{
const char *ext;
FILE *e;
unsigned char b1, b2, b3, b4, b5;
bfd_byte b1, b2, b3, b4, b5;
int magic;
/* If we have an extension, see if we recognize it as implying a
@ -683,7 +710,7 @@ quot (const char *string)
const char *src;
char *dest;
if ((buflen < slen * 2 + 2) || !buf)
if ((buflen < slen * 2 + 2) || ! buf)
{
buflen = slen * 2 + 2;
if (buf)
@ -750,7 +777,7 @@ main (int argc, char **argv)
char *preprocargs;
const char *quotedarg;
int language;
struct res_directory *resources;
rc_res_directory *resources;
int use_temp_file;
#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
@ -860,7 +887,8 @@ main (int argc, char **argv)
input_format_tmp = format_from_name (optarg, 0);
if (input_format_tmp != RES_FORMAT_UNKNOWN)
{
fprintf (stderr, _("Option -I is deprecated for setting the input format, please use -J instead.\n"));
fprintf (stderr,
_("Option -I is deprecated for setting the input format, please use -J instead.\n"));
input_format = input_format_tmp;
break;
}
@ -960,6 +988,8 @@ main (int argc, char **argv)
output_format = format_from_filename (output_filename, 0);
}
set_endianess (NULL, target);
/* Read the input file. */
switch (input_format)
{
@ -1005,3 +1035,339 @@ main (int argc, char **argv)
xexit (0);
return 0;
}
static void set_endianess (bfd *abfd, const char *target)
{
const bfd_target *target_vec;
def_target_arch = NULL;
target_vec = bfd_find_target (target, abfd);
if (! target_vec)
fatal ("Can't detect target endianess and architecture.");
target_is_bigendian = ((target_vec->byteorder == BFD_ENDIAN_BIG) ? 1 : 0);
{
const char *tname = target_vec->name;
const char **arch = bfd_arch_list();
if (arch && tname)
{
if (strchr (tname, '-') != NULL)
tname = strchr (tname, '-') + 1;
while (*arch != NULL)
{
const char *in_a = strstr (*arch, tname);
char end_ch = (in_a ? in_a[strlen(tname)] : 0);
if (in_a && (in_a == *arch || in_a[-1] == ':')
&& end_ch == 0)
{
def_target_arch = *arch;
break;
}
arch++;
}
}
if (! def_target_arch)
fatal ("Can't detect architecture.");
}
}
bfd *
windres_open_as_binary (const char *filename, int rdmode)
{
bfd *abfd;
abfd = (rdmode ? bfd_openr (filename, "binary") : bfd_openw (filename, "binary"));
if (! abfd)
fatal ("can't open `%s' for %s", filename, (rdmode ? "input" : "output"));
if (rdmode && ! bfd_check_format (abfd, bfd_object))
fatal ("can't open `%s' for input.", filename);
return abfd;
}
void
set_windres_bfd_endianess (windres_bfd *wrbfd, int is_bigendian)
{
assert (!! wrbfd);
switch (WR_KIND(wrbfd))
{
case WR_KIND_BFD_BIN_L:
if (is_bigendian)
WR_KIND(wrbfd) = WR_KIND_BFD_BIN_B;
break;
case WR_KIND_BFD_BIN_B:
if (! is_bigendian)
WR_KIND(wrbfd) = WR_KIND_BFD_BIN_L;
break;
default:
/* only binary bfd can be overriden. */
abort ();
}
}
void
set_windres_bfd (windres_bfd *wrbfd, bfd *abfd, asection *sec, rc_uint_type kind)
{
assert (!! wrbfd);
switch (kind)
{
case WR_KIND_TARGET:
abfd = NULL;
sec = NULL;
break;
case WR_KIND_BFD:
case WR_KIND_BFD_BIN_L:
case WR_KIND_BFD_BIN_B:
assert (!! abfd);
assert (!!sec);
break;
default:
abort ();
}
WR_KIND(wrbfd) = kind;
WR_BFD(wrbfd) = abfd;
WR_SECTION(wrbfd) = sec;
}
void
set_windres_bfd_content(windres_bfd *wrbfd, const void *data, rc_uint_type off,
rc_uint_type length)
{
if (WR_KIND(wrbfd) != WR_KIND_TARGET)
{
if (! bfd_set_section_contents (WR_BFD(wrbfd), WR_SECTION(wrbfd), data, off, length))
bfd_fatal ("bfd_set_section_contents");
}
else
abort ();
}
void
get_windres_bfd_content(windres_bfd *wrbfd, void *data, rc_uint_type off,
rc_uint_type length)
{
if (WR_KIND(wrbfd) != WR_KIND_TARGET)
{
if (! bfd_get_section_contents (WR_BFD(wrbfd), WR_SECTION(wrbfd), data, off, length))
bfd_fatal ("bfd_get_section_contents");
}
else
abort ();
}
void
windres_put_8 (windres_bfd *wrbfd, void *p, rc_uint_type value)
{
switch (WR_KIND(wrbfd))
{
case WR_KIND_TARGET:
target_put_8 (p, value);
break;
case WR_KIND_BFD:
case WR_KIND_BFD_BIN_L:
case WR_KIND_BFD_BIN_B:
bfd_put_8 (WR_BFD(wrbfd), value, p);
break;
default:
abort ();
}
}
void
windres_put_16 (windres_bfd *wrbfd, void *data, rc_uint_type value)
{
switch (WR_KIND(wrbfd))
{
case WR_KIND_TARGET:
target_put_16 (data, value);
break;
case WR_KIND_BFD:
case WR_KIND_BFD_BIN_B:
bfd_put_16 (WR_BFD(wrbfd), value, data);
break;
case WR_KIND_BFD_BIN_L:
bfd_putl16 (value, data);
break;
default:
abort ();
}
}
void
windres_put_32 (windres_bfd *wrbfd, void *data, rc_uint_type value)
{
switch (WR_KIND(wrbfd))
{
case WR_KIND_TARGET:
target_put_32 (data, value);
break;
case WR_KIND_BFD:
case WR_KIND_BFD_BIN_B:
bfd_put_32 (WR_BFD(wrbfd), value, data);
break;
case WR_KIND_BFD_BIN_L:
bfd_putl32 (value, data);
break;
default:
abort ();
}
}
rc_uint_type
windres_get_8 (windres_bfd *wrbfd, const void *data, rc_uint_type length)
{
if (length < 1)
fatal ("windres_get_8: unexpected eob.");
switch (WR_KIND(wrbfd))
{
case WR_KIND_TARGET:
return target_get_8 (data, length);
case WR_KIND_BFD:
case WR_KIND_BFD_BIN_B:
case WR_KIND_BFD_BIN_L:
return bfd_get_8 (WR_BFD(wrbfd), data);
default:
abort ();
}
return 0;
}
rc_uint_type
windres_get_16 (windres_bfd *wrbfd, const void *data, rc_uint_type length)
{
if (length < 2)
fatal ("windres_get_16: unexpected eob.");
switch (WR_KIND(wrbfd))
{
case WR_KIND_TARGET:
return target_get_16 (data, length);
case WR_KIND_BFD:
case WR_KIND_BFD_BIN_B:
return bfd_get_16 (WR_BFD(wrbfd), data);
case WR_KIND_BFD_BIN_L:
return bfd_getl16 (data);
default:
abort ();
}
return 0;
}
rc_uint_type
windres_get_32 (windres_bfd *wrbfd, const void *data, rc_uint_type length)
{
if (length < 4)
fatal ("windres_get_32: unexpected eob.");
switch (WR_KIND(wrbfd))
{
case WR_KIND_TARGET:
return target_get_32 (data, length);
case WR_KIND_BFD:
case WR_KIND_BFD_BIN_B:
return bfd_get_32 (WR_BFD(wrbfd), data);
case WR_KIND_BFD_BIN_L:
return bfd_getl32 (data);
default:
abort ();
}
return 0;
}
static rc_uint_type
target_get_8 (const void *p, rc_uint_type length)
{
rc_uint_type ret;
if (length < 1)
fatal ("Resource too small for getting 8-bit value.");
ret = (rc_uint_type) *((const bfd_byte *) p);
return ret & 0xff;
}
static rc_uint_type
target_get_16 (const void *p, rc_uint_type length)
{
if (length < 2)
fatal ("Resource too small for getting 16-bit value.");
if (target_is_bigendian)
return bfd_getb16 (p);
else
return bfd_getl16 (p);
}
static rc_uint_type
target_get_32 (const void *p, rc_uint_type length)
{
if (length < 4)
fatal ("Resource too small for getting 32-bit value.");
if (target_is_bigendian)
return bfd_getb32 (p);
else
return bfd_getl32 (p);
}
static void
target_put_8 (void *p, rc_uint_type value)
{
assert (!! p);
*((bfd_byte *) p)=(bfd_byte) value;
}
static void
target_put_16 (void *p, rc_uint_type value)
{
assert (!! p);
if (target_is_bigendian)
bfd_putb16 (value, p);
else
bfd_putl16 (value, p);
}
static void
target_put_32 (void *p, rc_uint_type value)
{
assert (!! p);
if (target_is_bigendian)
bfd_putb32 (value, p);
else
bfd_putl32 (value, p);
}
static int isInComment = 0;
int wr_printcomment (FILE *e, const char *fmt, ...)
{
va_list arg;
int r = 0;
if (isInComment)
r += fprintf (e, "\n ");
else
fprintf (e, "/* ");
isInComment = 1;
if (fmt == NULL)
return r;
va_start (arg, fmt);
r += vfprintf (e, fmt, arg);
va_end (arg);
return r;
}
int wr_print (FILE *e, const char *fmt, ...)
{
va_list arg;
int r = 0;
if (isInComment)
r += fprintf (e, ". */\n");
isInComment = 0;
if (! fmt)
return r;
va_start (arg, fmt);
r += vfprintf (e, fmt, arg);
va_end (arg);
return r;
}

View File

@ -1,7 +1,8 @@
/* windres.h -- header file for windres program.
Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005
Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007
Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
Rewritten by Kai Tietz, Onevision.
This file is part of GNU Binutils.
@ -26,771 +27,49 @@
structures and declares functions used within the program. */
#include "winduni.h"
/* We represent resources internally as a tree, similar to the tree
used in the .rsrc section of a COFF file. The root is a
res_directory structure. */
struct res_directory
{
/* Resource flags. According to the MS docs, this is currently
always zero. */
unsigned long characteristics;
/* Time/date stamp. */
unsigned long time;
/* Major version number. */
unsigned short major;
/* Minor version number. */
unsigned short minor;
/* Directory entries. */
struct res_entry *entries;
};
/* A resource ID is stored in a res_id structure. */
struct res_id
{
/* Non-zero if this entry has a name rather than an ID. */
unsigned int named : 1;
union
{
/* If the named field is non-zero, this is the name. */
struct
{
/* Length of the name. */
int length;
/* Pointer to the name, which is a Unicode string. */
unichar *name;
} n;
/* If the named field is zero, this is the ID. */
unsigned long id;
} u;
};
/* Each entry in the tree is a res_entry structure. We mix
directories and resources because in a COFF file all entries in a
directory are sorted together, whether the entries are
subdirectories or resources. */
struct res_entry
{
/* Next entry. */
struct res_entry *next;
/* Resource ID. */
struct res_id id;
/* Non-zero if this entry is a subdirectory rather than a leaf. */
unsigned int subdir : 1;
union
{
/* If the subdir field is non-zero, this is a pointer to the
subdirectory. */
struct res_directory *dir;
/* If the subdir field is zero, this is a pointer to the resource
data. */
struct res_resource *res;
} u;
};
/* Types of resources. */
enum res_type
{
RES_TYPE_UNINITIALIZED,
RES_TYPE_ACCELERATOR,
RES_TYPE_BITMAP,
RES_TYPE_CURSOR,
RES_TYPE_GROUP_CURSOR,
RES_TYPE_DIALOG,
RES_TYPE_FONT,
RES_TYPE_FONTDIR,
RES_TYPE_ICON,
RES_TYPE_GROUP_ICON,
RES_TYPE_MENU,
RES_TYPE_MESSAGETABLE,
RES_TYPE_RCDATA,
RES_TYPE_STRINGTABLE,
RES_TYPE_USERDATA,
RES_TYPE_VERSIONINFO
};
/* A res file and a COFF file store information differently. The
res_info structures holds data which in a res file is stored with
each resource, but in a COFF file is stored elsewhere. */
struct res_res_info
{
/* Language. In a COFF file, the third level of the directory is
keyed by the language, so the language of a resource is defined
by its location in the resource tree. */
unsigned short language;
/* Characteristics of the resource. Entirely user defined. In a
COFF file, the res_directory structure has a characteristics
field, but I don't know if it's related to the one in the res
file. */
unsigned long characteristics;
/* Version of the resource. Entirely user defined. In a COFF file,
the res_directory structure has a characteristics field, but I
don't know if it's related to the one in the res file. */
unsigned long version;
/* Memory flags. This is a combination of the MEMFLAG values
defined below. Most of these values are historical, and are not
meaningful for win32. I don't think there is any way to store
this information in a COFF file. */
unsigned short memflags;
};
/* Each resource in a COFF file has some information which can does
not appear in a res file. */
struct res_coff_info
{
/* The code page used for the data. I don't really know what this
should be. */
unsigned long codepage;
/* A resource entry in a COFF file has a reserved field, which we
record here when reading a COFF file. When writing a COFF file,
we set this field to zero. */
unsigned long reserved;
};
/* Resource data is stored in a res_resource structure. */
struct res_resource
{
/* The type of resource. */
enum res_type type;
/* The data for the resource. */
union
{
struct
{
unsigned long length;
const unsigned char *data;
} data;
struct accelerator *acc;
struct cursor *cursor;
struct group_cursor *group_cursor;
struct dialog *dialog;
struct fontdir *fontdir;
struct group_icon *group_icon;
struct menu *menu;
struct rcdata_item *rcdata;
struct stringtable *stringtable;
struct rcdata_item *userdata;
struct versioninfo *versioninfo;
} u;
/* Information from a res file. */
struct res_res_info res_info;
/* Information from a COFF file. */
struct res_coff_info coff_info;
};
#define SUBLANG_SHIFT 10
/* Memory flags in the memflags field of a struct res_resource. */
#define MEMFLAG_MOVEABLE 0x10
#define MEMFLAG_PURE 0x20
#define MEMFLAG_PRELOAD 0x40
#define MEMFLAG_DISCARDABLE 0x1000
/* Standard resource type codes. These are used in the ID field of a
res_entry structure. */
#define RT_CURSOR 1
#define RT_BITMAP 2
#define RT_ICON 3
#define RT_MENU 4
#define RT_DIALOG 5
#define RT_STRING 6
#define RT_FONTDIR 7
#define RT_FONT 8
#define RT_ACCELERATOR 9
#define RT_RCDATA 10
#define RT_MESSAGETABLE 11
#define RT_GROUP_CURSOR 12
#define RT_GROUP_ICON 14
#define RT_VERSION 16
#define RT_DLGINCLUDE 17
#define RT_PLUGPLAY 19
#define RT_VXD 20
#define RT_ANICURSOR 21
#define RT_ANIICON 22
/* An accelerator resource is a linked list of these structures. */
struct accelerator
{
/* Next accelerator. */
struct accelerator *next;
/* Flags. A combination of the ACC values defined below. */
unsigned short flags;
/* Key value. */
unsigned short key;
/* Resource ID. */
unsigned short id;
};
/* Accelerator flags in the flags field of a struct accelerator.
These are the same values that appear in a res file. I hope. */
#define ACC_VIRTKEY 0x01
#define ACC_NOINVERT 0x02
#define ACC_SHIFT 0x04
#define ACC_CONTROL 0x08
#define ACC_ALT 0x10
#define ACC_LAST 0x80
/* A cursor resource. */
struct cursor
{
/* X coordinate of hotspot. */
short xhotspot;
/* Y coordinate of hotspot. */
short yhotspot;
/* Length of bitmap data. */
unsigned long length;
/* Data. */
const unsigned char *data;
};
/* A group_cursor resource is a list of group_cursor structures. */
struct group_cursor
{
/* Next cursor in group. */
struct group_cursor *next;
/* Width. */
unsigned short width;
/* Height. */
unsigned short height;
/* Planes. */
unsigned short planes;
/* Bits per pixel. */
unsigned short bits;
/* Number of bytes in cursor resource. */
unsigned long bytes;
/* Index of cursor resource. */
unsigned short index;
};
/* A dialog resource. */
struct dialog
{
/* Basic window style. */
unsigned long style;
/* Extended window style. */
unsigned long exstyle;
/* X coordinate. */
unsigned short x;
/* Y coordinate. */
unsigned short y;
/* Width. */
unsigned short width;
/* Height. */
unsigned short height;
/* Menu name. */
struct res_id menu;
/* Class name. */
struct res_id class;
/* Caption. */
unichar *caption;
/* Font point size. */
unsigned short pointsize;
/* Font name. */
unichar *font;
/* Extended information for a dialogex. */
struct dialog_ex *ex;
/* Controls. */
struct dialog_control *controls;
};
/* An extended dialog has additional information. */
struct dialog_ex
{
/* Help ID. */
unsigned long help;
/* Font weight. */
unsigned short weight;
/* Whether the font is italic. */
unsigned char italic;
/* Character set. */
unsigned char charset;
};
/* Window style flags, from the winsup Defines.h header file. These
can appear in the style field of a struct dialog or a struct
dialog_control. */
#define CW_USEDEFAULT (0x80000000)
#define WS_BORDER (0x800000L)
#define WS_CAPTION (0xc00000L)
#define WS_CHILD (0x40000000L)
#define WS_CHILDWINDOW (0x40000000L)
#define WS_CLIPCHILDREN (0x2000000L)
#define WS_CLIPSIBLINGS (0x4000000L)
#define WS_DISABLED (0x8000000L)
#define WS_DLGFRAME (0x400000L)
#define WS_GROUP (0x20000L)
#define WS_HSCROLL (0x100000L)
#define WS_ICONIC (0x20000000L)
#define WS_MAXIMIZE (0x1000000L)
#define WS_MAXIMIZEBOX (0x10000L)
#define WS_MINIMIZE (0x20000000L)
#define WS_MINIMIZEBOX (0x20000L)
#define WS_OVERLAPPED (0L)
#define WS_OVERLAPPEDWINDOW (0xcf0000L)
#define WS_POPUP (0x80000000L)
#define WS_POPUPWINDOW (0x80880000L)
#define WS_SIZEBOX (0x40000L)
#define WS_SYSMENU (0x80000L)
#define WS_TABSTOP (0x10000L)
#define WS_THICKFRAME (0x40000L)
#define WS_TILED (0L)
#define WS_TILEDWINDOW (0xcf0000L)
#define WS_VISIBLE (0x10000000L)
#define WS_VSCROLL (0x200000L)
#define MDIS_ALLCHILDSTYLES (0x1)
#define BS_3STATE (0x5L)
#define BS_AUTO3STATE (0x6L)
#define BS_AUTOCHECKBOX (0x3L)
#define BS_AUTORADIOBUTTON (0x9L)
#define BS_BITMAP (0x80L)
#define BS_BOTTOM (0x800L)
#define BS_CENTER (0x300L)
#define BS_CHECKBOX (0x2L)
#define BS_DEFPUSHBUTTON (0x1L)
#define BS_GROUPBOX (0x7L)
#define BS_ICON (0x40L)
#define BS_LEFT (0x100L)
#define BS_LEFTTEXT (0x20L)
#define BS_MULTILINE (0x2000L)
#define BS_NOTIFY (0x4000L)
#define BS_OWNERDRAW (0xbL)
#define BS_PUSHBOX (0xcL) /* FIXME! What should this be? */
#define BS_PUSHBUTTON (0L)
#define BS_PUSHLIKE (0x1000L)
#define BS_RADIOBUTTON (0x4L)
#define BS_RIGHT (0x200L)
#define BS_RIGHTBUTTON (0x20L)
#define BS_TEXT (0L)
#define BS_TOP (0x400L)
#define BS_USERBUTTON (0x8L)
#define BS_VCENTER (0xc00L)
#define CBS_AUTOHSCROLL (0x40L)
#define CBS_DISABLENOSCROLL (0x800L)
#define CBS_DROPDOWN (0x2L)
#define CBS_DROPDOWNLIST (0x3L)
#define CBS_HASSTRINGS (0x200L)
#define CBS_LOWERCASE (0x4000L)
#define CBS_NOINTEGRALHEIGHT (0x400L)
#define CBS_OEMCONVERT (0x80L)
#define CBS_OWNERDRAWFIXED (0x10L)
#define CBS_OWNERDRAWVARIABLE (0x20L)
#define CBS_SIMPLE (0x1L)
#define CBS_SORT (0x100L)
#define CBS_UPPERCASE (0x2000L)
#define ES_AUTOHSCROLL (0x80L)
#define ES_AUTOVSCROLL (0x40L)
#define ES_CENTER (0x1L)
#define ES_LEFT (0L)
#define ES_LOWERCASE (0x10L)
#define ES_MULTILINE (0x4L)
#define ES_NOHIDESEL (0x100L)
#define ES_NUMBER (0x2000L)
#define ES_OEMCONVERT (0x400L)
#define ES_PASSWORD (0x20L)
#define ES_READONLY (0x800L)
#define ES_RIGHT (0x2L)
#define ES_UPPERCASE (0x8L)
#define ES_WANTRETURN (0x1000L)
#define LBS_DISABLENOSCROLL (0x1000L)
#define LBS_EXTENDEDSEL (0x800L)
#define LBS_HASSTRINGS (0x40L)
#define LBS_MULTICOLUMN (0x200L)
#define LBS_MULTIPLESEL (0x8L)
#define LBS_NODATA (0x2000L)
#define LBS_NOINTEGRALHEIGHT (0x100L)
#define LBS_NOREDRAW (0x4L)
#define LBS_NOSEL (0x4000L)
#define LBS_NOTIFY (0x1L)
#define LBS_OWNERDRAWFIXED (0x10L)
#define LBS_OWNERDRAWVARIABLE (0x20L)
#define LBS_SORT (0x2L)
#define LBS_STANDARD (0xa00003L)
#define LBS_USETABSTOPS (0x80L)
#define LBS_WANTKEYBOARDINPUT (0x400L)
#define SBS_BOTTOMALIGN (0x4L)
#define SBS_HORZ (0L)
#define SBS_LEFTALIGN (0x2L)
#define SBS_RIGHTALIGN (0x4L)
#define SBS_SIZEBOX (0x8L)
#define SBS_SIZEBOXBOTTOMRIGHTALIGN (0x4L)
#define SBS_SIZEBOXTOPLEFTALIGN (0x2L)
#define SBS_SIZEGRIP (0x10L)
#define SBS_TOPALIGN (0x2L)
#define SBS_VERT (0x1L)
#define SS_BITMAP (0xeL)
#define SS_BLACKFRAME (0x7L)
#define SS_BLACKRECT (0x4L)
#define SS_CENTER (0x1L)
#define SS_CENTERIMAGE (0x200L)
#define SS_ENHMETAFILE (0xfL)
#define SS_ETCHEDFRAME (0x12L)
#define SS_ETCHEDHORZ (0x10L)
#define SS_ETCHEDVERT (0x11L)
#define SS_GRAYFRAME (0x8L)
#define SS_GRAYRECT (0x5L)
#define SS_ICON (0x3L)
#define SS_LEFT (0L)
#define SS_LEFTNOWORDWRAP (0xcL)
#define SS_NOPREFIX (0x80L)
#define SS_NOTIFY (0x100L)
#define SS_OWNERDRAW (0xdL)
#define SS_REALSIZEIMAGE (0x800L)
#define SS_RIGHT (0x2L)
#define SS_RIGHTJUST (0x400L)
#define SS_SIMPLE (0xbL)
#define SS_SUNKEN (0x1000L)
#define SS_USERITEM (0xaL)
#define SS_WHITEFRAME (0x9L)
#define SS_WHITERECT (0x6L)
#define DS_3DLOOK (0x4L)
#define DS_ABSALIGN (0x1L)
#define DS_CENTER (0x800L)
#define DS_CENTERMOUSE (0x1000L)
#define DS_CONTEXTHELP (0x2000L)
#define DS_CONTROL (0x400L)
#define DS_FIXEDSYS (0x8L)
#define DS_LOCALEDIT (0x20L)
#define DS_MODALFRAME (0x80L)
#define DS_NOFAILCREATE (0x10L)
#define DS_NOIDLEMSG (0x100L)
#define DS_SETFONT (0x40L)
#define DS_SETFOREGROUND (0x200L)
#define DS_SYSMODAL (0x2L)
/* A dialog control. */
struct dialog_control
{
/* Next control. */
struct dialog_control *next;
/* ID. */
unsigned short id;
/* Style. */
unsigned long style;
/* Extended style. */
unsigned long exstyle;
/* X coordinate. */
unsigned short x;
/* Y coordinate. */
unsigned short y;
/* Width. */
unsigned short width;
/* Height. */
unsigned short height;
/* Class name. */
struct res_id class;
/* Associated text. */
struct res_id text;
/* Extra data for the window procedure. */
struct rcdata_item *data;
/* Help ID. Only used in an extended dialog. */
unsigned long help;
};
/* Control classes. These can be used as the ID field in a struct
dialog_control. */
#define CTL_BUTTON 0x80
#define CTL_EDIT 0x81
#define CTL_STATIC 0x82
#define CTL_LISTBOX 0x83
#define CTL_SCROLLBAR 0x84
#define CTL_COMBOBOX 0x85
/* A fontdir resource is a list of fontdir structures. */
struct fontdir
{
struct fontdir *next;
/* Index of font entry. */
short index;
/* Length of font information. */
unsigned long length;
/* Font information. */
const unsigned char *data;
};
/* A group_icon resource is a list of group_icon structures. */
struct group_icon
{
/* Next icon in group. */
struct group_icon *next;
/* Width. */
unsigned char width;
/* Height. */
unsigned char height;
/* Color count. */
unsigned char colors;
/* Planes. */
unsigned short planes;
/* Bits per pixel. */
unsigned short bits;
/* Number of bytes in cursor resource. */
unsigned long bytes;
/* Index of cursor resource. */
unsigned short index;
};
/* A menu resource. */
struct menu
{
/* List of menuitems. */
struct menuitem *items;
/* Help ID. I don't think there is any way to set this in an rc
file, but it can appear in the binary format. */
unsigned long help;
};
/* A menu resource is a list of menuitem structures. */
struct menuitem
{
/* Next menuitem. */
struct menuitem *next;
/* Type. In a normal menu, rather than a menuex, this is the flags
field. */
unsigned long type;
/* State. This is only used in a menuex. */
unsigned long state;
/* Id. */
unsigned short id;
/* Unicode text. */
unichar *text;
/* Popup menu items for a popup. */
struct menuitem *popup;
/* Help ID. This is only used in a menuex. */
unsigned long help;
};
/* Menu item flags. These can appear in the flags field of a struct
menuitem. */
#define MENUITEM_GRAYED 0x001
#define MENUITEM_INACTIVE 0x002
#define MENUITEM_BITMAP 0x004
#define MENUITEM_OWNERDRAW 0x100
#define MENUITEM_CHECKED 0x008
#define MENUITEM_POPUP 0x010
#define MENUITEM_MENUBARBREAK 0x020
#define MENUITEM_MENUBREAK 0x040
#define MENUITEM_ENDMENU 0x080
#define MENUITEM_HELP 0x4000
/* An rcdata resource is a pointer to a list of rcdata_item
structures. */
struct rcdata_item
{
/* Next data item. */
struct rcdata_item *next;
/* Type of data. */
enum
{
RCDATA_WORD,
RCDATA_DWORD,
RCDATA_STRING,
RCDATA_WSTRING,
RCDATA_BUFFER
} type;
union
{
unsigned int word;
unsigned long dword;
struct
{
unsigned long length;
const char *s;
} string;
struct
{
unsigned long length;
const unichar *w;
} wstring;
struct
{
unsigned long length;
const unsigned char *data;
} buffer;
} u;
};
/* A stringtable resource is a pointer to a stringtable structure. */
struct stringtable
{
/* Each stringtable resource is a list of 16 unicode strings. */
struct
{
/* Length of string. */
int length;
/* String data if length > 0. */
unichar *string;
} strings[16];
};
/* A versioninfo resource points to a versioninfo structure. */
struct versioninfo
{
/* Fixed version information. */
struct fixed_versioninfo *fixed;
/* Variable version information. */
struct ver_info *var;
};
/* The fixed portion of a versioninfo resource. */
struct fixed_versioninfo
{
/* The file version, which is two 32 bit integers. */
unsigned long file_version_ms;
unsigned long file_version_ls;
/* The product version, which is two 32 bit integers. */
unsigned long product_version_ms;
unsigned long product_version_ls;
/* The file flags mask. */
unsigned long file_flags_mask;
/* The file flags. */
unsigned long file_flags;
/* The OS type. */
unsigned long file_os;
/* The file type. */
unsigned long file_type;
/* The file subtype. */
unsigned long file_subtype;
/* The date, which in Windows is two 32 bit integers. */
unsigned long file_date_ms;
unsigned long file_date_ls;
};
/* A list of variable version information. */
struct ver_info
{
/* Next item. */
struct ver_info *next;
/* Type of data. */
enum { VERINFO_STRING, VERINFO_VAR } type;
union
{
/* StringFileInfo data. */
struct
{
/* Language. */
unichar *language;
/* Strings. */
struct ver_stringinfo *strings;
} string;
/* VarFileInfo data. */
struct
{
/* Key. */
unichar *key;
/* Values. */
struct ver_varinfo *var;
} var;
} u;
};
/* A list of string version information. */
struct ver_stringinfo
{
/* Next string. */
struct ver_stringinfo *next;
/* Key. */
unichar *key;
/* Value. */
unichar *value;
};
/* A list of variable version information. */
struct ver_varinfo
{
/* Next item. */
struct ver_varinfo *next;
/* Language ID. */
unsigned short language;
/* Character set ID. */
unsigned short charset;
};
/* This structure is used when converting resource information to
binary. */
struct bindata
{
/* Next data. */
struct bindata *next;
/* Length of data. */
unsigned long length;
/* Data. */
unsigned char *data;
};
#include "windint.h"
extern int verbose;
/* Function declarations. */
extern struct res_directory *read_rc_file
(const char *, const char *, const char *, int, int);
extern struct res_directory *read_res_file (const char *);
extern struct res_directory *read_coff_rsrc (const char *, const char *);
extern void write_rc_file (const char *, const struct res_directory *);
extern void write_res_file (const char *, const struct res_directory *);
extern void write_coff_file
(const char *, const char *, const struct res_directory *);
extern rc_res_directory *read_rc_file (const char *, const char *, const char *, int, int);
extern rc_res_directory *read_res_file (const char *);
extern rc_res_directory *read_coff_rsrc (const char *, const char *);
extern void write_rc_file (const char *, const rc_res_directory *);
extern void write_res_file (const char *, const rc_res_directory *);
extern void write_coff_file (const char *, const char *, const rc_res_directory *);
extern struct res_resource *bin_to_res
(struct res_id, const unsigned char *, unsigned long, int);
extern struct bindata *res_to_bin (const struct res_resource *, int);
extern rc_res_resource *bin_to_res (windres_bfd *, rc_res_id, const bfd_byte *,
rc_uint_type);
extern rc_uint_type res_to_bin (windres_bfd *, rc_uint_type, const rc_res_resource *);
extern FILE *open_file_search
(const char *, const char *, const char *, char **);
extern FILE *open_file_search (const char *, const char *, const char *, char **);
extern void *res_alloc (size_t);
extern void *reswr_alloc (size_t);
extern void *res_alloc (rc_uint_type);
extern void *reswr_alloc (rc_uint_type);
/* Resource ID handling. */
extern int res_id_cmp (struct res_id, struct res_id);
extern void res_id_print (FILE *, struct res_id, int);
extern void res_ids_print (FILE *, int, const struct res_id *);
extern void res_string_to_id (struct res_id *, const char *);
extern int res_id_cmp (rc_res_id, rc_res_id);
extern void res_id_print (FILE *, rc_res_id, int);
extern void res_ids_print (FILE *, int, const rc_res_id *);
extern void res_string_to_id (rc_res_id *, const char *);
extern void res_unistring_to_id (rc_res_id *, const unichar *);
/* Manipulation of the resource tree. */
extern struct res_resource *define_resource
(struct res_directory **, int, const struct res_id *, int);
extern struct res_resource *define_standard_resource
(struct res_directory **, int, struct res_id, int, int);
extern rc_res_resource *define_resource (rc_res_directory **, int, const rc_res_id *,
int);
extern rc_res_resource *define_standard_resource (rc_res_directory **, int, rc_res_id,
rc_uint_type, int);
extern int extended_dialog (const struct dialog *);
extern int extended_menu (const struct menu *);
extern int extended_dialog (const rc_dialog *);
extern int extended_menu (const rc_menu *);
/* Communication between the rc file support and the parser and lexer. */
extern int yydebug;
extern FILE *yyin;
extern char *rc_filename;
extern int rc_lineno;
@ -803,52 +82,40 @@ extern void rcparse_discard_strings (void);
extern void rcparse_rcdata (void);
extern void rcparse_normal (void);
extern void define_accelerator
(struct res_id, const struct res_res_info *, struct accelerator *);
extern void define_bitmap
(struct res_id, const struct res_res_info *, const char *);
extern void define_cursor
(struct res_id, const struct res_res_info *, const char *);
extern void define_dialog
(struct res_id, const struct res_res_info *, const struct dialog *);
extern struct dialog_control *define_control
(const struct res_id, unsigned long, unsigned long, unsigned long,
unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
extern struct dialog_control *define_icon_control
(struct res_id, unsigned long, unsigned long, unsigned long, unsigned long,
unsigned long, unsigned long, struct rcdata_item *, struct dialog_ex *);
extern void define_font
(struct res_id, const struct res_res_info *, const char *);
extern void define_icon
(struct res_id, const struct res_res_info *, const char *);
extern void define_menu
(struct res_id, const struct res_res_info *, struct menuitem *);
extern struct menuitem *define_menuitem
(const char *, int, unsigned long, unsigned long, unsigned long,
struct menuitem *);
extern void define_messagetable
(struct res_id, const struct res_res_info *, const char *);
extern void define_rcdata
(struct res_id, const struct res_res_info *, struct rcdata_item *);
extern void define_rcdata_file
(struct res_id, const struct res_res_info *, const char *);
extern struct rcdata_item *define_rcdata_string
(const char *, unsigned long);
extern struct rcdata_item *define_rcdata_number (unsigned long, int);
extern void define_stringtable
(const struct res_res_info *, unsigned long, const char *);
extern void define_user_data
(struct res_id, struct res_id, const struct res_res_info *,
struct rcdata_item *);
extern void define_user_file
(struct res_id, struct res_id, const struct res_res_info *, const char *);
extern void define_versioninfo
(struct res_id, int, struct fixed_versioninfo *, struct ver_info *);
extern struct ver_info *append_ver_stringfileinfo
(struct ver_info *, const char *, struct ver_stringinfo *);
extern struct ver_info *append_ver_varfileinfo
(struct ver_info *, const char *, struct ver_varinfo *);
extern struct ver_stringinfo *append_verval
(struct ver_stringinfo *, const char *, const char *);
extern struct ver_varinfo *append_vertrans
(struct ver_varinfo *, unsigned long, unsigned long);
extern void define_accelerator (rc_res_id, const rc_res_res_info *, rc_accelerator *);
extern void define_bitmap (rc_res_id, const rc_res_res_info *, const char *);
extern void define_cursor (rc_res_id, const rc_res_res_info *, const char *);
extern void define_dialog (rc_res_id, const rc_res_res_info *, const rc_dialog *);
extern rc_dialog_control *define_control (const rc_res_id, rc_uint_type, rc_uint_type,
rc_uint_type, rc_uint_type, rc_uint_type,
const rc_res_id, rc_uint_type, rc_uint_type);
extern rc_dialog_control *define_icon_control (rc_res_id, rc_uint_type, rc_uint_type,
rc_uint_type, rc_uint_type, rc_uint_type,
rc_uint_type, rc_rcdata_item *,
rc_dialog_ex *);
extern void define_font (rc_res_id, const rc_res_res_info *, const char *);
extern void define_icon (rc_res_id, const rc_res_res_info *, const char *);
extern void define_menu (rc_res_id, const rc_res_res_info *, rc_menuitem *);
extern rc_menuitem *define_menuitem (const unichar *, rc_uint_type, rc_uint_type,
rc_uint_type, rc_uint_type, rc_menuitem *);
extern void define_messagetable (rc_res_id, const rc_res_res_info *, const char *);
extern void define_rcdata (rc_res_id, const rc_res_res_info *, rc_rcdata_item *);
extern void define_rcdata_file (rc_res_id, const rc_res_res_info *, const char *);
extern rc_rcdata_item *define_rcdata_string (const char *, rc_uint_type);
extern rc_rcdata_item *define_rcdata_unistring (const unichar *, rc_uint_type);
extern rc_rcdata_item *define_rcdata_number (rc_uint_type, int);
extern void define_stringtable (const rc_res_res_info *, rc_uint_type, const unichar *);
extern void define_user_data (rc_res_id, rc_res_id, const rc_res_res_info *, rc_rcdata_item *);
extern void define_toolbar (rc_res_id, rc_res_res_info *, rc_uint_type ,rc_uint_type ,rc_toolbar_item *);
extern void define_user_file (rc_res_id, rc_res_id, const rc_res_res_info *, const char *);
extern void define_versioninfo (rc_res_id, rc_uint_type, rc_fixed_versioninfo *, rc_ver_info *);
extern rc_ver_info *append_ver_stringfileinfo (rc_ver_info *, const char *, rc_ver_stringinfo *);
extern rc_ver_info *append_ver_varfileinfo (rc_ver_info *, const unichar *, rc_ver_varinfo *);
extern rc_ver_stringinfo *append_verval (rc_ver_stringinfo *, const unichar *, const unichar *);
extern rc_ver_varinfo *append_vertrans (rc_ver_varinfo *, rc_uint_type, rc_uint_type);
extern bfd *windres_open_as_binary (const char *, int);
extern int wr_printcomment (FILE *, const char *, ...);
extern int wr_print (FILE *, const char *, ...);
#define wr_print_flush(FP) wr_print ((FP),NULL)

View File

@ -2,6 +2,7 @@
Copyright 1997, 1998, 2000, 2001, 2003, 2007
Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
Rewritten by Kai Tietz, Onevision.
This file is part of GNU Binutils.
@ -30,6 +31,7 @@
#include "sysdep.h"
#include "bfd.h"
#include "bucomm.h"
#include "winduni.h"
#include "safe-ctype.h"
@ -37,13 +39,16 @@
#include <windows.h>
#endif
/* Prototypes. */
static int unichar_isascii (const unichar *, rc_uint_type);
/* Convert an ASCII string to a unicode string. We just copy it,
expanding chars to shorts, rather than doing something intelligent. */
void
unicode_from_ascii (int *length, unichar **unicode, const char *ascii)
unicode_from_ascii (rc_uint_type *length, unichar **unicode, const char *ascii)
{
int len;
rc_uint_type len;
#ifndef _WIN32
const char *s;
unsigned short *w;
@ -57,11 +62,57 @@ unicode_from_ascii (int *length, unichar **unicode, const char *ascii)
/* We use MultiByteToWideChar rather than strlen to get the unicode
string length to allow multibyte "ascii" chars. The value returned
by this function includes the trailing '\0'. */
len = MultiByteToWideChar (CP_ACP, 0, ascii, -1, NULL, 0);
len = (rc_uint_type) MultiByteToWideChar (CP_ACP, 0, ascii, -1, NULL, 0);
if (len)
{
*unicode = ((unichar *) res_alloc (len * sizeof (unichar)));
MultiByteToWideChar (CP_ACP, 0, ascii, -1, *unicode, len);
MultiByteToWideChar (CP_ACP, 0, ascii, -1, *unicode, (int) len);
}
/* Discount the trailing '/0'. If MultiByteToWideChar failed,
this will set *length to -1. */
len--;
#endif
if (length != NULL)
*length = len;
}
/* Convert an unicode string to an ASCII string. We just copy it,
shrink shorts to chars, rather than doing something intelligent.
Shorts with not within the char range are replaced by '_'. */
void
ascii_from_unicode (rc_uint_type *length, const unichar *unicode, char **ascii)
{
rc_uint_type len;
#ifndef _WIN32
char *s;
const unsigned short *w;
len = 0;
while (unicode[len] != 0)
++len;
*ascii = ((char *) res_alloc (len + 1));
for (s = *ascii, w = unicode; *w != '\0'; w++, s++)
{
if(w[0]==(w[0]&0xff))
*s = (char) w[0];
else
*s = '_';
}
*s = 0;
#else
WINBOOL used_def = FALSE;
/* We use MultiByteToWideChar rather than strlen to get the unicode
string length to allow multibyte "ascii" chars. The value returned
by this function includes the trailing '\0'. */
len = (rc_uint_type) WideCharToMultiByte (CP_ACP, WC_DEFAULTCHAR, unicode, -1, NULL,
0, "_", &used_def);
if (len)
{
*ascii = (char *) res_alloc (len * sizeof (char));
WideCharToMultiByte (CP_ACP, WC_DEFAULTCHAR, unicode, -1, *ascii, (int) len,
"_", &used_def);
}
/* Discount the trailing '/0'. If MultiByteToWideChar failed,
this will set *length to -1. */
@ -78,7 +129,7 @@ unicode_from_ascii (int *length, unichar **unicode, const char *ascii)
some Windows function, probably WideCharToMultiByte. */
void
unicode_print (FILE *e, const unichar *unicode, int length)
unicode_print (FILE *e, const unichar *unicode, rc_uint_type length)
{
while (1)
{
@ -86,12 +137,12 @@ unicode_print (FILE *e, const unichar *unicode, int length)
if (length == 0)
return;
if (length > 0)
if ((bfd_signed_vma) length > 0)
--length;
ch = *unicode;
if (ch == 0 && length < 0)
if (ch == 0 && (bfd_signed_vma) length < 0)
return;
++unicode;
@ -99,7 +150,9 @@ unicode_print (FILE *e, const unichar *unicode, int length)
if ((ch & 0x7f) == ch)
{
if (ch == '\\')
fputs ("\\", e);
fputs ("\\\\", e);
else if (ch == '"')
fputs ("\"\"", e);
else if (ISPRINT (ch))
putc (ch, e);
else
@ -146,3 +199,147 @@ unicode_print (FILE *e, const unichar *unicode, int length)
fprintf (e, "\\x%x", (unsigned int) ch);
}
}
/* Print a unicode string to a file. */
void
ascii_print (FILE *e, const char *s, rc_uint_type length)
{
while (1)
{
char ch;
if (length == 0)
return;
if ((bfd_signed_vma) length > 0)
--length;
ch = *s;
if (ch == 0 && (bfd_signed_vma) length < 0)
return;
++s;
if ((ch & 0x7f) == ch)
{
if (ch == '\\')
fputs ("\\\\", e);
else if (ch == '"')
fputs ("\"\"", e);
else if (ISPRINT (ch))
putc (ch, e);
else
{
switch (ch)
{
case ESCAPE_A:
fputs ("\\a", e);
break;
case ESCAPE_B:
fputs ("\\b", e);
break;
case ESCAPE_F:
fputs ("\\f", e);
break;
case ESCAPE_N:
fputs ("\\n", e);
break;
case ESCAPE_R:
fputs ("\\r", e);
break;
case ESCAPE_T:
fputs ("\\t", e);
break;
case ESCAPE_V:
fputs ("\\v", e);
break;
default:
fprintf (e, "\\%03o", (unsigned int) ch);
break;
}
}
}
else
fprintf (e, "\\%03o", (unsigned int) ch & 0xff);
}
}
rc_uint_type
unichar_len (const unichar *unicode)
{
rc_uint_type r = 0;
if (unicode)
while (unicode[r] != 0)
r++;
else
--r;
return r;
}
unichar *
unichar_dup (const unichar *unicode)
{
unichar *r;
int len;
if (! unicode)
return NULL;
for (len = 0; unicode[len] != 0; ++len)
;
++len;
r = ((unichar *) res_alloc (len * sizeof (unichar)));
memcpy (r, unicode, len * sizeof (unichar));
return r;
}
unichar *
unichar_dup_uppercase (const unichar *u)
{
unichar *r = unichar_dup (u);
int i;
if (! r)
return NULL;
for (i = 0; r[i] != 0; ++i)
{
if (r[i] >= 'a' && r[i] <= 'z')
r[i] &= 0xdf;
}
return r;
}
static int
unichar_isascii (const unichar *u, rc_uint_type len)
{
rc_uint_type i;
if ((bfd_signed_vma) len < 0)
{
if (u)
len = (rc_uint_type) unichar_len (u);
else
len = 0;
}
for (i = 0; i < len; i++)
if ((u[i] & 0xff80) != 0)
return 0;
return 1;
}
void
unicode_print_quoted (FILE *e, const unichar *u, rc_uint_type len)
{
if (! unichar_isascii (u, len))
fputc ('L', e);
fputc ('"', e);
unicode_print (e, u, len);
fputc ('"', e);
}

View File

@ -1,6 +1,8 @@
/* winduni.h -- header file for unicode support for windres program.
Copyright 1997, 1998, 2002 Free Software Foundation, Inc.
Copyright 1997, 1998, 2002, 2007
Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
Rewritten by Kai Tietz, Onevision.
This file is part of GNU Binutils.
@ -21,6 +23,9 @@
#include "ansidecl.h"
#ifndef WINDUNI_H
#define WINDUNI_H
/* This header file declares the types and functions we use for
unicode support in windres. Our unicode support is very limited at
present.
@ -30,31 +35,55 @@
that would conflict with the definitions of Windows macros we
already have in windres.h. */
/* Use bfd_size_type to ensure a sufficient number of bits. */
#ifndef DEFINED_RC_UINT_TYPE
#define DEFINED_RC_UINT_TYPE
typedef bfd_size_type rc_uint_type;
#endif
/* We use this type to hold a unicode character. */
typedef unsigned short unichar;
/* Escape character translations. */
#define ESCAPE_A (007)
#define ESCAPE_B (010)
#define ESCAPE_F (014)
#define ESCAPE_N (012)
#define ESCAPE_R (015)
#define ESCAPE_T (011)
#define ESCAPE_V (013)
#define ESCAPE_A 007
#define ESCAPE_B 010
#define ESCAPE_F 014
#define ESCAPE_N 012
#define ESCAPE_R 015
#define ESCAPE_T 011
#define ESCAPE_V 013
/* Convert an ASCII string to a unicode string. */
extern void unicode_from_ascii
PARAMS ((int *, unichar **, const char *));
extern void unicode_from_ascii (rc_uint_type *, unichar **, const char *);
/* Convert an unicode string to an ASCII string. */
extern void ascii_from_unicode (rc_uint_type *, const unichar *, char **);
/* Duplicate a unicode string by using res_alloc. */
extern unichar *unichar_dup (const unichar *);
/* Duplicate a unicode string by using res_alloc and make it uppercase. */
extern unichar *unichar_dup_uppercase (const unichar *);
/* The count of unichar elements. */
extern rc_uint_type unichar_len (const unichar *);
/* Print a unicode string to a file. */
extern void unicode_print (FILE *, const unichar *, rc_uint_type);
extern void unicode_print PARAMS ((FILE *, const unichar *, int));
/* Print a ascii string to a file. */
extern void ascii_print (FILE *, const char *, rc_uint_type);
/* Print a quoted unicode string to a file. */
extern void unicode_print_quoted (FILE *, const unichar *, rc_uint_type);
/* Windres support routine called by unicode_from_ascii. This is both
here and in windres.h. It should probably be in a separate header
file, but it hardly seems worth it for one function. */
extern PTR res_alloc PARAMS ((size_t));
extern void * res_alloc (rc_uint_type);
#endif