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.
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
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
#include <time.h>
#include "bfd.h"
#include "getopt.h"
+#include "bucomm.h"
#include "libiberty.h"
#include "safe-ctype.h"
#include "obstack.h"
-#include "bucomm.h"
#include "windres.h"
+/* Defined in bfd/binary.c. Used to set architecture and machine of input
+ binary files. */
+extern enum bfd_architecture bfd_external_binary_architecture;
+extern unsigned long bfd_external_machine;
+
/* Used by resrc.c at least. */
int verbose = 0;
+int target_is_bigendian = 0;
+const char *def_target_arch;
+
+static void set_endianess (bfd *, const char *);
+
/* An enumeration of format types. */
enum res_format
/* 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 *);
+\f
+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);
+
\f
/* 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. */
/* 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
/* 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);
}
\f
/* Open a file using the include directory search list. */
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)
{
/* 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;
/* 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;
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)
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;
/* 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;
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;
/* 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++)
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;
/* 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)
{
{
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
-D --define <sym>[=<val>] Define SYM when preprocessing rc file\n\
-U --undefine <sym> Undefine SYM when preprocessing rc file\n\
-v --verbose Verbose - tells you what it's doing\n\
+ -c --codepage=<codepage> Specify default codepage\n\
-l --language=<val> Set language when reading rc file\n\
--use-temp-file Use a temporary file instead of popen to read\n\
the preprocessor output\n\
const char *src;
char *dest;
- if ((buflen < slen * 2 + 2) || !buf)
+ if ((buflen < slen * 2 + 2) || ! buf)
{
buflen = slen * 2 + 2;
if (buf)
{"define", required_argument, 0, 'D'},
{"undefine", required_argument, 0, 'U'},
{"verbose", no_argument, 0, 'v'},
+ {"codepage", required_argument, 0, 'c'},
{"language", required_argument, 0, 'l'},
{"use-temp-file", no_argument, 0, OPTION_USE_TEMP_FILE},
{"no-use-temp-file", no_argument, 0, OPTION_NO_USE_TEMP_FILE},
{0, no_argument, 0, 0}
};
+void
+windres_add_include_dir (const char *p)
+{
+ struct include_dir *n, **pp;
+
+ /* Computing paths is often complicated and error prone.
+ The easiest way to check for mistakes is at the time
+ we add them to include_dirs. */
+ assert (p != NULL);
+ assert (*p != '\0');
+
+ n = xmalloc (sizeof *n);
+ n->next = NULL;
+ n->dir = (char * ) p;
+
+ for (pp = &include_dirs; *pp != NULL; pp = &(*pp)->next)
+ ;
+ *pp = n;
+}
+
/* This keeps gcc happy when using -Wmissing-prototypes -Wstrict-prototypes. */
int main (int, char **);
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)
language = 0x409; /* LANG_ENGLISH, SUBLANG_ENGLISH_US. */
use_temp_file = 0;
- while ((c = getopt_long (argc, argv, "f:i:l:o:I:J:O:F:D:U:rhHvV", long_options,
+ while ((c = getopt_long (argc, argv, "c:f:i:l:o:I:J:O:F:D:U:rhHvV", long_options,
(int *) 0)) != EOF)
{
switch (c)
{
+ case 'c':
+ {
+ rc_uint_type ncp;
+
+ if (optarg[0] == '0' && (optarg[1] == 'x' || optarg[1] == 'X'))
+ ncp = (rc_uint_type) strtol (optarg + 2, NULL, 16);
+ else
+ ncp = (rc_uint_type) strtol (optarg, NULL, 10);
+ if (ncp == CP_UTF16 || ! unicode_is_valid_codepage (ncp))
+ fatal (_("invalid codepage specified.\n"));
+ wind_default_codepage = wind_current_codepage = ncp;
+ }
+ break;
+
case 'i':
input_filename = optarg;
break;
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;
}
preprocargs = n;
}
- {
- struct include_dir *n, **pp;
-
- n = (struct include_dir *) xmalloc (sizeof *n);
- n->next = NULL;
- n->dir = optarg;
-
- for (pp = &include_dirs; *pp != NULL; pp = &(*pp)->next)
- ;
- *pp = n;
- }
+ windres_add_include_dir (optarg);
break;
output_format = format_from_filename (output_filename, 0);
}
+ set_endianess (NULL, target);
+
/* Read the input file. */
switch (input_format)
{
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;
+}