Updated windres tool
This commit is contained in:
parent
950c3b7d2c
commit
4a594fce16
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
835
binutils/rclex.c
Normal 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;
|
||||
}
|
504
binutils/rclex.l
504
binutils/rclex.l
@ -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
2043
binutils/resbin.c
2043
binutils/resbin.c
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
|
1662
binutils/resrc.c
1662
binutils/resrc.c
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
|
@ -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.
|
||||
|
BIN
binutils/testsuite/binutils-all/windres/MSG00001.bin
Normal file
BIN
binutils/testsuite/binutils-all/windres/MSG00001.bin
Normal file
Binary file not shown.
@ -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 ....
|
||||
|
7
binutils/testsuite/binutils-all/windres/html.rc
Normal file
7
binutils/testsuite/binutils-all/windres/html.rc
Normal 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"
|
45
binutils/testsuite/binutils-all/windres/html.rsd
Normal file
45
binutils/testsuite/binutils-all/windres/html.rsd
Normal 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>
|
11
binutils/testsuite/binutils-all/windres/html1.hm
Normal file
11
binutils/testsuite/binutils-all/windres/html1.hm
Normal 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>
|
11
binutils/testsuite/binutils-all/windres/html2.hm
Normal file
11
binutils/testsuite/binutils-all/windres/html2.hm
Normal 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>
|
6
binutils/testsuite/binutils-all/windres/messagetable.rc
Normal file
6
binutils/testsuite/binutils-all/windres/messagetable.rc
Normal file
@ -0,0 +1,6 @@
|
||||
//#xfail x86_64-*-mingw*
|
||||
#include "windows.h"
|
||||
|
||||
LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
|
||||
|
||||
888 MESSAGETABLE MSG00001.bin
|
15
binutils/testsuite/binutils-all/windres/messagetable.rsd
Normal file
15
binutils/testsuite/binutils-all/windres/messagetable.rsd
Normal 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......
|
9
binutils/testsuite/binutils-all/windres/strtab2.rc
Normal file
9
binutils/testsuite/binutils-all/windres/strtab2.rc
Normal 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
|
8
binutils/testsuite/binutils-all/windres/strtab2.rsd
Normal file
8
binutils/testsuite/binutils-all/windres/strtab2.rsd
Normal 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 ........
|
33
binutils/testsuite/binutils-all/windres/version.rc
Normal file
33
binutils/testsuite/binutils-all/windres/version.rc
Normal 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
|
55
binutils/testsuite/binutils-all/windres/version.rsd
Normal file
55
binutils/testsuite/binutils-all/windres/version.rsd
Normal 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
1088
binutils/windint.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user