Tue Oct 6 18:20:10 1998 Geoffrey Noer <noer@cygnus.com>
From Anders Norlander <anorland@hem2.passagen.se>. * resres.c: New file. Implementation of read_res_file and write_res_file functions for windres. * rcparse.y: Handle CONTROL's with named classes. * resbin.c: Bug in res_to_bin_dialog and bin_to_res_dialog when dialog is extended: The version and signature fields should be reversed (despite what the docs say). Id is 32 bits long in extended dialogs. * resrc.c (write_rc_dialog): properly print controls with named classes. * windres.c (read_res_file, write_res_file): Remove stubs. * resres.c (write_res): Rename RT_ACCELERATORS to RT_ACCELERATOR. * Makefile.in (windres_SOURCES): Add resres.c. (windres_OBJECTS): Add resres.o.
This commit is contained in:
parent
87feff9dab
commit
b459678b2b
4 changed files with 727 additions and 23 deletions
|
@ -1,3 +1,21 @@
|
|||
Tue Oct 6 18:20:10 1998 Geoffrey Noer <noer@cygnus.com>
|
||||
|
||||
From Anders Norlander <anorland@hem2.passagen.se>.
|
||||
|
||||
* resres.c: New file. Implementation of read_res_file and
|
||||
write_res_file functions for windres.
|
||||
* rcparse.y: Handle CONTROL's with named classes.
|
||||
* resbin.c: Bug in res_to_bin_dialog and bin_to_res_dialog
|
||||
when dialog is extended: The version and signature fields should
|
||||
be reversed (despite what the docs say). Id is 32 bits long in
|
||||
extended dialogs.
|
||||
* resrc.c (write_rc_dialog): properly print controls with named
|
||||
classes.
|
||||
* windres.c (read_res_file, write_res_file): Remove stubs.
|
||||
* resres.c (write_res): Rename RT_ACCELERATORS to RT_ACCELERATOR.
|
||||
* Makefile.in (windres_SOURCES): Add resres.c.
|
||||
(windres_OBJECTS): Add resres.o.
|
||||
|
||||
Sun Oct 4 20:34:42 1998 Ian Lance Taylor <ian@cygnus.com>
|
||||
|
||||
From Nokubi Hirotaka <hnokubi@yyy.or.jp>:
|
||||
|
|
|
@ -82,7 +82,8 @@ CFILES = addr2line.c ar.c arsup.c bucomm.c coffdump.c coffgrok.c debug.c \
|
|||
maybe-strip.c nlmconv.c nm.c not-ranlib.c not-strip.c \
|
||||
objcopy.c objdump.c prdbg.c rdcoff.c rddbg.c size.c srconv.c \
|
||||
stabs.c strings.c sysdump.c version.c wrstabs.c \
|
||||
windres.c resrc.c rescoff.c resbin.c winduni.c readelf.c
|
||||
windres.c resrc.c rescoff.c resbin.c winduni.c readelf.c \
|
||||
resres.c
|
||||
|
||||
GENERATED_CFILES = \
|
||||
underscore.c arparse.c arlex.c sysroff.c sysinfo.c syslex.c \
|
||||
|
@ -252,7 +253,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 \
|
||||
winduni.c $(BULIBS)
|
||||
winduni.c resres.c $(BULIBS)
|
||||
windres_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(INTLLIBS)
|
||||
|
||||
DISTSTUFF = arparse.c arparse.h arlex.c nlmheader.c sysinfo.c sysinfo.h \
|
||||
|
@ -338,9 +339,9 @@ install-exec-local: $(bin_PROGRAMS) $(noinst_PROGRAMS)
|
|||
for i in $(TOOL_PROGS); do \
|
||||
if [ -f $$i$(EXEEXT) ]; then \
|
||||
j=`echo $$i | sed -e 's/-new//'`; \
|
||||
rm -f $(tooldir)/bin/$$j$(EXEEXT); \
|
||||
k=`echo $$j | sed '$(transform)'`; \
|
||||
if [ "$(bindir)/$$k$(EXEEXT)" != "$(tooldir)/bin/$$j$(EXEEXT)" ]; then \
|
||||
rm -f $(tooldir)/bin/$$j$(EXEEXT); \
|
||||
ln $(bindir)/$$k$(EXEEXT) $(tooldir)/bin/$$j$(EXEEXT) >/dev/null 2>/dev/null \
|
||||
|| $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$i$(EXEEXT) $(tooldir)/bin/$$j$(EXEEXT); \
|
||||
fi; \
|
||||
|
@ -444,6 +445,7 @@ rescoff.o: rescoff.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
|
|||
resbin.o: resbin.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
|
||||
bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
|
||||
windres.h winduni.h
|
||||
resres.o: resres.c windres.h
|
||||
winduni.o: winduni.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
|
||||
bucomm.h config.h $(INCDIR)/fopen-same.h winduni.h
|
||||
readelf.o: readelf.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Makefile.in generated automatically by automake 1.3 from Makefile.am
|
||||
# Makefile.in generated automatically by automake 1.3b from Makefile.am
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
|
@ -32,7 +32,7 @@ mandir = @mandir@
|
|||
includedir = @includedir@
|
||||
oldincludedir = /usr/include
|
||||
|
||||
DISTDIR =
|
||||
DESTDIR =
|
||||
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
|
@ -64,18 +64,46 @@ host_triplet = @host@
|
|||
target_alias = @target_alias@
|
||||
target_triplet = @target@
|
||||
AR = @AR@
|
||||
AS = @AS@
|
||||
BUILD_DLLTOOL = @BUILD_DLLTOOL@
|
||||
BUILD_DLLWRAP = @BUILD_DLLWRAP@
|
||||
BUILD_NLMCONV = @BUILD_NLMCONV@
|
||||
BUILD_SRCONV = @BUILD_SRCONV@
|
||||
BUILD_WINDRES = @BUILD_WINDRES@
|
||||
CATALOGS = @CATALOGS@
|
||||
CATOBJEXT = @CATOBJEXT@
|
||||
CC = @CC@
|
||||
DATADIRNAME = @DATADIRNAME@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DLLTOOL_DEFS = @DLLTOOL_DEFS@
|
||||
EXEEXT = @EXEEXT@
|
||||
GMOFILES = @GMOFILES@
|
||||
GMSGFMT = @GMSGFMT@
|
||||
GT_NO = @GT_NO@
|
||||
GT_YES = @GT_YES@
|
||||
HDEFINES = @HDEFINES@
|
||||
INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@
|
||||
INSTOBJEXT = @INSTOBJEXT@
|
||||
INTLDEPS = @INTLDEPS@
|
||||
INTLOBJS = @INTLOBJS@
|
||||
LD = @LD@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LN_S = @LN_S@
|
||||
MAINT = @MAINT@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKINSTALLDIRS = @MKINSTALLDIRS@
|
||||
MSGFMT = @MSGFMT@
|
||||
NLMCONV_DEFS = @NLMCONV_DEFS@
|
||||
NM = @NM@
|
||||
PACKAGE = @PACKAGE@
|
||||
POFILES = @POFILES@
|
||||
POSUB = @POSUB@
|
||||
RANLIB = @RANLIB@
|
||||
UNDERSCORE = @UNDERSCORE@
|
||||
USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
|
||||
USE_NLS = @USE_NLS@
|
||||
VERSION = @VERSION@
|
||||
l = @l@
|
||||
|
||||
INTLLIBS = @INTLLIBS@
|
||||
|
||||
|
@ -154,7 +182,8 @@ CFILES = addr2line.c ar.c arsup.c bucomm.c coffdump.c coffgrok.c debug.c \
|
|||
maybe-strip.c nlmconv.c nm.c not-ranlib.c not-strip.c \
|
||||
objcopy.c objdump.c prdbg.c rdcoff.c rddbg.c size.c srconv.c \
|
||||
stabs.c strings.c sysdump.c version.c wrstabs.c \
|
||||
windres.c resrc.c rescoff.c resbin.c winduni.c readelf.c
|
||||
windres.c resrc.c rescoff.c resbin.c winduni.c readelf.c \
|
||||
resres.c
|
||||
|
||||
GENERATED_CFILES = \
|
||||
underscore.c arparse.c arlex.c sysroff.c sysinfo.c syslex.c \
|
||||
|
@ -239,7 +268,7 @@ 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 \
|
||||
winduni.c $(BULIBS)
|
||||
winduni.c resres.c $(BULIBS)
|
||||
windres_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(INTLLIBS)
|
||||
|
||||
DISTSTUFF = arparse.c arparse.h arlex.c nlmheader.c sysinfo.c sysinfo.h \
|
||||
|
@ -291,7 +320,7 @@ filemode.o
|
|||
dlltool_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a
|
||||
dlltool_LDFLAGS =
|
||||
windres_OBJECTS = windres.o resrc.o rescoff.o resbin.o rcparse.o \
|
||||
rclex.o winduni.o bucomm.o version.o filemode.o
|
||||
rclex.o winduni.o resres.o bucomm.o version.o filemode.o
|
||||
windres_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a
|
||||
windres_LDFLAGS =
|
||||
size_OBJECTS = size.o bucomm.o version.o filemode.o
|
||||
|
@ -344,10 +373,9 @@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
|
|||
LEXLIB = @LEXLIB@
|
||||
YLWRAP = $(top_srcdir)/../ylwrap
|
||||
CFLAGS = @CFLAGS@
|
||||
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
|
||||
LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@
|
||||
MAKEINFO = `if test -f $(top_builddir)/../texinfo/makeinfo/makeinfo; then echo $(top_builddir)/../texinfo/makeinfo/makeinfo; else echo makeinfo; fi`
|
||||
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
LINK = $(LIBTOOL) --mode=link $(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
|
||||
TEXI2DVI = `if test -f $(top_srcdir)/../texinfo/util/texi2dvi; then echo $(top_srcdir)/../texinfo/util/texi2dvi; else echo texi2dvi; fi`
|
||||
TEXINFO_TEX = $(top_srcdir)/../texinfo/texinfo.tex
|
||||
INFO_DEPS = binutils.info
|
||||
|
@ -363,9 +391,6 @@ configure.in deflex.c defparse.c nlmheader.c rclex.c rcparse.c \
|
|||
stamp-h.in
|
||||
|
||||
|
||||
PACKAGE = @PACKAGE@
|
||||
VERSION = @VERSION@
|
||||
|
||||
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
TAR = tar
|
||||
|
@ -553,14 +578,14 @@ strip-new$(EXEEXT): $(strip_new_OBJECTS) $(strip_new_DEPENDENCIES)
|
|||
@rm -f strip-new$(EXEEXT)
|
||||
$(LINK) $(strip_new_LDFLAGS) $(strip_new_OBJECTS) $(strip_new_LDADD) $(LIBS)
|
||||
.y.c:
|
||||
$(SHELL) $(YLWRAP) "$(YACC)" $< y.tab.c $*.c y.tab.h $*.h -- $(YFLAGS)
|
||||
$(SHELL) $(YLWRAP) "$(YACC)" $< y.tab.c $*.c y.tab.h $*.h -- $(AM_YFLAGS) $(YFLAGS)
|
||||
defparse.h: defparse.c
|
||||
arparse.h: arparse.c
|
||||
rcparse.h: rcparse.c
|
||||
nlmheader.h: nlmheader.c
|
||||
|
||||
.l.c:
|
||||
$(SHELL) $(YLWRAP) "$(LEX)" $< $(LEX_OUTPUT_ROOT).c $@ -- $(LFLAGS)
|
||||
$(SHELL) $(YLWRAP) "$(LEX)" $< $(LEX_OUTPUT_ROOT).c $@ -- $(AM_LFLAGS) $(LFLAGS)
|
||||
|
||||
binutils.info: binutils.texi
|
||||
binutils.dvi: binutils.texi
|
||||
|
@ -881,7 +906,7 @@ uninstall: uninstall-recursive uninstall-am
|
|||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
|
||||
installdirs: installdirs-recursive
|
||||
$(mkinstalldirs) $(DATADIR)$(bindir) $(DESTDIR)$(mandir)/man1
|
||||
$(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man1
|
||||
|
||||
|
||||
mostlyclean-generic:
|
||||
|
@ -891,13 +916,12 @@ clean-generic:
|
|||
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
||||
|
||||
distclean-generic:
|
||||
-rm -f Makefile $(DISTCLEANFILES)
|
||||
-rm -f Makefile $(CONFIG_CLEAN_FILES)
|
||||
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
|
||||
-test -z "defparsehdefparsecarparseharparsecrcparsehrcparsecnlmheaderhnlmheadercrclexldeflexlarlexl$(MAINTAINERCLEANFILES)" || rm -f defparseh defparsec arparseh arparsec rcparseh rcparsec nlmheaderh nlmheaderc rclexl deflexl arlexl $(MAINTAINERCLEANFILES)
|
||||
mostlyclean-am: mostlyclean-hdr mostlyclean-binPROGRAMS \
|
||||
mostlyclean-noinstPROGRAMS mostlyclean-compile \
|
||||
mostlyclean-libtool mostlyclean-aminfo mostlyclean-tags \
|
||||
|
@ -1110,9 +1134,9 @@ install-exec-local: $(bin_PROGRAMS) $(noinst_PROGRAMS)
|
|||
for i in $(TOOL_PROGS); do \
|
||||
if [ -f $$i$(EXEEXT) ]; then \
|
||||
j=`echo $$i | sed -e 's/-new//'`; \
|
||||
rm -f $(tooldir)/bin/$$j$(EXEEXT); \
|
||||
k=`echo $$j | sed '$(transform)'`; \
|
||||
if [ "$(bindir)/$$k$(EXEEXT)" != "$(tooldir)/bin/$$j$(EXEEXT)" ]; then \
|
||||
rm -f $(tooldir)/bin/$$j$(EXEEXT); \
|
||||
ln $(bindir)/$$k$(EXEEXT) $(tooldir)/bin/$$j$(EXEEXT) >/dev/null 2>/dev/null \
|
||||
|| $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$i$(EXEEXT) $(tooldir)/bin/$$j$(EXEEXT); \
|
||||
fi; \
|
||||
|
@ -1216,6 +1240,7 @@ rescoff.o: rescoff.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
|
|||
resbin.o: resbin.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
|
||||
bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
|
||||
windres.h winduni.h
|
||||
resres.o: resres.c windres.h
|
||||
winduni.o: winduni.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
|
||||
bucomm.h config.h $(INCDIR)/fopen-same.h winduni.h
|
||||
readelf.o: readelf.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
|
||||
|
|
659
binutils/resres.c
Normal file
659
binutils/resres.c
Normal file
|
@ -0,0 +1,659 @@
|
|||
/* resres.c: read_res_file and write_res_file implementation for windres.
|
||||
|
||||
Copyright 1997, 1998 Free Software Foundation, Inc.
|
||||
Written by Anders Norlander <anorland@hem2.passagen.se>.
|
||||
|
||||
This file is part of GNU Binutils.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "windres.h"
|
||||
|
||||
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 void
|
||||
res_add_resource
|
||||
PARAMS ((struct res_resource *, const struct res_id *,
|
||||
const struct res_id *, int, int));
|
||||
|
||||
void
|
||||
res_append_resource
|
||||
PARAMS ((struct res_directory **, struct res_resource *,
|
||||
int, const struct res_id *, int));
|
||||
|
||||
static struct 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;
|
||||
{
|
||||
filename = fn;
|
||||
fres = fopen (filename, "rb");
|
||||
if (fres == NULL)
|
||||
fatal ("can't open `%s' for output: %s", filename, strerror (errno));
|
||||
|
||||
skip_null_resource ();
|
||||
|
||||
while (read_resource_entry ())
|
||||
;
|
||||
|
||||
fclose (fres);
|
||||
|
||||
return resources;
|
||||
}
|
||||
|
||||
/* Write resource file */
|
||||
void
|
||||
write_res_file (fn, resdir)
|
||||
const char *fn;
|
||||
const struct res_directory *resdir;
|
||||
{
|
||||
int language;
|
||||
static const unsigned char 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;
|
||||
struct res_entry *e;
|
||||
int i;
|
||||
|
||||
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 */
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* Read a resource entry, returns 0 when all resources are read */
|
||||
static int
|
||||
read_resource_entry (void)
|
||||
{
|
||||
struct res_id type;
|
||||
struct res_id name;
|
||||
struct res_res_info resinfo;
|
||||
struct res_hdr reshdr;
|
||||
enum res_type rtype;
|
||||
long version;
|
||||
long n;
|
||||
void *buff;
|
||||
|
||||
struct res_resource *r;
|
||||
|
||||
res_align_file ();
|
||||
|
||||
/* Read header */
|
||||
if (fread (&reshdr, sizeof (reshdr), 1, fres) != 1)
|
||||
return 0;
|
||||
|
||||
/* read resource type */
|
||||
read_res_id (&type);
|
||||
/* read resource id */
|
||||
read_res_id (&name);
|
||||
|
||||
res_align_file ();
|
||||
|
||||
/* 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);
|
||||
|
||||
res_align_file ();
|
||||
|
||||
/* Allocate buffer for data */
|
||||
buff = res_alloc (reshdr.data_size);
|
||||
/* Read data */
|
||||
read_res_data (buff, reshdr.data_size, 1);
|
||||
/* Convert binary data to resource */
|
||||
r = bin_to_res (type, buff, reshdr.data_size, 0);
|
||||
r->res_info = resinfo;
|
||||
/* Add resource to resource directory */
|
||||
res_add_resource (r, &type, &name, resinfo.language, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
{
|
||||
const struct res_entry *re;
|
||||
|
||||
for (re = rd->entries; re != NULL; re = re->next)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case 1:
|
||||
/* If we're at level 1, the key of this resource is the
|
||||
type. This normally duplicates the information we have
|
||||
stored with the resource itself, but we need to remember
|
||||
the type if this is a user define resource type. */
|
||||
type = &re->id;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* If we're at level 2, the key of this resource is the name
|
||||
we are going to use in the rc printout. */
|
||||
name = &re->id;
|
||||
break;
|
||||
|
||||
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
|
||||
&& re->id.u.id != *language
|
||||
&& (re->id.u.id & 0xffff) == re->id.u.id)
|
||||
{
|
||||
*language = re->id.u.id;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (re->subdir)
|
||||
write_res_directory (re->u.dir, type, name, language, level + 1);
|
||||
else
|
||||
{
|
||||
if (level == 3)
|
||||
{
|
||||
/* This is the normal case: the three levels are
|
||||
TYPE/NAME/LANGUAGE. NAME will have been set at 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "// Resource at unexpected level %d\n", level);
|
||||
write_res_resource (type, (struct res_id *) NULL, re->u.res,
|
||||
language);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
{
|
||||
int rt;
|
||||
|
||||
switch (res->type)
|
||||
{
|
||||
default:
|
||||
abort ();
|
||||
|
||||
case RES_TYPE_ACCELERATOR:
|
||||
rt = RT_ACCELERATOR;
|
||||
break;
|
||||
|
||||
case RES_TYPE_BITMAP:
|
||||
rt = RT_BITMAP;
|
||||
break;
|
||||
|
||||
case RES_TYPE_CURSOR:
|
||||
rt = RT_CURSOR;
|
||||
break;
|
||||
|
||||
case RES_TYPE_GROUP_CURSOR:
|
||||
rt = RT_GROUP_CURSOR;
|
||||
break;
|
||||
|
||||
case RES_TYPE_DIALOG:
|
||||
rt = RT_DIALOG;
|
||||
break;
|
||||
|
||||
case RES_TYPE_FONT:
|
||||
rt = RT_FONT;
|
||||
break;
|
||||
|
||||
case RES_TYPE_FONTDIR:
|
||||
rt = RT_FONTDIR;
|
||||
break;
|
||||
|
||||
case RES_TYPE_ICON:
|
||||
rt = RT_ICON;
|
||||
break;
|
||||
|
||||
case RES_TYPE_GROUP_ICON:
|
||||
rt = RT_GROUP_ICON;
|
||||
break;
|
||||
|
||||
case RES_TYPE_MENU:
|
||||
rt = RT_MENU;
|
||||
break;
|
||||
|
||||
case RES_TYPE_MESSAGETABLE:
|
||||
rt = RT_MESSAGETABLE;
|
||||
break;
|
||||
|
||||
case RES_TYPE_RCDATA:
|
||||
rt = RT_RCDATA;
|
||||
break;
|
||||
|
||||
case RES_TYPE_STRINGTABLE:
|
||||
rt = RT_STRING;
|
||||
break;
|
||||
|
||||
case RES_TYPE_USERDATA:
|
||||
rt = 0;
|
||||
break;
|
||||
|
||||
case RES_TYPE_VERSIONINFO:
|
||||
rt = RT_VERSION;
|
||||
break;
|
||||
}
|
||||
|
||||
if (rt != 0
|
||||
&& type != NULL
|
||||
&& (type->named || type->u.id != rt))
|
||||
{
|
||||
fprintf (stderr, "// Unexpected resource type mismatch: ");
|
||||
res_id_print (stderr, *type, 1);
|
||||
fprintf (stderr, " != %d", rt);
|
||||
abort ();
|
||||
}
|
||||
|
||||
write_res_bin (res, type, name, &res->res_info);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
{
|
||||
unsigned long datasize = 0;
|
||||
const struct bindata *bin_rep, *data;
|
||||
|
||||
bin_rep = res_to_bin (res, 0);
|
||||
for (data = bin_rep; data != NULL; data = data->next)
|
||||
datasize += data->length;
|
||||
|
||||
write_res_header (datasize, type, name, resinfo);
|
||||
|
||||
for (data = bin_rep; data != NULL; data = data->next)
|
||||
write_res_data (data->data, data->length, 1);
|
||||
}
|
||||
|
||||
/* Get number of bytes needed to store an id in binary format */
|
||||
static unsigned long
|
||||
get_id_size (id)
|
||||
const struct res_id *id;
|
||||
{
|
||||
if (id->named)
|
||||
return sizeof (unichar) * (id->u.n.length + 1);
|
||||
else
|
||||
return sizeof (unichar) * 2;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
{
|
||||
struct res_hdr reshdr;
|
||||
reshdr.data_size = datasize;
|
||||
reshdr.header_size = 24 + get_id_size (type) + get_id_size (name);
|
||||
|
||||
res_align_file ();
|
||||
write_res_data (&reshdr, sizeof (reshdr), 1);
|
||||
write_res_id (type);
|
||||
write_res_id (name);
|
||||
|
||||
res_align_file ();
|
||||
|
||||
write_res_info (resinfo);
|
||||
res_align_file ();
|
||||
}
|
||||
|
||||
|
||||
/* Write data to file, abort on failure */
|
||||
static void
|
||||
write_res_data (data, size, count)
|
||||
const void *data;
|
||||
size_t size;
|
||||
int count;
|
||||
{
|
||||
if (fwrite (data, size, count, fres) != count)
|
||||
fatal ("%s: %s: could not write to file", program_name, filename);
|
||||
}
|
||||
|
||||
/* Read data from file, abort on failure */
|
||||
static void
|
||||
read_res_data (data, size, count)
|
||||
void *data;
|
||||
size_t size;
|
||||
int count;
|
||||
{
|
||||
if (fread (data, size, count, fres) != count)
|
||||
fatal ("%s: %s: unexpected end of file", program_name, filename);
|
||||
}
|
||||
|
||||
/* Write a resource id */
|
||||
static void
|
||||
write_res_id (id)
|
||||
const struct 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned short i = 0xFFFF;
|
||||
write_res_data (&i, sizeof (i), 1);
|
||||
i = id->u.id;
|
||||
write_res_data (&i, sizeof (i), 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write resource info */
|
||||
static void
|
||||
write_res_info (info)
|
||||
const struct 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);
|
||||
}
|
||||
|
||||
/* read a resource identifier */
|
||||
void
|
||||
read_res_id (id)
|
||||
struct res_id *id;
|
||||
{
|
||||
unsigned short ord;
|
||||
unichar *id_s = NULL;
|
||||
int len;
|
||||
|
||||
read_res_data (&ord, sizeof (ord), 1);
|
||||
if (ord == 0xFFFF) /* an ordinal id */
|
||||
{
|
||||
read_res_data (&ord, sizeof (ord), 1);
|
||||
id->named = 0;
|
||||
id->u.id = ord;
|
||||
}
|
||||
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);
|
||||
id->named = 1;
|
||||
id->u.n.length = len;
|
||||
id->u.n.name = id_s;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read a null terminated UNICODE string */
|
||||
static unichar *
|
||||
read_unistring (len)
|
||||
int *len;
|
||||
{
|
||||
unichar *s;
|
||||
unichar c;
|
||||
unichar *p;
|
||||
int n;
|
||||
int l;
|
||||
|
||||
*len = 0;
|
||||
l = 0;
|
||||
|
||||
/* there are hardly any names longer than 256 characters */
|
||||
p = s = (unichar *) xmalloc (sizeof (unichar) * 256);
|
||||
do
|
||||
{
|
||||
read_res_data (&c, sizeof (c), 1);
|
||||
*p++ = c;
|
||||
if (c != 0)
|
||||
l++;
|
||||
}
|
||||
while (c != 0);
|
||||
*len = l;
|
||||
return s;
|
||||
}
|
||||
|
||||
/* align file on DWORD boundary */
|
||||
static void
|
||||
res_align_file (void)
|
||||
{
|
||||
if (fseek (fres, ftell (fres) % 4, SEEK_CUR) != 0)
|
||||
fatal ("%s: %s: unable to align file", program_name, filename);
|
||||
}
|
||||
|
||||
/* Check if file is a win32 binary resource file, if so
|
||||
skip past the null resource. Returns 0 if successful, -1 on
|
||||
error.
|
||||
*/
|
||||
static void
|
||||
skip_null_resource (void)
|
||||
{
|
||||
struct res_hdr reshdr =
|
||||
{0, 0};
|
||||
read_res_data (&reshdr, sizeof (reshdr), 1);
|
||||
if ((reshdr.data_size != 0) || (reshdr.header_size != 0x20))
|
||||
goto skip_err;
|
||||
|
||||
/* Subtract size of HeaderSize and DataSize */
|
||||
if (fseek (fres, reshdr.header_size - 8, SEEK_CUR) != 0)
|
||||
goto skip_err;
|
||||
|
||||
return;
|
||||
|
||||
skip_err:
|
||||
fprintf (stderr, "%s: %s: Not a valid WIN32 resource file\n", program_name,
|
||||
filename);
|
||||
xexit (1);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
{
|
||||
struct res_id a[3];
|
||||
|
||||
a[0] = *type;
|
||||
a[1] = *id;
|
||||
a[2].named = 0;
|
||||
a[2].u.id = language;
|
||||
res_append_resource (&resources, r, 3, a, dupok);
|
||||
}
|
||||
|
||||
/* Append a resource to resource directory.
|
||||
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;
|
||||
{
|
||||
struct res_entry *re = NULL;
|
||||
int i;
|
||||
|
||||
assert (cids > 0);
|
||||
for (i = 0; i < cids; i++)
|
||||
{
|
||||
struct res_entry **pp;
|
||||
|
||||
if (*resources == NULL)
|
||||
{
|
||||
static unsigned long 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)->characteristics = 0;
|
||||
(*resources)->time = timeval;
|
||||
(*resources)->major = 0;
|
||||
(*resources)->minor = 0;
|
||||
(*resources)->entries = NULL;
|
||||
}
|
||||
|
||||
for (pp = &(*resources)->entries; *pp != NULL; pp = &(*pp)->next)
|
||||
if (res_id_cmp ((*pp)->id, ids[i]) == 0)
|
||||
break;
|
||||
|
||||
if (*pp != NULL)
|
||||
re = *pp;
|
||||
else
|
||||
{
|
||||
re = (struct res_entry *) res_alloc (sizeof *re);
|
||||
re->next = NULL;
|
||||
re->id = ids[i];
|
||||
if ((i + 1) < cids)
|
||||
{
|
||||
re->subdir = 1;
|
||||
re->u.dir = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
re->subdir = 0;
|
||||
re->u.res = NULL;
|
||||
}
|
||||
|
||||
*pp = re;
|
||||
}
|
||||
|
||||
if ((i + 1) < cids)
|
||||
{
|
||||
if (!re->subdir)
|
||||
{
|
||||
fprintf (stderr, "%s: ", program_name);
|
||||
res_ids_print (stderr, i, ids);
|
||||
fprintf (stderr, ": expected to be a directory\n");
|
||||
xexit (1);
|
||||
}
|
||||
|
||||
resources = &re->u.dir;
|
||||
}
|
||||
}
|
||||
|
||||
if (re->subdir)
|
||||
{
|
||||
fprintf (stderr, "%s: ", program_name);
|
||||
res_ids_print (stderr, cids, ids);
|
||||
fprintf (stderr, ": expected to be a leaf\n");
|
||||
xexit (1);
|
||||
}
|
||||
|
||||
if (re->u.res != NULL)
|
||||
{
|
||||
if (dupok)
|
||||
return;
|
||||
|
||||
fprintf (stderr, "%s: warning: ", program_name);
|
||||
res_ids_print (stderr, cids, ids);
|
||||
fprintf (stderr, ": duplicate value\n");
|
||||
}
|
||||
|
||||
re->u.res = resource;
|
||||
}
|
Loading…
Reference in a new issue