+static void
+set_endianness (bfd *abfd, const char *target)
+{
+ const bfd_target *target_vec;
+
+ def_target_arch = NULL;
+ target_vec = bfd_get_target_info (target, abfd, &target_is_bigendian, NULL,
+ &def_target_arch);
+ if (! target_vec)
+ fatal ("Can't detect target endianness and architecture.");
+ 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_endianness (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;
+}