From 4a594fce16683232bbb2e239d3e3ebcfcde16d1a Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Wed, 23 May 2007 08:48:29 +0000 Subject: [PATCH] Updated windres tool --- binutils/ChangeLog | 31 + binutils/Makefile.am | 27 +- binutils/Makefile.in | 30 +- binutils/rclex.c | 835 +++++++ binutils/rclex.l | 504 ---- binutils/rcparse.y | 518 +++-- binutils/resbin.c | 2045 ++++++++--------- binutils/rescoff.c | 288 ++- binutils/resrc.c | 1624 +++++++++---- binutils/resres.c | 540 +++-- binutils/testsuite/ChangeLog | 15 + .../binutils-all/windres/MSG00001.bin | Bin 0 -> 112 bytes .../binutils-all/windres/dialogid.rsd | 8 +- .../testsuite/binutils-all/windres/html.rc | 7 + .../testsuite/binutils-all/windres/html.rsd | 45 + .../testsuite/binutils-all/windres/html1.hm | 11 + .../testsuite/binutils-all/windres/html2.hm | 11 + .../binutils-all/windres/messagetable.rc | 6 + .../binutils-all/windres/messagetable.rsd | 15 + .../testsuite/binutils-all/windres/strtab2.rc | 9 + .../binutils-all/windres/strtab2.rsd | 8 + .../testsuite/binutils-all/windres/version.rc | 33 + .../binutils-all/windres/version.rsd | 55 + binutils/windint.h | 1088 +++++++++ binutils/windres.c | 466 +++- binutils/windres.h | 859 +------ binutils/winduni.c | 213 +- binutils/winduni.h | 53 +- 28 files changed, 5785 insertions(+), 3559 deletions(-) create mode 100644 binutils/rclex.c delete mode 100644 binutils/rclex.l create mode 100644 binutils/testsuite/binutils-all/windres/MSG00001.bin create mode 100644 binutils/testsuite/binutils-all/windres/html.rc create mode 100644 binutils/testsuite/binutils-all/windres/html.rsd create mode 100644 binutils/testsuite/binutils-all/windres/html1.hm create mode 100644 binutils/testsuite/binutils-all/windres/html2.hm create mode 100644 binutils/testsuite/binutils-all/windres/messagetable.rc create mode 100644 binutils/testsuite/binutils-all/windres/messagetable.rsd create mode 100644 binutils/testsuite/binutils-all/windres/strtab2.rc create mode 100644 binutils/testsuite/binutils-all/windres/strtab2.rsd create mode 100644 binutils/testsuite/binutils-all/windres/version.rc create mode 100644 binutils/testsuite/binutils-all/windres/version.rsd create mode 100644 binutils/windint.h diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 9724584770f..96d391aeeab 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,34 @@ +2007-05-23 Kai Tietz + + * 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 * objdump.c (find_symbol_for_address): Merge section and target diff --git a/binutils/Makefile.am b/binutils/Makefile.am index c5254766311..45a6bb1f4d1 100644 --- a/binutils/Makefile.am +++ b/binutils/Makefile.am @@ -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 diff --git a/binutils/Makefile.in b/binutils/Makefile.in index 4faadd3eea5..356b5e4566c 100644 --- a/binutils/Makefile.in +++ b/binutils/Makefile.in @@ -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. diff --git a/binutils/rclex.c b/binutils/rclex.c new file mode 100644 index 00000000000..edcf2cece6b --- /dev/null +++ b/binutils/rclex.c @@ -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 + +/* 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; +} diff --git a/binutils/rclex.l b/binutils/rclex.l deleted file mode 100644 index cbc5c00d563..00000000000 --- a/binutils/rclex.l +++ /dev/null @@ -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 - -#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; -} diff --git a/binutils/rcparse.y b/binutils/rcparse.y index b1afe521cb5..989fac8d042 100644 --- a/binutils/rcparse.y +++ b/binutils/rcparse.y @@ -2,6 +2,7 @@ Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support. + Extended by Kai Tietz, Onevision. This file is part of GNU Binutils. @@ -25,6 +26,7 @@ #include "sysdep.h" #include "bfd.h" +#include "bucomm.h" #include "libiberty.h" #include "windres.h" #include "safe-ctype.h" @@ -35,12 +37,12 @@ static unsigned short language; /* The resource information during a sub statement. */ -static struct res_res_info sub_res_info; +static rc_res_res_info sub_res_info; /* Dialog information. This is built by the nonterminals styles and controls. */ -static struct dialog dialog; +static rc_dialog dialog; /* This is used when building a style. It is modified by the nonterminal styleexpr. */ @@ -50,56 +52,62 @@ static unsigned long style; /* These are used when building a control. They are set before using control_params. */ -static unsigned long base_style; -static unsigned long default_style; -static unsigned long class; -static struct res_id res_text_field; +static rc_uint_type base_style; +static rc_uint_type default_style; +static rc_res_id class; +static rc_res_id res_text_field; static unichar null_unichar; /* This is used for COMBOBOX, LISTBOX and EDITTEXT which do not allow resource 'text' field in control definition. */ -static const struct res_id res_null_text = { 1, {{0, &null_unichar}}}; +static const rc_res_id res_null_text = { 1, {{0, &null_unichar}}}; %} %union { - struct accelerator acc; - struct accelerator *pacc; - struct dialog_control *dialog_control; - struct menuitem *menuitem; + rc_accelerator acc; + rc_accelerator *pacc; + rc_dialog_control *dialog_control; + rc_menuitem *menuitem; struct { - struct rcdata_item *first; - struct rcdata_item *last; + rc_rcdata_item *first; + rc_rcdata_item *last; } rcdata; - struct rcdata_item *rcdata_item; - struct stringtable_data *stringtable; - struct fixed_versioninfo *fixver; - struct ver_info *verinfo; - struct ver_stringinfo *verstring; - struct ver_varinfo *vervar; - struct res_id id; - struct res_res_info res_info; + rc_rcdata_item *rcdata_item; + rc_fixed_versioninfo *fixver; + rc_ver_info *verinfo; + rc_ver_stringinfo *verstring; + rc_ver_varinfo *vervar; + rc_toolbar_item *toobar_item; + rc_res_id id; + rc_res_res_info res_info; struct { - unsigned short on; - unsigned short off; + rc_uint_type on; + rc_uint_type off; } memflags; struct { - unsigned long val; + rc_uint_type val; /* Nonzero if this number was explicitly specified as long. */ int dword; } i; - unsigned long il; - unsigned short is; + rc_uint_type il; + rc_uint_type is; const char *s; struct { - unsigned long length; + rc_uint_type length; const char *s; } ss; + unichar *uni; + struct + { + rc_uint_type length; + const unichar *s; + } suni; }; %token BEG END @@ -113,6 +121,7 @@ static const struct res_id res_null_text = { 1, {{0, &null_unichar}}}; %token BEDIT HEDIT IEDIT %token FONT %token ICON +%token ANICURSOR ANIICON DLGINCLUDE DLGINIT FONTDIR HTML MANIFEST PLUGPLAY VXD TOOLBAR BUTTON %token LANGUAGE CHARACTERISTICS VERSIONK %token MENU MENUEX MENUITEM SEPARATOR POPUP CHECKED GRAYED HELP INACTIVE %token MENUBARBREAK MENUBREAK @@ -125,8 +134,10 @@ static const struct res_id res_null_text = { 1, {{0, &null_unichar}}}; %token BLOCK %token MOVEABLE FIXED PURE IMPURE PRELOAD LOADONCALL DISCARDABLE %token NOT +%token QUOTEDUNISTRING %token QUOTEDSTRING STRING %token NUMBER +%token SIZEDUNISTRING %token SIZEDSTRING %token IGNORED_TOKEN @@ -140,13 +151,17 @@ static const struct res_id res_null_text = { 1, {{0, &null_unichar}}}; %type verblocks %type vervals %type vertrans +%type toolbar_data %type suboptions memflags_move_discard memflags_move %type memflag -%type id optresidc resref +%type id rcdata_id optresidc resref resid cresid %type exstyle parennumber %type numexpr posnumexpr cnumexpr optcnumexpr cposnumexpr %type acc_options acc_option menuitem_flags menuitem_flag -%type file_name resname +%type file_name +%type res_unicode_string resname +%type sizedstring +%type sizedunistring %type sizednumexpr sizedposnumexpr %left '|' @@ -170,8 +185,8 @@ input: | input menu | input menuex | input messagetable - | input rcdata | input stringtable + | input toolbar | input user | input versioninfo | input IGNORED_TOKEN @@ -196,15 +211,15 @@ acc_entries: } | acc_entries acc_entry { - struct accelerator *a; + rc_accelerator *a; - a = (struct accelerator *) res_alloc (sizeof *a); + a = (rc_accelerator *) res_alloc (sizeof *a); *a = $2; if ($1 == NULL) $$ = a; else { - struct accelerator **pp; + rc_accelerator **pp; for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next) ; @@ -246,8 +261,7 @@ acc_event: { $$.flags = ACC_CONTROL | ACC_VIRTKEY; ++s; - ch = *s; - ch = TOUPPER (ch); + ch = TOUPPER (s[0]); } $$.key = ch; if (s[1] != '\0') @@ -371,9 +385,9 @@ dialog: dialog.menu.named = 1; dialog.class.named = 1; dialog.font = NULL; - dialog.ex = ((struct dialog_ex *) - res_alloc (sizeof (struct dialog_ex))); - memset (dialog.ex, 0, sizeof (struct dialog_ex)); + dialog.ex = ((rc_dialog_ex *) + res_alloc (sizeof (rc_dialog_ex))); + memset (dialog.ex, 0, sizeof (rc_dialog_ex)); dialog.controls = NULL; sub_res_info = $3; style = 0; @@ -398,9 +412,9 @@ dialog: dialog.menu.named = 1; dialog.class.named = 1; dialog.font = NULL; - dialog.ex = ((struct dialog_ex *) - res_alloc (sizeof (struct dialog_ex))); - memset (dialog.ex, 0, sizeof (struct dialog_ex)); + dialog.ex = ((rc_dialog_ex *) + res_alloc (sizeof (rc_dialog_ex))); + memset (dialog.ex, 0, sizeof (rc_dialog_ex)); dialog.ex->help = $9; dialog.controls = NULL; sub_res_info = $3; @@ -428,11 +442,11 @@ exstyle: styles: /* empty */ - | styles CAPTION QUOTEDSTRING + | styles CAPTION res_unicode_string { dialog.style |= WS_CAPTION; style |= WS_CAPTION; - unicode_from_ascii ((int *) NULL, &dialog.caption, $3); + dialog.caption = $3; } | styles CLASS id { @@ -447,16 +461,16 @@ styles: { dialog.exstyle = $3; } - | styles CLASS QUOTEDSTRING + | styles CLASS res_unicode_string { - res_string_to_id (& dialog.class, $3); + res_unistring_to_id (& dialog.class, $3); } - | styles FONT numexpr ',' QUOTEDSTRING + | styles FONT numexpr ',' res_unicode_string { dialog.style |= DS_SETFONT; style |= DS_SETFONT; dialog.pointsize = $3; - unicode_from_ascii ((int *) NULL, &dialog.font, $5); + dialog.font = $5; if (dialog.ex != NULL) { dialog.ex->weight = 0; @@ -464,12 +478,12 @@ styles: dialog.ex->charset = 1; } } - | styles FONT numexpr ',' QUOTEDSTRING cnumexpr + | styles FONT numexpr ',' res_unicode_string cnumexpr { dialog.style |= DS_SETFONT; style |= DS_SETFONT; dialog.pointsize = $3; - unicode_from_ascii ((int *) NULL, &dialog.font, $5); + dialog.font = $5; if (dialog.ex == NULL) rcparse_warning (_("extended FONT requires DIALOGEX")); else @@ -479,12 +493,12 @@ styles: dialog.ex->charset = 1; } } - | styles FONT numexpr ',' QUOTEDSTRING cnumexpr cnumexpr + | styles FONT numexpr ',' res_unicode_string cnumexpr cnumexpr { dialog.style |= DS_SETFONT; style |= DS_SETFONT; dialog.pointsize = $3; - unicode_from_ascii ((int *) NULL, &dialog.font, $5); + dialog.font = $5; if (dialog.ex == NULL) rcparse_warning (_("extended FONT requires DIALOGEX")); else @@ -494,12 +508,12 @@ styles: dialog.ex->charset = 1; } } - | styles FONT numexpr ',' QUOTEDSTRING cnumexpr cnumexpr cnumexpr + | styles FONT numexpr ',' res_unicode_string cnumexpr cnumexpr cnumexpr { dialog.style |= DS_SETFONT; style |= DS_SETFONT; dialog.pointsize = $3; - unicode_from_ascii ((int *) NULL, &dialog.font, $5); + dialog.font = $5; if (dialog.ex == NULL) rcparse_warning (_("extended FONT requires DIALOGEX")); else @@ -531,7 +545,7 @@ controls: /* empty */ | controls control { - struct dialog_control **pp; + rc_dialog_control **pp; for (pp = &dialog.controls; *pp != NULL; pp = &(*pp)->next) ; @@ -544,7 +558,8 @@ control: { default_style = BS_AUTO3STATE | WS_TABSTOP; base_style = BS_AUTO3STATE; - class = CTL_BUTTON; + class.named = 0; + class.u.id = CTL_BUTTON; res_text_field = $2; } control_params @@ -555,7 +570,8 @@ control: { default_style = BS_AUTOCHECKBOX | WS_TABSTOP; base_style = BS_AUTOCHECKBOX; - class = CTL_BUTTON; + class.named = 0; + class.u.id = CTL_BUTTON; res_text_field = $2; } control_params @@ -566,7 +582,8 @@ control: { default_style = BS_AUTORADIOBUTTON | WS_TABSTOP; base_style = BS_AUTORADIOBUTTON; - class = CTL_BUTTON; + class.named = 0; + class.u.id = CTL_BUTTON; res_text_field = $2; } control_params @@ -577,7 +594,8 @@ control: { default_style = ES_LEFT | WS_BORDER | WS_TABSTOP; base_style = ES_LEFT | WS_BORDER | WS_TABSTOP; - class = CTL_EDIT; + class.named = 0; + class.u.id = CTL_EDIT; res_text_field = $2; } control_params @@ -591,7 +609,8 @@ control: { default_style = BS_CHECKBOX | WS_TABSTOP; base_style = BS_CHECKBOX | WS_TABSTOP; - class = CTL_BUTTON; + class.named = 0; + class.u.id = CTL_BUTTON; res_text_field = $2; } control_params @@ -604,14 +623,15 @@ control: versions of MS rc.exe their is no default style. */ default_style = CBS_SIMPLE | WS_TABSTOP; base_style = 0; - class = CTL_COMBOBOX; + class.named = 0; + class.u.id = CTL_COMBOBOX; res_text_field = res_null_text; } control_params { $$ = $3; } - | CONTROL optresidc numexpr cnumexpr control_styleexpr cnumexpr + | CONTROL optresidc numexpr cresid control_styleexpr cnumexpr cnumexpr cnumexpr cnumexpr optcnumexpr opt_control_data { $$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10); @@ -622,7 +642,7 @@ control: $$->data = $11; } } - | CONTROL optresidc numexpr cnumexpr control_styleexpr cnumexpr + | CONTROL optresidc numexpr cresid control_styleexpr cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data { $$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10); @@ -631,35 +651,12 @@ control: $$->help = $11; $$->data = $12; } - | CONTROL optresidc numexpr ',' QUOTEDSTRING control_styleexpr - cnumexpr cnumexpr cnumexpr cnumexpr optcnumexpr opt_control_data - { - $$ = define_control ($2, $3, $7, $8, $9, $10, 0, style, $11); - if ($12 != NULL) - { - if (dialog.ex == NULL) - rcparse_warning ("control data requires DIALOGEX"); - $$->data = $12; - } - $$->class.named = 1; - unicode_from_ascii (&$$->class.u.n.length, &$$->class.u.n.name, $5); - } - | CONTROL optresidc numexpr ',' QUOTEDSTRING control_styleexpr - cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data - { - $$ = define_control ($2, $3, $7, $8, $9, $10, 0, style, $11); - if (dialog.ex == NULL) - rcparse_warning ("help ID requires DIALOGEX"); - $$->help = $12; - $$->data = $13; - $$->class.named = 1; - unicode_from_ascii (&$$->class.u.n.length, &$$->class.u.n.name, $5); - } | CTEXT optresidc { default_style = SS_CENTER | WS_GROUP; base_style = SS_CENTER; - class = CTL_STATIC; + class.named = 0; + class.u.id = CTL_STATIC; res_text_field = $2; } control_params @@ -670,7 +667,8 @@ control: { default_style = BS_DEFPUSHBUTTON | WS_TABSTOP; base_style = BS_DEFPUSHBUTTON | WS_TABSTOP; - class = CTL_BUTTON; + class.named = 0; + class.u.id = CTL_BUTTON; res_text_field = $2; } control_params @@ -681,7 +679,8 @@ control: { default_style = ES_LEFT | WS_BORDER | WS_TABSTOP; base_style = ES_LEFT | WS_BORDER | WS_TABSTOP; - class = CTL_EDIT; + class.named = 0; + class.u.id = CTL_EDIT; res_text_field = res_null_text; } control_params @@ -692,7 +691,8 @@ control: { default_style = BS_GROUPBOX; base_style = BS_GROUPBOX; - class = CTL_BUTTON; + class.named = 0; + class.u.id = CTL_BUTTON; res_text_field = $2; } control_params @@ -703,7 +703,8 @@ control: { default_style = ES_LEFT | WS_BORDER | WS_TABSTOP; base_style = ES_LEFT | WS_BORDER | WS_TABSTOP; - class = CTL_EDIT; + class.named = 0; + class.u.id = CTL_EDIT; res_text_field = $2; } control_params @@ -740,7 +741,8 @@ control: { default_style = ES_LEFT | WS_BORDER | WS_TABSTOP; base_style = ES_LEFT | WS_BORDER | WS_TABSTOP; - class = CTL_EDIT; + class.named = 0; + class.u.id = CTL_EDIT; res_text_field = $2; } control_params @@ -754,7 +756,8 @@ control: { default_style = LBS_NOTIFY | WS_BORDER; base_style = LBS_NOTIFY | WS_BORDER; - class = CTL_LISTBOX; + class.named = 0; + class.u.id = CTL_LISTBOX; res_text_field = res_null_text; } control_params @@ -765,7 +768,8 @@ control: { default_style = SS_LEFT | WS_GROUP; base_style = SS_LEFT; - class = CTL_STATIC; + class.named = 0; + class.u.id = CTL_STATIC; res_text_field = $2; } control_params @@ -776,7 +780,8 @@ control: { default_style = BS_PUSHBOX | WS_TABSTOP; base_style = BS_PUSHBOX; - class = CTL_BUTTON; + class.named = 0; + class.u.id = CTL_BUTTON; } control_params { @@ -786,7 +791,8 @@ control: { default_style = BS_PUSHBUTTON | WS_TABSTOP; base_style = BS_PUSHBUTTON | WS_TABSTOP; - class = CTL_BUTTON; + class.named = 0; + class.u.id = CTL_BUTTON; res_text_field = $2; } control_params @@ -797,7 +803,8 @@ control: { default_style = BS_RADIOBUTTON | WS_TABSTOP; base_style = BS_RADIOBUTTON; - class = CTL_BUTTON; + class.named = 0; + class.u.id = CTL_BUTTON; res_text_field = $2; } control_params @@ -808,7 +815,8 @@ control: { default_style = SS_RIGHT | WS_GROUP; base_style = SS_RIGHT; - class = CTL_STATIC; + class.named = 0; + class.u.id = CTL_STATIC; res_text_field = $2; } control_params @@ -819,7 +827,8 @@ control: { default_style = SBS_HORZ; base_style = 0; - class = CTL_SCROLLBAR; + class.named = 0; + class.u.id = CTL_SCROLLBAR; res_text_field = res_null_text; } control_params @@ -830,7 +839,8 @@ control: { default_style = BS_3STATE | WS_TABSTOP; base_style = BS_3STATE; - class = CTL_BUTTON; + class.named = 0; + class.u.id = CTL_BUTTON; res_text_field = $2; } control_params @@ -842,7 +852,10 @@ control: { style = WS_CHILD | WS_VISIBLE; } styleexpr optcnumexpr { - $$ = define_control ($2, $3, $5, $7, $9, $11, CTL_BUTTON, + rc_res_id cid; + cid.named = 0; + cid.u.id = CTL_BUTTON; + $$ = define_control ($2, $3, $5, $7, $9, $11, cid, style, $15); } ; @@ -888,23 +901,35 @@ control_params: } ; +cresid: + ',' resid + { + if ($2.named) + res_unistring_to_id (&$$, $2.u.n.name); + else + $$=$2; + } + ; + optresidc: /* empty */ { res_string_to_id (&$$, ""); } - | posnumexpr ',' + | resid ',' { $$=$1; } + ; + +resid: + posnumexpr { $$.named = 0; $$.u.id = $1; } - | QUOTEDSTRING + | res_unicode_string { - res_string_to_id (&$$, $1); - } - | QUOTEDSTRING ',' - { - res_string_to_id (&$$, $1); + $$.named = 1; + $$.u.n.name = $1; + $$.u.n.length = unichar_len ($1); } ; @@ -996,7 +1021,7 @@ menuitems: $$ = $2; else { - struct menuitem **pp; + rc_menuitem **pp; for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next) ; @@ -1007,7 +1032,7 @@ menuitems: ; menuitem: - MENUITEM QUOTEDSTRING cnumexpr menuitem_flags + MENUITEM res_unicode_string cnumexpr menuitem_flags { $$ = define_menuitem ($2, $3, $4, 0, 0, NULL); } @@ -1015,7 +1040,7 @@ menuitem: { $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL); } - | POPUP QUOTEDSTRING menuitem_flags BEG menuitems END + | POPUP res_unicode_string menuitem_flags BEG menuitems END { $$ = define_menuitem ($2, 0, $3, 0, 0, $5); } @@ -1086,7 +1111,7 @@ menuexitems: $$ = $2; else { - struct menuitem **pp; + rc_menuitem **pp; for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next) ; @@ -1097,15 +1122,15 @@ menuexitems: ; menuexitem: - MENUITEM QUOTEDSTRING + MENUITEM res_unicode_string { $$ = define_menuitem ($2, 0, 0, 0, 0, NULL); } - | MENUITEM QUOTEDSTRING cnumexpr + | MENUITEM res_unicode_string cnumexpr { $$ = define_menuitem ($2, $3, 0, 0, 0, NULL); } - | MENUITEM QUOTEDSTRING cnumexpr cnumexpr optcnumexpr + | MENUITEM res_unicode_string cnumexpr cnumexpr optcnumexpr { $$ = define_menuitem ($2, $3, $4, $5, 0, NULL); } @@ -1113,19 +1138,19 @@ menuexitem: { $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL); } - | POPUP QUOTEDSTRING BEG menuexitems END + | POPUP res_unicode_string BEG menuexitems END { $$ = define_menuitem ($2, 0, 0, 0, 0, $4); } - | POPUP QUOTEDSTRING cnumexpr BEG menuexitems END + | POPUP res_unicode_string cnumexpr BEG menuexitems END { $$ = define_menuitem ($2, $3, 0, 0, 0, $5); } - | POPUP QUOTEDSTRING cnumexpr cnumexpr BEG menuexitems END + | POPUP res_unicode_string cnumexpr cnumexpr BEG menuexitems END { $$ = define_menuitem ($2, $3, $4, 0, 0, $6); } - | POPUP QUOTEDSTRING cnumexpr cnumexpr cnumexpr optcnumexpr + | POPUP res_unicode_string cnumexpr cnumexpr cnumexpr optcnumexpr BEG menuexitems END { $$ = define_menuitem ($2, $3, $4, $5, $6, $8); @@ -1144,25 +1169,6 @@ messagetable: } ; -/* Rcdata resources. */ - -rcdata: - id RCDATA suboptions BEG optrcdata_data END - { - define_rcdata ($1, &$3, $5.first); - if (yychar != YYEMPTY) - YYERROR; - rcparse_discard_strings (); - } - | id RCDATA suboptions file_name - { - define_rcdata_file ($1, &$3, $4); - if (yychar != YYEMPTY) - YYERROR; - rcparse_discard_strings (); - } - ; - /* We use a different lexing algorithm, because rcdata strings may contain embedded null bytes, and we need to know the length to use. */ @@ -1190,34 +1196,51 @@ optrcdata_data_int: ; rcdata_data: - SIZEDSTRING + sizedstring { - struct rcdata_item *ri; + rc_rcdata_item *ri; ri = define_rcdata_string ($1.s, $1.length); $$.first = ri; $$.last = ri; } + | sizedunistring + { + rc_rcdata_item *ri; + + ri = define_rcdata_unistring ($1.s, $1.length); + $$.first = ri; + $$.last = ri; + } | sizednumexpr { - struct rcdata_item *ri; + rc_rcdata_item *ri; ri = define_rcdata_number ($1.val, $1.dword); $$.first = ri; $$.last = ri; } - | rcdata_data ',' SIZEDSTRING + | rcdata_data ',' sizedstring { - struct rcdata_item *ri; + rc_rcdata_item *ri; ri = define_rcdata_string ($3.s, $3.length); $$.first = $1.first; $1.last->next = ri; $$.last = ri; } + | rcdata_data ',' sizedunistring + { + rc_rcdata_item *ri; + + ri = define_rcdata_unistring ($3.s, $3.length); + $$.first = $1.first; + $1.last->next = ri; + $$.last = ri; + } | rcdata_data ',' sizednumexpr { - struct rcdata_item *ri; + rc_rcdata_item *ri; ri = define_rcdata_number ($3.val, $3.dword); $$.first = $1.first; @@ -1236,14 +1259,14 @@ stringtable: string_data: /* empty */ - | string_data numexpr QUOTEDSTRING + | string_data numexpr res_unicode_string { define_stringtable (&sub_res_info, $2, $3); if (yychar != YYEMPTY) YYERROR; rcparse_discard_strings (); } - | string_data numexpr ',' QUOTEDSTRING + | string_data numexpr ',' res_unicode_string { define_stringtable (&sub_res_info, $2, $4); if (yychar != YYEMPTY) @@ -1252,18 +1275,70 @@ string_data: } ; +rcdata_id: + id + { + $$=$1; + } + | HTML + { + $$.named = 0; + $$.u.id = 23; + } + | RCDATA + { + $$.named = 0; + $$.u.id = RT_RCDATA; + } + | MANIFEST + { + $$.named = 0; + $$.u.id = RT_MANIFEST; + } + | PLUGPLAY + { + $$.named = 0; + $$.u.id = RT_PLUGPLAY; + } + | VXD + { + $$.named = 0; + $$.u.id = RT_VXD; + } + | DLGINCLUDE + { + $$.named = 0; + $$.u.id = RT_DLGINCLUDE; + } + | DLGINIT + { + $$.named = 0; + $$.u.id = RT_DLGINIT; + } + | ANICURSOR + { + $$.named = 0; + $$.u.id = RT_ANICURSOR; + } + | ANIICON + { + $$.named = 0; + $$.u.id = RT_ANIICON; + } + ; + /* User defined resources. We accept general suboptions in the file_name case to keep the parser happy. */ user: - id id suboptions BEG optrcdata_data END + id rcdata_id suboptions BEG optrcdata_data END { define_user_data ($1, $2, &$3, $5.first); if (yychar != YYEMPTY) YYERROR; rcparse_discard_strings (); } - | id id suboptions file_name + | id rcdata_id suboptions file_name { define_user_file ($1, $2, &$3, $4); if (yychar != YYEMPTY) @@ -1272,6 +1347,55 @@ user: } ; +toolbar: + id TOOLBAR suboptions numexpr cnumexpr BEG toolbar_data END + { + define_toolbar ($1, &$3, $4, $5, $7); + } + ; + +toolbar_data: /* empty */ { $$= NULL; } + | toolbar_data BUTTON id + { + rc_toolbar_item *c,*n; + c = $1; + n= (rc_toolbar_item *) + res_alloc (sizeof (rc_toolbar_item)); + if (c != NULL) + while (c->next != NULL) + c = c->next; + n->prev = c; + n->next = NULL; + if (c != NULL) + c->next = n; + n->id = $3; + if ($1 == NULL) + $$ = n; + else + $$ = $1; + } + | toolbar_data SEPARATOR + { + rc_toolbar_item *c,*n; + c = $1; + n= (rc_toolbar_item *) + res_alloc (sizeof (rc_toolbar_item)); + if (c != NULL) + while (c->next != NULL) + c = c->next; + n->prev = c; + n->next = NULL; + if (c != NULL) + c->next = n; + n->id.named = 0; + n->id.u.id = 0; + if ($1 == NULL) + $$ = n; + else + $$ = $1; + } + ; + /* Versioninfo resources. */ versioninfo: @@ -1287,9 +1411,9 @@ versioninfo: fixedverinfo: /* empty */ { - $$ = ((struct fixed_versioninfo *) - res_alloc (sizeof (struct fixed_versioninfo))); - memset ($$, 0, sizeof (struct fixed_versioninfo)); + $$ = ((rc_fixed_versioninfo *) + res_alloc (sizeof (rc_fixed_versioninfo))); + memset ($$, 0, sizeof (rc_fixed_versioninfo)); } | fixedverinfo FILEVERSION numexpr cnumexpr cnumexpr cnumexpr { @@ -1345,7 +1469,7 @@ verblocks: { $$ = append_ver_stringfileinfo ($1, $4, $6); } - | verblocks BLOCKVARFILEINFO BEG VALUE QUOTEDSTRING vertrans END + | verblocks BLOCKVARFILEINFO BEG VALUE res_unicode_string vertrans END { $$ = append_ver_varfileinfo ($1, $5, $6); } @@ -1356,7 +1480,7 @@ vervals: { $$ = NULL; } - | vervals VALUE QUOTEDSTRING ',' QUOTEDSTRING + | vervals VALUE res_unicode_string ',' res_unicode_string { $$ = append_verval ($1, $3, $5); } @@ -1381,33 +1505,25 @@ id: $$.named = 0; $$.u.id = $1; } - | STRING - { - char *copy, *s; - /* It seems that resource ID's are forced to upper case. */ - copy = xstrdup ($1); - for (s = copy; *s != '\0'; s++) - *s = TOUPPER (*s); - res_string_to_id (&$$, copy); - free (copy); + | resname + { + res_unistring_to_id (&$$, $1); } ; /* A resource reference. */ resname: - QUOTEDSTRING - { - $$ = $1; - } - | QUOTEDSTRING ',' + res_unicode_string { $$ = $1; } - | STRING ',' + | STRING { - $$ = $1; + unichar *h = NULL; + unicode_from_ascii ((rc_uint_type *) NULL, &h, $1); + $$ = h; } ; @@ -1420,14 +1536,11 @@ resref: } | resname { - char *copy, *s; - - /* It seems that resource ID's are forced to upper case. */ - copy = xstrdup ($1); - for (s = copy; *s != '\0'; s++) - *s = TOUPPER (*s); - res_string_to_id (&$$, copy); - free (copy); + res_unistring_to_id (&$$, $1); + } + | resname ',' + { + res_unistring_to_id (&$$, $1); } ; @@ -1437,7 +1550,7 @@ resref: suboptions: /* empty */ { - memset (&$$, 0, sizeof (struct res_res_info)); + memset (&$$, 0, sizeof (rc_res_res_info)); $$.language = language; /* FIXME: Is this the right default? */ $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_PURE | MEMFLAG_DISCARDABLE; @@ -1470,7 +1583,7 @@ suboptions: memflags_move_discard: /* empty */ { - memset (&$$, 0, sizeof (struct res_res_info)); + memset (&$$, 0, sizeof (rc_res_res_info)); $$.language = language; $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_DISCARDABLE; } @@ -1487,7 +1600,7 @@ memflags_move_discard: memflags_move: /* empty */ { - memset (&$$, 0, sizeof (struct res_res_info)); + memset (&$$, 0, sizeof (rc_res_res_info)); $$.language = language; $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_PURE | MEMFLAG_DISCARDABLE; } @@ -1553,6 +1666,51 @@ file_name: } ; +res_unicode_string: + QUOTEDUNISTRING + { + $$ = unichar_dup ($1); + } + | QUOTEDSTRING + { + unichar *h = NULL; + unicode_from_ascii ((rc_uint_type *) NULL, &h, $1); + $$ = h; + } + ; + +sizedstring: + SIZEDSTRING + { + $$ = $1; + } + | sizedstring SIZEDSTRING + { + rc_uint_type l = $1.length + $2.length; + char *h = (char *) res_alloc (l); + memcpy (h, $1.s, $1.length); + memcpy (h + $1.length, $2.s, $2.length); + $$.s = h; + $$.length = l; + } + ; + +sizedunistring: + SIZEDUNISTRING + { + $$ = $1; + } + | sizedunistring SIZEDUNISTRING + { + rc_uint_type l = $1.length + $2.length; + unichar *h = (unichar *) res_alloc (l * sizeof (unichar)); + memcpy (h, $1.s, $1.length * sizeof (unichar)); + memcpy (h + $1.length, $2.s, $2.length * sizeof (unichar)); + $$.s = h; + $$.length = l; + } + ; + /* A style expression. This changes the static variable STYLE. We do it this way because rc appears to permit a style to be set to something like diff --git a/binutils/resbin.c b/binutils/resbin.c index 5d8b53be196..7c8f5019641 100644 --- a/binutils/resbin.c +++ b/binutils/resbin.c @@ -2,6 +2,7 @@ Copyright 1997, 1998, 1999, 2002, 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. @@ -26,101 +27,86 @@ #include "sysdep.h" #include "bfd.h" -#include "libiberty.h" #include "bucomm.h" +#include "libiberty.h" #include "windres.h" -/* Macros to swap in values. */ - -#define get_8(s) (*((unsigned char *)(s))) -#define get_16(be, s) ((be) ? bfd_getb16 (s) : bfd_getl16 (s)) -#define get_32(be, s) ((be) ? bfd_getb32 (s) : bfd_getl32 (s)) - /* Local functions. */ static void toosmall (const char *); -static unichar *get_unicode - (const unsigned char *, unsigned long, int, int *); -static int get_resid - (struct res_id *, const unsigned char *, unsigned long, int); -static struct res_resource *bin_to_res_generic - (enum res_type, const unsigned char *, unsigned long); -static struct res_resource *bin_to_res_cursor - (const unsigned char *, unsigned long, int); -static struct res_resource *bin_to_res_menu - (const unsigned char *, unsigned long, int); -static struct menuitem *bin_to_res_menuitems - (const unsigned char *, unsigned long, int, int *); -static struct menuitem *bin_to_res_menuexitems - (const unsigned char *, unsigned long, int, int *); -static struct res_resource *bin_to_res_dialog - (const unsigned char *, unsigned long, int); -static struct res_resource *bin_to_res_string - (const unsigned char *, unsigned long, int); -static struct res_resource *bin_to_res_fontdir - (const unsigned char *, unsigned long, int); -static struct res_resource *bin_to_res_accelerators - (const unsigned char *, unsigned long, int); -static struct res_resource *bin_to_res_rcdata - (const unsigned char *, unsigned long, int); -static struct res_resource *bin_to_res_group_cursor - (const unsigned char *, unsigned long, int); -static struct res_resource *bin_to_res_group_icon - (const unsigned char *, unsigned long, int); -static struct res_resource *bin_to_res_version - (const unsigned char *, unsigned long, int); -static struct res_resource *bin_to_res_userdata - (const unsigned char *, unsigned long, int); -static void get_version_header - (const unsigned char *, unsigned long, int, const char *, - unichar **, int *, int *, int *, int *); +static unichar *get_unicode (windres_bfd *, const bfd_byte *, rc_uint_type, rc_uint_type *); +static int get_resid (windres_bfd *, rc_res_id *, const bfd_byte *, rc_uint_type); +static rc_res_resource *bin_to_res_generic (windres_bfd *, enum rc_res_type, + const bfd_byte *, rc_uint_type); +static rc_res_resource *bin_to_res_cursor (windres_bfd *, const bfd_byte *, rc_uint_type); +static rc_res_resource *bin_to_res_menu (windres_bfd *,const bfd_byte *, rc_uint_type); +static rc_menuitem *bin_to_res_menuitems (windres_bfd *, const bfd_byte *, rc_uint_type, + rc_uint_type *); +static rc_menuitem *bin_to_res_menuexitems (windres_bfd *, const bfd_byte *, rc_uint_type, + rc_uint_type *); +static rc_res_resource *bin_to_res_dialog (windres_bfd *, const bfd_byte *, rc_uint_type); +static rc_res_resource *bin_to_res_string (windres_bfd *,const bfd_byte *, rc_uint_type); +static rc_res_resource *bin_to_res_fontdir (windres_bfd *, const bfd_byte *, rc_uint_type); +static rc_res_resource *bin_to_res_accelerators (windres_bfd *, const bfd_byte *, rc_uint_type); +static rc_res_resource *bin_to_res_rcdata (windres_bfd *, const bfd_byte *, rc_uint_type, int); +static rc_res_resource *bin_to_res_group_cursor (windres_bfd *, const bfd_byte *, rc_uint_type); +static rc_res_resource *bin_to_res_group_icon (windres_bfd *, const bfd_byte *, rc_uint_type); +static rc_res_resource *bin_to_res_version (windres_bfd *, const bfd_byte *, rc_uint_type); +static rc_res_resource *bin_to_res_userdata (windres_bfd *, const bfd_byte *, rc_uint_type); +static rc_res_resource *bin_to_res_toolbar (windres_bfd *, const bfd_byte *, rc_uint_type); +static void get_version_header (windres_bfd *, const bfd_byte *, rc_uint_type, const char *, + unichar **, rc_uint_type *, rc_uint_type *, rc_uint_type *, + rc_uint_type *); /* Given a resource type ID, a pointer to data, a length, return a - res_resource structure which represents that resource. The caller + rc_res_resource structure which represents that resource. The caller is responsible for initializing the res_info and coff_info fields of the returned structure. */ -struct res_resource * -bin_to_res (struct res_id type, const unsigned char *data, - unsigned long length, int big_endian) +rc_res_resource * +bin_to_res (windres_bfd *wrbfd, rc_res_id type, const bfd_byte *data, + rc_uint_type length) { if (type.named) - return bin_to_res_userdata (data, length, big_endian); + return bin_to_res_userdata (wrbfd, data, length); else { switch (type.u.id) { default: - return bin_to_res_userdata (data, length, big_endian); + return bin_to_res_userdata (wrbfd, data, length); case RT_CURSOR: - return bin_to_res_cursor (data, length, big_endian); + return bin_to_res_cursor (wrbfd, data, length); case RT_BITMAP: - return bin_to_res_generic (RES_TYPE_BITMAP, data, length); + return bin_to_res_generic (wrbfd, RES_TYPE_BITMAP, data, length); case RT_ICON: - return bin_to_res_generic (RES_TYPE_ICON, data, length); + return bin_to_res_generic (wrbfd, RES_TYPE_ICON, data, length); case RT_MENU: - return bin_to_res_menu (data, length, big_endian); + return bin_to_res_menu (wrbfd, data, length); case RT_DIALOG: - return bin_to_res_dialog (data, length, big_endian); + return bin_to_res_dialog (wrbfd, data, length); case RT_STRING: - return bin_to_res_string (data, length, big_endian); + return bin_to_res_string (wrbfd, data, length); case RT_FONTDIR: - return bin_to_res_fontdir (data, length, big_endian); + return bin_to_res_fontdir (wrbfd, data, length); case RT_FONT: - return bin_to_res_generic (RES_TYPE_FONT, data, length); + return bin_to_res_generic (wrbfd, RES_TYPE_FONT, data, length); case RT_ACCELERATOR: - return bin_to_res_accelerators (data, length, big_endian); + return bin_to_res_accelerators (wrbfd, data, length); case RT_RCDATA: - return bin_to_res_rcdata (data, length, big_endian); + return bin_to_res_rcdata (wrbfd, data, length, RES_TYPE_RCDATA); case RT_MESSAGETABLE: - return bin_to_res_generic (RES_TYPE_MESSAGETABLE, data, length); + return bin_to_res_generic (wrbfd, RES_TYPE_MESSAGETABLE, data, length); case RT_GROUP_CURSOR: - return bin_to_res_group_cursor (data, length, big_endian); + return bin_to_res_group_cursor (wrbfd, data, length); case RT_GROUP_ICON: - return bin_to_res_group_icon (data, length, big_endian); + return bin_to_res_group_icon (wrbfd, data, length); case RT_VERSION: - return bin_to_res_version (data, length, big_endian); + return bin_to_res_version (wrbfd, data, length); + case RT_TOOLBAR: + return bin_to_res_toolbar (wrbfd, data, length); + } } } @@ -136,18 +122,18 @@ toosmall (const char *msg) /* Swap in a NULL terminated unicode string. */ static unichar * -get_unicode (const unsigned char *data, unsigned long length, - int big_endian, int *retlen) +get_unicode (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length, + rc_uint_type *retlen) { - int c, i; + rc_uint_type c, i; unichar *ret; c = 0; while (1) { - if (length < (unsigned long) c * 2 + 2) + if (length < c * 2 + 2) toosmall (_("null terminated unicode string")); - if (get_16 (big_endian, data + c * 2) == 0) + if (windres_get_16 (wrbfd, data + c * 2, 2) == 0) break; ++c; } @@ -155,7 +141,7 @@ get_unicode (const unsigned char *data, unsigned long length, ret = (unichar *) res_alloc ((c + 1) * sizeof (unichar)); for (i = 0; i < c; i++) - ret[i] = get_16 (big_endian, data + i * 2); + ret[i] = windres_get_16 (wrbfd, data + i * 2, 2); ret[i] = 0; if (retlen != NULL) @@ -167,27 +153,27 @@ get_unicode (const unsigned char *data, unsigned long length, /* Get a resource identifier. This returns the number of bytes used. */ static int -get_resid (struct res_id *id, const unsigned char *data, - unsigned long length, int big_endian) +get_resid (windres_bfd *wrbfd, rc_res_id *id, const bfd_byte *data, + rc_uint_type length) { - int first; + rc_uint_type first; if (length < 2) toosmall (_("resource ID")); - first = get_16 (big_endian, data); + first = windres_get_16 (wrbfd, data, 2); if (first == 0xffff) { if (length < 4) toosmall (_("resource ID")); id->named = 0; - id->u.id = get_16 (big_endian, data + 2); + id->u.id = windres_get_16 (wrbfd, data + 2, 2); return 4; } else { id->named = 1; - id->u.n.name = get_unicode (data, length, big_endian, &id->u.n.length); + id->u.n.name = get_unicode (wrbfd, data, length, &id->u.n.length); return id->u.n.length * 2 + 2; } } @@ -195,13 +181,13 @@ get_resid (struct res_id *id, const unsigned char *data, /* Convert a resource which just stores uninterpreted data from binary. */ -struct res_resource * -bin_to_res_generic (enum res_type type, const unsigned char *data, - unsigned long length) +rc_res_resource * +bin_to_res_generic (windres_bfd *wrbfd ATTRIBUTE_UNUSED, enum rc_res_type type, + const bfd_byte *data, rc_uint_type length) { - struct res_resource *r; + rc_res_resource *r; - r = (struct res_resource *) res_alloc (sizeof *r); + r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource)); r->type = type; r->u.data.data = data; r->u.data.length = length; @@ -211,23 +197,22 @@ bin_to_res_generic (enum res_type type, const unsigned char *data, /* Convert a cursor resource from binary. */ -struct res_resource * -bin_to_res_cursor (const unsigned char *data, unsigned long length, - int big_endian) +rc_res_resource * +bin_to_res_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) { - struct cursor *c; - struct res_resource *r; + rc_cursor *c; + rc_res_resource *r; if (length < 4) toosmall (_("cursor")); - c = (struct cursor *) res_alloc (sizeof *c); - c->xhotspot = get_16 (big_endian, data); - c->yhotspot = get_16 (big_endian, data + 2); + c = (rc_cursor *) res_alloc (sizeof (rc_cursor)); + c->xhotspot = windres_get_16 (wrbfd, data, 2); + c->yhotspot = windres_get_16 (wrbfd, data + 2, 2); c->length = length - 4; c->data = data + 4; - r = (struct res_resource *) res_alloc (sizeof *r); + r = (rc_res_resource *) res_alloc (sizeof *r); r->type = RES_TYPE_CURSOR; r->u.cursor = c; @@ -236,61 +221,57 @@ bin_to_res_cursor (const unsigned char *data, unsigned long length, /* Convert a menu resource from binary. */ -struct res_resource * -bin_to_res_menu (const unsigned char *data, unsigned long length, - int big_endian) +rc_res_resource * +bin_to_res_menu (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) { - struct res_resource *r; - struct menu *m; - int version, read; + rc_res_resource *r; + rc_menu *m; + rc_uint_type version, read; - r = (struct res_resource *) res_alloc (sizeof *r); + r = (rc_res_resource *) res_alloc (sizeof *r); r->type = RES_TYPE_MENU; - m = (struct menu *) res_alloc (sizeof *m); + m = (rc_menu *) res_alloc (sizeof (rc_menu)); r->u.menu = m; if (length < 2) toosmall (_("menu header")); - version = get_16 (big_endian, data); + version = windres_get_16 (wrbfd, data, 2); if (version == 0) { if (length < 4) toosmall (_("menu header")); m->help = 0; - m->items = bin_to_res_menuitems (data + 4, length - 4, big_endian, - &read); + m->items = bin_to_res_menuitems (wrbfd, data + 4, length - 4, &read); } else if (version == 1) { - unsigned int offset; + rc_uint_type offset; if (length < 8) toosmall (_("menuex header")); - m->help = get_32 (big_endian, data + 4); - offset = get_16 (big_endian, data + 2); + m->help = windres_get_32 (wrbfd, data + 4, 4); + offset = windres_get_16 (wrbfd, data + 2, 2); if (offset + 4 >= length) toosmall (_("menuex offset")); - m->items = bin_to_res_menuexitems (data + 4 + offset, - length - (4 + offset), - big_endian, - &read); + m->items = bin_to_res_menuexitems (wrbfd, data + 4 + offset, + length - (4 + offset), &read); } else - fatal (_("unsupported menu version %d"), version); + fatal (_("unsupported menu version %d"), (int) version); return r; } /* Convert menu items from binary. */ -static struct menuitem * -bin_to_res_menuitems (const unsigned char *data, unsigned long length, - int big_endian, int *read) +static rc_menuitem * +bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length, + rc_uint_type *read) { - struct menuitem *first, **pp; + rc_menuitem *first, **pp; first = NULL; pp = &first; @@ -299,18 +280,18 @@ bin_to_res_menuitems (const unsigned char *data, unsigned long length, while (length > 0) { - int flags, slen, itemlen; - unsigned int stroff; - struct menuitem *mi; + rc_uint_type flags, slen, itemlen; + rc_uint_type stroff; + rc_menuitem *mi; if (length < 4) toosmall (_("menuitem header")); - mi = (struct menuitem *) res_alloc (sizeof *mi); + mi = (rc_menuitem *) res_alloc (sizeof *mi); mi->state = 0; mi->help = 0; - flags = get_16 (big_endian, data); + flags = windres_get_16 (wrbfd, data, 2); mi->type = flags &~ (MENUITEM_POPUP | MENUITEM_ENDMENU); if ((flags & MENUITEM_POPUP) == 0) @@ -321,29 +302,28 @@ bin_to_res_menuitems (const unsigned char *data, unsigned long length, if (length < stroff + 2) toosmall (_("menuitem header")); - if (get_16 (big_endian, data + stroff) == 0) + if (windres_get_16 (wrbfd, data + stroff, 2) == 0) { slen = 0; mi->text = NULL; } else - mi->text = get_unicode (data + stroff, length - stroff, big_endian, - &slen); + mi->text = get_unicode (wrbfd, data + stroff, length - stroff, &slen); itemlen = stroff + slen * 2 + 2; if ((flags & MENUITEM_POPUP) == 0) { mi->popup = NULL; - mi->id = get_16 (big_endian, data + 2); + mi->id = windres_get_16 (wrbfd, data + 2, 2); } else { - int subread; + rc_uint_type subread; mi->id = 0; - mi->popup = bin_to_res_menuitems (data + itemlen, length - itemlen, - big_endian, &subread); + mi->popup = bin_to_res_menuitems (wrbfd, data + itemlen, length - itemlen, + &subread); itemlen += subread; } @@ -364,11 +344,11 @@ bin_to_res_menuitems (const unsigned char *data, unsigned long length, /* Convert menuex items from binary. */ -static struct menuitem * -bin_to_res_menuexitems (const unsigned char *data, unsigned long length, - int big_endian, int *read) +static rc_menuitem * +bin_to_res_menuexitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length, + rc_uint_type *read) { - struct menuitem *first, **pp; + rc_menuitem *first, **pp; first = NULL; pp = &first; @@ -377,29 +357,29 @@ bin_to_res_menuexitems (const unsigned char *data, unsigned long length, while (length > 0) { - int flags, slen; - unsigned int itemlen; - struct menuitem *mi; + rc_uint_type flags, slen; + rc_uint_type itemlen; + rc_menuitem *mi; - if (length < 14) + if (length < 16) toosmall (_("menuitem header")); - mi = (struct menuitem *) res_alloc (sizeof *mi); - mi->type = get_32 (big_endian, data); - mi->state = get_32 (big_endian, data + 4); - mi->id = get_16 (big_endian, data + 8); + mi = (rc_menuitem *) res_alloc (sizeof (rc_menuitem)); + mi->type = windres_get_32 (wrbfd, data, 4); + mi->state = windres_get_32 (wrbfd, data + 4, 4); + mi->id = windres_get_32 (wrbfd, data + 8, 4); - flags = get_16 (big_endian, data + 10); + flags = windres_get_16 (wrbfd, data + 12, 2); - if (get_16 (big_endian, data + 12) == 0) + if (windres_get_16 (wrbfd, data + 14, 2) == 0) { slen = 0; mi->text = NULL; } else - mi->text = get_unicode (data + 12, length - 12, big_endian, &slen); + mi->text = get_unicode (wrbfd, data + 14, length - 14, &slen); - itemlen = 12 + slen * 2 + 2; + itemlen = 14 + slen * 2 + 2; itemlen = (itemlen + 3) &~ 3; if ((flags & 1) == 0) @@ -409,16 +389,15 @@ bin_to_res_menuexitems (const unsigned char *data, unsigned long length, } else { - int subread; + rc_uint_type subread; if (length < itemlen + 4) toosmall (_("menuitem")); - mi->help = get_32 (big_endian, data + itemlen); + mi->help = windres_get_32 (wrbfd, data + itemlen, 4); itemlen += 4; - mi->popup = bin_to_res_menuexitems (data + itemlen, - length - itemlen, - big_endian, &subread); + mi->popup = bin_to_res_menuexitems (wrbfd, data + itemlen, + length - itemlen, &subread); itemlen += subread; } @@ -439,63 +418,62 @@ bin_to_res_menuexitems (const unsigned char *data, unsigned long length, /* Convert a dialog resource from binary. */ -static struct res_resource * -bin_to_res_dialog (const unsigned char *data, unsigned long length, - int big_endian) +static rc_res_resource * +bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) { - int signature; - struct dialog *d; - int c, sublen, i; - unsigned int off; - struct dialog_control **pp; - struct res_resource *r; + rc_uint_type signature; + rc_dialog *d; + rc_uint_type c, sublen, i; + rc_uint_type off; + rc_dialog_control **pp; + rc_res_resource *r; if (length < 18) toosmall (_("dialog header")); - d = (struct dialog *) res_alloc (sizeof *d); + d = (rc_dialog *) res_alloc (sizeof (rc_dialog)); - signature = get_16 (big_endian, data + 2); + signature = windres_get_16 (wrbfd, data + 2, 2); if (signature != 0xffff) { d->ex = NULL; - d->style = get_32 (big_endian, data); - d->exstyle = get_32 (big_endian, data + 4); + d->style = windres_get_32 (wrbfd, data, 4); + d->exstyle = windres_get_32 (wrbfd, data + 4, 4); off = 8; } else { int version; - version = get_16 (big_endian, data); + version = windres_get_16 (wrbfd, data, 2); if (version != 1) fatal (_("unexpected DIALOGEX version %d"), version); - d->ex = (struct dialog_ex *) res_alloc (sizeof (struct dialog_ex)); - d->ex->help = get_32 (big_endian, data + 4); - d->exstyle = get_32 (big_endian, data + 8); - d->style = get_32 (big_endian, data + 12); + d->ex = (rc_dialog_ex *) res_alloc (sizeof (rc_dialog_ex)); + d->ex->help = windres_get_32 (wrbfd, data + 4, 4); + d->exstyle = windres_get_32 (wrbfd, data + 8, 4); + d->style = windres_get_32 (wrbfd, data + 12, 4); off = 16; } if (length < off + 10) toosmall (_("dialog header")); - c = get_16 (big_endian, data + off); - d->x = get_16 (big_endian, data + off + 2); - d->y = get_16 (big_endian, data + off + 4); - d->width = get_16 (big_endian, data + off + 6); - d->height = get_16 (big_endian, data + off + 8); + c = windres_get_16 (wrbfd, data + off, 2); + d->x = windres_get_16 (wrbfd, data + off + 2, 2); + d->y = windres_get_16 (wrbfd, data + off + 4, 2); + d->width = windres_get_16 (wrbfd, data + off + 6, 2); + d->height = windres_get_16 (wrbfd, data + off + 8, 2); off += 10; - sublen = get_resid (&d->menu, data + off, length - off, big_endian); + sublen = get_resid (wrbfd, &d->menu, data + off, length - off); off += sublen; - sublen = get_resid (&d->class, data + off, length - off, big_endian); + sublen = get_resid (wrbfd, &d->class, data + off, length - off); off += sublen; - d->caption = get_unicode (data + off, length - off, big_endian, &sublen); + d->caption = get_unicode (wrbfd, data + off, length - off, &sublen); off += sublen * 2 + 2; if (sublen == 0) d->caption = NULL; @@ -516,20 +494,20 @@ bin_to_res_dialog (const unsigned char *data, unsigned long length, if (length < off + 2) toosmall (_("dialog font point size")); - d->pointsize = get_16 (big_endian, data + off); + d->pointsize = windres_get_16 (wrbfd, data + off, 2); off += 2; if (d->ex != NULL) { if (length < off + 4) toosmall (_("dialogex font information")); - d->ex->weight = get_16 (big_endian, data + off); - d->ex->italic = get_8 (data + off + 2); - d->ex->charset = get_8 (data + off + 3); + d->ex->weight = windres_get_16 (wrbfd, data + off, 2); + d->ex->italic = windres_get_8 (wrbfd, data + off + 2, 1); + d->ex->charset = windres_get_8 (wrbfd, data + off + 3, 1); off += 4; } - d->font = get_unicode (data + off, length - off, big_endian, &sublen); + d->font = get_unicode (wrbfd, data + off, length - off, &sublen); off += sublen * 2 + 2; } @@ -538,20 +516,20 @@ bin_to_res_dialog (const unsigned char *data, unsigned long length, for (i = 0; i < c; i++) { - struct dialog_control *dc; + rc_dialog_control *dc; int datalen; off = (off + 3) &~ 3; - dc = (struct dialog_control *) res_alloc (sizeof *dc); + dc = (rc_dialog_control *) res_alloc (sizeof (rc_dialog_control)); if (d->ex == NULL) { if (length < off + 8) toosmall (_("dialog control")); - dc->style = get_32 (big_endian, data + off); - dc->exstyle = get_32 (big_endian, data + off + 4); + dc->style = windres_get_32 (wrbfd, data + off, 4); + dc->exstyle = windres_get_32 (wrbfd, data + off + 4, 4); dc->help = 0; off += 8; } @@ -559,37 +537,37 @@ bin_to_res_dialog (const unsigned char *data, unsigned long length, { if (length < off + 12) toosmall (_("dialogex control")); - dc->help = get_32 (big_endian, data + off); - dc->exstyle = get_32 (big_endian, data + off + 4); - dc->style = get_32 (big_endian, data + off + 8); + dc->help = windres_get_32 (wrbfd, data + off, 4); + dc->exstyle = windres_get_32 (wrbfd, data + off + 4, 4); + dc->style = windres_get_32 (wrbfd, data + off + 8, 4); off += 12; } - if (length < off + 10) + if (length < off + (d->ex != NULL ? 2 : 0) + 10) toosmall (_("dialog control")); - dc->x = get_16 (big_endian, data + off); - dc->y = get_16 (big_endian, data + off + 2); - dc->width = get_16 (big_endian, data + off + 4); - dc->height = get_16 (big_endian, data + off + 6); + dc->x = windres_get_16 (wrbfd, data + off, 2); + dc->y = windres_get_16 (wrbfd, data + off + 2, 2); + dc->width = windres_get_16 (wrbfd, data + off + 4, 2); + dc->height = windres_get_16 (wrbfd, data + off + 6, 2); if (d->ex != NULL) - dc->id = get_32 (big_endian, data + off + 8); + dc->id = windres_get_32 (wrbfd, data + off + 8, 4); else - dc->id = get_16 (big_endian, data + off + 8); + dc->id = windres_get_16 (wrbfd, data + off + 8, 2); off += 10 + (d->ex != NULL ? 2 : 0); - sublen = get_resid (&dc->class, data + off, length - off, big_endian); + sublen = get_resid (wrbfd, &dc->class, data + off, length - off); off += sublen; - sublen = get_resid (&dc->text, data + off, length - off, big_endian); + sublen = get_resid (wrbfd, &dc->text, data + off, length - off); off += sublen; if (length < off + 2) toosmall (_("dialog control end")); - datalen = get_16 (big_endian, data + off); + datalen = windres_get_16 (wrbfd, data + off, 2); off += 2; if (datalen == 0) @@ -601,8 +579,8 @@ bin_to_res_dialog (const unsigned char *data, unsigned long length, if (length < off + datalen) toosmall (_("dialog control data")); - dc->data = ((struct rcdata_item *) - res_alloc (sizeof (struct rcdata_item))); + dc->data = ((rc_rcdata_item *) + res_alloc (sizeof (rc_rcdata_item))); dc->data->next = NULL; dc->data->type = RCDATA_BUFFER; dc->data->u.buffer.length = datalen; @@ -616,7 +594,7 @@ bin_to_res_dialog (const unsigned char *data, unsigned long length, pp = &dc->next; } - r = (struct res_resource *) res_alloc (sizeof *r); + r = (rc_res_resource *) res_alloc (sizeof *r); r->type = RES_TYPE_DIALOG; r->u.dialog = d; @@ -625,15 +603,14 @@ bin_to_res_dialog (const unsigned char *data, unsigned long length, /* Convert a stringtable resource from binary. */ -static struct res_resource * -bin_to_res_string (const unsigned char *data, unsigned long length, - int big_endian) +static rc_res_resource * +bin_to_res_string (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) { - struct stringtable *st; + rc_stringtable *st; int i; - struct res_resource *r; + rc_res_resource *r; - st = (struct stringtable *) res_alloc (sizeof *st); + st = (rc_stringtable *) res_alloc (sizeof (rc_stringtable)); for (i = 0; i < 16; i++) { @@ -641,7 +618,7 @@ bin_to_res_string (const unsigned char *data, unsigned long length, if (length < 2) toosmall (_("stringtable string length")); - slen = get_16 (big_endian, data); + slen = windres_get_16 (wrbfd, data, 2); st->strings[i].length = slen; if (slen > 0) @@ -656,14 +633,14 @@ bin_to_res_string (const unsigned char *data, unsigned long length, st->strings[i].string = s; for (j = 0; j < slen; j++) - s[j] = get_16 (big_endian, data + 2 + j * 2); + s[j] = windres_get_16 (wrbfd, data + 2 + j * 2, 2); } data += 2 + 2 * slen; length -= 2 + 2 * slen; } - r = (struct res_resource *) res_alloc (sizeof *r); + r = (rc_res_resource *) res_alloc (sizeof *r); r->type = RES_TYPE_STRINGTABLE; r->u.stringtable = st; @@ -672,36 +649,37 @@ bin_to_res_string (const unsigned char *data, unsigned long length, /* Convert a fontdir resource from binary. */ -static struct res_resource * -bin_to_res_fontdir (const unsigned char *data, unsigned long length, - int big_endian) +static rc_res_resource * +bin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) { - int c, i; - struct fontdir *first, **pp; - struct res_resource *r; + rc_uint_type c, i; + rc_fontdir *first, **pp; + rc_res_resource *r; if (length < 2) toosmall (_("fontdir header")); - c = get_16 (big_endian, data); + c = windres_get_16 (wrbfd, data, 2); first = NULL; pp = &first; for (i = 0; i < c; i++) { - struct fontdir *fd; + const struct bin_fontdir_item *bfi; + rc_fontdir *fd; unsigned int off; if (length < 56) toosmall (_("fontdir")); - fd = (struct fontdir *) res_alloc (sizeof *fd); - fd->index = get_16 (big_endian, data); + bfi = (const struct bin_fontdir_item *) data; + fd = (rc_fontdir *) res_alloc (sizeof *fd); + fd->index = windres_get_16 (wrbfd, bfi->index, 2); /* To work out the length of the fontdir data, we must get the length of the device name and face name strings, even though - we don't store them in the fontdir structure. The + we don't store them in the rc_fontdir. The documentation says that these are NULL terminated char strings, not Unicode strings. */ @@ -733,7 +711,7 @@ bin_to_res_fontdir (const unsigned char *data, unsigned long length, length -= off; } - r = (struct res_resource *) res_alloc (sizeof *r); + r = (rc_res_resource *) res_alloc (sizeof *r); r->type = RES_TYPE_FONTDIR; r->u.fontdir = first; @@ -742,28 +720,27 @@ bin_to_res_fontdir (const unsigned char *data, unsigned long length, /* Convert an accelerators resource from binary. */ -static struct res_resource * -bin_to_res_accelerators (const unsigned char *data, unsigned long length, - int big_endian) +static rc_res_resource * +bin_to_res_accelerators (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) { - struct accelerator *first, **pp; - struct res_resource *r; + rc_accelerator *first, **pp; + rc_res_resource *r; first = NULL; pp = &first; while (1) { - struct accelerator *a; + rc_accelerator *a; if (length < 8) toosmall (_("accelerator")); - a = (struct accelerator *) res_alloc (sizeof *a); + a = (rc_accelerator *) res_alloc (sizeof (rc_accelerator)); - a->flags = get_16 (big_endian, data); - a->key = get_16 (big_endian, data + 2); - a->id = get_16 (big_endian, data + 4); + a->flags = windres_get_16 (wrbfd, data, 2); + a->key = windres_get_16 (wrbfd, data + 2, 2); + a->id = windres_get_16 (wrbfd, data + 4, 2); a->next = NULL; *pp = a; @@ -776,7 +753,7 @@ bin_to_res_accelerators (const unsigned char *data, unsigned long length, length -= 8; } - r = (struct res_resource *) res_alloc (sizeof *r); + r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource)); r->type = RES_TYPE_ACCELERATOR; r->u.acc = first; @@ -785,22 +762,22 @@ bin_to_res_accelerators (const unsigned char *data, unsigned long length, /* Convert an rcdata resource from binary. */ -static struct res_resource * -bin_to_res_rcdata (const unsigned char *data, unsigned long length, - int big_endian ATTRIBUTE_UNUSED) +static rc_res_resource * +bin_to_res_rcdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data, + rc_uint_type length, int rctyp) { - struct rcdata_item *ri; - struct res_resource *r; + rc_rcdata_item *ri; + rc_res_resource *r; - ri = (struct rcdata_item *) res_alloc (sizeof *ri); + ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item)); ri->next = NULL; ri->type = RCDATA_BUFFER; ri->u.buffer.length = length; ri->u.buffer.data = data; - r = (struct res_resource *) res_alloc (sizeof *r); - r->type = RES_TYPE_RCDATA; + r = (rc_res_resource *) res_alloc (sizeof *r); + r->type = rctyp; r->u.rcdata = ri; return r; @@ -808,22 +785,21 @@ bin_to_res_rcdata (const unsigned char *data, unsigned long length, /* Convert a group cursor resource from binary. */ -static struct res_resource * -bin_to_res_group_cursor (const unsigned char *data, unsigned long length, - int big_endian) +static rc_res_resource * +bin_to_res_group_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) { int type, c, i; - struct group_cursor *first, **pp; - struct res_resource *r; + rc_group_cursor *first, **pp; + rc_res_resource *r; if (length < 6) toosmall (_("group cursor header")); - type = get_16 (big_endian, data + 2); + type = windres_get_16 (wrbfd, data + 2, 2); if (type != 2) fatal (_("unexpected group cursor type %d"), type); - c = get_16 (big_endian, data + 4); + c = windres_get_16 (wrbfd, data + 4, 2); data += 6; length -= 6; @@ -833,19 +809,19 @@ bin_to_res_group_cursor (const unsigned char *data, unsigned long length, for (i = 0; i < c; i++) { - struct group_cursor *gc; + rc_group_cursor *gc; if (length < 14) toosmall (_("group cursor")); - gc = (struct group_cursor *) res_alloc (sizeof *gc); + gc = (rc_group_cursor *) res_alloc (sizeof *gc); - gc->width = get_16 (big_endian, data); - gc->height = get_16 (big_endian, data + 2); - gc->planes = get_16 (big_endian, data + 4); - gc->bits = get_16 (big_endian, data + 6); - gc->bytes = get_32 (big_endian, data + 8); - gc->index = get_16 (big_endian, data + 12); + gc->width = windres_get_16 (wrbfd, data, 2); + gc->height = windres_get_16 (wrbfd, data + 2, 2); + gc->planes = windres_get_16 (wrbfd, data + 4, 2); + gc->bits = windres_get_16 (wrbfd, data + 6, 2); + gc->bytes = windres_get_32 (wrbfd, data + 8, 4); + gc->index = windres_get_16 (wrbfd, data + 12, 2); gc->next = NULL; *pp = gc; @@ -855,7 +831,7 @@ bin_to_res_group_cursor (const unsigned char *data, unsigned long length, length -= 14; } - r = (struct res_resource *) res_alloc (sizeof *r); + r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource)); r->type = RES_TYPE_GROUP_CURSOR; r->u.group_cursor = first; @@ -864,22 +840,21 @@ bin_to_res_group_cursor (const unsigned char *data, unsigned long length, /* Convert a group icon resource from binary. */ -static struct res_resource * -bin_to_res_group_icon (const unsigned char *data, unsigned long length, - int big_endian) +static rc_res_resource * +bin_to_res_group_icon (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) { int type, c, i; - struct group_icon *first, **pp; - struct res_resource *r; + rc_group_icon *first, **pp; + rc_res_resource *r; if (length < 6) toosmall (_("group icon header")); - type = get_16 (big_endian, data + 2); + type = windres_get_16 (wrbfd, data + 2, 2); if (type != 1) fatal (_("unexpected group icon type %d"), type); - c = get_16 (big_endian, data + 4); + c = windres_get_16 (wrbfd, data + 4, 2); data += 6; length -= 6; @@ -889,20 +864,20 @@ bin_to_res_group_icon (const unsigned char *data, unsigned long length, for (i = 0; i < c; i++) { - struct group_icon *gi; + rc_group_icon *gi; if (length < 14) toosmall (_("group icon")); - gi = (struct group_icon *) res_alloc (sizeof *gi); + gi = (rc_group_icon *) res_alloc (sizeof (rc_group_icon)); - gi->width = data[0]; - gi->height = data[1]; - gi->colors = data[2]; - gi->planes = get_16 (big_endian, data + 4); - gi->bits = get_16 (big_endian, data + 6); - gi->bytes = get_32 (big_endian, data + 8); - gi->index = get_16 (big_endian, data + 12); + gi->width = windres_get_8 (wrbfd, data, 1); + gi->height = windres_get_8 (wrbfd, data + 1, 1); + gi->colors = windres_get_8 (wrbfd, data + 2, 1); + gi->planes = windres_get_16 (wrbfd, data + 4, 2); + gi->bits = windres_get_16 (wrbfd, data + 6, 2); + gi->bytes = windres_get_32 (wrbfd, data + 8, 4); + gi->index = windres_get_16 (wrbfd, data + 12, 2); gi->next = NULL; *pp = gi; @@ -912,7 +887,7 @@ bin_to_res_group_icon (const unsigned char *data, unsigned long length, length -= 14; } - r = (struct res_resource *) res_alloc (sizeof *r); + r = (rc_res_resource *) res_alloc (sizeof *r); r->type = RES_TYPE_GROUP_ICON; r->u.group_icon = first; @@ -925,16 +900,17 @@ bin_to_res_group_icon (const unsigned char *data, unsigned long length, to the type, and *OFF to the offset to the children. */ static void -get_version_header (const unsigned char *data, unsigned long length, - int big_endian, const char *key, unichar **pkey, - int *len, int *vallen, int *type, int *off) +get_version_header (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length, + const char *key, unichar **pkey, + rc_uint_type *len, rc_uint_type *vallen, rc_uint_type *type, + rc_uint_type *off) { if (length < 8) toosmall (key); - *len = get_16 (big_endian, data); - *vallen = get_16 (big_endian, data + 2); - *type = get_16 (big_endian, data + 4); + *len = windres_get_16 (wrbfd, data, 2); + *vallen = windres_get_16 (wrbfd, data + 2, 2); + *type = windres_get_16 (wrbfd, data + 4, 2); *off = 6; @@ -943,10 +919,10 @@ get_version_header (const unsigned char *data, unsigned long length, if (key == NULL) { - int sublen; + rc_uint_type sublen; - *pkey = get_unicode (data, length, big_endian, &sublen); - *off += sublen * 2 + 2; + *pkey = get_unicode (wrbfd, data, length, &sublen); + *off += (sublen + 1) * sizeof (unichar); } else { @@ -954,7 +930,7 @@ get_version_header (const unsigned char *data, unsigned long length, { if (length < 2) toosmall (key); - if (get_16 (big_endian, data) != (unsigned char) *key) + if (windres_get_16 (wrbfd, data, 2) != (bfd_byte) *key) fatal (_("unexpected version string")); *off += 2; @@ -973,25 +949,24 @@ get_version_header (const unsigned char *data, unsigned long length, /* Convert a version resource from binary. */ -static struct res_resource * -bin_to_res_version (const unsigned char *data, unsigned long length, - int big_endian) +static rc_res_resource * +bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) { - int verlen, vallen, type, off; - struct fixed_versioninfo *fi; - struct ver_info *first, **pp; - struct versioninfo *v; - struct res_resource *r; + rc_uint_type verlen, vallen, type, off; + rc_fixed_versioninfo *fi; + rc_ver_info *first, **pp; + rc_versioninfo *v; + rc_res_resource *r; - get_version_header (data, length, big_endian, "VS_VERSION_INFO", + get_version_header (wrbfd, data, length, "VS_VERSION_INFO", (unichar **) NULL, &verlen, &vallen, &type, &off); if ((unsigned int) verlen != length) fatal (_("version length %d does not match resource length %lu"), - verlen, length); + (int) verlen, (unsigned long) length); if (type != 0) - fatal (_("unexpected version type %d"), type); + fatal (_("unexpected version type %d"), (int) type); data += off; length -= off; @@ -1003,32 +978,32 @@ bin_to_res_version (const unsigned char *data, unsigned long length, unsigned long signature, fiv; if (vallen != 52) - fatal (_("unexpected fixed version information length %d"), vallen); + fatal (_("unexpected fixed version information length %ld"), (long) vallen); if (length < 52) toosmall (_("fixed version info")); - signature = get_32 (big_endian, data); + signature = windres_get_32 (wrbfd, data, 4); if (signature != 0xfeef04bd) fatal (_("unexpected fixed version signature %lu"), signature); - fiv = get_32 (big_endian, data + 4); + fiv = windres_get_32 (wrbfd, data + 4, 4); if (fiv != 0 && fiv != 0x10000) fatal (_("unexpected fixed version info version %lu"), fiv); - fi = (struct fixed_versioninfo *) res_alloc (sizeof *fi); + fi = (rc_fixed_versioninfo *) res_alloc (sizeof (rc_fixed_versioninfo)); - fi->file_version_ms = get_32 (big_endian, data + 8); - fi->file_version_ls = get_32 (big_endian, data + 12); - fi->product_version_ms = get_32 (big_endian, data + 16); - fi->product_version_ls = get_32 (big_endian, data + 20); - fi->file_flags_mask = get_32 (big_endian, data + 24); - fi->file_flags = get_32 (big_endian, data + 28); - fi->file_os = get_32 (big_endian, data + 32); - fi->file_type = get_32 (big_endian, data + 36); - fi->file_subtype = get_32 (big_endian, data + 40); - fi->file_date_ms = get_32 (big_endian, data + 44); - fi->file_date_ls = get_32 (big_endian, data + 48); + fi->file_version_ms = windres_get_32 (wrbfd, data + 8, 4); + fi->file_version_ls = windres_get_32 (wrbfd, data + 12, 4); + fi->product_version_ms = windres_get_32 (wrbfd, data + 16, 4); + fi->product_version_ls = windres_get_32 (wrbfd, data + 20, 4); + fi->file_flags_mask = windres_get_32 (wrbfd, data + 24, 4); + fi->file_flags = windres_get_32 (wrbfd, data + 28, 4); + fi->file_os = windres_get_32 (wrbfd, data + 32, 4); + fi->file_type = windres_get_32 (wrbfd, data + 36, 4); + fi->file_subtype = windres_get_32 (wrbfd, data + 40, 4); + fi->file_date_ms = windres_get_32 (wrbfd, data + 44, 4); + fi->file_date_ls = windres_get_32 (wrbfd, data + 48, 4); data += 52; length -= 52; @@ -1039,38 +1014,38 @@ bin_to_res_version (const unsigned char *data, unsigned long length, while (length > 0) { - struct ver_info *vi; + rc_ver_info *vi; int ch; if (length < 8) toosmall (_("version var info")); - vi = (struct ver_info *) res_alloc (sizeof *vi); + vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info)); - ch = get_16 (big_endian, data + 6); + ch = windres_get_16 (wrbfd, data + 6, 2); if (ch == 'S') { - struct ver_stringinfo **ppvs; + rc_ver_stringinfo **ppvs; vi->type = VERINFO_STRING; - get_version_header (data, length, big_endian, "StringFileInfo", + get_version_header (wrbfd, data, length, "StringFileInfo", (unichar **) NULL, &verlen, &vallen, &type, &off); if (vallen != 0) - fatal (_("unexpected stringfileinfo value length %d"), vallen); + fatal (_("unexpected stringfileinfo value length %ld"), (long) vallen); data += off; length -= off; - get_version_header (data, length, big_endian, (const char *) NULL, + get_version_header (wrbfd, data, length, (const char *) NULL, &vi->u.string.language, &verlen, &vallen, &type, &off); if (vallen != 0) - fatal (_("unexpected version stringtable value length %d"), vallen); + fatal (_("unexpected version stringtable value length %ld"), (long) vallen); data += off; length -= off; @@ -1085,12 +1060,12 @@ bin_to_res_version (const unsigned char *data, unsigned long length, while (verlen > 0) { - struct ver_stringinfo *vs; - int subverlen, vslen, valoff; + rc_ver_stringinfo *vs; + rc_uint_type subverlen, vslen, valoff; - vs = (struct ver_stringinfo *) res_alloc (sizeof *vs); + vs = (rc_ver_stringinfo *) res_alloc (sizeof *vs); - get_version_header (data, length, big_endian, + get_version_header (wrbfd, data, length, (const char *) NULL, &vs->key, &subverlen, &vallen, &type, &off); @@ -1099,13 +1074,13 @@ bin_to_res_version (const unsigned char *data, unsigned long length, data += off; length -= off; - vs->value = get_unicode (data, length, big_endian, &vslen); + vs->value = get_unicode (wrbfd, data, length, &vslen); valoff = vslen * 2 + 2; valoff = (valoff + 3) &~ 3; if (off + valoff != subverlen) - fatal (_("unexpected version string length %d != %d + %d"), - subverlen, off, valoff); + fatal (_("unexpected version string length %ld != %ld + %ld"), + (long) subverlen, (long) off, (long) valoff); vs->next = NULL; *ppvs = vs; @@ -1115,29 +1090,29 @@ bin_to_res_version (const unsigned char *data, unsigned long length, length -= valoff; if (verlen < subverlen) - fatal (_("unexpected version string length %d < %d"), - verlen, subverlen); + fatal (_("unexpected version string length %ld < %ld"), + (long) verlen, (long) subverlen); verlen -= subverlen; } } else if (ch == 'V') { - struct ver_varinfo **ppvv; + rc_ver_varinfo **ppvv; vi->type = VERINFO_VAR; - get_version_header (data, length, big_endian, "VarFileInfo", + get_version_header (wrbfd, data, length, "VarFileInfo", (unichar **) NULL, &verlen, &vallen, &type, &off); if (vallen != 0) - fatal (_("unexpected varfileinfo value length %d"), vallen); + fatal (_("unexpected varfileinfo value length %ld"), (long) vallen); data += off; length -= off; - get_version_header (data, length, big_endian, (const char *) NULL, + get_version_header (wrbfd, data, length, (const char *) NULL, &vi->u.var.key, &verlen, &vallen, &type, &off); data += off; @@ -1148,15 +1123,15 @@ bin_to_res_version (const unsigned char *data, unsigned long length, while (vallen > 0) { - struct ver_varinfo *vv; + rc_ver_varinfo *vv; if (length < 4) toosmall (_("version varfileinfo")); - vv = (struct ver_varinfo *) res_alloc (sizeof *vv); + vv = (rc_ver_varinfo *) res_alloc (sizeof (rc_ver_varinfo)); - vv->language = get_16 (big_endian, data); - vv->charset = get_16 (big_endian, data + 2); + vv->language = windres_get_16 (wrbfd, data, 2); + vv->charset = windres_get_16 (wrbfd, data + 2, 2); vv->next = NULL; *ppvv = vv; @@ -1166,7 +1141,7 @@ bin_to_res_version (const unsigned char *data, unsigned long length, length -= 4; if (vallen < 4) - fatal (_("unexpected version value length %d"), vallen); + fatal (_("unexpected version value length %ld"), (long) vallen); vallen -= 4; } @@ -1179,11 +1154,11 @@ bin_to_res_version (const unsigned char *data, unsigned long length, pp = &vi->next; } - v = (struct versioninfo *) res_alloc (sizeof *v); + v = (rc_versioninfo *) res_alloc (sizeof (rc_versioninfo)); v->fixed = fi; v->var = first; - r = (struct res_resource *) res_alloc (sizeof *r); + r = (rc_res_resource *) res_alloc (sizeof *r); r->type = RES_TYPE_VERSIONINFO; r->u.versioninfo = v; @@ -1192,1128 +1167,968 @@ bin_to_res_version (const unsigned char *data, unsigned long length, /* Convert an arbitrary user defined resource from binary. */ -static struct res_resource * -bin_to_res_userdata (const unsigned char *data, unsigned long length, - int big_endian ATTRIBUTE_UNUSED) +static rc_res_resource * +bin_to_res_userdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data, + rc_uint_type length) { - struct rcdata_item *ri; - struct res_resource *r; + rc_rcdata_item *ri; + rc_res_resource *r; - ri = (struct rcdata_item *) res_alloc (sizeof *ri); + ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item)); ri->next = NULL; ri->type = RCDATA_BUFFER; ri->u.buffer.length = length; ri->u.buffer.data = data; - r = (struct res_resource *) res_alloc (sizeof *r); + r = (rc_res_resource *) res_alloc (sizeof *r); r->type = RES_TYPE_USERDATA; r->u.rcdata = ri; return r; } -/* Macros to swap out values. */ +static rc_res_resource * +bin_to_res_toolbar (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) +{ + rc_toolbar *ri; + rc_res_resource *r; + rc_uint_type i; + + ri = (rc_toolbar *) res_alloc (sizeof (rc_toolbar)); + ri->button_width = windres_get_32 (wrbfd, data, 4); + ri->button_height = windres_get_32 (wrbfd, data + 4, 4); + ri->nitems = windres_get_32 (wrbfd, data + 8, 4); + ri->items = NULL; + + data += 12; + length -= 12; + for (i=0 ; i < ri->nitems; i++) + { + rc_toolbar_item *it; + it = (rc_toolbar_item *) res_alloc (sizeof (rc_toolbar_item)); + it->id.named = 0; + it->id.u.id = (int) windres_get_32 (wrbfd, data, 4); + it->prev = it->next = NULL; + data += 4; + length -= 4; + if(ri->items) { + rc_toolbar_item *ii = ri->items; + while (ii->next != NULL) + ii = ii->next; + it->prev = ii; + ii->next = it; + } + else + ri->items = it; + } + r = (rc_res_resource *) res_alloc (sizeof *r); + r->type = RES_TYPE_TOOLBAR; + r->u.toolbar = ri; + return r; +} -#define put_8(v, s) (*((unsigned char *) (s)) = (unsigned char) (v)) -#define put_16(be, v, s) ((be) ? bfd_putb16 ((v), (s)) : bfd_putl16 ((v), (s))) -#define put_32(be, v, s) ((be) ? bfd_putb32 ((v), (s)) : bfd_putl32 ((v), (s))) /* Local functions used to convert resources to binary format. */ -static void dword_align_bin (struct bindata ***, unsigned long *); -static struct bindata *resid_to_bin (struct res_id, int); -static struct bindata *unicode_to_bin (const unichar *, int); -static struct bindata *res_to_bin_accelerator - (const struct accelerator *, int); -static struct bindata *res_to_bin_cursor - (const struct cursor *, int); -static struct bindata *res_to_bin_group_cursor - (const struct group_cursor *, int); -static struct bindata *res_to_bin_dialog - (const struct dialog *, int); -static struct bindata *res_to_bin_fontdir - (const struct fontdir *, int); -static struct bindata *res_to_bin_group_icon - (const struct group_icon *, int); -static struct bindata *res_to_bin_menu - (const struct menu *, int); -static struct bindata *res_to_bin_menuitems - (const struct menuitem *, int); -static struct bindata *res_to_bin_menuexitems - (const struct menuitem *, int); -static struct bindata *res_to_bin_rcdata - (const struct rcdata_item *, int); -static struct bindata *res_to_bin_stringtable - (const struct stringtable *, int); -static struct bindata *string_to_unicode_bin (const char *, int); -static struct bindata *res_to_bin_versioninfo - (const struct versioninfo *, int); -static struct bindata *res_to_bin_generic - (unsigned long, const unsigned char *); +static rc_uint_type resid_to_bin (windres_bfd *, rc_uint_type, rc_res_id); +static rc_uint_type unicode_to_bin (windres_bfd *, rc_uint_type, const unichar *); +static rc_uint_type res_to_bin_accelerator (windres_bfd *, rc_uint_type, const rc_accelerator *); +static rc_uint_type res_to_bin_cursor (windres_bfd *, rc_uint_type, const rc_cursor *); +static rc_uint_type res_to_bin_group_cursor (windres_bfd *, rc_uint_type, const rc_group_cursor *); +static rc_uint_type res_to_bin_dialog (windres_bfd *, rc_uint_type, const rc_dialog *); +static rc_uint_type res_to_bin_fontdir (windres_bfd *, rc_uint_type, const rc_fontdir *); +static rc_uint_type res_to_bin_group_icon (windres_bfd *, rc_uint_type, const rc_group_icon *); +static rc_uint_type res_to_bin_menu (windres_bfd *, rc_uint_type, const rc_menu *); +static rc_uint_type res_to_bin_menuitems (windres_bfd *, rc_uint_type, const rc_menuitem *); +static rc_uint_type res_to_bin_menuexitems (windres_bfd *, rc_uint_type, const rc_menuitem *); +static rc_uint_type res_to_bin_rcdata (windres_bfd *, rc_uint_type, const rc_rcdata_item *); +static rc_uint_type res_to_bin_stringtable (windres_bfd *, rc_uint_type, const rc_stringtable *); +static rc_uint_type string_to_unicode_bin (windres_bfd *, rc_uint_type, const char *); +static rc_uint_type res_to_bin_toolbar (windres_bfd *, rc_uint_type, rc_toolbar *tb); +static rc_uint_type res_to_bin_versioninfo (windres_bfd *, rc_uint_type, const rc_versioninfo *); +static rc_uint_type res_to_bin_generic (windres_bfd *, rc_uint_type, rc_uint_type, + const bfd_byte *); /* Convert a resource to binary. */ -struct bindata * -res_to_bin (const struct res_resource *res, int big_endian) +rc_uint_type +res_to_bin (windres_bfd *wrbfd, rc_uint_type off, const rc_res_resource *res) { switch (res->type) { - default: - abort (); case RES_TYPE_BITMAP: case RES_TYPE_FONT: case RES_TYPE_ICON: case RES_TYPE_MESSAGETABLE: - return res_to_bin_generic (res->u.data.length, res->u.data.data); + return res_to_bin_generic (wrbfd, off, res->u.data.length, res->u.data.data); case RES_TYPE_ACCELERATOR: - return res_to_bin_accelerator (res->u.acc, big_endian); + return res_to_bin_accelerator (wrbfd, off, res->u.acc); case RES_TYPE_CURSOR: - return res_to_bin_cursor (res->u.cursor, big_endian); + return res_to_bin_cursor (wrbfd, off, res->u.cursor); case RES_TYPE_GROUP_CURSOR: - return res_to_bin_group_cursor (res->u.group_cursor, big_endian); + return res_to_bin_group_cursor (wrbfd, off, res->u.group_cursor); case RES_TYPE_DIALOG: - return res_to_bin_dialog (res->u.dialog, big_endian); + return res_to_bin_dialog (wrbfd, off, res->u.dialog); case RES_TYPE_FONTDIR: - return res_to_bin_fontdir (res->u.fontdir, big_endian); + return res_to_bin_fontdir (wrbfd, off, res->u.fontdir); case RES_TYPE_GROUP_ICON: - return res_to_bin_group_icon (res->u.group_icon, big_endian); + return res_to_bin_group_icon (wrbfd, off, res->u.group_icon); case RES_TYPE_MENU: - return res_to_bin_menu (res->u.menu, big_endian); - case RES_TYPE_RCDATA: - return res_to_bin_rcdata (res->u.rcdata, big_endian); + return res_to_bin_menu (wrbfd, off, res->u.menu); case RES_TYPE_STRINGTABLE: - return res_to_bin_stringtable (res->u.stringtable, big_endian); - case RES_TYPE_USERDATA: - return res_to_bin_rcdata (res->u.rcdata, big_endian); + return res_to_bin_stringtable (wrbfd, off, res->u.stringtable); case RES_TYPE_VERSIONINFO: - return res_to_bin_versioninfo (res->u.versioninfo, big_endian); + return res_to_bin_versioninfo (wrbfd, off, res->u.versioninfo); + case RES_TYPE_TOOLBAR: + return res_to_bin_toolbar (wrbfd, off, res->u.toolbar); + case RES_TYPE_USERDATA: + case RES_TYPE_RCDATA: + default: + return res_to_bin_rcdata (wrbfd, off, res->u.rcdata); } } -/* Align to a 32 bit boundary. PPP points to the of a list of bindata - structures. LENGTH points to the length of the structures. If - necessary, this adds a new bindata to bring length up to a 32 bit - boundary. It updates *PPP and *LENGTH. */ - -static void -dword_align_bin (struct bindata ***ppp, unsigned long *length) -{ - int add; - struct bindata *d; - - if ((*length & 3) == 0) - return; - - add = 4 - (*length & 3); - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = add; - d->data = (unsigned char *) reswr_alloc (add); - memset (d->data, 0, add); - - d->next = NULL; - **ppp = d; - *ppp = &(**ppp)->next; - - *length += add; -} - /* Convert a resource ID to binary. This always returns exactly one bindata structure. */ -static struct bindata * -resid_to_bin (struct res_id id, int big_endian) +static rc_uint_type +resid_to_bin (windres_bfd *wrbfd, rc_uint_type off, rc_res_id id) { - struct bindata *d; - - d = (struct bindata *) reswr_alloc (sizeof *d); - if (! id.named) { - d->length = 4; - d->data = (unsigned char *) reswr_alloc (d->length); - put_16 (big_endian, 0xffff, d->data); - put_16 (big_endian, id.u.id, d->data + 2); + if (wrbfd) + { + struct bin_res_id bri; + + windres_put_16 (wrbfd, bri.sig, 0xffff); + windres_put_16 (wrbfd, bri.id, id.u.id); + set_windres_bfd_content (wrbfd, &bri, off, BIN_RES_ID); + } + off += BIN_RES_ID; } else { - int i; - - d->length = id.u.n.length * 2 + 2; - d->data = (unsigned char *) reswr_alloc (d->length); - for (i = 0; i < id.u.n.length; i++) - put_16 (big_endian, id.u.n.name[i], d->data + i * 2); - put_16 (big_endian, 0, d->data + i * 2); + rc_uint_type len = (id.u.n.name ? unichar_len (id.u.n.name) : 0); + if (wrbfd) + { + bfd_byte *d = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar)); + rc_uint_type i; + for (i = 0; i < len; i++) + windres_put_16 (wrbfd, d + (i * sizeof (unichar)), id.u.n.name[i]); + windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0); + set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar)); } - - d->next = NULL; - - return d; + off += (rc_uint_type) ((len + 1) * sizeof (unichar)); + } + return off; } /* Convert a null terminated unicode string to binary. This always returns exactly one bindata structure. */ -static struct bindata * -unicode_to_bin (const unichar *str, int big_endian) +static rc_uint_type +unicode_to_bin (windres_bfd *wrbfd, rc_uint_type off, const unichar *str) { - int len; - struct bindata *d; + rc_uint_type len = 0; - len = 0; if (str != NULL) - { - const unichar *s; - - for (s = str; *s != 0; s++) - ++len; - } - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = len * 2 + 2; - d->data = (unsigned char *) reswr_alloc (d->length); + len = unichar_len (str); - if (str == NULL) - put_16 (big_endian, 0, d->data); - else + if (wrbfd) { - const unichar *s; - int i; - - for (s = str, i = 0; *s != 0; s++, i++) - put_16 (big_endian, *s, d->data + i * 2); - put_16 (big_endian, 0, d->data + i * 2); + bfd_byte *d; + rc_uint_type i; + d = (bfd_byte *) reswr_alloc ( (len + 1) * sizeof (unichar)); + for (i = 0; i < len; i++) + windres_put_16 (wrbfd, d + (i * sizeof (unichar)), str[i]); + windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0); + set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar)); } + off += (rc_uint_type) ((len + 1) * sizeof (unichar)); - d->next = NULL; - - return d; + return off; } /* Convert an accelerator resource to binary. */ -static struct bindata * -res_to_bin_accelerator (const struct accelerator *accelerators, - int big_endian) +static rc_uint_type +res_to_bin_accelerator (windres_bfd *wrbfd, rc_uint_type off, + const rc_accelerator *accelerators) { - struct bindata *first, **pp; - const struct accelerator *a; + bindata *first, **pp; + const rc_accelerator *a; first = NULL; pp = &first; for (a = accelerators; a != NULL; a = a->next) { - struct bindata *d; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = 8; - d->data = (unsigned char *) reswr_alloc (d->length); - - put_16 (big_endian, - a->flags | (a->next != NULL ? 0 : ACC_LAST), - d->data); - put_16 (big_endian, a->key, d->data + 2); - put_16 (big_endian, a->id, d->data + 4); - put_16 (big_endian, 0, d->data + 6); - - d->next = NULL; - *pp = d; - pp = &d->next; - } + if (wrbfd) + { + struct bin_accelerator ba; - return first; + windres_put_16 (wrbfd, ba.flags, a->flags | (a->next != NULL ? 0 : ACC_LAST)); + windres_put_16 (wrbfd, ba.key, a->key); + windres_put_16 (wrbfd, ba.id, a->id); + windres_put_16 (wrbfd, ba.pad, 0); + set_windres_bfd_content (wrbfd, &ba, off, BIN_ACCELERATOR_SIZE); + } + off += BIN_ACCELERATOR_SIZE; + } + return off; } /* Convert a cursor resource to binary. */ -static struct bindata * -res_to_bin_cursor (const struct cursor *c, int big_endian) +static rc_uint_type +res_to_bin_cursor (windres_bfd *wrbfd, rc_uint_type off, const rc_cursor *c) { - struct bindata *d; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = 4; - d->data = (unsigned char *) reswr_alloc (d->length); - - put_16 (big_endian, c->xhotspot, d->data); - put_16 (big_endian, c->yhotspot, d->data + 2); - - d->next = (struct bindata *) reswr_alloc (sizeof *d); - d->next->length = c->length; - d->next->data = (unsigned char *) c->data; - d->next->next = NULL; + if (wrbfd) + { + struct bin_cursor bc; - return d; + windres_put_16 (wrbfd, bc.xhotspot, c->xhotspot); + windres_put_16 (wrbfd, bc.yhotspot, c->yhotspot); + set_windres_bfd_content (wrbfd, &bc, off, BIN_CURSOR_SIZE); + if (c->length) + set_windres_bfd_content (wrbfd, c->data, off + BIN_CURSOR_SIZE, c->length); + } + off = (off + BIN_CURSOR_SIZE + (rc_uint_type) c->length); + return off; } /* Convert a group cursor resource to binary. */ -static struct bindata * -res_to_bin_group_cursor (const struct group_cursor *group_cursors, - int big_endian) +static rc_uint_type +res_to_bin_group_cursor (windres_bfd *wrbfd, rc_uint_type off, + const rc_group_cursor *group_cursors) { - struct bindata *first, **pp; - int c; - const struct group_cursor *gc; + int c = 0; + const rc_group_cursor *gc; + struct bin_group_cursor bgc; + struct bin_group_cursor_item bgci; + rc_uint_type start = off; - first = (struct bindata *) reswr_alloc (sizeof *first); - first->length = 6; - first->data = (unsigned char *) reswr_alloc (first->length); + off += BIN_GROUP_CURSOR_SIZE; - put_16 (big_endian, 0, first->data); - put_16 (big_endian, 2, first->data + 2); - - first->next = NULL; - pp = &first->next; - - c = 0; - for (gc = group_cursors; gc != NULL; gc = gc->next) + for (c = 0, gc = group_cursors; gc != NULL; gc = gc->next, c++) { - struct bindata *d; - - ++c; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = 14; - d->data = (unsigned char *) reswr_alloc (d->length); - - put_16 (big_endian, gc->width, d->data); - put_16 (big_endian, gc->height, d->data + 2); - put_16 (big_endian, gc->planes, d->data + 4); - put_16 (big_endian, gc->bits, d->data + 6); - put_32 (big_endian, gc->bytes, d->data + 8); - put_16 (big_endian, gc->index, d->data + 12); - - d->next = NULL; - *pp = d; - pp = &d->next; + if (wrbfd) + { + windres_put_16 (wrbfd, bgci.width, gc->width); + windres_put_16 (wrbfd, bgci.height, gc->height); + windres_put_16 (wrbfd, bgci.planes, gc->planes); + windres_put_16 (wrbfd, bgci.bits, gc->bits); + windres_put_32 (wrbfd, bgci.bytes, gc->bytes); + windres_put_16 (wrbfd, bgci.index, gc->index); + set_windres_bfd_content (wrbfd, &bgci, off, BIN_GROUP_CURSOR_ITEM_SIZE); } - put_16 (big_endian, c, first->data + 4); - - return first; + off += BIN_GROUP_CURSOR_ITEM_SIZE; + } + if (wrbfd) + { + windres_put_16 (wrbfd, bgc.sig1, 0); + windres_put_16 (wrbfd, bgc.sig2, 2); + windres_put_16 (wrbfd, bgc.nitems, c); + set_windres_bfd_content (wrbfd, &bgc, start, BIN_GROUP_CURSOR_SIZE); + } + return off; } /* Convert a dialog resource to binary. */ -static struct bindata * -res_to_bin_dialog (const struct dialog *dialog, int big_endian) +static rc_uint_type +res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog) { + rc_uint_type off_delta; + rc_uint_type start, marker; int dialogex; - struct bindata *first, **pp; - unsigned long length; - int off, c; - struct dialog_control *dc; + int c; + rc_dialog_control *dc; + struct bin_dialogex bdx; + struct bin_dialog bd; + off_delta = off; + start = off; dialogex = extended_dialog (dialog); - first = (struct bindata *) reswr_alloc (sizeof *first); - first->length = dialogex ? 26 : 18; - first->data = (unsigned char *) reswr_alloc (first->length); - - length = first->length; - + if (wrbfd) + { if (! dialogex) { - put_32 (big_endian, dialog->style, first->data); - put_32 (big_endian, dialog->exstyle, first->data + 4); - off = 8; + windres_put_32 (wrbfd, bd.style, dialog->style); + windres_put_32 (wrbfd, bd.exstyle, dialog->exstyle); + windres_put_16 (wrbfd, bd.x, dialog->x); + windres_put_16 (wrbfd, bd.y, dialog->y); + windres_put_16 (wrbfd, bd.width, dialog->width); + windres_put_16 (wrbfd, bd.height, dialog->height); } else { - put_16 (big_endian, 1, first->data); - put_16 (big_endian, 0xffff, first->data + 2); - - if (dialog->ex == NULL) - put_32 (big_endian, 0, first->data + 4); - else - put_32 (big_endian, dialog->ex->help, first->data + 4); - put_32 (big_endian, dialog->exstyle, first->data + 8); - put_32 (big_endian, dialog->style, first->data + 12); - off = 16; + windres_put_16 (wrbfd, bdx.sig1, 1); + windres_put_16 (wrbfd, bdx.sig2, 0xffff); + windres_put_32 (wrbfd, bdx.help, (dialog->ex ? dialog->ex->help : 0)); + windres_put_32 (wrbfd, bdx.exstyle, dialog->exstyle); + windres_put_32 (wrbfd, bdx.style, dialog->style); + windres_put_16 (wrbfd, bdx.x, dialog->x); + windres_put_16 (wrbfd, bdx.y, dialog->y); + windres_put_16 (wrbfd, bdx.width, dialog->width); + windres_put_16 (wrbfd, bdx.height, dialog->height); + } } - put_16 (big_endian, dialog->x, first->data + off + 2); - put_16 (big_endian, dialog->y, first->data + off + 4); - put_16 (big_endian, dialog->width, first->data + off + 6); - put_16 (big_endian, dialog->height, first->data + off + 8); - - pp = &first->next; - - *pp = resid_to_bin (dialog->menu, big_endian); - length += (*pp)->length; - pp = &(*pp)->next; + off += (dialogex != 0 ? BIN_DIALOGEX_SIZE : BIN_DIALOG_SIZE); - *pp = resid_to_bin (dialog->class, big_endian); - length += (*pp)->length; - pp = &(*pp)->next; - - *pp = unicode_to_bin (dialog->caption, big_endian); - length += (*pp)->length; - pp = &(*pp)->next; + off = resid_to_bin (wrbfd, off, dialog->menu); + off = resid_to_bin (wrbfd, off, dialog->class); + off = unicode_to_bin (wrbfd, off, dialog->caption); if ((dialog->style & DS_SETFONT) != 0) { - struct bindata *d; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = dialogex ? 6 : 2; - d->data = (unsigned char *) reswr_alloc (d->length); - - length += d->length; - - put_16 (big_endian, dialog->pointsize, d->data); - - if (dialogex) + if (wrbfd) { - if (dialog->ex == NULL) + if (! dialogex) { - put_16 (big_endian, 0, d->data + 2); - put_8 (0, d->data + 4); - put_8 (1, d->data + 5); + struct bin_dialogfont bdf; + windres_put_16 (wrbfd, bdf.pointsize, dialog->pointsize); + set_windres_bfd_content (wrbfd, &bdf, off, BIN_DIALOGFONT_SIZE); } else { - put_16 (big_endian, dialog->ex->weight, d->data + 2); - put_8 (dialog->ex->italic, d->data + 4); - put_8 (dialog->ex->charset, d->data + 5); + struct bin_dialogexfont bdxf; + windres_put_16 (wrbfd, bdxf.pointsize, dialog->pointsize); + windres_put_16 (wrbfd, bdxf.weight, (dialog->ex == NULL ? 0 : dialog->ex->weight)); + windres_put_8 (wrbfd, bdxf.italic, (dialog->ex == NULL ? 0 : dialog->ex->italic)); + windres_put_8 (wrbfd, bdxf.charset, (dialog->ex == NULL ? 1 : dialog->ex->charset)); + set_windres_bfd_content (wrbfd, &bdxf, off, BIN_DIALOGEXFONT_SIZE); } } - - *pp = d; - pp = &d->next; - - *pp = unicode_to_bin (dialog->font, big_endian); - length += (*pp)->length; - pp = &(*pp)->next; + off += (dialogex ? BIN_DIALOGEXFONT_SIZE : BIN_DIALOGFONT_SIZE); + off = unicode_to_bin (wrbfd, off, dialog->font); } - - c = 0; - for (dc = dialog->controls; dc != NULL; dc = dc->next) + for (c = 0, dc = dialog->controls; dc != NULL; dc = dc->next, c++) { - struct bindata *d; - int dcoff; - - ++c; - - dword_align_bin (&pp, &length); - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = dialogex ? 24 : 18; - d->data = (unsigned char *) reswr_alloc (d->length); - - length += d->length; + bfd_byte dc_rclen[2]; + off += (4 - ((off - off_delta) & 3)) & 3; + if (wrbfd) + { if (! dialogex) { - put_32 (big_endian, dc->style, d->data); - put_32 (big_endian, dc->exstyle, d->data + 4); - dcoff = 8; + struct bin_dialog_control bdc; + + windres_put_32 (wrbfd, bdc.style, dc->style); + windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle); + windres_put_16 (wrbfd, bdc.x, dc->x); + windres_put_16 (wrbfd, bdc.y, dc->y); + windres_put_16 (wrbfd, bdc.width, dc->width); + windres_put_16 (wrbfd, bdc.height, dc->height); + windres_put_16 (wrbfd, bdc.id, dc->id); + set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOG_CONTROL_SIZE); } else { - put_32 (big_endian, dc->help, d->data); - put_32 (big_endian, dc->exstyle, d->data + 4); - put_32 (big_endian, dc->style, d->data + 8); - dcoff = 12; - } - - put_16 (big_endian, dc->x, d->data + dcoff); - put_16 (big_endian, dc->y, d->data + dcoff + 2); - put_16 (big_endian, dc->width, d->data + dcoff + 4); - put_16 (big_endian, dc->height, d->data + dcoff + 6); - - if (dialogex) - put_32 (big_endian, dc->id, d->data + dcoff + 8); - else - put_16 (big_endian, dc->id, d->data + dcoff + 8); - - *pp = d; - pp = &d->next; - - *pp = resid_to_bin (dc->class, big_endian); - length += (*pp)->length; - pp = &(*pp)->next; - - *pp = resid_to_bin (dc->text, big_endian); - length += (*pp)->length; - pp = &(*pp)->next; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = 2; - d->data = (unsigned char *) reswr_alloc (d->length); + struct bin_dialogex_control bdc; + + windres_put_32 (wrbfd, bdc.help, dc->help); + windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle); + windres_put_32 (wrbfd, bdc.style, dc->style); + windres_put_16 (wrbfd, bdc.x, dc->x); + windres_put_16 (wrbfd, bdc.y, dc->y); + windres_put_16 (wrbfd, bdc.width, dc->width); + windres_put_16 (wrbfd, bdc.height, dc->height); + windres_put_32 (wrbfd, bdc.id, dc->id); + set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOGEX_CONTROL_SIZE); + } + } + off += (dialogex != 0 ? BIN_DIALOGEX_CONTROL_SIZE : BIN_DIALOG_CONTROL_SIZE); - length += 2; + off = resid_to_bin (wrbfd, off, dc->class); + off = resid_to_bin (wrbfd, off, dc->text); - d->next = NULL; - *pp = d; - pp = &d->next; + marker = off; /* Save two bytes for size of optional data. */ + off += 2; if (dc->data == NULL) - put_16 (big_endian, 0, d->data); + { + if (wrbfd) + windres_put_16 (wrbfd, dc_rclen, 0); + } else { - unsigned long sublen; - - dword_align_bin (&pp, &length); - - *pp = res_to_bin_rcdata (dc->data, big_endian); - sublen = 0; - while (*pp != NULL) - { - sublen += (*pp)->length; - pp = &(*pp)->next; + rc_uint_type saved_off = off; + rc_uint_type old_off; + off += (4 - ((off - off_delta) & 3)) & 3; + + old_off = off; + off = res_to_bin_rcdata (wrbfd, off, dc->data); + if ((off - old_off) == 0) + old_off = off = saved_off; + if (wrbfd) + windres_put_16 (wrbfd, dc_rclen, off - old_off); } - - put_16 (big_endian, sublen, d->data); - - length += sublen; + if (wrbfd) + set_windres_bfd_content (wrbfd, dc_rclen, marker, 2); } + + if (wrbfd) + { + windres_put_16 (wrbfd, (dialogex != 0 ? bdx.off : bd.off), c); + if (! dialogex) + set_windres_bfd_content (wrbfd, &bd, start, BIN_DIALOG_SIZE); + else + set_windres_bfd_content (wrbfd, &bdx, start, BIN_DIALOGEX_SIZE); } - put_16 (big_endian, c, first->data + off); - return first; + return off; } /* Convert a fontdir resource to binary. */ - -static struct bindata * -res_to_bin_fontdir (const struct fontdir *fontdirs, int big_endian) +static rc_uint_type +res_to_bin_fontdir (windres_bfd *wrbfd, rc_uint_type off, const rc_fontdir *fontdirs) { - struct bindata *first, **pp; + rc_uint_type start; int c; - const struct fontdir *fd; - - first = (struct bindata *) reswr_alloc (sizeof *first); - first->length = 2; - first->data = (unsigned char *) reswr_alloc (first->length); + const rc_fontdir *fd; - first->next = NULL; - pp = &first->next; + start = off; + off += 2; - c = 0; - for (fd = fontdirs; fd != NULL; fd = fd->next) + for (c = 0, fd = fontdirs; fd != NULL; fd = fd->next, c++) { - struct bindata *d; - - ++c; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = 2; - d->data = (unsigned char *) reswr_alloc (d->length); - - put_16 (big_endian, fd->index, d->data); - - *pp = d; - pp = &d->next; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = fd->length; - d->data = (unsigned char *) fd->data; - - d->next = NULL; - *pp = d; - pp = &d->next; + if (wrbfd) + { + bfd_byte d[2]; + windres_put_16 (wrbfd, d, fd->index); + set_windres_bfd_content (wrbfd, d, off, 2); + if (fd->length) + set_windres_bfd_content (wrbfd, fd->data, off + 2, fd->length); + } + off += (rc_uint_type) fd->length + 2; } - put_16 (big_endian, c, first->data); - - return first; + if (wrbfd) + { + bfd_byte d[2]; + windres_put_16 (wrbfd, d, c); + set_windres_bfd_content (wrbfd, d, start, 2); + } + return off; } /* Convert a group icon resource to binary. */ -static struct bindata * -res_to_bin_group_icon (const struct group_icon *group_icons, int big_endian) +static rc_uint_type +res_to_bin_group_icon (windres_bfd *wrbfd, rc_uint_type off, const rc_group_icon *group_icons) { - struct bindata *first, **pp; + rc_uint_type start; + struct bin_group_icon bgi; int c; - const struct group_icon *gi; + const rc_group_icon *gi; - first = (struct bindata *) reswr_alloc (sizeof *first); - first->length = 6; - first->data = (unsigned char *) reswr_alloc (first->length); + start = off; + off += BIN_GROUP_ICON_SIZE; - put_16 (big_endian, 0, first->data); - put_16 (big_endian, 1, first->data + 2); - - first->next = NULL; - pp = &first->next; - - c = 0; - for (gi = group_icons; gi != NULL; gi = gi->next) + for (c = 0, gi = group_icons; gi != NULL; gi = gi->next, c++) { - struct bindata *d; - - ++c; + struct bin_group_icon_item bgii; - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = 14; - d->data = (unsigned char *) reswr_alloc (d->length); - - d->data[0] = gi->width; - d->data[1] = gi->height; - d->data[2] = gi->colors; - d->data[3] = 0; - put_16 (big_endian, gi->planes, d->data + 4); - put_16 (big_endian, gi->bits, d->data + 6); - put_32 (big_endian, gi->bytes, d->data + 8); - put_16 (big_endian, gi->index, d->data + 12); - - d->next = NULL; - *pp = d; - pp = &d->next; + if (wrbfd) + { + windres_put_8 (wrbfd, bgii.width, gi->width); + windres_put_8 (wrbfd, bgii.height, gi->height); + windres_put_8 (wrbfd, bgii.colors, gi->colors); + windres_put_8 (wrbfd, bgii.pad, 0); + windres_put_16 (wrbfd, bgii.planes, gi->planes); + windres_put_16 (wrbfd, bgii.bits, gi->bits); + windres_put_32 (wrbfd, bgii.bytes, gi->bytes); + windres_put_16 (wrbfd, bgii.index, gi->index); + set_windres_bfd_content (wrbfd, &bgii, off, BIN_GROUP_ICON_ITEM_SIZE); + } + off += BIN_GROUP_ICON_ITEM_SIZE; } - put_16 (big_endian, c, first->data + 4); - - return first; + if (wrbfd) + { + windres_put_16 (wrbfd, bgi.sig1, 0); + windres_put_16 (wrbfd, bgi.sig2, 1); + windres_put_16 (wrbfd, bgi.count, c); + set_windres_bfd_content (wrbfd, &bgi, start, BIN_GROUP_ICON_SIZE); + } + return off; } /* Convert a menu resource to binary. */ -static struct bindata * -res_to_bin_menu (const struct menu *menu, int big_endian) +static rc_uint_type +res_to_bin_menu (windres_bfd *wrbfd, rc_uint_type off, const rc_menu *menu) { int menuex; - struct bindata *d; menuex = extended_menu (menu); - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = menuex ? 8 : 4; - d->data = (unsigned char *) reswr_alloc (d->length); - + if (wrbfd) + { if (! menuex) { - put_16 (big_endian, 0, d->data); - put_16 (big_endian, 0, d->data + 2); - - d->next = res_to_bin_menuitems (menu->items, big_endian); + struct bin_menu bm; + windres_put_16 (wrbfd, bm.sig1, 0); + windres_put_16 (wrbfd, bm.sig2, 0); + set_windres_bfd_content (wrbfd, &bm, off, BIN_MENU_SIZE); } else { - put_16 (big_endian, 1, d->data); - put_16 (big_endian, 4, d->data + 2); - put_32 (big_endian, menu->help, d->data + 4); - - d->next = res_to_bin_menuexitems (menu->items, big_endian); + struct bin_menuex bm; + windres_put_16 (wrbfd, bm.sig1, 1); + windres_put_16 (wrbfd, bm.sig2, 4); + windres_put_32 (wrbfd, bm.help, menu->help); + set_windres_bfd_content (wrbfd, &bm, off, BIN_MENUEX_SIZE); } - - return d; + } + off += (menuex != 0 ? BIN_MENUEX_SIZE : BIN_MENU_SIZE); + if (! menuex) + { + off = res_to_bin_menuitems (wrbfd, off, menu->items); + } + else + { + off = res_to_bin_menuexitems (wrbfd, off, menu->items); + } + return off; } /* Convert menu items to binary. */ -static struct bindata * -res_to_bin_menuitems (const struct menuitem *items, int big_endian) +static rc_uint_type +res_to_bin_menuitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items) { - struct bindata *first, **pp; - const struct menuitem *mi; - - first = NULL; - pp = &first; + const rc_menuitem *mi; for (mi = items; mi != NULL; mi = mi->next) { - struct bindata *d; + struct bin_menuitem bmi; int flags; - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = mi->popup == NULL ? 4 : 2; - d->data = (unsigned char *) reswr_alloc (d->length); - flags = mi->type; if (mi->next == NULL) flags |= MENUITEM_ENDMENU; if (mi->popup != NULL) flags |= MENUITEM_POPUP; - put_16 (big_endian, flags, d->data); - + if (wrbfd) + { + windres_put_16 (wrbfd, bmi.flags, flags); if (mi->popup == NULL) - put_16 (big_endian, mi->id, d->data + 2); - - *pp = d; - pp = &d->next; + windres_put_16 (wrbfd, bmi.id, mi->id); + set_windres_bfd_content (wrbfd, &bmi, off, + mi->popup == NULL ? BIN_MENUITEM_SIZE + : BIN_MENUITEM_POPUP_SIZE); + } + off += (mi->popup == NULL ? BIN_MENUITEM_SIZE : BIN_MENUITEM_POPUP_SIZE); - *pp = unicode_to_bin (mi->text, big_endian); - pp = &(*pp)->next; + off = unicode_to_bin (wrbfd, off, mi->text); if (mi->popup != NULL) { - *pp = res_to_bin_menuitems (mi->popup, big_endian); - while (*pp != NULL) - pp = &(*pp)->next; + off = res_to_bin_menuitems (wrbfd, off, mi->popup); } } - - return first; + return off; } /* Convert menuex items to binary. */ -static struct bindata * -res_to_bin_menuexitems (const struct menuitem *items, int big_endian) +static rc_uint_type +res_to_bin_menuexitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items) { - struct bindata *first, **pp; - unsigned long length; - const struct menuitem *mi; - - first = NULL; - pp = &first; - - length = 0; + rc_uint_type off_delta = off; + const rc_menuitem *mi; for (mi = items; mi != NULL; mi = mi->next) { - struct bindata *d; + struct bin_menuitemex bmi; int flags; - dword_align_bin (&pp, &length); - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = 12; - d->data = (unsigned char *) reswr_alloc (d->length); - - length += 12; - - put_32 (big_endian, mi->type, d->data); - put_32 (big_endian, mi->state, d->data + 4); - put_16 (big_endian, mi->id, d->data + 8); + off += (4 - ((off - off_delta) & 3)) & 3; flags = 0; if (mi->next == NULL) flags |= 0x80; if (mi->popup != NULL) flags |= 1; - put_16 (big_endian, flags, d->data + 10); - *pp = d; - pp = &d->next; + if (wrbfd) + { + windres_put_32 (wrbfd, bmi.type, mi->type); + windres_put_32 (wrbfd, bmi.state, mi->state); + windres_put_32 (wrbfd, bmi.id, mi->id); + windres_put_16 (wrbfd, bmi.flags, flags); + set_windres_bfd_content (wrbfd, &bmi, off, BIN_MENUITEMEX_SIZE); + } + off += BIN_MENUITEMEX_SIZE; - *pp = unicode_to_bin (mi->text, big_endian); - length += (*pp)->length; - pp = &(*pp)->next; + off = unicode_to_bin (wrbfd, off, mi->text); if (mi->popup != NULL) { - dword_align_bin (&pp, &length); - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = 4; - d->data = (unsigned char *) reswr_alloc (d->length); + bfd_byte help[4]; - put_32 (big_endian, mi->help, d->data); + off += (4 - ((off - off_delta) & 3)) & 3; - *pp = d; - pp = &d->next; - - *pp = res_to_bin_menuexitems (mi->popup, big_endian); - while (*pp != NULL) + if (wrbfd) { - length += (*pp)->length; - pp = &(*pp)->next; + windres_put_32 (wrbfd, help, mi->help); + set_windres_bfd_content (wrbfd, help, off, 4); } + off += 4; + off = res_to_bin_menuexitems (wrbfd, off, mi->popup); } } - - return first; + return off; } /* Convert an rcdata resource to binary. This is also used to convert - other information which happens to be stored in rcdata_item lists + other information which happens to be stored in rc_rcdata_item lists to binary. */ -static struct bindata * -res_to_bin_rcdata (const struct rcdata_item *items, int big_endian) +static rc_uint_type +res_to_bin_rcdata (windres_bfd *wrbfd, rc_uint_type off, const rc_rcdata_item *items) { - struct bindata *first, **pp; - const struct rcdata_item *ri; - - first = NULL; - pp = &first; + const rc_rcdata_item *ri; for (ri = items; ri != NULL; ri = ri->next) { - struct bindata *d; - - d = (struct bindata *) reswr_alloc (sizeof *d); - + rc_uint_type len; switch (ri->type) { default: abort (); - case RCDATA_WORD: - d->length = 2; - d->data = (unsigned char *) reswr_alloc (d->length); - put_16 (big_endian, ri->u.word, d->data); + len = 2; break; - case RCDATA_DWORD: - d->length = 4; - d->data = (unsigned char *) reswr_alloc (d->length); - put_32 (big_endian, ri->u.dword, d->data); + len = 4; break; - case RCDATA_STRING: - d->length = ri->u.string.length; - d->data = (unsigned char *) ri->u.string.s; + len = ri->u.string.length; + break; + case RCDATA_WSTRING: + len = ri->u.wstring.length * sizeof (unichar); + break; + case RCDATA_BUFFER: + len = ri->u.buffer.length; + break; + } + if (wrbfd) + { + bfd_byte h[4]; + bfd_byte *hp = &h[0]; + switch (ri->type) + { + case RCDATA_WORD: + windres_put_16 (wrbfd, hp, ri->u.word); + break; + case RCDATA_DWORD: + windres_put_32 (wrbfd, hp, ri->u.dword); + break; + case RCDATA_STRING: + hp = (bfd_byte *) ri->u.string.s; break; - case RCDATA_WSTRING: { - unsigned long i; + rc_uint_type i; - d->length = ri->u.wstring.length * 2; - d->data = (unsigned char *) reswr_alloc (d->length); + hp = (bfd_byte *) reswr_alloc (len); for (i = 0; i < ri->u.wstring.length; i++) - put_16 (big_endian, ri->u.wstring.w[i], d->data + i * 2); - break; + windres_put_16 (wrbfd, hp + i * sizeof (unichar), ri->u.wstring.w[i]); } - + break; case RCDATA_BUFFER: - d->length = ri->u.buffer.length; - d->data = (unsigned char *) ri->u.buffer.data; + hp = (bfd_byte *) ri->u.buffer.data; break; } - - d->next = NULL; - *pp = d; - pp = &d->next; + set_windres_bfd_content (wrbfd, hp, off, len); } - - return first; + off += len; + } + return off; } /* Convert a stringtable resource to binary. */ -static struct bindata * -res_to_bin_stringtable (const struct stringtable *st, int big_endian) +static rc_uint_type +res_to_bin_stringtable (windres_bfd *wrbfd, rc_uint_type off, + const rc_stringtable *st) { - struct bindata *first, **pp; int i; - first = NULL; - pp = &first; - for (i = 0; i < 16; i++) { - int slen, j; - struct bindata *d; + rc_uint_type slen, length; unichar *s; - slen = st->strings[i].length; + slen = (rc_uint_type) st->strings[i].length; s = st->strings[i].string; - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = 2 + slen * 2; - d->data = (unsigned char *) reswr_alloc (d->length); + length = 2 + slen * 2; + if (wrbfd) + { + bfd_byte *hp; + rc_uint_type j; - put_16 (big_endian, slen, d->data); + hp = (bfd_byte *) reswr_alloc (length); + windres_put_16 (wrbfd, hp, slen); for (j = 0; j < slen; j++) - put_16 (big_endian, s[j], d->data + 2 + j * 2); - - d->next = NULL; - *pp = d; - pp = &d->next; + windres_put_16 (wrbfd, hp + 2 + j * 2, s[j]); + set_windres_bfd_content (wrbfd, hp, off, length); } - - return first; + off += length; + } + return off; } /* Convert an ASCII string to a unicode binary string. This always returns exactly one bindata structure. */ -static struct bindata * -string_to_unicode_bin (const char *s, int big_endian) +static rc_uint_type +string_to_unicode_bin (windres_bfd *wrbfd, rc_uint_type off, const char *s) { - size_t len, i; - struct bindata *d; - - len = strlen (s); + rc_uint_type len; - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = len * 2 + 2; - d->data = (unsigned char *) reswr_alloc (d->length); + len = (rc_uint_type) strlen (s); - for (i = 0; i < len; i++) - put_16 (big_endian, s[i], d->data + i * 2); - put_16 (big_endian, 0, d->data + i * 2); + if (wrbfd) + { + rc_uint_type i; + bfd_byte *hp; - d->next = NULL; + hp = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar)); - return d; + for (i = 0; i < len; i++) + windres_put_16 (wrbfd, hp + i * 2, s[i]); + windres_put_16 (wrbfd, hp + i * 2, 0); + set_windres_bfd_content (wrbfd, hp, off, (len + 1) * sizeof (unichar)); + } + off += (rc_uint_type) ((len + 1) * sizeof (unichar)); + return off; } -/* Convert a versioninfo resource to binary. */ - -static struct bindata * -res_to_bin_versioninfo (const struct versioninfo *versioninfo, int big_endian) +static rc_uint_type +res_to_bin_toolbar (windres_bfd *wrbfd, rc_uint_type off, rc_toolbar *tb) { - struct bindata *first, **pp; - unsigned long length; - struct ver_info *vi; - - first = (struct bindata *) reswr_alloc (sizeof *first); - first->length = 6; - first->data = (unsigned char *) reswr_alloc (first->length); - - length = 6; + if (wrbfd) + { + struct bin_toolbar bt; + windres_put_32 (wrbfd, bt.button_width, tb->button_width); + windres_put_32 (wrbfd, bt.button_height, tb->button_height); + windres_put_32 (wrbfd, bt.nitems, tb->nitems); + set_windres_bfd_content (wrbfd, &bt, off, BIN_TOOLBAR_SIZE); + if (tb->nitems > 0) + { + rc_toolbar_item *it; + bfd_byte *ids; + rc_uint_type i = 0; - if (versioninfo->fixed == NULL) - put_16 (big_endian, 0, first->data + 2); - else - put_16 (big_endian, 52, first->data + 2); + ids = (bfd_byte *) reswr_alloc (tb->nitems * 4); + it=tb->items; + while(it != NULL) + { + windres_put_32 (wrbfd, ids + i, it->id.u.id); + i += 4; + it = it->next; + } + set_windres_bfd_content (wrbfd, ids, off + BIN_TOOLBAR_SIZE, i); + } + } + off += BIN_TOOLBAR_SIZE + tb->nitems * 4; - put_16 (big_endian, 0, first->data + 4); + return off; +} - pp = &first->next; +/* Convert a versioninfo resource to binary. */ - *pp = string_to_unicode_bin ("VS_VERSION_INFO", big_endian); - length += (*pp)->length; - pp = &(*pp)->next; +static rc_uint_type +res_to_bin_versioninfo (windres_bfd *wrbfd, rc_uint_type off, + const rc_versioninfo *versioninfo) +{ + rc_uint_type off_delta = off; + rc_uint_type start; + struct bin_versioninfo bvi; + rc_ver_info *vi; - dword_align_bin (&pp, &length); + start = off; + off += BIN_VERSIONINFO_SIZE; + off = string_to_unicode_bin (wrbfd, off, "VS_VERSION_INFO"); + off += (4 - ((off - off_delta) & 3)) & 3; if (versioninfo->fixed != NULL) { - const struct fixed_versioninfo *fi; - struct bindata *d; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = 52; - d->data = (unsigned char *) reswr_alloc (d->length); - - length += 52; + if (wrbfd) + { + struct bin_fixed_versioninfo bfv; + const rc_fixed_versioninfo *fi; fi = versioninfo->fixed; - - put_32 (big_endian, 0xfeef04bd, d->data); - put_32 (big_endian, 0x10000, d->data + 4); - put_32 (big_endian, fi->file_version_ms, d->data + 8); - put_32 (big_endian, fi->file_version_ls, d->data + 12); - put_32 (big_endian, fi->product_version_ms, d->data + 16); - put_32 (big_endian, fi->product_version_ls, d->data + 20); - put_32 (big_endian, fi->file_flags_mask, d->data + 24); - put_32 (big_endian, fi->file_flags, d->data + 28); - put_32 (big_endian, fi->file_os, d->data + 32); - put_32 (big_endian, fi->file_type, d->data + 36); - put_32 (big_endian, fi->file_subtype, d->data + 40); - put_32 (big_endian, fi->file_date_ms, d->data + 44); - put_32 (big_endian, fi->file_date_ls, d->data + 48); - - d->next = NULL; - *pp = d; - pp = &d->next; + windres_put_32 (wrbfd, bfv.sig1, 0xfeef04bd); + windres_put_32 (wrbfd, bfv.sig2, 0x10000); + windres_put_32 (wrbfd, bfv.file_version, fi->file_version_ms); + windres_put_32 (wrbfd, bfv.file_version_ls, fi->file_version_ls); + windres_put_32 (wrbfd, bfv.product_version_ms, fi->product_version_ms); + windres_put_32 (wrbfd, bfv.product_version_ls, fi->product_version_ls); + windres_put_32 (wrbfd, bfv.file_flags_mask, fi->file_flags_mask); + windres_put_32 (wrbfd, bfv.file_flags, fi->file_flags); + windres_put_32 (wrbfd, bfv.file_os, fi->file_os); + windres_put_32 (wrbfd, bfv.file_type, fi->file_type); + windres_put_32 (wrbfd, bfv.file_subtype, fi->file_subtype); + windres_put_32 (wrbfd, bfv.file_date_ms, fi->file_date_ms); + windres_put_32 (wrbfd, bfv.file_date_ls, fi->file_date_ls); + set_windres_bfd_content (wrbfd, &bfv, off, BIN_FIXED_VERSIONINFO_SIZE); + } + off += BIN_FIXED_VERSIONINFO_SIZE; } for (vi = versioninfo->var; vi != NULL; vi = vi->next) { - struct bindata *vid; - unsigned long vilen; - - dword_align_bin (&pp, &length); - - vid = (struct bindata *) reswr_alloc (sizeof *vid); - vid->length = 6; - vid->data = (unsigned char *) reswr_alloc (vid->length); + struct bin_ver_info bv; + rc_uint_type bv_off; - length += 6; - vilen = 6; + off += (4 - ((off - off_delta) & 3)) & 3; - put_16 (big_endian, 0, vid->data + 2); - put_16 (big_endian, 0, vid->data + 4); + bv_off = off; - *pp = vid; - pp = &vid->next; + off += BIN_VER_INFO_SIZE; switch (vi->type) { default: abort (); - case VERINFO_STRING: { - unsigned long hold, vslen; - struct bindata *vsd; - const struct ver_stringinfo *vs; + struct bin_ver_info bvsd; + rc_uint_type vs_off; + const rc_ver_stringinfo *vs; - *pp = string_to_unicode_bin ("StringFileInfo", big_endian); - length += (*pp)->length; - vilen += (*pp)->length; - pp = &(*pp)->next; + off = string_to_unicode_bin (wrbfd, off, "StringFileInfo"); + off += (4 - ((off - off_delta) & 3)) & 3; - hold = length; - dword_align_bin (&pp, &length); - vilen += length - hold; + vs_off = off; - vsd = (struct bindata *) reswr_alloc (sizeof *vsd); - vsd->length = 6; - vsd->data = (unsigned char *) reswr_alloc (vsd->length); + off += BIN_VER_INFO_SIZE; - length += 6; - vilen += 6; - vslen = 6; + off = unicode_to_bin (wrbfd, off, vi->u.string.language); - put_16 (big_endian, 0, vsd->data + 2); - put_16 (big_endian, 0, vsd->data + 4); + for (vs = vi->u.string.strings; vs != NULL; vs = vs->next) + { + struct bin_ver_info bvss; + rc_uint_type vss_off,str_off; - *pp = vsd; - pp = &vsd->next; + off += (4 - ((off - off_delta) & 3)) & 3; - *pp = unicode_to_bin (vi->u.string.language, big_endian); - length += (*pp)->length; - vilen += (*pp)->length; - vslen += (*pp)->length; - pp = &(*pp)->next; + vss_off = off; + off += BIN_VER_INFO_SIZE; - for (vs = vi->u.string.strings; vs != NULL; vs = vs->next) - { - struct bindata *vssd; - unsigned long vsslen; - - hold = length; - dword_align_bin (&pp, &length); - vilen += length - hold; - vslen += length - hold; - - vssd = (struct bindata *) reswr_alloc (sizeof *vssd); - vssd->length = 6; - vssd->data = (unsigned char *) reswr_alloc (vssd->length); - - length += 6; - vilen += 6; - vslen += 6; - vsslen = 6; - - put_16 (big_endian, 1, vssd->data + 4); - - *pp = vssd; - pp = &vssd->next; - - *pp = unicode_to_bin (vs->key, big_endian); - length += (*pp)->length; - vilen += (*pp)->length; - vslen += (*pp)->length; - vsslen += (*pp)->length; - pp = &(*pp)->next; - - hold = length; - dword_align_bin (&pp, &length); - vilen += length - hold; - vslen += length - hold; - vsslen += length - hold; - - *pp = unicode_to_bin (vs->value, big_endian); - put_16 (big_endian, (*pp)->length / 2, vssd->data + 2); - length += (*pp)->length; - vilen += (*pp)->length; - vslen += (*pp)->length; - vsslen += (*pp)->length; - pp = &(*pp)->next; - - put_16 (big_endian, vsslen, vssd->data); - } + off = unicode_to_bin (wrbfd, off, vs->key); - put_16 (big_endian, vslen, vsd->data); + off += (4 - ((off - off_delta) & 3)) & 3; + str_off = off; + off = unicode_to_bin (wrbfd, off, vs->value); + if (wrbfd) + { + windres_put_16 (wrbfd, bvss.size, off - vss_off); + windres_put_16 (wrbfd, bvss.sig1, (off - str_off) / 2); + windres_put_16 (wrbfd, bvss.sig2, 1); + set_windres_bfd_content (wrbfd, &bvss, vss_off, + BIN_VER_INFO_SIZE); + } + } + if (wrbfd) + { + windres_put_16 (wrbfd, bvsd.size, off - vs_off); + windres_put_16 (wrbfd, bvsd.sig1, 0); + windres_put_16 (wrbfd, bvsd.sig2, 0); + set_windres_bfd_content (wrbfd, &bvsd, vs_off, + BIN_VER_INFO_SIZE); + } break; } case VERINFO_VAR: { - unsigned long hold, vvlen, vvvlen; - struct bindata *vvd; - const struct ver_varinfo *vv; - - *pp = string_to_unicode_bin ("VarFileInfo", big_endian); - length += (*pp)->length; - vilen += (*pp)->length; - pp = &(*pp)->next; - - hold = length; - dword_align_bin (&pp, &length); - vilen += length - hold; - - vvd = (struct bindata *) reswr_alloc (sizeof *vvd); - vvd->length = 6; - vvd->data = (unsigned char *) reswr_alloc (vvd->length); + rc_uint_type vvd_off, vvvd_off; + struct bin_ver_info bvvd; + const rc_ver_varinfo *vv; - length += 6; - vilen += 6; - vvlen = 6; + off = string_to_unicode_bin (wrbfd, off, "VarFileInfo"); - put_16 (big_endian, 0, vvd->data + 4); + off += (4 - ((off - off_delta) & 3)) & 3; - *pp = vvd; - pp = &vvd->next; + vvd_off = off; + off += BIN_VER_INFO_SIZE; - *pp = unicode_to_bin (vi->u.var.key, big_endian); - length += (*pp)->length; - vilen += (*pp)->length; - vvlen += (*pp)->length; - pp = &(*pp)->next; + off = unicode_to_bin (wrbfd, off, vi->u.var.key); - hold = length; - dword_align_bin (&pp, &length); - vilen += length - hold; - vvlen += length - hold; + off += (4 - ((off - off_delta) & 3)) & 3; - vvvlen = 0; + vvvd_off = off; for (vv = vi->u.var.var; vv != NULL; vv = vv->next) { - struct bindata *vvsd; - - vvsd = (struct bindata *) reswr_alloc (sizeof *vvsd); - vvsd->length = 4; - vvsd->data = (unsigned char *) reswr_alloc (vvsd->length); - - length += 4; - vilen += 4; - vvlen += 4; - vvvlen += 4; - - put_16 (big_endian, vv->language, vvsd->data); - put_16 (big_endian, vv->charset, vvsd->data + 2); - - vvsd->next = NULL; - *pp = vvsd; - pp = &vvsd->next; + if (wrbfd) + { + bfd_byte vvsd[4]; + + windres_put_16 (wrbfd, &vvsd[0], vv->language); + windres_put_16 (wrbfd, &vvsd[2], vv->charset); + set_windres_bfd_content (wrbfd, vvsd, off, 4); + } + off += 4; } - - put_16 (big_endian, vvlen, vvd->data); - put_16 (big_endian, vvvlen, vvd->data + 2); + if (wrbfd) + { + windres_put_16 (wrbfd, bvvd.size, off - vvd_off); + windres_put_16 (wrbfd, bvvd.sig1, off - vvvd_off); + windres_put_16 (wrbfd, bvvd.sig2, 0); + set_windres_bfd_content (wrbfd, &bvvd, vvd_off, + BIN_VER_INFO_SIZE); + } break; } } - put_16 (big_endian, vilen, vid->data); + if (wrbfd) + { + windres_put_16 (wrbfd, bv.size, off-bv_off); + windres_put_16 (wrbfd, bv.sig1, 0); + windres_put_16 (wrbfd, bv.sig2, 0); + set_windres_bfd_content (wrbfd, &bv, bv_off, + BIN_VER_INFO_SIZE); + } } - put_16 (big_endian, length, first->data); - - return first; + if (wrbfd) + { + windres_put_16 (wrbfd, bvi.size, off - start); + windres_put_16 (wrbfd, bvi.fixed_size, + versioninfo->fixed == NULL ? 0 + : BIN_FIXED_VERSIONINFO_SIZE); + windres_put_16 (wrbfd, bvi.sig2, 0); + set_windres_bfd_content (wrbfd, &bvi, start, BIN_VER_INFO_SIZE); + } + return off; } /* Convert a generic resource to binary. */ -static struct bindata * -res_to_bin_generic (unsigned long length, const unsigned char *data) +static rc_uint_type +res_to_bin_generic (windres_bfd *wrbfd, rc_uint_type off, rc_uint_type length, + const bfd_byte *data) { - struct bindata *d; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = length; - d->data = (unsigned char *) data; - - d->next = NULL; - - return d; + if (wrbfd && length != 0) + set_windres_bfd_content (wrbfd, data, off, length); + return off + (rc_uint_type) length; } diff --git a/binutils/rescoff.c b/binutils/rescoff.c index 9bba548afd1..737eb4f0ba9 100644 --- a/binutils/rescoff.c +++ b/binutils/rescoff.c @@ -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 @@ -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; } diff --git a/binutils/resrc.c b/binutils/resrc.c index 0ec2875947b..24b423d93e9 100644 --- a/binutils/resrc.c +++ b/binutils/resrc.c @@ -2,6 +2,7 @@ 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. @@ -25,13 +26,17 @@ #include "sysdep.h" #include "bfd.h" +#include "bucomm.h" #include "libiberty.h" #include "safe-ctype.h" -#include "bucomm.h" #include "windres.h" #include +#include #include +#ifdef HAVE_UNISTD_H +#include +#endif #ifdef HAVE_SYS_WAIT_H #include @@ -84,11 +89,11 @@ struct icondir { /* Width of image. */ - unsigned char width; + bfd_byte width; /* Height of image. */ - unsigned char height; + bfd_byte height; /* Number of colors in image. */ - unsigned char colorcount; + bfd_byte colorcount; union { struct @@ -122,7 +127,7 @@ int rc_lineno; /* The pipe we are reading from, so that we can close it if we exit. */ -static FILE *cpp_pipe; +FILE *cpp_pipe; /* The temporary file used if we're not using popen, so we can delete it if we exit. */ @@ -135,7 +140,7 @@ static enum {ISTREAM_PIPE, ISTREAM_FILE} istream_type; /* As we read the rc file, we attach information to this structure. */ -static struct res_directory *resources; +static rc_res_directory *resources; /* The number of cursor resources we have written out. */ @@ -147,17 +152,39 @@ static int fonts; /* Font directory information. */ -struct fontdir *fontdirs; +rc_fontdir *fontdirs; /* Resource info to use for fontdirs. */ -struct res_res_info fontdirs_resinfo; +rc_res_res_info fontdirs_resinfo; /* The number of icon resources we have written out. */ static int icons; -/* Local functions. */ +/* The windres target bfd . */ + +static windres_bfd wrtarget = +{ + (bfd *) NULL, (asection *) NULL, WR_KIND_TARGET +}; + +/* Local functions for rcdata based resource definitions. */ + +static void define_font_rcdata (rc_res_id, const rc_res_res_info *, + rc_rcdata_item *); +static void define_icon_rcdata (rc_res_id, const rc_res_res_info *, + rc_rcdata_item *); +static void define_bitmap_rcdata (rc_res_id, const rc_res_res_info *, + rc_rcdata_item *); +static void define_cursor_rcdata (rc_res_id, const rc_res_res_info *, + rc_rcdata_item *); +static void define_fontdir_rcdata (rc_res_id, const rc_res_res_info *, + rc_rcdata_item *); +static void define_messagetable_rcdata (rc_res_id, const rc_res_res_info *, + rc_rcdata_item *); +static rc_uint_type rcdata_copy (const rc_rcdata_item *, bfd_byte *); +static bfd_byte *rcdata_render_as_buffer (const rc_rcdata_item *, rc_uint_type *); static int run_cmd (char *, const char *); static FILE *open_input_stream (char *); @@ -167,7 +194,7 @@ static void close_input_stream (void); static void unexpected_eof (const char *); static int get_word (FILE *, const char *); static unsigned long get_long (FILE *, const char *); -static void get_data (FILE *, unsigned char *, unsigned long, const char *); +static void get_data (FILE *, bfd_byte *, rc_uint_type, const char *); static void define_fontdirs (void); /* Run `cmd' and redirect the output to `redir'. */ @@ -375,7 +402,7 @@ look_for_default (char *cmd, const char *prefix, int end_prefix, /* Read an rc file. */ -struct res_directory * +rc_res_directory * read_rc_file (const char *filename, const char *preprocessor, const char *preprocargs, int language, int use_temp_file) { @@ -437,20 +464,20 @@ read_rc_file (const char *filename, const char *preprocessor, /* First, try looking for a prefixed gcc in the windres directory, with the same prefix as windres */ - cpp_pipe = look_for_default (cmd, program_name, dash-program_name+1, + cpp_pipe = look_for_default (cmd, program_name, dash - program_name + 1, preprocargs, filename); } - if (slash && !cpp_pipe) + if (slash && ! cpp_pipe) { /* Next, try looking for a gcc in the same directory as that windres */ - cpp_pipe = look_for_default (cmd, program_name, slash-program_name+1, + cpp_pipe = look_for_default (cmd, program_name, slash - program_name + 1, preprocargs, filename); } - if (!cpp_pipe) + if (! cpp_pipe) { /* Sigh, try the default */ @@ -465,7 +492,6 @@ read_rc_file (const char *filename, const char *preprocessor, rc_lineno = 1; if (language != -1) rcparse_set_language (language); - yyin = cpp_pipe; yyparse (); rcparse_discard_strings (); @@ -572,24 +598,24 @@ get_long (FILE *e, const char *msg) /* Read data from a file. This is a wrapper to do error checking. */ static void -get_data (FILE *e, unsigned char *p, unsigned long c, const char *msg) +get_data (FILE *e, bfd_byte *p, rc_uint_type c, const char *msg) { - unsigned long got; + rc_uint_type got; // $$$d - got = fread (p, 1, c, e); + got = (rc_uint_type) fread (p, 1, c, e); if (got == c) return; - fatal (_("%s: read of %lu returned %lu"), msg, c, got); + fatal (_("%s: read of %lu returned %lu"), msg, (long) c, (long) got); } /* Define an accelerator resource. */ void -define_accelerator (struct res_id id, const struct res_res_info *resinfo, - struct accelerator *data) +define_accelerator (rc_res_id id, const rc_res_res_info *resinfo, + rc_accelerator *data) { - struct res_resource *r; + rc_res_resource *r; r = define_standard_resource (&resources, RT_ACCELERATOR, id, resinfo->language, 0); @@ -605,15 +631,15 @@ define_accelerator (struct res_id id, const struct res_res_info *resinfo, #define BITMAP_SKIP (14) void -define_bitmap (struct res_id id, const struct res_res_info *resinfo, +define_bitmap (rc_res_id id, const rc_res_res_info *resinfo, const char *filename) { FILE *e; char *real_filename; struct stat s; - unsigned char *data; - int i; - struct res_resource *r; + bfd_byte *data; + rc_uint_type i; + rc_res_resource *r; e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename); @@ -621,7 +647,7 @@ define_bitmap (struct res_id id, const struct res_res_info *resinfo, fatal (_("stat failed on bitmap file `%s': %s"), real_filename, strerror (errno)); - data = (unsigned char *) res_alloc (s.st_size - BITMAP_SKIP); + data = (bfd_byte *) res_alloc (s.st_size - BITMAP_SKIP); for (i = 0; i < BITMAP_SKIP; i++) getc (e); @@ -647,7 +673,7 @@ define_bitmap (struct res_id id, const struct res_res_info *resinfo, select one of the actual cursors. */ void -define_cursor (struct res_id id, const struct res_res_info *resinfo, +define_cursor (rc_res_id id, const rc_res_res_info *resinfo, const char *filename) { FILE *e; @@ -655,8 +681,8 @@ define_cursor (struct res_id id, const struct res_res_info *resinfo, int type, count, i; struct icondir *icondirs; int first_cursor; - struct res_resource *r; - struct group_cursor *first, **pp; + rc_res_resource *r; + rc_group_cursor *first, **pp; e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename); @@ -696,19 +722,19 @@ define_cursor (struct res_id id, const struct res_res_info *resinfo, for (i = 0; i < count; i++) { - unsigned char *data; - struct res_id name; - struct cursor *c; + bfd_byte *data; + rc_res_id name; + rc_cursor *c; if (fseek (e, icondirs[i].offset, SEEK_SET) != 0) fatal (_("%s: fseek to %lu failed: %s"), real_filename, icondirs[i].offset, strerror (errno)); - data = (unsigned char *) res_alloc (icondirs[i].bytes); + data = (bfd_byte *) res_alloc (icondirs[i].bytes); get_data (e, data, icondirs[i].bytes, real_filename); - c = (struct cursor *) res_alloc (sizeof *c); + c = (rc_cursor *) res_alloc (sizeof (rc_cursor)); c->xhotspot = icondirs[i].u.cursor.xhotspot; c->yhotspot = icondirs[i].u.cursor.yhotspot; c->length = icondirs[i].bytes; @@ -735,9 +761,9 @@ define_cursor (struct res_id id, const struct res_res_info *resinfo, pp = &first; for (i = 0; i < count; i++) { - struct group_cursor *cg; + rc_group_cursor *cg; - cg = (struct group_cursor *) res_alloc (sizeof *cg); + cg = (rc_group_cursor *) res_alloc (sizeof (rc_group_cursor)); cg->next = NULL; cg->width = icondirs[i].width; cg->height = 2 * icondirs[i].height; @@ -765,13 +791,13 @@ define_cursor (struct res_id id, const struct res_res_info *resinfo, /* Define a dialog resource. */ void -define_dialog (struct res_id id, const struct res_res_info *resinfo, - const struct dialog *dialog) +define_dialog (rc_res_id id, const rc_res_res_info *resinfo, + const rc_dialog *dialog) { - struct dialog *copy; - struct res_resource *r; + rc_dialog *copy; + rc_res_resource *r; - copy = (struct dialog *) res_alloc (sizeof *copy); + copy = (rc_dialog *) res_alloc (sizeof *copy); *copy = *dialog; r = define_standard_resource (&resources, RT_DIALOG, id, @@ -784,15 +810,15 @@ define_dialog (struct res_id id, const struct res_res_info *resinfo, /* Define a dialog control. This does not define a resource, but merely allocates and fills in a structure. */ -struct dialog_control * -define_control (const struct res_id iid, unsigned long id, unsigned long x, - unsigned long y, unsigned long width, unsigned long height, - unsigned long class, unsigned long style, - unsigned long exstyle) +rc_dialog_control * +define_control (const rc_res_id iid, rc_uint_type id, rc_uint_type x, + rc_uint_type y, rc_uint_type width, rc_uint_type height, + const rc_res_id class, rc_uint_type style, + rc_uint_type exstyle) { - struct dialog_control *n; + rc_dialog_control *n; - n = (struct dialog_control *) res_alloc (sizeof *n); + n = (rc_dialog_control *) res_alloc (sizeof (rc_dialog_control)); n->next = NULL; n->id = id; n->style = style; @@ -801,8 +827,7 @@ define_control (const struct res_id iid, unsigned long id, unsigned long x, n->y = y; n->width = width; n->height = height; - n->class.named = 0; - n->class.u.id = class; + n->class = class; n->text = iid; n->data = NULL; n->help = 0; @@ -810,23 +835,26 @@ define_control (const struct res_id iid, unsigned long id, unsigned long x, return n; } -struct dialog_control * -define_icon_control (struct res_id iid, unsigned long id, unsigned long x, - unsigned long y, unsigned long style, - unsigned long exstyle, unsigned long help, - struct rcdata_item *data, struct dialog_ex *ex) +rc_dialog_control * +define_icon_control (rc_res_id iid, rc_uint_type id, rc_uint_type x, + rc_uint_type y, rc_uint_type style, + rc_uint_type exstyle, rc_uint_type help, + rc_rcdata_item *data, rc_dialog_ex *ex) { - struct dialog_control *n; - struct res_id tid; + rc_dialog_control *n; + rc_res_id tid; + rc_res_id cid; if (style == 0) style = SS_ICON | WS_CHILD | WS_VISIBLE; res_string_to_id (&tid, ""); - n = define_control (tid, id, x, y, 0, 0, CTL_STATIC, style, exstyle); + cid.named = 0; + cid.u.id = CTL_STATIC; + n = define_control (tid, id, x, y, 0, 0, cid, style, exstyle); n->text = iid; - if (help && !ex) + if (help && ! ex) rcparse_warning (_("help ID requires DIALOGEX")); - if (data && !ex) + if (data && ! ex) rcparse_warning (_("control data requires DIALOGEX")); n->help = help; n->data = data; @@ -837,20 +865,20 @@ define_icon_control (struct res_id iid, unsigned long id, unsigned long x, /* Define a font resource. */ void -define_font (struct res_id id, const struct res_res_info *resinfo, +define_font (rc_res_id id, const rc_res_res_info *resinfo, const char *filename) { FILE *e; char *real_filename; struct stat s; - unsigned char *data; - struct res_resource *r; + bfd_byte *data; + rc_res_resource *r; long offset; long fontdatalength; - unsigned char *fontdata; - struct fontdir *fd; + bfd_byte *fontdata; + rc_fontdir *fd; const char *device, *face; - struct fontdir **pp; + rc_fontdir **pp; e = open_file_search (filename, FOPEN_RB, "font file", &real_filename); @@ -858,7 +886,7 @@ define_font (struct res_id id, const struct res_res_info *resinfo, fatal (_("stat failed on font file `%s': %s"), real_filename, strerror (errno)); - data = (unsigned char *) res_alloc (s.st_size); + data = (bfd_byte *) res_alloc (s.st_size); get_data (e, data, s.st_size, real_filename); @@ -899,12 +927,12 @@ define_font (struct res_id id, const struct res_res_info *resinfo, ++fonts; fontdatalength = 58 + strlen (device) + strlen (face); - fontdata = (unsigned char *) res_alloc (fontdatalength); + fontdata = (bfd_byte *) res_alloc (fontdatalength); memcpy (fontdata, data, 56); strcpy ((char *) fontdata + 56, device); strcpy ((char *) fontdata + 57 + strlen (device), face); - fd = (struct fontdir *) res_alloc (sizeof *fd); + fd = (rc_fontdir *) res_alloc (sizeof (rc_fontdir)); fd->next = NULL; fd->index = fonts; fd->length = fontdatalength; @@ -919,14 +947,33 @@ define_font (struct res_id id, const struct res_res_info *resinfo, fontdirs_resinfo = *resinfo; } +static void +define_font_rcdata (rc_res_id id,const rc_res_res_info *resinfo, + rc_rcdata_item *data) +{ + rc_res_resource *r; + rc_uint_type len_data; + bfd_byte *pb_data; + + r = define_standard_resource (&resources, RT_FONT, id, + resinfo->language, 0); + + pb_data = rcdata_render_as_buffer (data, &len_data); + + r->type = RES_TYPE_FONT; + r->u.data.length = len_data; + r->u.data.data = pb_data; + r->res_info = *resinfo; +} + /* Define the fontdirs resource. This is called after the entire rc file has been parsed, if any font resources were seen. */ static void define_fontdirs (void) { - struct res_resource *r; - struct res_id id; + rc_res_resource *r; + rc_res_id id; id.named = 0; id.u.id = 1; @@ -938,6 +985,89 @@ define_fontdirs (void) r->res_info = fontdirs_resinfo; } +static bfd_byte * +rcdata_render_as_buffer (const rc_rcdata_item *data, rc_uint_type *plen) +{ + const rc_rcdata_item *d; + bfd_byte *ret = NULL, *pret; + rc_uint_type len = 0; + + for (d = data; d != NULL; d = d->next) + len += rcdata_copy (d, NULL); + if (len != 0) + { + ret = pret = (bfd_byte *) res_alloc (len); + for (d = data; d != NULL; d = d->next) + pret += rcdata_copy (d, pret); + } + if (plen) + *plen = len; + return ret; +} + +static void +define_fontdir_rcdata (rc_res_id id,const rc_res_res_info *resinfo, + rc_rcdata_item *data) +{ + rc_res_resource *r; + rc_fontdir *fd, *fd_first, *fd_cur; + rc_uint_type len_data; + bfd_byte *pb_data; + rc_uint_type c; + + fd_cur = fd_first = NULL; + r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0); + + pb_data = rcdata_render_as_buffer (data, &len_data); + + if (pb_data) + { + rc_uint_type off = 2; + c = windres_get_16 (&wrtarget, pb_data, len_data); + for (; c > 0; c--) + { + size_t len; + rc_uint_type safe_pos = off; + const struct bin_fontdir_item *bfi; + + bfi = (const struct bin_fontdir_item *) pb_data + off; + fd = (rc_fontdir *) res_alloc (sizeof (rc_fontdir)); + fd->index = windres_get_16 (&wrtarget, bfi->index, len_data - off); + fd->data = pb_data + off; + off += 56; + len = strlen ((char *) bfi->device_name) + 1; + off += (rc_uint_type) len; + off += (rc_uint_type) strlen ((char *) bfi->device_name + len) + 1; + fd->length = (off - safe_pos); + fd->next = NULL; + if (fd_first == NULL) + fd_first = fd; + else + fd_cur->next = fd; + fd_cur = fd; + } + } + r->type = RES_TYPE_FONTDIR; + r->u.fontdir = fd_first; + r->res_info = *resinfo; +} + +static void define_messagetable_rcdata (rc_res_id id, const rc_res_res_info *resinfo, + rc_rcdata_item *data) +{ + rc_res_resource *r; + rc_uint_type len_data; + bfd_byte *pb_data; + + r = define_standard_resource (&resources, RT_MESSAGETABLE, id, resinfo->language, 0); + + pb_data = rcdata_render_as_buffer (data, &len_data); + r->type = RES_TYPE_MESSAGETABLE; + r->u.data.length = len_data; + r->u.data.data = pb_data; + r->res_info = *resinfo; +} + /* Define an icon resource. An icon file may contain a set of bitmaps, each representing the same icon at various different resolutions. They each get written out with a different ID. The @@ -945,7 +1075,7 @@ define_fontdirs (void) select one of the actual icon bitmaps. */ void -define_icon (struct res_id id, const struct res_res_info *resinfo, +define_icon (rc_res_id id, const rc_res_res_info *resinfo, const char *filename) { FILE *e; @@ -953,8 +1083,8 @@ define_icon (struct res_id id, const struct res_res_info *resinfo, int type, count, i; struct icondir *icondirs; int first_icon; - struct res_resource *r; - struct group_icon *first, **pp; + rc_res_resource *r; + rc_group_icon *first, **pp; e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename); @@ -993,14 +1123,14 @@ define_icon (struct res_id id, const struct res_res_info *resinfo, for (i = 0; i < count; i++) { - unsigned char *data; - struct res_id name; + bfd_byte *data; + rc_res_id name; if (fseek (e, icondirs[i].offset, SEEK_SET) != 0) fatal (_("%s: fseek to %lu failed: %s"), real_filename, icondirs[i].offset, strerror (errno)); - data = (unsigned char *) res_alloc (icondirs[i].bytes); + data = (bfd_byte *) res_alloc (icondirs[i].bytes); get_data (e, data, icondirs[i].bytes, real_filename); @@ -1026,13 +1156,13 @@ define_icon (struct res_id id, const struct res_res_info *resinfo, pp = &first; for (i = 0; i < count; i++) { - struct group_icon *cg; + rc_group_icon *cg; /* For some reason, at least in some files the planes and bits are zero. We instead set them from the color. This is copied from rcl. */ - cg = (struct group_icon *) res_alloc (sizeof *cg); + cg = (rc_group_icon *) res_alloc (sizeof (rc_group_icon)); cg->next = NULL; cg->width = icondirs[i].width; cg->height = icondirs[i].height; @@ -1069,16 +1199,180 @@ define_icon (struct res_id id, const struct res_res_info *resinfo, r->res_info = *resinfo; } +static void +define_group_icon_rcdata (rc_res_id id, const rc_res_res_info *resinfo, + rc_rcdata_item *data) +{ + rc_res_resource *r; + rc_group_icon *cg, *first, *cur; + rc_uint_type len_data; + bfd_byte *pb_data; + + pb_data = rcdata_render_as_buffer (data, &len_data); + + cur = NULL; + first = NULL; + + while (len_data >= 6) + { + int c, i; + unsigned short type; + type = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2); + if (type != 1) + fatal (_("unexpected group icon type %d"), type); + c = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4); + len_data -= 6; + pb_data += 6; + + for (i = 0; i < c; i++) + { + if (len_data < 14) + fatal ("too small group icon rcdata"); + cg = (rc_group_icon *) res_alloc (sizeof (rc_group_icon)); + cg->next = NULL; + cg->width = pb_data[0]; + cg->height = pb_data[1]; + cg->colors = pb_data[2]; + cg->planes = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4); + cg->bits = windres_get_16 (&wrtarget, pb_data + 6, len_data - 6); + cg->bytes = windres_get_32 (&wrtarget, pb_data + 8, len_data - 8); + cg->index = windres_get_16 (&wrtarget, pb_data + 12, len_data - 12); + if (! first) + first = cg; + else + cur->next = cg; + cur = cg; + pb_data += 14; + len_data -= 14; + } + } + r = define_standard_resource (&resources, RT_GROUP_ICON, id, + resinfo->language, 0); + r->type = RES_TYPE_GROUP_ICON; + r->u.group_icon = first; + r->res_info = *resinfo; +} + +static void +define_group_cursor_rcdata (rc_res_id id, const rc_res_res_info *resinfo, + rc_rcdata_item *data) +{ + rc_res_resource *r; + rc_group_cursor *cg, *first, *cur; + rc_uint_type len_data; + bfd_byte *pb_data; + + pb_data = rcdata_render_as_buffer (data, &len_data); + + first = cur = NULL; + + while (len_data >= 6) + { + int c, i; + unsigned short type; + type = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2); + if (type != 2) + fatal (_("unexpected group cursor type %d"), type); + c = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4); + len_data -= 6; + pb_data += 6; + + for (i = 0; i < c; i++) + { + if (len_data < 14) + fatal ("too small group icon rcdata"); + cg = (rc_group_cursor *) res_alloc (sizeof (rc_group_cursor)); + cg->next = NULL; + cg->width = windres_get_16 (&wrtarget, pb_data, len_data); + cg->height = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2); + cg->planes = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4); + cg->bits = windres_get_16 (&wrtarget, pb_data + 6, len_data - 6); + cg->bytes = windres_get_32 (&wrtarget, pb_data + 8, len_data - 8); + cg->index = windres_get_16 (&wrtarget, pb_data + 12, len_data - 12); + if (! first) + first = cg; + else + cur->next = cg; + cur = cg; + pb_data += 14; + len_data -= 14; + } + } + + r = define_standard_resource (&resources, RT_GROUP_ICON, id, + resinfo->language, 0); + r->type = RES_TYPE_GROUP_CURSOR; + r->u.group_cursor = first; + r->res_info = *resinfo; +} + +static void +define_cursor_rcdata (rc_res_id id, const rc_res_res_info *resinfo, + rc_rcdata_item *data) +{ + rc_cursor *c; + rc_res_resource *r; + rc_uint_type len_data; + bfd_byte *pb_data; + + pb_data = rcdata_render_as_buffer (data, &len_data); + + c = (rc_cursor *) res_alloc (sizeof (rc_cursor)); + c->xhotspot = windres_get_16 (&wrtarget, pb_data, len_data); + c->yhotspot = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2); + c->length = len_data - BIN_CURSOR_SIZE; + c->data = (const bfd_byte *) (data + BIN_CURSOR_SIZE); + + r = define_standard_resource (&resources, RT_CURSOR, id, resinfo->language, 0); + r->type = RES_TYPE_CURSOR; + r->u.cursor = c; + r->res_info = *resinfo; +} + +static void +define_bitmap_rcdata (rc_res_id id, const rc_res_res_info *resinfo, + rc_rcdata_item *data) +{ + rc_res_resource *r; + rc_uint_type len_data; + bfd_byte *pb_data; + + pb_data = rcdata_render_as_buffer (data, &len_data); + + r = define_standard_resource (&resources, RT_BITMAP, id, resinfo->language, 0); + r->type = RES_TYPE_BITMAP; + r->u.data.length = len_data; + r->u.data.data = pb_data; + r->res_info = *resinfo; +} + +static void +define_icon_rcdata (rc_res_id id, const rc_res_res_info *resinfo, + rc_rcdata_item *data) +{ + rc_res_resource *r; + rc_uint_type len_data; + bfd_byte *pb_data; + + pb_data = rcdata_render_as_buffer (data, &len_data); + + r = define_standard_resource (&resources, RT_ICON, id, resinfo->language, 0); + r->type = RES_TYPE_ICON; + r->u.data.length = len_data; + r->u.data.data = pb_data; + r->res_info = *resinfo; +} + /* Define a menu resource. */ void -define_menu (struct res_id id, const struct res_res_info *resinfo, - struct menuitem *menuitems) +define_menu (rc_res_id id, const rc_res_res_info *resinfo, + rc_menuitem *menuitems) { - struct menu *m; - struct res_resource *r; + rc_menu *m; + rc_res_resource *r; - m = (struct menu *) res_alloc (sizeof *m); + m = (rc_menu *) res_alloc (sizeof (rc_menu)); m->items = menuitems; m->help = 0; @@ -1091,22 +1385,19 @@ define_menu (struct res_id id, const struct res_res_info *resinfo, /* Define a menu item. This does not define a resource, but merely allocates and fills in a structure. */ -struct menuitem * -define_menuitem (const char *text, int menuid, unsigned long type, - unsigned long state, unsigned long help, - struct menuitem *menuitems) +rc_menuitem * +define_menuitem (const unichar *text, rc_uint_type menuid, rc_uint_type type, + rc_uint_type state, rc_uint_type help, + rc_menuitem *menuitems) { - struct menuitem *mi; + rc_menuitem *mi; - mi = (struct menuitem *) res_alloc (sizeof *mi); + mi = (rc_menuitem *) res_alloc (sizeof (rc_menuitem)); mi->next = NULL; mi->type = type; mi->state = state; mi->id = menuid; - if (text == NULL) - mi->text = NULL; - else - unicode_from_ascii ((int *) NULL, &mi->text, text); + mi->text = unichar_dup (text); mi->help = help; mi->popup = menuitems; return mi; @@ -1115,14 +1406,14 @@ define_menuitem (const char *text, int menuid, unsigned long type, /* Define a messagetable resource. */ void -define_messagetable (struct res_id id, const struct res_res_info *resinfo, +define_messagetable (rc_res_id id, const rc_res_res_info *resinfo, const char *filename) { FILE *e; char *real_filename; struct stat s; - unsigned char *data; - struct res_resource *r; + bfd_byte *data; + rc_res_resource *r; e = open_file_search (filename, FOPEN_RB, "messagetable file", &real_filename); @@ -1131,7 +1422,7 @@ define_messagetable (struct res_id id, const struct res_res_info *resinfo, fatal (_("stat failed on bitmap file `%s': %s"), real_filename, strerror (errno)); - data = (unsigned char *) res_alloc (s.st_size); + data = (bfd_byte *) res_alloc (s.st_size); get_data (e, data, s.st_size, real_filename); @@ -1150,10 +1441,10 @@ define_messagetable (struct res_id id, const struct res_res_info *resinfo, /* Define an rcdata resource. */ void -define_rcdata (struct res_id id, const struct res_res_info *resinfo, - struct rcdata_item *data) +define_rcdata (rc_res_id id, const rc_res_res_info *resinfo, + rc_rcdata_item *data) { - struct res_resource *r; + rc_res_resource *r; r = define_standard_resource (&resources, RT_RCDATA, id, resinfo->language, 0); @@ -1164,13 +1455,13 @@ define_rcdata (struct res_id id, const struct res_res_info *resinfo, /* Create an rcdata item holding a string. */ -struct rcdata_item * -define_rcdata_string (const char *string, unsigned long len) +rc_rcdata_item * +define_rcdata_string (const char *string, rc_uint_type len) { - struct rcdata_item *ri; + rc_rcdata_item *ri; char *s; - ri = (struct rcdata_item *) res_alloc (sizeof *ri); + ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item)); ri->next = NULL; ri->type = RCDATA_STRING; ri->u.string.length = len; @@ -1181,14 +1472,33 @@ define_rcdata_string (const char *string, unsigned long len) return ri; } +/* Create an rcdata item holding a unicode string. */ + +rc_rcdata_item * +define_rcdata_unistring (const unichar *string, rc_uint_type len) +{ + rc_rcdata_item *ri; + unichar *s; + + ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item)); + ri->next = NULL; + ri->type = RCDATA_WSTRING; + ri->u.wstring.length = len; + s = (unichar *) res_alloc (len * sizeof (unichar)); + memcpy (s, string, len * sizeof (unichar)); + ri->u.wstring.w = s; + + return ri; +} + /* Create an rcdata item holding a number. */ -struct rcdata_item * -define_rcdata_number (unsigned long val, int dword) +rc_rcdata_item * +define_rcdata_number (rc_uint_type val, int dword) { - struct rcdata_item *ri; + rc_rcdata_item *ri; - ri = (struct rcdata_item *) res_alloc (sizeof *ri); + ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item)); ri->next = NULL; ri->type = dword ? RCDATA_DWORD : RCDATA_WORD; ri->u.word = val; @@ -1200,11 +1510,11 @@ define_rcdata_number (unsigned long val, int dword) which appears in a STRINGTABLE statement. */ void -define_stringtable (const struct res_res_info *resinfo, - unsigned long stringid, const char *string) +define_stringtable (const rc_res_res_info *resinfo, + rc_uint_type stringid, const unichar *string) { - struct res_id id; - struct res_resource *r; + rc_res_id id; + rc_res_resource *r; id.named = 0; id.u.id = (stringid >> 4) + 1; @@ -1216,8 +1526,8 @@ define_stringtable (const struct res_res_info *resinfo, int i; r->type = RES_TYPE_STRINGTABLE; - r->u.stringtable = ((struct stringtable *) - res_alloc (sizeof (struct stringtable))); + r->u.stringtable = ((rc_stringtable *) + res_alloc (sizeof (rc_stringtable))); for (i = 0; i < 16; i++) { r->u.stringtable->strings[i].length = 0; @@ -1227,21 +1537,79 @@ define_stringtable (const struct res_res_info *resinfo, r->res_info = *resinfo; } - unicode_from_ascii (&r->u.stringtable->strings[stringid & 0xf].length, - &r->u.stringtable->strings[stringid & 0xf].string, - string); + r->u.stringtable->strings[stringid & 0xf].length = unichar_len (string); + r->u.stringtable->strings[stringid & 0xf].string = unichar_dup (string); +} + +void +define_toolbar (rc_res_id id, rc_res_res_info *resinfo, rc_uint_type width, rc_uint_type height, + rc_toolbar_item *items) +{ + rc_toolbar *t; + rc_res_resource *r; + + t = (rc_toolbar *) res_alloc (sizeof (rc_toolbar)); + t->button_width = width; + t->button_height = height; + t->nitems = 0; + t->items = items; + while (items != NULL) + { + t->nitems+=1; + items = items->next; + } + r = define_standard_resource (&resources, RT_TOOLBAR, id, resinfo->language, 0); + r->type = RES_TYPE_TOOLBAR; + r->u.toolbar = t; + r->res_info = *resinfo; } /* Define a user data resource where the data is in the rc file. */ void -define_user_data (struct res_id id, struct res_id type, - const struct res_res_info *resinfo, - struct rcdata_item *data) +define_user_data (rc_res_id id, rc_res_id type, + const rc_res_res_info *resinfo, + rc_rcdata_item *data) { - struct res_id ids[3]; - struct res_resource *r; + rc_res_id ids[3]; + rc_res_resource *r; + bfd_byte *pb_data; + rc_uint_type len_data; + /* We have to check if the binary data is parsed specially. */ + if (type.named == 0) + { + switch (type.u.id) + { + case RT_FONTDIR: + define_fontdir_rcdata (id, resinfo, data); + return; + case RT_FONT: + define_font_rcdata (id, resinfo, data); + return; + case RT_ICON: + define_icon_rcdata (id, resinfo, data); + return; + case RT_BITMAP: + define_bitmap_rcdata (id, resinfo, data); + return; + case RT_CURSOR: + define_cursor_rcdata (id, resinfo, data); + return; + case RT_GROUP_ICON: + define_group_icon_rcdata (id, resinfo, data); + return; + case RT_GROUP_CURSOR: + define_group_cursor_rcdata (id, resinfo, data); + return; + case RT_MESSAGETABLE: + define_messagetable_rcdata (id, resinfo, data); + return; + default: + /* Treat as normal user-data. */ + break; + } + } ids[0] = type; ids[1] = id; ids[2].named = 0; @@ -1249,19 +1617,25 @@ define_user_data (struct res_id id, struct res_id type, r = define_resource (& resources, 3, ids, 0); r->type = RES_TYPE_USERDATA; - r->u.userdata = data; + r->u.userdata = ((rc_rcdata_item *) + res_alloc (sizeof (rc_rcdata_item))); + r->u.userdata->next = NULL; + r->u.userdata->type = RCDATA_BUFFER; + pb_data = rcdata_render_as_buffer (data, &len_data); + r->u.userdata->u.buffer.length = len_data; + r->u.userdata->u.buffer.data = pb_data; r->res_info = *resinfo; } void -define_rcdata_file (struct res_id id, const struct res_res_info *resinfo, +define_rcdata_file (rc_res_id id, const rc_res_res_info *resinfo, const char *filename) { - struct rcdata_item *ri; + rc_rcdata_item *ri; FILE *e; char *real_filename; struct stat s; - unsigned char *data; + bfd_byte *data; e = open_file_search (filename, FOPEN_RB, "file", &real_filename); @@ -1270,14 +1644,14 @@ define_rcdata_file (struct res_id id, const struct res_res_info *resinfo, fatal (_("stat failed on file `%s': %s"), real_filename, strerror (errno)); - data = (unsigned char *) res_alloc (s.st_size); + data = (bfd_byte *) res_alloc (s.st_size); get_data (e, data, s.st_size, real_filename); fclose (e); free (real_filename); - ri = (struct rcdata_item *) res_alloc (sizeof *ri); + ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item)); ri->next = NULL; ri->type = RCDATA_BUFFER; ri->u.buffer.length = s.st_size; @@ -1289,15 +1663,15 @@ define_rcdata_file (struct res_id id, const struct res_res_info *resinfo, /* Define a user data resource where the data is in a file. */ void -define_user_file (struct res_id id, struct res_id type, - const struct res_res_info *resinfo, const char *filename) +define_user_file (rc_res_id id, rc_res_id type, + const rc_res_res_info *resinfo, const char *filename) { FILE *e; char *real_filename; struct stat s; - unsigned char *data; - struct res_id ids[3]; - struct res_resource *r; + bfd_byte *data; + rc_res_id ids[3]; + rc_res_resource *r; e = open_file_search (filename, FOPEN_RB, "file", &real_filename); @@ -1305,7 +1679,7 @@ define_user_file (struct res_id id, struct res_id type, fatal (_("stat failed on file `%s': %s"), real_filename, strerror (errno)); - data = (unsigned char *) res_alloc (s.st_size); + data = (bfd_byte *) res_alloc (s.st_size); get_data (e, data, s.st_size, real_filename); @@ -1319,8 +1693,8 @@ define_user_file (struct res_id id, struct res_id type, r = define_resource (&resources, 3, ids, 0); r->type = RES_TYPE_USERDATA; - r->u.userdata = ((struct rcdata_item *) - res_alloc (sizeof (struct rcdata_item))); + r->u.userdata = ((rc_rcdata_item *) + res_alloc (sizeof (rc_rcdata_item))); r->u.userdata->next = NULL; r->u.userdata->type = RCDATA_BUFFER; r->u.userdata->u.buffer.length = s.st_size; @@ -1331,16 +1705,16 @@ define_user_file (struct res_id id, struct res_id type, /* Define a versioninfo resource. */ void -define_versioninfo (struct res_id id, int language, - struct fixed_versioninfo *fixedverinfo, - struct ver_info *verinfo) +define_versioninfo (rc_res_id id, rc_uint_type language, + rc_fixed_versioninfo *fixedverinfo, + rc_ver_info *verinfo) { - struct res_resource *r; + rc_res_resource *r; r = define_standard_resource (&resources, RT_VERSION, id, language, 0); r->type = RES_TYPE_VERSIONINFO; - r->u.versioninfo = ((struct versioninfo *) - res_alloc (sizeof (struct versioninfo))); + r->u.versioninfo = ((rc_versioninfo *) + res_alloc (sizeof (rc_versioninfo))); r->u.versioninfo->fixed = fixedverinfo; r->u.versioninfo->var = verinfo; r->res_info.language = language; @@ -1348,16 +1722,16 @@ define_versioninfo (struct res_id id, int language, /* Add string version info to a list of version information. */ -struct ver_info * -append_ver_stringfileinfo (struct ver_info *verinfo, const char *language, - struct ver_stringinfo *strings) +rc_ver_info * +append_ver_stringfileinfo (rc_ver_info *verinfo, const char *language, + rc_ver_stringinfo *strings) { - struct ver_info *vi, **pp; + rc_ver_info *vi, **pp; - vi = (struct ver_info *) res_alloc (sizeof *vi); + vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info)); vi->next = NULL; vi->type = VERINFO_STRING; - unicode_from_ascii ((int *) NULL, &vi->u.string.language, language); + unicode_from_ascii ((rc_uint_type *) NULL, &vi->u.string.language, language); vi->u.string.strings = strings; for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next) @@ -1369,16 +1743,16 @@ append_ver_stringfileinfo (struct ver_info *verinfo, const char *language, /* Add variable version info to a list of version information. */ -struct ver_info * -append_ver_varfileinfo (struct ver_info *verinfo, const char *key, - struct ver_varinfo *var) +rc_ver_info * +append_ver_varfileinfo (rc_ver_info *verinfo, const unichar *key, + rc_ver_varinfo *var) { - struct ver_info *vi, **pp; + rc_ver_info *vi, **pp; - vi = (struct ver_info *) res_alloc (sizeof *vi); + vi = (rc_ver_info *) res_alloc (sizeof *vi); vi->next = NULL; vi->type = VERINFO_VAR; - unicode_from_ascii ((int *) NULL, &vi->u.var.key, key); + vi->u.var.key = unichar_dup (key); vi->u.var.var = var; for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next) @@ -1390,16 +1764,16 @@ append_ver_varfileinfo (struct ver_info *verinfo, const char *key, /* Append version string information to a list. */ -struct ver_stringinfo * -append_verval (struct ver_stringinfo *strings, const char *key, - const char *value) +rc_ver_stringinfo * +append_verval (rc_ver_stringinfo *strings, const unichar *key, + const unichar *value) { - struct ver_stringinfo *vs, **pp; + rc_ver_stringinfo *vs, **pp; - vs = (struct ver_stringinfo *) res_alloc (sizeof *vs); + vs = (rc_ver_stringinfo *) res_alloc (sizeof (rc_ver_stringinfo)); vs->next = NULL; - unicode_from_ascii ((int *) NULL, &vs->key, key); - unicode_from_ascii ((int *) NULL, &vs->value, value); + vs->key = unichar_dup (key); + vs->value = unichar_dup (value); for (pp = &strings; *pp != NULL; pp = &(*pp)->next) ; @@ -1410,13 +1784,13 @@ append_verval (struct ver_stringinfo *strings, const char *key, /* Append version variable information to a list. */ -struct ver_varinfo * -append_vertrans (struct ver_varinfo *var, unsigned long language, - unsigned long charset) +rc_ver_varinfo * +append_vertrans (rc_ver_varinfo *var, rc_uint_type language, + rc_uint_type charset) { - struct ver_varinfo *vv, **pp; + rc_ver_varinfo *vv, **pp; - vv = (struct ver_varinfo *) res_alloc (sizeof *vv); + vv = (rc_ver_varinfo *) res_alloc (sizeof (rc_ver_varinfo)); vv->next = NULL; vv->language = language; vv->charset = charset; @@ -1431,29 +1805,28 @@ append_vertrans (struct ver_varinfo *var, unsigned long language, /* Local functions used to write out an rc file. */ static void indent (FILE *, int); -static void write_rc_directory - (FILE *, const struct res_directory *, const struct res_id *, - const struct res_id *, int *, int); -static void write_rc_subdir - (FILE *, const struct res_entry *, const struct res_id *, - const struct res_id *, int *, int); -static void write_rc_resource - (FILE *, const struct res_id *, const struct res_id *, - const struct res_resource *, int *); -static void write_rc_accelerators (FILE *, const struct accelerator *); -static void write_rc_cursor (FILE *, const struct cursor *); -static void write_rc_group_cursor (FILE *, const struct group_cursor *); -static void write_rc_dialog (FILE *, const struct dialog *); -static void write_rc_dialog_control (FILE *, const struct dialog_control *); -static void write_rc_fontdir (FILE *, const struct fontdir *); -static void write_rc_group_icon (FILE *, const struct group_icon *); -static void write_rc_menu (FILE *, const struct menu *, int); -static void write_rc_menuitems (FILE *, const struct menuitem *, int, int); -static void write_rc_rcdata (FILE *, const struct rcdata_item *, int); -static void write_rc_stringtable - (FILE *, const struct res_id *, const struct stringtable *); -static void write_rc_versioninfo (FILE *, const struct versioninfo *); -static void write_rc_filedata (FILE *, unsigned long, const unsigned char *); +static void write_rc_directory (FILE *, const rc_res_directory *, const rc_res_id *, + const rc_res_id *, rc_uint_type *, int); +static void write_rc_subdir (FILE *, const rc_res_entry *, const rc_res_id *, + const rc_res_id *, rc_uint_type *, int); +static void write_rc_resource (FILE *, const rc_res_id *, const rc_res_id *, + const rc_res_resource *, rc_uint_type *); +static void write_rc_accelerators (FILE *, const rc_accelerator *); +static void write_rc_cursor (FILE *, const rc_cursor *); +static void write_rc_group_cursor (FILE *, const rc_group_cursor *); +static void write_rc_dialog (FILE *, const rc_dialog *); +static void write_rc_dialog_control (FILE *, const rc_dialog_control *); +static void write_rc_fontdir (FILE *, const rc_fontdir *); +static void write_rc_group_icon (FILE *, const rc_group_icon *); +static void write_rc_menu (FILE *, const rc_menu *, int); +static void write_rc_toolbar (FILE *, const rc_toolbar *); +static void write_rc_menuitems (FILE *, const rc_menuitem *, int, int); +static void write_rc_messagetable (FILE *, rc_uint_type , const bfd_byte *); + +static void write_rc_datablock (FILE *, rc_uint_type , const bfd_byte *, int, int, int); +static void write_rc_rcdata (FILE *, const rc_rcdata_item *, int); +static void write_rc_stringtable (FILE *, const rc_res_id *, const rc_stringtable *); +static void write_rc_versioninfo (FILE *, const rc_versioninfo *); /* Indent a given number of spaces. */ @@ -1468,19 +1841,15 @@ indent (FILE *e, int c) /* Dump the resources we have read in the format of an rc file. - Actually, we don't use the format of an rc file, because it's way - too much of a pain--for example, we'd have to write icon resources - into a file and refer to that file. We just generate a readable - format that kind of looks like an rc file, and is useful for - understanding the contents of a resource file. Someday we may want - to generate an rc file which the rc compiler can read; if that day - comes, this code will have to be fixed up. */ + Reasoned by the fact, that some resources need to be stored into file and + refer to that file, we use the user-data model for that to express it binary + without the need to store it somewhere externally. */ void -write_rc_file (const char *filename, const struct res_directory *resources) +write_rc_file (const char *filename, const rc_res_directory *resources) { FILE *e; - int language; + rc_uint_type language; if (filename == NULL) e = stdout; @@ -1491,9 +1860,9 @@ write_rc_file (const char *filename, const struct res_directory *resources) fatal (_("can't open `%s' for output: %s"), filename, strerror (errno)); } - language = -1; - write_rc_directory (e, resources, (const struct res_id *) NULL, - (const struct res_id *) NULL, &language, 1); + language = (rc_uint_type) ((bfd_signed_vma) -1); + write_rc_directory (e, resources, (const rc_res_id *) NULL, + (const rc_res_id *) NULL, &language, 1); } /* Write out a directory. E is the file to write to. RD is the @@ -1503,20 +1872,23 @@ write_rc_file (const char *filename, const struct res_directory *resources) language. LEVEL is the level in the tree. */ static void -write_rc_directory (FILE *e, const struct res_directory *rd, - const struct res_id *type, const struct res_id *name, - int *language, int level) +write_rc_directory (FILE *e, 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; /* Print out some COFF information that rc files can't represent. */ - + if (rd->time != 0 || rd->characteristics != 0 || rd->major != 0 || rd->minor != 0) + { + wr_printcomment (e, "COFF information not part of RC"); if (rd->time != 0) - fprintf (e, "// Time stamp: %lu\n", rd->time); + wr_printcomment (e, "Time stamp: %u", rd->time); if (rd->characteristics != 0) - fprintf (e, "// Characteristics: %lu\n", rd->characteristics); + wr_printcomment (e, "Characteristics: %u", rd->characteristics); if (rd->major != 0 || rd->minor != 0) - fprintf (e, "// Version: %d %d\n", rd->major, rd->minor); + wr_printcomment (e, "Version major:%d minor:%d", rd->major, rd->minor); + } for (re = rd->entries; re != NULL; re = re->next) { @@ -1543,7 +1915,7 @@ write_rc_directory (FILE *e, const struct res_directory *rd, && re->id.u.id != (unsigned long) (unsigned int) *language && (re->id.u.id & 0xffff) == re->id.u.id) { - fprintf (e, "LANGUAGE %lu, %lu\n", + wr_print (e, "LANGUAGE %u, %u\n", re->id.u.id & ((1 << SUBLANG_SHIFT) - 1), (re->id.u.id >> SUBLANG_SHIFT) & 0xff); *language = re->id.u.id; @@ -1569,12 +1941,16 @@ write_rc_directory (FILE *e, const struct res_directory *rd, } else { - fprintf (e, "// Resource at unexpected level %d\n", level); - write_rc_resource (e, type, (struct res_id *) NULL, re->u.res, + wr_printcomment (e, "Resource at unexpected level %d", level); + write_rc_resource (e, type, (rc_res_id *) NULL, re->u.res, language); } } } + if (rd->entries == NULL) + { + wr_print_flush (e); + } } /* Write out a subdirectory entry. E is the file to write to. RE is @@ -1583,15 +1959,15 @@ write_rc_directory (FILE *e, const struct res_directory *rd, LEVEL is the level in the tree. */ static void -write_rc_subdir (FILE *e, const struct res_entry *re, - const struct res_id *type, const struct res_id *name, - int *language, int level) +write_rc_subdir (FILE *e, const rc_res_entry *re, + const rc_res_id *type, const rc_res_id *name, + rc_uint_type *language, int level) { fprintf (e, "\n"); switch (level) { case 1: - fprintf (e, "// Type: "); + wr_printcomment (e, "Type: "); if (re->id.named) res_id_print (e, re->id, 1); else @@ -1619,6 +1995,8 @@ write_rc_subdir (FILE *e, const struct res_entry *re, case RT_VXD: s = "vxd"; break; case RT_ANICURSOR: s = "anicursor"; break; case RT_ANIICON: s = "aniicon"; break; + case RT_TOOLBAR: s = "toolbar"; break; + case RT_HTML: s = "html"; break; default: s = NULL; break; } @@ -1627,25 +2005,21 @@ write_rc_subdir (FILE *e, const struct res_entry *re, else res_id_print (e, re->id, 1); } - fprintf (e, "\n"); break; case 2: - fprintf (e, "// Name: "); + wr_printcomment (e, "Name: "); res_id_print (e, re->id, 1); - fprintf (e, "\n"); break; case 3: - fprintf (e, "// Language: "); + wr_printcomment (e, "Language: "); res_id_print (e, re->id, 1); - fprintf (e, "\n"); break; default: - fprintf (e, "// Level %d: ", level); + wr_printcomment (e, "Level %d: ", level); res_id_print (e, re->id, 1); - fprintf (e, "\n"); } write_rc_directory (e, re->u.dir, type, name, language, level + 1); @@ -1658,38 +2032,36 @@ write_rc_subdir (FILE *e, const struct res_entry *re, language. */ static void -write_rc_resource (FILE *e, const struct res_id *type, - const struct res_id *name, const struct res_resource *res, - int *language) +write_rc_resource (FILE *e, const rc_res_id *type, + const rc_res_id *name, const rc_res_resource *res, + rc_uint_type *language) { const char *s; int rt; int menuex = 0; - fprintf (e, "\n"); - switch (res->type) { default: abort (); case RES_TYPE_ACCELERATOR: - s = "ACCELERATOR"; + s = "ACCELERATORS"; rt = RT_ACCELERATOR; break; case RES_TYPE_BITMAP: - s = "BITMAP"; + s = "2 /* RT_BITMAP */"; rt = RT_BITMAP; break; case RES_TYPE_CURSOR: - s = "CURSOR"; + s = "1 /* RT_CURSOR */"; rt = RT_CURSOR; break; case RES_TYPE_GROUP_CURSOR: - s = "GROUP_CURSOR"; + s = "12 /* RT_GROUP_CURSOR */"; rt = RT_GROUP_CURSOR; break; @@ -1702,22 +2074,22 @@ write_rc_resource (FILE *e, const struct res_id *type, break; case RES_TYPE_FONT: - s = "FONT"; + s = "8 /* RT_FONT */"; rt = RT_FONT; break; case RES_TYPE_FONTDIR: - s = "FONTDIR"; + s = "7 /* RT_FONTDIR */"; rt = RT_FONTDIR; break; case RES_TYPE_ICON: - s = "ICON"; + s = "3 /* RT_ICON */"; rt = RT_ICON; break; case RES_TYPE_GROUP_ICON: - s = "GROUP_ICON"; + s = "14 /* RT_GROUP_ICON */"; rt = RT_GROUP_ICON; break; @@ -1736,7 +2108,7 @@ write_rc_resource (FILE *e, const struct res_id *type, break; case RES_TYPE_MESSAGETABLE: - s = "MESSAGETABLE"; + s = "11 /* RT_MESSAGETABLE */"; rt = RT_MESSAGETABLE; break; @@ -1759,32 +2131,76 @@ write_rc_resource (FILE *e, const struct res_id *type, s = "VERSIONINFO"; rt = RT_VERSION; break; + + case RES_TYPE_TOOLBAR: + s = "TOOLBAR"; + rt = RT_TOOLBAR; + break; } if (rt != 0 && type != NULL && (type->named || type->u.id != (unsigned long) rt)) { - fprintf (e, "// Unexpected resource type mismatch: "); + wr_printcomment (e, "Unexpected resource type mismatch: "); res_id_print (e, *type, 1); fprintf (e, " != %d", rt); } if (res->coff_info.codepage != 0) - fprintf (e, "// Code page: %lu\n", res->coff_info.codepage); + wr_printcomment (e, "Code page: %u", res->coff_info.codepage); if (res->coff_info.reserved != 0) - fprintf (e, "// COFF reserved value: %lu\n", res->coff_info.reserved); + wr_printcomment (e, "COFF reserved value: %u", res->coff_info.reserved); + wr_print (e, "\n"); + if (rt == RT_STRING) + ; + else + { if (name != NULL) - res_id_print (e, *name, 0); + res_id_print (e, *name, 1); else fprintf (e, "??Unknown-Name??"); - fprintf (e, " "); + } + if (s != NULL) fprintf (e, "%s", s); else if (type != NULL) + { + if (type->named == 0) + { +#define PRINT_RT_NAME(NAME) case NAME: \ + fprintf (e, "%u /* %s */", (unsigned int) NAME, #NAME); \ + break + + switch (type->u.id) + { + default: res_id_print (e, *type, 0); + break; + + PRINT_RT_NAME(RT_MANIFEST); + PRINT_RT_NAME(RT_ANICURSOR); + PRINT_RT_NAME(RT_ANIICON); + PRINT_RT_NAME(RT_RCDATA); + PRINT_RT_NAME(RT_ICON); + PRINT_RT_NAME(RT_CURSOR); + PRINT_RT_NAME(RT_BITMAP); + PRINT_RT_NAME(RT_PLUGPLAY); + PRINT_RT_NAME(RT_VXD); + PRINT_RT_NAME(RT_FONT); + PRINT_RT_NAME(RT_FONTDIR); + PRINT_RT_NAME(RT_HTML); + PRINT_RT_NAME(RT_MESSAGETABLE); + PRINT_RT_NAME(RT_DLGINCLUDE); + PRINT_RT_NAME(RT_DLGINIT); + } +#undef PRINT_RT_NAME + } + else + res_id_print (e, *type, 1); + } else fprintf (e, "??Unknown-Type??"); @@ -1802,11 +2218,17 @@ write_rc_resource (FILE *e, const struct res_id *type, if (res->type == RES_TYPE_DIALOG) { - fprintf (e, " %d, %d, %d, %d", res->u.dialog->x, res->u.dialog->y, - res->u.dialog->width, res->u.dialog->height); + fprintf (e, " %d, %d, %d, %d", + (int) res->u.dialog->x, (int) res->u.dialog->y, + (int) res->u.dialog->width, (int) res->u.dialog->height); if (res->u.dialog->ex != NULL && res->u.dialog->ex->help != 0) - fprintf (e, ", %lu", res->u.dialog->ex->help); + fprintf (e, ", %u", (unsigned int) res->u.dialog->ex->help); + } + else if (res->type == RES_TYPE_TOOLBAR) + { + fprintf (e, " %d, %d", (int) res->u.toolbar->button_width, + (int) res->u.toolbar->button_height); } fprintf (e, "\n"); @@ -1835,16 +2257,16 @@ write_rc_resource (FILE *e, const struct res_id *type, if (res->res_info.language != 0 && res->res_info.language != *language) fprintf (e, "%sLANGUAGE %d, %d\n", modifiers ? "// " : "", - res->res_info.language & ((1<res_info.language >> SUBLANG_SHIFT) & 0xff); + (int) res->res_info.language & ((1<res_info.language >> SUBLANG_SHIFT) & 0xff); if (res->res_info.characteristics != 0) - fprintf (e, "%sCHARACTERISTICS %lu\n", + fprintf (e, "%sCHARACTERISTICS %u\n", modifiers ? "// " : "", - res->res_info.characteristics); + (unsigned int) res->res_info.characteristics); if (res->res_info.version != 0) - fprintf (e, "%sVERSION %lu\n", + fprintf (e, "%sVERSION %u\n", modifiers ? "// " : "", - res->res_info.version); + (unsigned int) res->res_info.version); } switch (res->type) @@ -1892,6 +2314,10 @@ write_rc_resource (FILE *e, const struct res_id *type, write_rc_rcdata (e, res->u.userdata, 0); break; + case RES_TYPE_TOOLBAR: + write_rc_toolbar (e, res->u.toolbar); + break; + case RES_TYPE_VERSIONINFO: write_rc_versioninfo (e, res->u.versioninfo); break; @@ -1899,8 +2325,10 @@ write_rc_resource (FILE *e, const struct res_id *type, case RES_TYPE_BITMAP: case RES_TYPE_FONT: case RES_TYPE_ICON: + write_rc_datablock (e, res->u.data.length, res->u.data.data, 0, 1, 0); + break; case RES_TYPE_MESSAGETABLE: - write_rc_filedata (e, res->u.data.length, res->u.data.data); + write_rc_messagetable (e, res->u.data.length, res->u.data.data); break; } } @@ -1908,9 +2336,9 @@ write_rc_resource (FILE *e, const struct res_id *type, /* Write out accelerator information. */ static void -write_rc_accelerators (FILE *e, const struct accelerator *accelerators) +write_rc_accelerators (FILE *e, const rc_accelerator *accelerators) { - const struct accelerator *acc; + const rc_accelerator *acc; fprintf (e, "BEGIN\n"); for (acc = accelerators; acc != NULL; acc = acc->next) @@ -1923,16 +2351,16 @@ write_rc_accelerators (FILE *e, const struct accelerator *accelerators) && ISPRINT (acc->key) && (acc->flags & ACC_VIRTKEY) == 0) { - fprintf (e, "\"%c\"", acc->key); + fprintf (e, "\"%c\"", (char) acc->key); printable = 1; } else { - fprintf (e, "%d", acc->key); + fprintf (e, "%d", (int) acc->key); printable = 0; } - fprintf (e, ", %d", acc->id); + fprintf (e, ", %d", (int) acc->id); if (! printable) { @@ -1959,41 +2387,60 @@ write_rc_accelerators (FILE *e, const struct accelerator *accelerators) file, which the rc file would include. */ static void -write_rc_cursor (FILE *e, const struct cursor *cursor) +write_rc_cursor (FILE *e, const rc_cursor *cursor) { - fprintf (e, "// Hotspot: x: %d; y: %d\n", cursor->xhotspot, - cursor->yhotspot); - write_rc_filedata (e, cursor->length, cursor->data); + fprintf (e, "BEGIN\n"); + indent (e, 2); + fprintf (e, " 0x%x, 0x%x,\t/* Hotspot x: %d, y: %d. */\n", + (unsigned int) cursor->xhotspot, (unsigned int) cursor->yhotspot, + (int) cursor->xhotspot, (int) cursor->yhotspot); + write_rc_datablock (e, (rc_uint_type) cursor->length, (const bfd_byte *) cursor->data, + 0, 0, 0); + fprintf (e, "END\n"); } /* Write out group cursor data. This would normally be built from the cursor data. */ static void -write_rc_group_cursor (FILE *e, const struct group_cursor *group_cursor) +write_rc_group_cursor (FILE *e, const rc_group_cursor *group_cursor) { - const struct group_cursor *gc; + const rc_group_cursor *gc; + int c; + + for (c = 0, gc = group_cursor; gc != NULL; gc = gc->next, c++) + ; + fprintf (e, "BEGIN\n"); - for (gc = group_cursor; gc != NULL; gc = gc->next) + indent (e, 2); + fprintf (e, "0, 2, %d%s\t /* Having %d items. */\n", c, (c != 0 ? "," : ""), c); + indent (e, 4); + fprintf (e, "/* width, height, planes, bits, bytes, index. */\n"); + + for (c = 1, gc = group_cursor; gc != NULL; gc = gc->next, c++) { - fprintf (e, "// width: %d; height %d; planes %d; bits %d\n", - gc->width, gc->height, gc->planes, gc->bits); - fprintf (e, "// data bytes: %lu; index: %d\n", - gc->bytes, gc->index); + indent (e, 4); + fprintf (e, "%d, %d, %d, %d, 0x%xL, %d%s /* Element %d. */\n", + (int) gc->width, (int) gc->height, (int) gc->planes, (int) gc->bits, + (unsigned int) gc->bytes, (int) gc->index, (gc->next != NULL ? "," : ""), c); + fprintf (e, "/* width: %d; height %d; planes %d; bits %d. */\n", + (int) gc->width, (int) gc->height, (int) gc->planes, + (int) gc->bits); } + fprintf (e, "END\n"); } /* Write dialog data. */ static void -write_rc_dialog (FILE *e, const struct dialog *dialog) +write_rc_dialog (FILE *e, const rc_dialog *dialog) { - const struct dialog_control *control; + const rc_dialog_control *control; - fprintf (e, "STYLE 0x%lx\n", dialog->style); + fprintf (e, "STYLE 0x%x\n", dialog->style); if (dialog->exstyle != 0) - fprintf (e, "EXSTYLE 0x%lx\n", dialog->exstyle); + fprintf (e, "EXSTYLE 0x%x\n", (unsigned int) dialog->exstyle); if ((dialog->class.named && dialog->class.u.n.length > 0) || dialog->class.u.id != 0) @@ -2005,9 +2452,9 @@ write_rc_dialog (FILE *e, const struct dialog *dialog) if (dialog->caption != NULL) { - fprintf (e, "CAPTION \""); - unicode_print (e, dialog->caption, -1); - fprintf (e, "\"\n"); + fprintf (e, "CAPTION "); + unicode_print_quoted (e, dialog->caption, -1); + fprintf (e, "\n"); } if ((dialog->menu.named && dialog->menu.u.n.length > 0) @@ -2020,15 +2467,16 @@ write_rc_dialog (FILE *e, const struct dialog *dialog) if (dialog->font != NULL) { - fprintf (e, "FONT %d, \"", dialog->pointsize); - unicode_print (e, dialog->font, -1); - fprintf (e, "\""); + fprintf (e, "FONT %d, ", (int) dialog->pointsize); + unicode_print_quoted (e, dialog->font, -1); if (dialog->ex != NULL && (dialog->ex->weight != 0 || dialog->ex->italic != 0 || dialog->ex->charset != 1)) fprintf (e, ", %d, %d, %d", - dialog->ex->weight, dialog->ex->italic, dialog->ex->charset); + (int) dialog->ex->weight, + (int) dialog->ex->italic, + (int) dialog->ex->charset); fprintf (e, "\n"); } @@ -2079,7 +2527,7 @@ static const struct control_info control_info[] = /* Write a dialog control. */ static void -write_rc_dialog_control (FILE *e, const struct dialog_control *control) +write_rc_dialog_control (FILE *e, const rc_dialog_control *control) { const struct control_info *ci; @@ -2100,7 +2548,10 @@ write_rc_dialog_control (FILE *e, const struct dialog_control *control) else if (ci->name != NULL) fprintf (e, "%s", ci->name); else + { fprintf (e, "CONTROL"); + ci = NULL; + } if (control->text.named || control->text.u.id != 0) { @@ -2109,7 +2560,7 @@ write_rc_dialog_control (FILE *e, const struct dialog_control *control) fprintf (e, ","); } - fprintf (e, " %d, ", control->id); + fprintf (e, " %d, ", (int) control->id); if (ci == NULL) { @@ -2118,10 +2569,10 @@ write_rc_dialog_control (FILE *e, const struct dialog_control *control) res_id_print (e, control->class, 0); if (control->class.named) fprintf (e, "\""); - fprintf (e, ", 0x%lx, ", control->style); + fprintf (e, ", 0x%x, ", (unsigned int) control->style); } - fprintf (e, "%d, %d", control->x, control->y); + fprintf (e, "%d, %d", (int) control->x, (int) control->y); if (control->style != SS_ICON || control->exstyle != 0 @@ -2129,15 +2580,17 @@ write_rc_dialog_control (FILE *e, const struct dialog_control *control) || control->height != 0 || control->help != 0) { - fprintf (e, ", %d, %d", control->width, control->height); + fprintf (e, ", %d, %d", (int) control->width, (int) control->height); /* FIXME: We don't need to print the style if it is the default. More importantly, in certain cases we actually need to turn off parts of the forced style, by using NOT. */ - fprintf (e, ", 0x%lx", control->style); + if (ci != NULL) + fprintf (e, ", 0x%x", (unsigned int) control->style); if (control->exstyle != 0 || control->help != 0) - fprintf (e, ", 0x%lx, %lu", control->exstyle, control->help); + fprintf (e, ", 0x%x, %u", (unsigned int) control->exstyle, + (unsigned int) control->help); } fprintf (e, "\n"); @@ -2150,51 +2603,93 @@ write_rc_dialog_control (FILE *e, const struct dialog_control *control) the font data. */ static void -write_rc_fontdir (FILE *e, const struct fontdir *fontdir) +write_rc_fontdir (FILE *e, const rc_fontdir *fontdir) { - const struct fontdir *fc; + const rc_fontdir *fc; + int c; - for (fc = fontdir; fc != NULL; fc = fc->next) + for (c = 0, fc = fontdir; fc != NULL; fc = fc->next, c++) + ; + fprintf (e, "BEGIN\n"); + indent (e, 2); + fprintf (e, "%d%s\t /* Has %d elements. */\n", c, (c != 0 ? "," : ""), c); + for (c = 1, fc = fontdir; fc != NULL; fc = fc->next, c++) { - fprintf (e, "// Font index: %d\n", fc->index); - write_rc_filedata (e, fc->length, fc->data); + indent (e, 4); + fprintf (e, "%d,\t/* Font no %d with index %d. */\n", + (int) fc->index, c, (int) fc->index); + write_rc_datablock (e, (rc_uint_type) fc->length - 2, + (const bfd_byte *) fc->data + 4,fc->next != NULL, + 0, 0); } + fprintf (e, "END\n"); } /* Write out group icon data. This would normally be built from the icon data. */ static void -write_rc_group_icon (FILE *e, const struct group_icon *group_icon) +write_rc_group_icon (FILE *e, const rc_group_icon *group_icon) { - const struct group_icon *gi; + const rc_group_icon *gi; + int c; + + for (c = 0, gi = group_icon; gi != NULL; gi = gi->next, c++) + ; - for (gi = group_icon; gi != NULL; gi = gi->next) + fprintf (e, "BEGIN\n"); + indent (e, 2); + fprintf (e, " 0, 1, %d%s\t /* Has %d elements. */\n", c, (c != 0 ? "," : ""), c); + + indent (e, 4); + fprintf (e, "/* \"width height colors pad\", planes, bits, bytes, index. */\n"); + for (c = 1, gi = group_icon; gi != NULL; gi = gi->next, c++) { - fprintf (e, "// width: %d; height %d; colors: %d; planes %d; bits %d\n", - gi->width, gi->height, gi->colors, gi->planes, gi->bits); - fprintf (e, "// data bytes: %lu; index: %d\n", - gi->bytes, gi->index); + indent (e, 4); + fprintf (e, "\"\\%03o\\%03o\\%03o\\%03o\", %d, %d, 0x%xL, %d%s\t/* Element no %d. */\n", + gi->width, gi->height, gi->colors, 0, (int) gi->planes, (int) gi->bits, + (unsigned int) gi->bytes, (int) gi->index, (gi->next != NULL ? "," : ""), c); } + fprintf (e, "END\n"); } /* Write out a menu resource. */ static void -write_rc_menu (FILE *e, const struct menu *menu, int menuex) +write_rc_menu (FILE *e, const rc_menu *menu, int menuex) { if (menu->help != 0) - fprintf (e, "// Help ID: %lu\n", menu->help); + fprintf (e, "// Help ID: %u\n", (unsigned int) menu->help); write_rc_menuitems (e, menu->items, menuex, 0); } +static void +write_rc_toolbar (FILE *e, const rc_toolbar *tb) +{ + rc_toolbar_item *it; + indent (e, 0); + fprintf (e, "BEGIN\n"); + it = tb->items; + while(it != NULL) + { + indent (e, 2); + if (it->id.u.id == 0) + fprintf (e, "SEPARATOR\n"); + else + fprintf (e, "BUTTON %d\n", (int) it->id.u.id); + it = it->next; + } + indent (e, 0); + fprintf (e, "END\n"); +} + /* Write out menuitems. */ static void -write_rc_menuitems (FILE *e, const struct menuitem *menuitems, int menuex, +write_rc_menuitems (FILE *e, const rc_menuitem *menuitems, int menuex, int ind) { - const struct menuitem *mi; + const rc_menuitem *mi; indent (e, ind); fprintf (e, "BEGIN\n"); @@ -2222,15 +2717,14 @@ write_rc_menuitems (FILE *e, const struct menuitem *menuitems, int menuex, fprintf (e, " \"\""); else { - fprintf (e, " \""); - unicode_print (e, mi->text, -1); - fprintf (e, "\""); + fprintf (e, " "); + unicode_print_quoted (e, mi->text, -1); } if (! menuex) { if (mi->popup == NULL) - fprintf (e, ", %d", mi->id); + fprintf (e, ", %d", (int) mi->id); if ((mi->type & MENUITEM_CHECKED) != 0) fprintf (e, ", CHECKED"); @@ -2249,15 +2743,15 @@ write_rc_menuitems (FILE *e, const struct menuitem *menuitems, int menuex, { if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0) { - fprintf (e, ", %d", mi->id); + fprintf (e, ", %d", (int) mi->id); if (mi->type != 0 || mi->state != 0 || mi->help != 0) { - fprintf (e, ", %lu", mi->type); + fprintf (e, ", %u", (unsigned int) mi->type); if (mi->state != 0 || mi->help != 0) { - fprintf (e, ", %lu", mi->state); + fprintf (e, ", %u", (unsigned int) mi->state); if (mi->help != 0) - fprintf (e, ", %lu", mi->help); + fprintf (e, ", %u", (unsigned int) mi->help); } } } @@ -2273,158 +2767,332 @@ write_rc_menuitems (FILE *e, const struct menuitem *menuitems, int menuex, fprintf (e, "END\n"); } -/* Write out an rcdata resource. This is also used for other types of - resources that need to print arbitrary data. */ - -static void -write_rc_rcdata (FILE *e, const struct rcdata_item *rcdata, int ind) +static int +test_rc_datablock_unicode (rc_uint_type length, const bfd_byte *data) { - const struct rcdata_item *ri; + rc_uint_type i; + if ((length & 1) != 0) + return 0; - indent (e, ind); - fprintf (e, "BEGIN\n"); + for (i = 0; i < length; i += 2) + { + if (data[i] == 0 && data[i + 1] == 0 && (i + 2) < length) + return 0; + if (data[i] == 0xff && data[i + 1] == 0xff) + return 0; + } + return 1; +} - for (ri = rcdata; ri != NULL; ri = ri->next) +static int +test_rc_datablock_text (rc_uint_type length, const bfd_byte *data) +{ + int has_nl; + rc_uint_type c; + rc_uint_type i; + + if (length <= 1) + return 0; + + has_nl = 0; + for (i = 0, c = 0; i < length; i++) { - if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0) - continue; + if (! ISPRINT (data[i]) && data[i] != '\n' + && ! (data[i] == '\r' && (i + 1) < length && data[i + 1] == '\n') + && data[i] != '\t' + && ! (data[i] == 0 && (i + 1) != length)) + { + if (data[i] <= 7) + return 0; + c++; + } + else if (data[i] == '\n') has_nl++; + } + if (length > 80 && ! has_nl) + return 0; + c = (((c * 10000) + (i / 100) - 1)) / i; + if (c >= 150) + return 0; + return 1; +} - indent (e, ind + 2); +static void +write_rc_messagetable (FILE *e, rc_uint_type length, const bfd_byte *data) +{ + int has_error = 0; + const struct bin_messagetable *mt; + fprintf (e, "BEGIN\n"); - switch (ri->type) - { - default: - abort (); + write_rc_datablock (e, length, data, 0, 0, 0); - case RCDATA_WORD: - fprintf (e, "%d", ri->u.word); + fprintf (e, "\n"); + wr_printcomment (e, "MC syntax dump"); + if (length < BIN_MESSAGETABLE_SIZE) + has_error = 1; + else + do { + rc_uint_type m, i; + mt = (const struct bin_messagetable *) data; + m = windres_get_32 (&wrtarget, mt->cblocks, length); + if (length < (BIN_MESSAGETABLE_SIZE + m * BIN_MESSAGETABLE_BLOCK_SIZE)) + { + has_error = 1; break; + } + for (i = 0; i < m; i++) + { + rc_uint_type low, high, offset; + const struct bin_messagetable_item *mti; - case RCDATA_DWORD: - fprintf (e, "%luL", ri->u.dword); + low = windres_get_32 (&wrtarget, mt->items[i].lowid, 4); + high = windres_get_32 (&wrtarget, mt->items[i].highid, 4); + offset = windres_get_32 (&wrtarget, mt->items[i].offset, 4); + while (low <= high) + { + rc_uint_type elen, flags; + if ((offset + BIN_MESSAGETABLE_ITEM_SIZE) > length) + { + has_error = 1; break; + } + mti = (const struct bin_messagetable_item *) &data[offset]; + elen = windres_get_16 (&wrtarget, mti->length, 2); + flags = windres_get_16 (&wrtarget, mti->flags, 2); + if ((offset + elen) > length) + { + has_error = 1; + break; + } + wr_printcomment (e, "MessageId = 0x%x", low); + wr_printcomment (e, ""); + if ((flags & MESSAGE_RESOURCE_UNICODE) == MESSAGE_RESOURCE_UNICODE) + unicode_print (e, (const unichar *) mti->data, + (elen - BIN_MESSAGETABLE_ITEM_SIZE) / 2); + else + ascii_print (e, (const char *) mti->data, + (elen - BIN_MESSAGETABLE_ITEM_SIZE)); + wr_printcomment (e,""); + ++low; + offset += elen; + } + } + } while (0); + if (has_error) + wr_printcomment (e, "Illegal data"); + wr_print_flush (e); + fprintf (e, "END\n"); +} - case RCDATA_STRING: - { - const char *s; - unsigned long i; +static void +write_rc_datablock (FILE *e, rc_uint_type length, const bfd_byte *data, int has_next, + int hasblock, int show_comment) +{ + int plen; + if (hasblock) + fprintf (e, "BEGIN\n"); + + if (show_comment == -1) + { + if (test_rc_datablock_text(length, data)) + { + rc_uint_type i, c; + for (i = 0; i < length;) + { + indent (e, 2); + fprintf (e, "\""); + + for (c = 0; i < length && c < 160 && data[i] != '\n'; c++, i++) + ; + if (i < length && data[i] == '\n') + ++i, ++c; + ascii_print (e, (const char *) &data[i - c], c); fprintf (e, "\""); - s = ri->u.string.s; - for (i = 0; i < ri->u.string.length; i++) + if (i < length) + fprintf (e, "\n"); + } + + if (i == 0) { - if (ISPRINT (*s)) - putc (*s, e); - else - fprintf (e, "\\%03o", *s); + indent (e, 2); + fprintf (e, "\"\""); } - fprintf (e, "\""); - break; + if (has_next) + fprintf (e, ","); + fprintf (e, "\n"); + if (hasblock) + fprintf (e, "END\n"); + return; } + if (test_rc_datablock_unicode (length, data)) + { + rc_uint_type i, c; + for (i = 0; i < length;) + { + const unichar *u; - case RCDATA_WSTRING: + u = (const unichar *) &data[i]; + indent (e, 2); fprintf (e, "L\""); - unicode_print (e, ri->u.wstring.w, ri->u.wstring.length); + + for (c = 0; i < length && c < 160 && u[c] != '\n'; c++, i += 2) + ; + if (i < length && u[c] == '\n') + i += 2, ++c; + unicode_print (e, u, c); fprintf (e, "\""); - break; + if (i < length) + fprintf (e, "\n"); + } - case RCDATA_BUFFER: + if (i == 0) { - unsigned long i; - int first; + indent (e, 2); + fprintf (e, "L\"\""); + } + if (has_next) + fprintf (e, ","); + fprintf (e, "\n"); + if (hasblock) + fprintf (e, "END\n"); + return; + } - /* Assume little endian data. */ + show_comment = 0; + } - first = 1; - for (i = 0; i + 3 < ri->u.buffer.length; i += 4) + if (length != 0) { - unsigned long l; - int j; + rc_uint_type i, max_row; + int first = 1; - if (! first) - indent (e, ind + 2); - l = ((((((ri->u.buffer.data[i + 3] << 8) - | ri->u.buffer.data[i + 2]) << 8) - | ri->u.buffer.data[i + 1]) << 8) - | ri->u.buffer.data[i]); - fprintf (e, "%luL", l); - if (i + 4 < ri->u.buffer.length || ri->next != NULL) - fprintf (e, ","); - for (j = 0; j < 4; ++j) - if (! ISPRINT (ri->u.buffer.data[i + j]) - && ri->u.buffer.data[i + j] != 0) - break; - if (j >= 4) + max_row = (show_comment ? 4 : 8); + indent (e, 2); + for (i = 0; i + 3 < length;) { - fprintf (e, "\t// "); - for (j = 0; j < 4; ++j) + rc_uint_type k; + rc_uint_type comment_start; + + comment_start = i; + + if (! first) + indent (e, 2); + + for (k = 0; k < max_row && i + 3 < length; k++, i += 4) { - if (! ISPRINT (ri->u.buffer.data[i + j])) - fprintf (e, "\\%03o", ri->u.buffer.data[i + j]); + if (k == 0) + plen = fprintf (e, "0x%lxL", + (long) windres_get_32 (&wrtarget, data + i, length - i)); else + plen = fprintf (e, " 0x%lxL", + (long) windres_get_32 (&wrtarget, data + i, length - i)) - 1; + if (has_next || (i + 4) < length) { - if (ri->u.buffer.data[i + j] == '\\') - fprintf (e, "\\"); - fprintf (e, "%c", ri->u.buffer.data[i + j]); + if (plen>0 && plen < 11) + indent (e, 11 - plen); + fprintf (e, ","); } } + if (show_comment) + { + fprintf (e, "\t/* "); + ascii_print (e, (const char *) &data[comment_start], i - comment_start); + fprintf (e, ". */"); } fprintf (e, "\n"); first = 0; } - if (i + 1 < ri->u.buffer.length) + if (i + 1 < length) { - int s; - int j; - if (! first) - indent (e, ind + 2); - s = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i]; - fprintf (e, "%d", s); - if (i + 2 < ri->u.buffer.length || ri->next != NULL) - fprintf (e, ","); - for (j = 0; j < 2; ++j) - if (! ISPRINT (ri->u.buffer.data[i + j]) - && ri->u.buffer.data[i + j] != 0) - break; - if (j >= 2) + indent (e, 2); + plen = fprintf (e, "0x%x", + (int) windres_get_16 (&wrtarget, data + i, length - i)); + if (has_next || i + 2 < length) { - fprintf (e, "\t// "); - for (j = 0; j < 2; ++j) - { - if (! ISPRINT (ri->u.buffer.data[i + j])) - fprintf (e, "\\%03o", ri->u.buffer.data[i + j]); - else - { - if (ri->u.buffer.data[i + j] == '\\') - fprintf (e, "\\"); - fprintf (e, "%c", ri->u.buffer.data[i + j]); - } + if (plen > 0 && plen < 11) + indent (e, 11 - plen); + fprintf (e, ","); } + if (show_comment) + { + fprintf (e, "\t/* "); + ascii_print (e, (const char *) &data[i], 2); + fprintf (e, ". */"); } fprintf (e, "\n"); i += 2; first = 0; } - if (i < ri->u.buffer.length) + if (i < length) { if (! first) - indent (e, ind + 2); - if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i] - && ISPRINT (ri->u.buffer.data[i])) - fprintf (e, "\"%c\"", ri->u.buffer.data[i]); - else - fprintf (e, "\"\\%03o\"", ri->u.buffer.data[i]); - if (ri->next != NULL) + indent (e, 2); + fprintf (e, "\""); + ascii_print (e, (const char *) &data[i], 1); + fprintf (e, "\""); + if (has_next) fprintf (e, ","); fprintf (e, "\n"); first = 0; } + } + if (hasblock) + fprintf (e, "END\n"); +} + +/* Write out an rcdata resource. This is also used for other types of + resources that need to print arbitrary data. */ + +static void +write_rc_rcdata (FILE *e, const rc_rcdata_item *rcdata, int ind) +{ + const rc_rcdata_item *ri; + + indent (e, ind); + fprintf (e, "BEGIN\n"); + + for (ri = rcdata; ri != NULL; ri = ri->next) + { + if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0) + continue; + switch (ri->type) + { + default: + abort (); + + case RCDATA_WORD: + indent (e, ind + 2); + fprintf (e, "%ld", (long) (ri->u.word & 0xffff)); + break; + + case RCDATA_DWORD: + indent (e, ind + 2); + fprintf (e, "%luL", (unsigned long) ri->u.dword); + break; + + case RCDATA_STRING: + indent (e, ind + 2); + fprintf (e, "\""); + ascii_print (e, ri->u.string.s, ri->u.string.length); + fprintf (e, "\""); + break; + + case RCDATA_WSTRING: + indent (e, ind + 2); + fprintf (e, "L\""); + unicode_print (e, ri->u.wstring.w, ri->u.wstring.length); + fprintf (e, "\""); + break; + + case RCDATA_BUFFER: + write_rc_datablock (e, (rc_uint_type) ri->u.buffer.length, + (const bfd_byte *) ri->u.buffer.data, + ri->next != NULL, 0, -1); break; - } } if (ri->type != RCDATA_BUFFER) @@ -2442,17 +3110,17 @@ write_rc_rcdata (FILE *e, const struct rcdata_item *rcdata, int ind) /* Write out a stringtable resource. */ static void -write_rc_stringtable (FILE *e, const struct res_id *name, - const struct stringtable *stringtable) +write_rc_stringtable (FILE *e, const rc_res_id *name, + const rc_stringtable *stringtable) { - unsigned long offset; + rc_uint_type offset; int i; if (name != NULL && ! name->named) offset = (name->u.id - 1) << 4; else { - fprintf (e, "// %s string table name\n", + fprintf (e, "/* %s string table name. */\n", name == NULL ? "Missing" : "Invalid"); offset = 0; } @@ -2463,10 +3131,10 @@ write_rc_stringtable (FILE *e, const struct res_id *name, { if (stringtable->strings[i].length != 0) { - fprintf (e, " %lu, \"", offset + i); - unicode_print (e, stringtable->strings[i].string, + fprintf (e, " %lu, ", (long) offset + i); + unicode_print_quoted (e, stringtable->strings[i].string, stringtable->strings[i].length); - fprintf (e, "\"\n"); + fprintf (e, "\n"); } } @@ -2476,36 +3144,37 @@ write_rc_stringtable (FILE *e, const struct res_id *name, /* Write out a versioninfo resource. */ static void -write_rc_versioninfo (FILE *e, const struct versioninfo *versioninfo) +write_rc_versioninfo (FILE *e, const rc_versioninfo *versioninfo) { - const struct fixed_versioninfo *f; - const struct ver_info *vi; + const rc_fixed_versioninfo *f; + const rc_ver_info *vi; f = versioninfo->fixed; if (f->file_version_ms != 0 || f->file_version_ls != 0) - fprintf (e, " FILEVERSION %lu, %lu, %lu, %lu\n", - (f->file_version_ms >> 16) & 0xffff, - f->file_version_ms & 0xffff, - (f->file_version_ls >> 16) & 0xffff, - f->file_version_ls & 0xffff); + fprintf (e, " FILEVERSION %u, %u, %u, %u\n", + (unsigned int) ((f->file_version_ms >> 16) & 0xffff), + (unsigned int) (f->file_version_ms & 0xffff), + (unsigned int) ((f->file_version_ls >> 16) & 0xffff), + (unsigned int) (f->file_version_ls & 0xffff)); if (f->product_version_ms != 0 || f->product_version_ls != 0) - fprintf (e, " PRODUCTVERSION %lu, %lu, %lu, %lu\n", - (f->product_version_ms >> 16) & 0xffff, - f->product_version_ms & 0xffff, - (f->product_version_ls >> 16) & 0xffff, - f->product_version_ls & 0xffff); + fprintf (e, " PRODUCTVERSION %u, %u, %u, %u\n", + (unsigned int) ((f->product_version_ms >> 16) & 0xffff), + (unsigned int) (f->product_version_ms & 0xffff), + (unsigned int) ((f->product_version_ls >> 16) & 0xffff), + (unsigned int) (f->product_version_ls & 0xffff)); if (f->file_flags_mask != 0) - fprintf (e, " FILEFLAGSMASK 0x%lx\n", f->file_flags_mask); + fprintf (e, " FILEFLAGSMASK 0x%x\n", (unsigned int) f->file_flags_mask); if (f->file_flags != 0) - fprintf (e, " FILEFLAGS 0x%lx\n", f->file_flags); + fprintf (e, " FILEFLAGS 0x%x\n", (unsigned int) f->file_flags); if (f->file_os != 0) - fprintf (e, " FILEOS 0x%lx\n", f->file_os); + fprintf (e, " FILEOS 0x%x\n", (unsigned int) f->file_os); if (f->file_type != 0) - fprintf (e, " FILETYPE 0x%lx\n", f->file_type); + fprintf (e, " FILETYPE 0x%x\n", (unsigned int) f->file_type); if (f->file_subtype != 0) - fprintf (e, " FILESUBTYPE 0x%lx\n", f->file_subtype); + fprintf (e, " FILESUBTYPE 0x%x\n", (unsigned int) f->file_subtype); if (f->file_date_ms != 0 || f->file_date_ls != 0) - fprintf (e, "// Date: %lu, %lu\n", f->file_date_ms, f->file_date_ls); + fprintf (e, "/* Date: %u, %u. */\n", + (unsigned int) f->file_date_ms, (unsigned int) f->file_date_ls); fprintf (e, "BEGIN\n"); @@ -2515,22 +3184,22 @@ write_rc_versioninfo (FILE *e, const struct versioninfo *versioninfo) { case VERINFO_STRING: { - const struct ver_stringinfo *vs; + const rc_ver_stringinfo *vs; fprintf (e, " BLOCK \"StringFileInfo\"\n"); fprintf (e, " BEGIN\n"); - fprintf (e, " BLOCK \""); - unicode_print (e, vi->u.string.language, -1); - fprintf (e, "\"\n"); + fprintf (e, " BLOCK "); + unicode_print_quoted (e, vi->u.string.language, -1); + fprintf (e, "\n"); fprintf (e, " BEGIN\n"); for (vs = vi->u.string.strings; vs != NULL; vs = vs->next) { - fprintf (e, " VALUE \""); - unicode_print (e, vs->key, -1); - fprintf (e, "\", \""); - unicode_print (e, vs->value, -1); - fprintf (e, "\"\n"); + fprintf (e, " VALUE "); + unicode_print_quoted (e, vs->key, -1); + fprintf (e, ", "); + unicode_print_quoted (e, vs->value, -1); + fprintf (e, "\n"); } fprintf (e, " END\n"); @@ -2540,17 +3209,16 @@ write_rc_versioninfo (FILE *e, const struct versioninfo *versioninfo) case VERINFO_VAR: { - const struct ver_varinfo *vv; + const rc_ver_varinfo *vv; fprintf (e, " BLOCK \"VarFileInfo\"\n"); fprintf (e, " BEGIN\n"); - fprintf (e, " VALUE \""); - unicode_print (e, vi->u.var.key, -1); - fprintf (e, "\""); + fprintf (e, " VALUE "); + unicode_print_quoted (e, vi->u.var.key, -1); for (vv = vi->u.var.var; vv != NULL; vv = vv->next) fprintf (e, ", 0x%x, %d", (unsigned int) vv->language, - vv->charset); + (int) vv->charset); fprintf (e, "\n END\n"); @@ -2562,32 +3230,36 @@ write_rc_versioninfo (FILE *e, const struct versioninfo *versioninfo) fprintf (e, "END\n"); } -/* Write out data which would normally be read from a file. */ - -static void -write_rc_filedata (FILE *e, unsigned long length, const unsigned char *data) +static rc_uint_type +rcdata_copy (const rc_rcdata_item *src, bfd_byte *dst) { - unsigned long i; - - for (i = 0; i + 15 < length; i += 16) - { - fprintf (e, "// %4lx: ", i); - fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x ", - data[i + 0], data[i + 1], data[i + 2], data[i + 3], - data[i + 4], data[i + 5], data[i + 6], data[i + 7]); - fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x\n", - data[i + 8], data[i + 9], data[i + 10], data[i + 11], - data[i + 12], data[i + 13], data[i + 14], data[i + 15]); - } - - if (i < length) - { - fprintf (e, "// %4lx:", i); - while (i < length) + if (! src) + return 0; + switch (src->type) { - fprintf (e, " %02x", data[i]); - ++i; - } - fprintf (e, "\n"); + case RCDATA_WORD: + if (dst) + windres_put_16 (&wrtarget, dst, (rc_uint_type) src->u.word); + return 2; + case RCDATA_DWORD: + if (dst) + windres_put_32 (&wrtarget, dst, (rc_uint_type) src->u.dword); + return 4; + case RCDATA_STRING: + if (dst && src->u.string.length) + memcpy (dst, src->u.string.s, src->u.string.length); + return (rc_uint_type) src->u.string.length; + case RCDATA_WSTRING: + if (dst && src->u.wstring.length) + memcpy (dst, src->u.wstring.w, src->u.wstring.length * sizeof (unichar)); + return (rc_uint_type) (src->u.wstring.length * sizeof (unichar)); + case RCDATA_BUFFER: + if (dst && src->u.buffer.length) + memcpy (dst, src->u.buffer.data, src->u.buffer.length); + return (rc_uint_type) src->u.buffer.length; + default: + abort (); } + /* Never reached. */ + return 0; } diff --git a/binutils/resres.c b/binutils/resres.c index b5677d2bec5..8b75bcf5942 100644 --- a/binutils/resres.c +++ b/binutils/resres.c @@ -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 . + 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 #include -struct res_hdr - { - unsigned long data_size; - unsigned long header_size; - }; - -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 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 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 unsigned long get_id_size PARAMS ((const struct res_id *)); -static void res_align_file PARAMS ((void)); +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 - res_add_resource - PARAMS ((struct res_resource *, const struct res_id *, - const struct res_id *, int, int)); +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 *); -void - res_append_resource - PARAMS ((struct res_directory **, struct res_resource *, - int, const struct res_id *, int)); +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 (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 (const rc_res_id *); + +static void res_add_resource (rc_res_resource *, const rc_res_id *, + const rc_res_id *, rc_uint_type, int); -static struct res_directory *resources = NULL; +static void res_append_resource (rc_res_directory **, rc_res_resource *, + int, const rc_res_id *, int); + +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; + + if (! probe_binary (&wrbfd, flen)) + set_windres_bfd_endianess (&wrbfd, ! target_is_bigendian); + + skip_null_resource (&wrbfd, &off, flen); - while (read_resource_entry ()) + 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)); - - /* Write 32 bit resource signature */ - write_res_data (sign, sizeof (sign), 1); - - /* write resources */ + 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; + + 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); - - /* end file on DWORD boundary */ - fpos = ftell (fres); - if (fpos % 4) - write_res_data (sign, fpos % 4, 1); - - fclose (fres); + 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); + + 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; + + off = write_res_data_hdr (wrbfd, off, &reshdr); + off = write_res_id (wrbfd, off, type); + off = write_res_id (wrbfd, off, name); - res_align_file (); + off = (off + 3) & ~3; - write_res_info (resinfo); - res_align_file (); + off = write_res_info (wrbfd, off, resinfo); + off = (off + 3) & ~3; + return off; } +static rc_uint_type +write_res_data_hdr (windres_bfd *wrbfd, rc_uint_type off, res_hdr *hdr) +{ + 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; +} -/* Write data to file, abort on failure */ static void -write_res_data (data, size, count) - const void *data; - size_t size; - int count; +read_res_data_hdr (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax, + res_hdr *reshdr) { - if ((size_t) fwrite (data, size, count, fres) != (size_t) count) - fatal ("%s: could not write to file", filename); + 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); diff --git a/binutils/testsuite/ChangeLog b/binutils/testsuite/ChangeLog index 7e8a8b3cffd..265dcaacf7b 100644 --- a/binutils/testsuite/ChangeLog +++ b/binutils/testsuite/ChangeLog @@ -1,3 +1,18 @@ +2007-05-23 Kai Tietz + + * 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 * binutils-all/strip-3.d: Strip .pdr section. diff --git a/binutils/testsuite/binutils-all/windres/MSG00001.bin b/binutils/testsuite/binutils-all/windres/MSG00001.bin new file mode 100644 index 0000000000000000000000000000000000000000..0092b834152554406337dcf3f1cf7ba0edb26cba GIT binary patch literal 112 zcmZQ%fB;q?B>==CK%q$WJEC=VtJ;=2|Vs5yUJ2mKhAk literal 0 HcmV?d00001 diff --git a/binutils/testsuite/binutils-all/windres/dialogid.rsd b/binutils/testsuite/binutils-all/windres/dialogid.rsd index 1e6bb1885dc..6c655a1c117 100644 --- a/binutils/testsuite/binutils-all/windres/dialogid.rsd +++ b/binutils/testsuite/binutils-all/windres/dialogid.rsd @@ -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 .... diff --git a/binutils/testsuite/binutils-all/windres/html.rc b/binutils/testsuite/binutils-all/windres/html.rc new file mode 100644 index 00000000000..ead6a11829c --- /dev/null +++ b/binutils/testsuite/binutils-all/windres/html.rc @@ -0,0 +1,7 @@ +//#xfail x86_64-*-mingw* +#include "windows.h" + +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN + +129 HTML "html1.hm" +130 HTML "html2.hm" diff --git a/binutils/testsuite/binutils-all/windres/html.rsd b/binutils/testsuite/binutils-all/windres/html.rsd new file mode 100644 index 00000000000..c124a82b662 --- /dev/null +++ b/binutils/testsuite/binutils-all/windres/html.rsd @@ -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 ...... .. + 00e0 20203c74 69746c65 3e57696e 64726573 Windres + 00f0 3c2f7469 746c653e 0d0a3c2f 68656164 ........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........ + 0150 14010000 20000000 ffff1700 ffff8200 .... ........... + 0160 00000000 30100704 00000000 00000000 ....0........... + 0170 3c21444f 43545950 4520646f 63747970 ...... .. + 0210 20203c74 69746c65 3e57696e 64726573 Windres + 0220 3c2f7469 746c653e 0d0a3c2f 68656164 ........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..... diff --git a/binutils/testsuite/binutils-all/windres/html1.hm b/binutils/testsuite/binutils-all/windres/html1.hm new file mode 100644 index 00000000000..ffc5a1825cc --- /dev/null +++ b/binutils/testsuite/binutils-all/windres/html1.hm @@ -0,0 +1,11 @@ + + + + + Windres + + + +This is a test page for windres HTML resource. + + \ No newline at end of file diff --git a/binutils/testsuite/binutils-all/windres/html2.hm b/binutils/testsuite/binutils-all/windres/html2.hm new file mode 100644 index 00000000000..2fb343bf528 --- /dev/null +++ b/binutils/testsuite/binutils-all/windres/html2.hm @@ -0,0 +1,11 @@ + + + + + Windres + + + +This is a second test page for windres HTML resource. + + \ No newline at end of file diff --git a/binutils/testsuite/binutils-all/windres/messagetable.rc b/binutils/testsuite/binutils-all/windres/messagetable.rc new file mode 100644 index 00000000000..e10ee639db5 --- /dev/null +++ b/binutils/testsuite/binutils-all/windres/messagetable.rc @@ -0,0 +1,6 @@ +//#xfail x86_64-*-mingw* +#include "windows.h" + +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN + +888 MESSAGETABLE MSG00001.bin diff --git a/binutils/testsuite/binutils-all/windres/messagetable.rsd b/binutils/testsuite/binutils-all/windres/messagetable.rsd new file mode 100644 index 00000000000..9d108a58932 --- /dev/null +++ b/binutils/testsuite/binutils-all/windres/messagetable.rsd @@ -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...... diff --git a/binutils/testsuite/binutils-all/windres/strtab2.rc b/binutils/testsuite/binutils-all/windres/strtab2.rc new file mode 100644 index 00000000000..9322034946c --- /dev/null +++ b/binutils/testsuite/binutils-all/windres/strtab2.rc @@ -0,0 +1,9 @@ +//#xfail x86_64-*-mingw* +#include "windows.h" + +LANGUAGE 0, 0 + +STRINGTABLE MOVEABLE PURE DISCARDABLE +BEGIN + 1 L"hello, world" +END diff --git a/binutils/testsuite/binutils-all/windres/strtab2.rsd b/binutils/testsuite/binutils-all/windres/strtab2.rsd new file mode 100644 index 00000000000..4d610739352 --- /dev/null +++ b/binutils/testsuite/binutils-all/windres/strtab2.rsd @@ -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 ........ diff --git a/binutils/testsuite/binutils-all/windres/version.rc b/binutils/testsuite/binutils-all/windres/version.rc new file mode 100644 index 00000000000..5eea3353e0d --- /dev/null +++ b/binutils/testsuite/binutils-all/windres/version.rc @@ -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 diff --git a/binutils/testsuite/binutils-all/windres/version.rsd b/binutils/testsuite/binutils-all/windres/version.rsd new file mode 100644 index 00000000000..85dd5d35281 --- /dev/null +++ b/binutils/testsuite/binutils-all/windres/version.rsd @@ -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......... diff --git a/binutils/windint.h b/binutils/windint.h new file mode 100644 index 00000000000..b46f857a7a8 --- /dev/null +++ b/binutils/windint.h @@ -0,0 +1,1088 @@ +/* windint.h -- internal header file for windres program. + Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 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. */ + +#include "winduni.h" + +#ifndef WINDINT_H +#define WINDINT_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 + +/* Resource directory structure. */ + +typedef struct res_hdr +{ + rc_uint_type data_size; + rc_uint_type header_size; +} res_hdr; + +struct __attribute__ ((__packed__)) bin_res_hdr +{ + bfd_byte data_size[4]; + bfd_byte header_size[4]; +}; +#define BIN_RES_HDR_SIZE 8 + +struct __attribute__ ((__packed__)) bin_res_id +{ + bfd_byte sig[2]; /* Has to be 0xffff for unnamed ids. */ + bfd_byte id[2]; +}; +#define BIN_RES_ID 4 + +/* This structure is used when converting resource information to + binary. */ + +typedef struct bindata +{ + /* Next data. */ + struct bindata *next; + /* Length of data. */ + rc_uint_type length; + /* Data. */ + bfd_byte *data; +} bindata; + +/* This structure is used when converting resource information to + coff. */ +typedef struct coff_res_data +{ + /* Next data. */ + struct coff_res_data *next; + /* Length of data. */ + rc_uint_type length; + /* Data. */ + const struct rc_res_resource *res; +} coff_res_data; + +/* We represent resources internally as a tree, similar to the tree + used in the .rsrc section of a COFF file. The root is a + rc_res_directory structure. */ + +typedef struct rc_res_directory +{ + /* Resource flags. According to the MS docs, this is currently + always zero. */ + rc_uint_type characteristics; + /* Time/date stamp. */ + rc_uint_type time; + /* Major version number. */ + rc_uint_type major; + /* Minor version number. */ + rc_uint_type minor; + /* Directory entries. */ + struct rc_res_entry *entries; +} rc_res_directory; + +/* A resource ID is stored in a rc_res_id structure. */ + +typedef struct rc_res_id +{ + /* Non-zero if this entry has a name rather than an ID. */ + rc_uint_type named : 1; + union + { + /* If the named field is non-zero, this is the name. */ + struct + { + /* Length of the name. */ + rc_uint_type length; + /* Pointer to the name, which is a Unicode string. */ + unichar *name; + } n; + /* If the named field is zero, this is the ID. */ + rc_uint_type id; + } u; +} rc_res_id; + +/* Each entry in the tree is a rc_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. */ + +typedef struct rc_res_entry +{ + /* Next entry. */ + struct rc_res_entry *next; + /* Resource ID. */ + rc_res_id id; + /* Non-zero if this entry is a subdirectory rather than a leaf. */ + rc_uint_type subdir : 1; + union + { + /* If the subdir field is non-zero, this is a pointer to the + subdirectory. */ + rc_res_directory *dir; + /* If the subdir field is zero, this is a pointer to the resource + data. */ + struct rc_res_resource *res; + } u; +} rc_res_entry; + +/* Types of resources. */ + +enum rc_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, + RES_TYPE_DLGINCLUDE, + RES_TYPE_PLUGPLAY, + RES_TYPE_VXD, + RES_TYPE_ANICURSOR, + RES_TYPE_ANIICON, + RES_TYPE_DLGINIT, + RES_TYPE_TOOLBAR +}; + +/* 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. */ + +typedef struct rc_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. */ + rc_uint_type language; + /* Characteristics of the resource. Entirely user defined. In a + COFF file, the rc_res_directory structure has a characteristics + field, but I don't know if it's related to the one in the res + file. */ + rc_uint_type characteristics; + /* Version of the resource. Entirely user defined. In a COFF file, + the rc_res_directory structure has a characteristics field, but I + don't know if it's related to the one in the res file. */ + rc_uint_type 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. */ + rc_uint_type memflags; +} rc_res_res_info; + +/* Binary layout of rc_res_info. */ + +struct __attribute__ ((__packed__)) bin_res_info +{ + bfd_byte version[4]; + bfd_byte memflags[2]; + bfd_byte language[2]; + bfd_byte version2[4]; + bfd_byte characteristics[4]; +}; +#define BIN_RES_INFO_SIZE 16 + +/* Each resource in a COFF file has some information which can does + not appear in a res file. */ + +typedef struct rc_res_coff_info +{ + /* The code page used for the data. I don't really know what this + should be. It has something todo with ASCII to Unicode encoding. */ + rc_uint_type 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. */ + rc_uint_type reserved; +} rc_res_coff_info; + +/* Resource data is stored in a rc_res_resource structure. */ + +typedef struct rc_res_resource +{ + /* The type of resource. */ + enum rc_res_type type; + /* The data for the resource. */ + union + { + struct + { + rc_uint_type length; + const bfd_byte *data; + } data; + struct rc_accelerator *acc; + struct rc_cursor *cursor; + struct rc_group_cursor *group_cursor; + struct rc_dialog *dialog; + struct rc_fontdir *fontdir; + struct rc_group_icon *group_icon; + struct rc_menu *menu; + struct rc_rcdata_item *rcdata; + struct rc_stringtable *stringtable; + struct rc_rcdata_item *userdata; + struct rc_versioninfo *versioninfo; + struct rc_toolbar *toolbar; + } u; + /* Information from a res file. */ + struct rc_res_res_info res_info; + /* Information from a COFF file. */ + rc_res_coff_info coff_info; +} rc_res_resource; + +#define SUBLANG_SHIFT 10 + +/* Memory flags in the memflags field of a rc_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 + rc_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 +#define RT_HTML 23 +#define RT_MANIFEST 24 +#define RT_DLGINIT 240 +#define RT_TOOLBAR 241 + +/* An accelerator resource is a linked list of these structures. */ + +typedef struct rc_accelerator +{ + /* Next accelerator. */ + struct rc_accelerator *next; + /* Flags. A combination of the ACC values defined below. */ + rc_uint_type flags; + /* Key value. */ + rc_uint_type key; + /* Resource ID. */ + rc_uint_type id; +} rc_accelerator; + +struct __attribute__ ((__packed__)) bin_accelerator +{ + bfd_byte flags[2]; + bfd_byte key[2]; + bfd_byte id[2]; + bfd_byte pad[2]; +}; +#define BIN_ACCELERATOR_SIZE 8 + +/* Accelerator flags in the flags field of a rc_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. */ + +typedef struct rc_cursor +{ + /* X coordinate of hotspot. */ + bfd_signed_vma xhotspot; + /* Y coordinate of hotspot. */ + bfd_signed_vma yhotspot; + /* Length of bitmap data. */ + rc_uint_type length; + /* Data. */ + const bfd_byte *data; +} rc_cursor; + +struct __attribute__ ((__packed__)) bin_cursor +{ + bfd_byte xhotspot[2]; + bfd_byte yhotspot[2]; +}; +#define BIN_CURSOR_SIZE 4 + +/* A group_cursor resource is a list of rc_i_group_cursor structures. */ + +typedef struct rc_group_cursor +{ + /* Next cursor in group. */ + struct rc_group_cursor *next; + /* Width. */ + rc_uint_type width; + /* Height. */ + rc_uint_type height; + /* Planes. */ + rc_uint_type planes; + /* Bits per pixel. */ + rc_uint_type bits; + /* Number of bytes in cursor resource. */ + rc_uint_type bytes; + /* Index of cursor resource. */ + rc_uint_type index; +} rc_group_cursor; + +struct __attribute__ ((__packed__)) bin_group_cursor_item +{ + bfd_byte width[2]; + bfd_byte height[2]; + bfd_byte planes[2]; + bfd_byte bits[2]; + bfd_byte bytes[4]; + bfd_byte index[2]; +}; +#define BIN_GROUP_CURSOR_ITEM_SIZE 14 + +struct __attribute__ ((__packed__)) bin_group_cursor +{ + bfd_byte sig1[2]; + bfd_byte sig2[2]; + bfd_byte nitems[2]; + /* struct bin_group_cursor_item item[nitems]; */ +}; +#define BIN_GROUP_CURSOR_SIZE 6 + +/* A dialog resource. */ + +typedef struct rc_dialog +{ + /* Basic window style. */ + unsigned int style; + /* Extended window style. */ + rc_uint_type exstyle; + /* X coordinate. */ + rc_uint_type x; + /* Y coordinate. */ + rc_uint_type y; + /* Width. */ + rc_uint_type width; + /* Height. */ + rc_uint_type height; + /* Menu name. */ + rc_res_id menu; + /* Class name. */ + rc_res_id class; + /* Caption. */ + unichar *caption; + /* Font point size. */ + rc_uint_type pointsize; + /* Font name. */ + unichar *font; + /* Extended information for a dialogex. */ + struct rc_dialog_ex *ex; + /* Controls. */ + struct rc_dialog_control *controls; +} rc_dialog; + +struct __attribute__ ((__packed__)) bin_dialog +{ + bfd_byte style[4]; + bfd_byte exstyle[4]; + bfd_byte off[2]; + bfd_byte x[2]; + bfd_byte y[2]; + bfd_byte width[2]; + bfd_byte height[2]; +}; +#define BIN_DIALOG_SIZE 18 + +/* An extended dialog has additional information. */ + +typedef struct rc_dialog_ex +{ + /* Help ID. */ + rc_uint_type help; + /* Font weight. */ + rc_uint_type weight; + /* Whether the font is italic. */ + bfd_byte italic; + /* Character set. */ + bfd_byte charset; +} rc_dialog_ex; + +struct __attribute__ ((__packed__)) bin_dialogex +{ + bfd_byte sig1[2]; + bfd_byte sig2[2]; + bfd_byte help[4]; + bfd_byte exstyle[4]; + bfd_byte style[4]; + bfd_byte off[2]; + bfd_byte x[2]; + bfd_byte y[2]; + bfd_byte width[2]; + bfd_byte height[2]; +}; +#define BIN_DIALOGEX_SIZE 26 + +struct __attribute__ ((__packed__)) bin_dialogfont +{ + bfd_byte pointsize[2]; +}; +#define BIN_DIALOGFONT_SIZE 2 + +struct __attribute__ ((__packed__)) bin_dialogexfont +{ + bfd_byte pointsize[2]; + bfd_byte weight[2]; + bfd_byte italic[1]; + bfd_byte charset[1]; +}; +#define BIN_DIALOGEXFONT_SIZE 6 + +/* Window style flags, from the winsup Defines.h header file. These + can appear in the style field of a rc_dialog or a rc_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. */ + +typedef struct rc_dialog_control +{ + /* Next control. */ + struct rc_dialog_control *next; + /* ID. */ + rc_uint_type id; + /* Style. */ + rc_uint_type style; + /* Extended style. */ + rc_uint_type exstyle; + /* X coordinate. */ + rc_uint_type x; + /* Y coordinate. */ + rc_uint_type y; + /* Width. */ + rc_uint_type width; + /* Height. */ + rc_uint_type height; + /* Class name. */ + rc_res_id class; + /* Associated text. */ + rc_res_id text; + /* Extra data for the window procedure. */ + struct rc_rcdata_item *data; + /* Help ID. Only used in an extended dialog. */ + rc_uint_type help; +} rc_dialog_control; + +struct __attribute__ ((__packed__)) bin_dialog_control +{ + bfd_byte style[4]; + bfd_byte exstyle[4]; + bfd_byte x[2]; + bfd_byte y[2]; + bfd_byte width[2]; + bfd_byte height[2]; + bfd_byte id[2]; +}; +#define BIN_DIALOG_CONTROL_SIZE 18 + +struct __attribute__ ((__packed__)) bin_dialogex_control +{ + bfd_byte help[4]; + bfd_byte exstyle[4]; + bfd_byte style[4]; + bfd_byte x[2]; + bfd_byte y[2]; + bfd_byte width[2]; + bfd_byte height[2]; + bfd_byte id[4]; +}; +#define BIN_DIALOGEX_CONTROL_SIZE 24 + +/* Control classes. These can be used as the ID field in a rc_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 rc_fontdir. */ + +typedef struct rc_fontdir +{ + struct rc_fontdir *next; + /* Index of font entry. */ + rc_uint_type index; + /* Length of font information. */ + rc_uint_type length; + /* Font information. */ + const bfd_byte *data; +} rc_fontdir; + +struct __attribute__ ((__packed__)) bin_fontdir_item +{ + bfd_byte index[2]; + bfd_byte header[54]; + bfd_byte device_name[1]; + /* bfd_byte face_name[]; */ +}; + +/* A group_icon resource is a list of rc_group_icon. */ + +typedef struct rc_group_icon +{ + /* Next icon in group. */ + struct rc_group_icon *next; + /* Width. */ + bfd_byte width; + /* Height. */ + bfd_byte height; + /* Color count. */ + bfd_byte colors; + /* Planes. */ + rc_uint_type planes; + /* Bits per pixel. */ + rc_uint_type bits; + /* Number of bytes in cursor resource. */ + rc_uint_type bytes; + /* Index of cursor resource. */ + rc_uint_type index; +} rc_group_icon; + +struct __attribute__ ((__packed__)) bin_group_icon +{ + bfd_byte sig1[2]; + bfd_byte sig2[2]; + bfd_byte count[2]; +}; +#define BIN_GROUP_ICON_SIZE 6 + +struct __attribute__ ((__packed__)) bin_group_icon_item +{ + bfd_byte width[1]; + bfd_byte height[1]; + bfd_byte colors[1]; + bfd_byte pad[1]; + bfd_byte planes[2]; + bfd_byte bits[2]; + bfd_byte bytes[4]; + bfd_byte index[2]; +}; +#define BIN_GROUP_ICON_ITEM_SIZE 14 + +/* A menu resource. */ + +typedef struct rc_menu +{ + /* List of menuitems. */ + struct rc_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. */ + rc_uint_type help; +} rc_menu; + +struct __attribute__ ((__packed__)) bin_menu +{ + bfd_byte sig1[2]; + bfd_byte sig2[2]; +}; +#define BIN_MENU_SIZE 4 + +struct __attribute__ ((__packed__)) bin_menuex +{ + bfd_byte sig1[2]; + bfd_byte sig2[2]; + bfd_byte help[4]; +}; +#define BIN_MENUEX_SIZE 8 + +/* A menu resource is a list of rc_menuitem. */ + +typedef struct rc_menuitem +{ + /* Next menu item. */ + struct rc_menuitem *next; + /* Type. In a normal menu, rather than a menuex, this is the flags + field. */ + rc_uint_type type; + /* State. This is only used in a menuex. */ + rc_uint_type state; + /* Id. */ + rc_uint_type id; + /* Unicode text. */ + unichar *text; + /* Popup menu items for a popup. */ + struct rc_menuitem *popup; + /* Help ID. This is only used in a menuex. */ + rc_uint_type help; +} rc_menuitem; + +struct __attribute__ ((__packed__)) bin_menuitem +{ + bfd_byte flags[2]; + bfd_byte id[2]; +}; +#define BIN_MENUITEM_SIZE 4 +#define BIN_MENUITEM_POPUP_SIZE 2 + +struct __attribute__ ((__packed__)) bin_menuitemex +{ + bfd_byte type[4]; + bfd_byte state[4]; + bfd_byte id[4]; + bfd_byte flags[2]; + /* unicode text */ + /* if popup: align, bfd_byte help[4], align, bin_menuitemex[]; */ +}; +#define BIN_MENUITEMEX_SIZE 14 + +/* Menu item flags. These can appear in the flags field of a rc_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 rc_rcdata_item. */ + +typedef struct rc_rcdata_item +{ + /* Next data item. */ + struct rc_rcdata_item *next; + /* Type of data. */ + enum + { + RCDATA_WORD, + RCDATA_DWORD, + RCDATA_STRING, + RCDATA_WSTRING, + RCDATA_BUFFER + } type; + union + { + rc_uint_type word; + rc_uint_type dword; + struct + { + rc_uint_type length; + const char *s; + } string; + struct + { + rc_uint_type length; + const unichar *w; + } wstring; + struct + { + rc_uint_type length; + const bfd_byte *data; + } buffer; + } u; +} rc_rcdata_item; + +/* A stringtable resource is a pointer to a rc_stringtable. */ + +typedef struct rc_stringtable +{ + /* Each stringtable resource is a list of 16 unicode strings. */ + struct + { + /* Length of string. */ + rc_uint_type length; + /* String data if length > 0. */ + unichar *string; + } strings[16]; +} rc_stringtable; + +/* A versioninfo resource points to a rc_versioninfo. */ + +typedef struct rc_versioninfo +{ + /* Fixed version information. */ + struct rc_fixed_versioninfo *fixed; + /* Variable version information. */ + struct rc_ver_info *var; +} rc_versioninfo; + +struct __attribute__ ((__packed__)) bin_versioninfo +{ + bfd_byte size[2]; + bfd_byte fixed_size[2]; + bfd_byte sig2[2]; +}; +#define BIN_VERSIONINFO_SIZE 6 + +/* The fixed portion of a versioninfo resource. */ + +typedef struct rc_fixed_versioninfo +{ + /* The file version, which is two 32 bit integers. */ + rc_uint_type file_version_ms; + rc_uint_type file_version_ls; + /* The product version, which is two 32 bit integers. */ + rc_uint_type product_version_ms; + rc_uint_type product_version_ls; + /* The file flags mask. */ + rc_uint_type file_flags_mask; + /* The file flags. */ + rc_uint_type file_flags; + /* The OS type. */ + rc_uint_type file_os; + /* The file type. */ + rc_uint_type file_type; + /* The file subtype. */ + rc_uint_type file_subtype; + /* The date, which in Windows is two 32 bit integers. */ + rc_uint_type file_date_ms; + rc_uint_type file_date_ls; +} rc_fixed_versioninfo; + +struct __attribute__ ((__packed__)) bin_fixed_versioninfo +{ + bfd_byte sig1[4]; + bfd_byte sig2[4]; + bfd_byte file_version[4]; + bfd_byte file_version_ls[4]; + bfd_byte product_version_ms[4]; + bfd_byte product_version_ls[4]; + bfd_byte file_flags_mask[4]; + bfd_byte file_flags[4]; + bfd_byte file_os[4]; + bfd_byte file_type[4]; + bfd_byte file_subtype[4]; + bfd_byte file_date_ms[4]; + bfd_byte file_date_ls[4]; +}; +#define BIN_FIXED_VERSIONINFO_SIZE 52 + +/* A list of variable version information. */ + +typedef struct rc_ver_info +{ + /* Next item. */ + struct rc_ver_info *next; + /* Type of data. */ + enum { VERINFO_STRING, VERINFO_VAR } type; + union + { + /* StringFileInfo data. */ + struct + { + /* Language. */ + unichar *language; + /* Strings. */ + struct rc_ver_stringinfo *strings; + } string; + /* VarFileInfo data. */ + struct + { + /* Key. */ + unichar *key; + /* Values. */ + struct rc_ver_varinfo *var; + } var; + } u; +} rc_ver_info; + +struct __attribute__ ((__packed__)) bin_ver_info +{ + bfd_byte size[2]; + bfd_byte sig1[2]; + bfd_byte sig2[2]; +}; +#define BIN_VER_INFO_SIZE 6 + +/* A list of string version information. */ + +typedef struct rc_ver_stringinfo +{ + /* Next string. */ + struct rc_ver_stringinfo *next; + /* Key. */ + unichar *key; + /* Value. */ + unichar *value; +} rc_ver_stringinfo; + +/* A list of variable version information. */ + +typedef struct rc_ver_varinfo +{ + /* Next item. */ + struct rc_ver_varinfo *next; + /* Language ID. */ + rc_uint_type language; + /* Character set ID. */ + rc_uint_type charset; +} rc_ver_varinfo; + +typedef struct rc_toolbar_item +{ + struct rc_toolbar_item *next; + struct rc_toolbar_item *prev; + rc_res_id id; +} rc_toolbar_item; + +struct __attribute__ ((__packed__)) bin_messagetable_item +{ + bfd_byte length[2]; + bfd_byte flags[2]; + bfd_byte data[1]; +}; +#define BIN_MESSAGETABLE_ITEM_SIZE 4 + +#define MESSAGE_RESOURCE_UNICODE 0x0001 + +struct __attribute__ ((__packed__)) bin_messagetable_block +{ + bfd_byte lowid[4]; + bfd_byte highid[4]; + bfd_byte offset[4]; +}; +#define BIN_MESSAGETABLE_BLOCK_SIZE 12 + +struct __attribute__ ((__packed__)) bin_messagetable +{ + bfd_byte cblocks[4]; + struct bin_messagetable_block items[1]; +}; +#define BIN_MESSAGETABLE_SIZE 8 + +typedef struct rc_toolbar +{ + rc_uint_type button_width; + rc_uint_type button_height; + rc_uint_type nitems; + rc_toolbar_item *items; +} rc_toolbar; + +struct __attribute__ ((__packed__)) bin_toolbar +{ + bfd_byte button_width[4]; + bfd_byte button_height[4]; + bfd_byte nitems[4]; + /* { bfd_byte id[4]; } * nitems; */ +}; +#define BIN_TOOLBAR_SIZE 12 + +extern int target_is_bigendian; + +typedef struct windres_bfd +{ + bfd *abfd; + asection *sec; + rc_uint_type kind : 4; +} windres_bfd; + +#define WR_KIND_TARGET 0 +#define WR_KIND_BFD 1 +#define WR_KIND_BFD_BIN_L 2 +#define WR_KIND_BFD_BIN_B 3 + +#define WR_KIND(PTR) (PTR)->kind +#define WR_SECTION(PTR) (PTR)->sec +#define WR_BFD(PTR) (PTR)->abfd + +extern void set_windres_bfd_content (windres_bfd *, const void *, rc_uint_type, rc_uint_type); +extern void get_windres_bfd_content (windres_bfd *, void *, rc_uint_type, rc_uint_type); + +extern void windres_put_8 (windres_bfd *, void *, rc_uint_type); +extern void windres_put_16 (windres_bfd *, void *, rc_uint_type); +extern void windres_put_32 (windres_bfd *, void *, rc_uint_type); +extern rc_uint_type windres_get_8 (windres_bfd *, const void *, rc_uint_type); +extern rc_uint_type windres_get_16 (windres_bfd *, const void *, rc_uint_type); +extern rc_uint_type windres_get_32 (windres_bfd *, const void *, rc_uint_type); + +extern void set_windres_bfd (windres_bfd *, bfd *, asection *, rc_uint_type); +extern void set_windres_bfd_endianess (windres_bfd *, int); + +#endif diff --git a/binutils/windres.c b/binutils/windres.c index d6623543e04..90918a6e905 100644 --- a/binutils/windres.c +++ b/binutils/windres.c @@ -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 #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; +} diff --git a/binutils/windres.h b/binutils/windres.h index 6a9dfa73797..d7494ec6a27 100644 --- a/binutils/windres.h +++ b/binutils/windres.h @@ -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) diff --git a/binutils/winduni.c b/binutils/winduni.c index cd02666d0e7..9def8dff54d 100644 --- a/binutils/winduni.c +++ b/binutils/winduni.c @@ -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 #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); +} diff --git a/binutils/winduni.h b/binutils/winduni.h index 71cd055a9da..349f6845784 100644 --- a/binutils/winduni.h +++ b/binutils/winduni.h @@ -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 -- 2.30.2