gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / binutils / resres.c
index 39264f445a22749999ffaa1ed29bdfc5edb1ba21..c6004ddf653c68b0435d629b51432787e9161cf5 100644 (file)
@@ -1,13 +1,13 @@
 /* resres.c: read_res_file and write_res_file implementation for windres.
-
-   Copyright 1998, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1998-2020 Free Software Foundation, Inc.
    Written by Anders Norlander <anorland@hem2.passagen.se>.
+   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,
 
    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.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+/* FIXME: This file does not work correctly in a cross configuration.
+   It assumes that it can use fread and fwrite to read and write
+   integers.  It does no swapping.  */
 
+#include "sysdep.h"
 #include "bfd.h"
 #include "bucomm.h"
 #include "libiberty.h"
 #include "windres.h"
 
 #include <assert.h>
-#include <time.h>
-
-struct res_hdr
-  {
-    unsigned long data_size;
-    unsigned long header_size;
-  };
-
-static 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));
+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 *);
 
-void
-  res_append_resource
-  PARAMS ((struct res_directory **, struct res_resource *,
-          int, const struct res_id *, 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 *);
+
+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 struct res_directory *resources = NULL;
+static void res_add_resource (rc_res_resource *, const rc_res_id *,
+                             const rc_res_id *, rc_uint_type, int);
+
+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_endianness (&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));
+  abfd = windres_open_as_binary (filename, 0);
+  sec = bfd_make_section_with_flags (abfd, ".data",
+                                    (SEC_HAS_CONTENTS | SEC_ALLOC
+                                     | SEC_LOAD | SEC_DATA));
+  if (sec == NULL)
+    bfd_fatal ("bfd_make_section");
+  /* Requiring this is probably a bug in BFD.  */
+  sec->output_section = sec;
 
-  /* Write 32 bit resource signature */
-  write_res_data (sign, sizeof (sign), 1);
-
-  /* write resources */
+  set_windres_bfd (&wrbfd, abfd, sec,
+                  (target_is_bigendian ? WR_KIND_BFD_BIN_B
+                                       : WR_KIND_BFD_BIN_L));
 
   language = -1;
-  write_res_directory (resdir, (const struct res_id *) NULL,
-                      (const struct res_id *) NULL, &language, 1);
-
-  /* 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 (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).",
+          (unsigned long) sec_length, (unsigned 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);
@@ -184,15 +211,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)
     {
@@ -208,15 +232,15 @@ write_res_directory (rd, type, name, language, level)
 
        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. */
+            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
+         if (! re->id.named
+             && re->id.u.id != (unsigned long) *language
              && (re->id.u.id & 0xffff) == re->id.u.id)
            {
              *language = re->id.u.id;
@@ -228,7 +252,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)
@@ -238,25 +263,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;
+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;
 
@@ -324,11 +349,15 @@ 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
       && type != NULL
-      && (type->named || type->u.id != rt))
+      && (type->named || type->u.id != (unsigned long) rt))
     {
       fprintf (stderr, "// Unexpected resource type mismatch: ");
       res_id_print (stderr, *type, 1);
@@ -336,35 +365,28 @@ 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;
-
-  bin_rep = res_to_bin (res, 0);
-  for (data = bin_rep; data != NULL; data = data->next)
-    datasize += data->length;
+  rc_uint_type noff;
+  rc_uint_type datasize = 0;
 
-  write_res_header (datasize, type, name, resinfo);
+  noff = res_to_bin ((windres_bfd *) NULL, off, res);
+  datasize = noff - off;
 
-  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;
+get_id_size (const rc_res_id *id)
 {
   if (id->named)
     return sizeof (unichar) * (id->u.n.length + 1);
@@ -373,106 +395,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);
 
-  res_align_file ();
-  write_res_data (&reshdr, sizeof (reshdr), 1);
-  write_res_id (type);
-  write_res_id (name);
+  reshdr.header_size = (reshdr.header_size + 3) & ~3;
 
-  res_align_file ();
+  off = (off + 3) & ~3;
 
-  write_res_info (resinfo);
-  res_align_file ();
+  off = write_res_data_hdr (wrbfd, off, &reshdr);
+  off = write_res_id (wrbfd, off, type);
+  off = write_res_id (wrbfd, off, name);
+
+  off = (off + 3) & ~3;
+
+  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 (fwrite (data, size, count, fres) != count)
-    fatal ("%s: %s: could not write to file", program_name, 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) != count)
-    fatal ("%s: %s: unexpected end of file", program_name, 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;
@@ -481,37 +539,62 @@ 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)
 {
-  if (fseek (fres, ftell (fres) % 4, 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);
+  /* off is advanced by BIN_RES_HDR_SIZE in read_res_data_hdr()
+     which is part of reshdr.header_size. We shouldn't take it
+     into account twice.  */
+  if ((off - BIN_RES_HDR_SIZE + reshdr.data_size + reshdr.header_size) > omax)
+    return 0;
+  return 1;
 }
 
 /* Check if file is a win32 binary resource file, if so
@@ -519,36 +602,35 @@ 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;
 
-skip_err:
+ 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;
+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;
@@ -561,41 +643,33 @@ 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 **res_dirs, 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)
+      if (*res_dirs == 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;
+         *res_dirs = ((rc_res_directory *)
+                       res_alloc (sizeof (rc_res_directory)));
+
+         (*res_dirs)->characteristics = 0;
+         /* Using a real timestamp only serves to create non-deterministic
+            results.  Use zero instead.  */
+         (*res_dirs)->time = 0;
+         (*res_dirs)->major = 0;
+         (*res_dirs)->minor = 0;
+         (*res_dirs)->entries = NULL;
        }
 
-      for (pp = &(*resources)->entries; *pp != NULL; pp = &(*pp)->next)
+      for (pp = &(*res_dirs)->entries; *pp != NULL; pp = &(*pp)->next)
        if (res_id_cmp ((*pp)->id, ids[i]) == 0)
          break;
 
@@ -603,7 +677,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)
@@ -622,7 +696,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);
@@ -630,7 +704,7 @@ res_append_resource (resources, resource, cids, ids, dupok)
              xexit (1);
            }
 
-         resources = &re->u.dir;
+         res_dirs = &re->u.dir;
        }
     }
 
This page took 0.032276 seconds and 4 git commands to generate.