2009-02-23 Tristan Gingold <gingold@adacore.com>
[deliverable/binutils-gdb.git] / bfd / vms-misc.c
index 048c643aba0c2f4a0b9ce45b0877dea47d155a49..21816587ef458f7a32add36a53ce3e52ea287b26 100644 (file)
@@ -1,59 +1,62 @@
-/* vms-misc.c -- Miscellaneous functions for VAX (openVMS/VAX) and
+/* vms-misc.c -- BFD back-end for VMS/VAX (openVMS/VAX) and
    EVAX (openVMS/Alpha) files.
-   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
-   Free Software Foundation, Inc.
+   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+   2007, 2008, 2009  Free Software Foundation, Inc.
+
+   Miscellaneous functions.
 
    Written by Klaus K"ampf (kkaempf@rmi.de)
 
-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 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 3 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.
+   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.  */
+   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.  */
 
 #if __STDC__
 #include <stdarg.h>
 #endif
 
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "bfdlink.h"
 #include "libbfd.h"
 
 #include "vms.h"
 
-static vms_section *add_new_contents PARAMS ((bfd *, sec_ptr));
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
 static int hash_string PARAMS ((const char *));
 static asymbol *new_symbol PARAMS ((bfd *, char *));
+static void maybe_adjust_record_pointer_for_object PARAMS ((bfd *));
+static int vms_get_remaining_object_record PARAMS ((bfd *, int ));
+static int vms_get_remaining_image_record PARAMS ((bfd *, int ));
 
-/*-----------------------------------------------------------------------------*/
 #if VMS_DEBUG
-/* debug functions */
+/* Debug functions.  */
 
-/* debug function for all vms extensions
-   evaluates environment variable VMS_DEBUG for a
-   numerical value on the first call
-   all error levels below this value are printed
+/* Debug function for all vms extensions evaluates environment
+   variable VMS_DEBUG for a numerical value on the first call all
+   error levels below this value are printed:
 
-   levels:
+   Levels:
    1   toplevel bfd calls (functions from the bfd vector)
    2   functions called by bfd calls
    ...
    9   almost everything
 
-   level is also indentation level. Indentation is performed
-   if level > 0
-       */
+   Level is also indentation level. Indentation is performed
+   if level > 0.  */
 
-#if __STDC__
 void
 _bfd_vms_debug (int level, char *format, ...)
 {
@@ -61,13 +64,13 @@ _bfd_vms_debug (int level, char *format, ...)
   static FILE *output = NULL;
   char *eptr;
   va_list args;
-  int abslvl = (level > 0)?level:-level;
+  int abslvl = (level > 0) ? level : - level;
 
   if (min_level == -1)
     {
-      if ((eptr = getenv("VMS_DEBUG")) != NULL)
+      if ((eptr = getenv ("VMS_DEBUG")) != NULL)
        {
-         min_level = atoi(eptr);
+         min_level = atoi (eptr);
          output = stderr;
        }
       else
@@ -80,60 +83,20 @@ _bfd_vms_debug (int level, char *format, ...)
 
   while (--level>0)
     fprintf (output, " ");
-  va_start(args, format);
+  va_start (args, format);
   vfprintf (output, format, args);
-  fflush(output);
-  va_end(args);
-
-  return;
+  fflush (output);
+  va_end (args);
 }
 
-#else /* not __STDC__ */
+/* A debug function
+   hex dump 'size' bytes starting at 'ptr'.  */
 
 void
-_bfd_vms_debug (level, format, a1, a2, a3, a4, a5, a6)
-     int level;
-     char *format;
-     long a1; long a2; long a3;
-     long a4; long a5; long a6;
-{
-  static int min_level = -1;
-  static FILE *output = NULL;
-  char *eptr;
-
-  if (min_level == -1)
-    {
-      if ((eptr = getenv("VMS_DEBUG")) != NULL)
-       {
-         min_level = atoi(eptr);
-         output = stderr;
-       }
-      else
-       min_level = 0;
-    }
-  if (output == NULL)
-    return;
-  if (level > min_level)
-    return;
-
-  while (--level>0)
-    fprintf (output, " ");
-  fprintf (output, format, a1, a2, a3, a4, a5, a6);
-  fflush(output);
-
-  return;
-}
-#endif /* __STDC__ */
-
-/* a debug function
-   hex dump 'size' bytes starting at 'ptr'  */
-
-void
-_bfd_hexdump (level, ptr, size, offset)
-     int level;
-     unsigned char *ptr;
-     int size;
-     int offset;
+_bfd_hexdump (int level,
+             unsigned char *ptr,
+             int size,
+             int offset)
 {
   unsigned char *lptr = ptr;
   int count = 0;
@@ -167,366 +130,450 @@ _bfd_hexdump (level, ptr, size, offset)
     }
   if ((count%16) != 0)
     vms_debug (-level, "\n");
-
-  return;
 }
 #endif
 \f
-/* hash functions
+/* Hash functions
 
    These are needed when reading an object file.  */
 
-/* allocate new vms_hash_entry
-   keep the symbol name and a pointer to the bfd symbol in the table  */
+/* Allocate new vms_hash_entry
+   keep the symbol name and a pointer to the bfd symbol in the table.  */
 
 struct bfd_hash_entry *
-_bfd_vms_hash_newfunc (entry, table, string)
-     struct bfd_hash_entry *entry;
-     struct bfd_hash_table *table;
-     const char *string;
+_bfd_vms_hash_newfunc (struct bfd_hash_entry *entry,
+                      struct bfd_hash_table *table,
+                      const char *string)
 {
   vms_symbol_entry *ret;
 
 #if VMS_DEBUG
-  vms_debug (5, "_bfd_vms_hash_newfunc(%p, %p, %s)\n", entry, table, string);
+  vms_debug (5, "_bfd_vms_hash_newfunc (%p, %p, %s)\n", entry, table, string);
 #endif
 
-  if (entry == (struct bfd_hash_entry *)NULL)
+  if (entry == NULL)
     {
       ret = (vms_symbol_entry *)
              bfd_hash_allocate (table, sizeof (vms_symbol_entry));
-      if (ret == (vms_symbol_entry *) NULL)
+      if (ret ==  NULL)
        {
          bfd_set_error (bfd_error_no_memory);
-         return (struct bfd_hash_entry *)NULL;
+         return NULL;
        }
       entry = (struct bfd_hash_entry *) ret;
     }
 
   /* Call the allocation method of the base class.  */
-
   ret = (vms_symbol_entry *) bfd_hash_newfunc (entry, table, string);
 #if VMS_DEBUG
   vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret);
 #endif
 
-  ret->symbol = (asymbol *)NULL;
+  ret->symbol = NULL;
 
   return (struct bfd_hash_entry *)ret;
 }
 \f
-/* object file input functions */
+/* Object file input functions.  */
 
-/* Return type and length from record header (buf) on Alpha.  */
+/* Return type and size from record header (buf) on Alpha.  */
 
 void
-_bfd_vms_get_header_values (abfd, buf, type, length)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     unsigned char *buf;
-     int *type;
-     int *length;
+_bfd_vms_get_header_values (bfd * abfd ATTRIBUTE_UNUSED,
+                           unsigned char *buf,
+                           int *type,
+                           int *size)
 {
-  if (type != 0)
+  if (type)
     *type = bfd_getl16 (buf);
-  buf += 2;
-  if (length != 0)
-    *length = bfd_getl16 (buf);
+
+  if (size)
+    *size = bfd_getl16 (buf+2);
 
 #if VMS_DEBUG
-  vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type?*type:0), (length?*length:0));
+  vms_debug (10, "_bfd_vms_get_header_values type %x, size %x\n",
+            type ? *type : 0, size ? *size : 0);
 #endif
-
-  return;
 }
 
-/* Get next record from object file to vms_buf
-   set PRIV(buf_size) and return it
+/* Get next record from object file to vms_buf.
+   Set PRIV(buf_size) and return it
 
-   this is a little tricky since it should be portable.
+   This is a little tricky since it should be portable.
 
-   the openVMS object file has 'variable length' which means that
+   The openVMS object file has 'variable length' which means that
    read() returns data in chunks of (hopefully) correct and expected
-   size. The linker (and other tools on vms) depend on that. Unix doesn't
-   know about 'formatted' files, so reading and writing such an object
-   file in a unix environment is not trivial.
+   size.  The linker (and other tools on VMS) depend on that. Unix
+   doesn't know about 'formatted' files, so reading and writing such
+   an object file in a Unix environment is not trivial.
 
-   With the tool 'file' (available on all vms ftp sites), one
-   can view and change the attributes of a file. Changing from
+   With the tool 'file' (available on all VMS FTP sites), one
+   can view and change the attributes of a file.  Changing from
    'variable length' to 'fixed length, 512 bytes' reveals the
-   record length at the first 2 bytes of every record. The same
-   happens during the transfer of object files from vms to unix,
-   at least with ucx, dec's implementation of tcp/ip.
+   record size at the first 2 bytes of every record.  The same
+   happens during the transfer of object files from VMS to Unix,
+   at least with UCX, the DEC implementation of TCP/IP.
 
-   The vms format repeats the length at bytes 2 & 3 of every record.
+   The VMS format repeats the size at bytes 2 & 3 of every record.
 
    On the first call (file_format == FF_UNKNOWN) we check if
    the first and the third byte pair (!) of the record match.
-   If they do it's an object file in an unix environment or with
-   wrong attributes (FF_FOREIGN), else we should be in a vms
+   If they do it's an object file in an Unix environment or with
+   wrong attributes (FF_FOREIGN), else we should be in a VMS
    environment where read() returns the record size (FF_NATIVE).
 
-   reading is always done in 2 steps.
-   first just the record header is read and the length extracted
-   by get_header_values
-   then the read buffer is adjusted and the remaining bytes are
-   read in.
+   Reading is always done in 2 steps:
+    1. first just the record header is read and the size extracted,
+    2. then the read buffer is adjusted and the remaining bytes are
+       read in.
+
+   All file I/O is done on even file positions.  */
 
-   all file i/o is always done on even file positions  */
+#define VMS_OBJECT_ADJUSTMENT  2
+
+static void
+maybe_adjust_record_pointer_for_object (bfd *abfd)
+{
+  /* Set the file format once for all on the first invocation.  */
+  if (PRIV (file_format) == FF_UNKNOWN)
+    {
+      if (PRIV (vms_rec)[0] == PRIV (vms_rec)[4]
+         && PRIV (vms_rec)[1] == PRIV (vms_rec)[5])
+       PRIV (file_format) = FF_FOREIGN;
+      else
+       PRIV (file_format) = FF_NATIVE;
+    }
+
+  /* The adjustment is needed only in an Unix environment.  */
+  if (PRIV (file_format) == FF_FOREIGN)
+    PRIV (vms_rec) += VMS_OBJECT_ADJUSTMENT;
+}
+
+/* Get first record from file and return the file type.  */
 
 int
-_bfd_vms_get_record (abfd)
-     bfd *abfd;
+_bfd_vms_get_first_record (bfd *abfd)
 {
-  int test_len, test_start, remaining;
-  unsigned char *vms_buf;
+  unsigned int test_len;
 
 #if VMS_DEBUG
-  vms_debug (8, "_bfd_vms_get_record\n");
+  vms_debug (8, "_bfd_vms_get_first_record\n");
 #endif
 
-  /* minimum is 6 bytes on Alpha
-     (2 bytes length, 2 bytes record id, 2 bytes length repeated)
-
-     on VAX there's no length information in the record
-     so start with OBJ_S_C_MAXRECSIZ  */
+  if (PRIV (is_vax))
+    test_len = 0;
+  else
+    /* Minimum is 6 bytes for objects (2 bytes size, 2 bytes record id,
+       2 bytes size repeated) and 12 bytes for images (4 bytes major id,
+       4 bytes minor id, 4 bytes length).  */
+    test_len = 12;
 
+  /* Size the main buffer.  */
   if (PRIV (buf_size) == 0)
     {
-      bfd_size_type amt;
-
-      if (PRIV (is_vax))
-       {
-         amt = OBJ_S_C_MAXRECSIZ;
-         PRIV (file_format) = FF_VAX;
-       }
-      else
-       amt = 6;
+      /* On VAX there's no size information in the record, so
+        start with OBJ_S_C_MAXRECSIZ.  */
+      bfd_size_type amt = (test_len ? test_len : OBJ_S_C_MAXRECSIZ);
       PRIV (vms_buf) = (unsigned char *) bfd_malloc (amt);
       PRIV (buf_size) = amt;
     }
 
-  vms_buf = PRIV (vms_buf);
-
-  if (vms_buf == 0)
-    return -1;
+  /* Initialize the record pointer.  */
+  PRIV (vms_rec) = PRIV (vms_buf);
 
-  switch (PRIV (file_format))
+  /* We only support modules on VAX.  */
+  if (PRIV (is_vax))
     {
-    case FF_UNKNOWN:
-    case FF_FOREIGN:
-      test_len = 6;                    /* probe 6 bytes */
-      test_start = 2;                  /* where the record starts */
-      break;
-
-    case FF_NATIVE:
-      test_len = 4;
-      test_start = 0;
-      break;
-
-    default:
-    case FF_VAX:
-      test_len = 0;
-      test_start = 0;
-      break;
+      if (vms_get_remaining_object_record (abfd, test_len) <= 0)
+       return FT_UNKNOWN;
+
+#if VMS_DEBUG
+      vms_debug (2, "file type is VAX module\n");
+#endif
+
+      return FT_MODULE;
     }
 
-  /* skip odd alignment byte  */
+  if (bfd_bread (PRIV (vms_buf), test_len, abfd) != test_len)
+    {
+      bfd_set_error (bfd_error_file_truncated);
+      return FT_UNKNOWN;
+    }
 
-  if (bfd_tell (abfd) & 1)
+  /* Is it an image?  */
+  if ((bfd_getl32 (PRIV (vms_rec)) == EIHD_S_K_MAJORID)
+      && (bfd_getl32 (PRIV (vms_rec) + 4) == EIHD_S_K_MINORID))
     {
-      if (bfd_bread (PRIV (vms_buf), (bfd_size_type) 1, abfd) != 1)
-       {
-         bfd_set_error (bfd_error_file_truncated);
-         return 0;
-       }
+      if (vms_get_remaining_image_record (abfd, test_len) <= 0)
+       return FT_UNKNOWN;
+
+#if VMS_DEBUG
+      vms_debug (2, "file type is image\n");
+#endif
+
+      return FT_IMAGE;
     }
 
-  /* read the record header on Alpha.  */
+  /* Assume it's a module and adjust record pointer if necessary.  */
+  maybe_adjust_record_pointer_for_object (abfd);
 
-  if ((test_len != 0)
-      && (bfd_bread (PRIV (vms_buf), (bfd_size_type) test_len, abfd)
-         != (bfd_size_type) test_len))
+  /* But is it really a module?  */
+  if (bfd_getl16 (PRIV (vms_rec)) <= EOBJ_S_C_MAXRECTYP
+      && bfd_getl16 (PRIV (vms_rec) + 2) <= EOBJ_S_C_MAXRECSIZ)
     {
-      bfd_set_error (bfd_error_file_truncated);
-      return 0;
+      if (vms_get_remaining_object_record (abfd, test_len) <= 0)
+       return FT_UNKNOWN;
+
+#if VMS_DEBUG
+      vms_debug (2, "file type is module\n");
+#endif
+
+      return FT_MODULE;
     }
 
-  /* check file format on first call  */
+#if VMS_DEBUG
+  vms_debug (2, "file type is unknown\n");
+#endif
+
+  return FT_UNKNOWN;
+}
 
-  if (PRIV (file_format) == FF_UNKNOWN)
-    {                                          /* record length repeats ? */
-      if (vms_buf[0] == vms_buf[4]
-         && vms_buf[1] == vms_buf[5])
+/* Implement step #1 of the object record reading procedure.
+   Return the record type or -1 on failure.  */
+
+int
+_bfd_vms_get_object_record (bfd *abfd)
+{
+  unsigned int test_len;
+  int type;
+
+#if VMS_DEBUG
+  vms_debug (8, "_bfd_vms_get_obj_record\n");
+#endif
+
+  if (PRIV (is_vax))
+    test_len = 0;
+  else
+    {
+      /* See _bfd_vms_get_first_record.  */
+      test_len = 6;
+
+      /* Skip odd alignment byte.  */
+      if (bfd_tell (abfd) & 1)
        {
-         PRIV (file_format) = FF_FOREIGN;      /* Y: foreign environment */
-         test_start = 2;
+         if (bfd_bread (PRIV (vms_buf), 1, abfd) != 1)
+           {
+             bfd_set_error (bfd_error_file_truncated);
+             return -1;
+           }
        }
-      else
+
+      /* Read the record header  */
+      if (bfd_bread (PRIV (vms_buf), test_len, abfd) != test_len)
        {
-         PRIV (file_format) = FF_NATIVE;       /* N: native environment */
-         test_start = 0;
+         bfd_set_error (bfd_error_file_truncated);
+         return -1;
        }
+
+      /* Reset the record pointer.  */
+      PRIV (vms_rec) = PRIV (vms_buf);
+      maybe_adjust_record_pointer_for_object (abfd);
     }
 
+  if (vms_get_remaining_object_record (abfd, test_len) <= 0)
+    return -1;
+
+  if (PRIV (is_vax))
+    type = PRIV (vms_rec) [0];
+  else
+    type = bfd_getl16 (PRIV (vms_rec));
+
+#if VMS_DEBUG
+  vms_debug (8, "_bfd_vms_get_obj_record: rec %p, size %d, type %d\n",
+             PRIV (vms_rec), PRIV (rec_size), type);
+#endif
+
+  return type;
+}
+
+/* Implement step #2 of the object record reading procedure.
+   Return the size of the record or 0 on failure.  */
+
+static int
+vms_get_remaining_object_record (bfd *abfd, int read_so_far)
+{
+#if VMS_DEBUG
+  vms_debug (8, "vms_get_remaining_obj_record\n");
+#endif
+
   if (PRIV (is_vax))
     {
-      PRIV (rec_length) = bfd_bread (vms_buf, (bfd_size_type) PRIV (buf_size),
-                                    abfd);
-      if (PRIV (rec_length) <= 0)
+      if (read_so_far != 0)
+        abort ();
+
+      PRIV (rec_size) = bfd_bread (PRIV (vms_buf), PRIV (buf_size), abfd);
+
+      if (PRIV (rec_size) <= 0)
        {
          bfd_set_error (bfd_error_file_truncated);
          return 0;
        }
-      PRIV (vms_rec) = vms_buf;
+
+      /* Reset the record pointer.  */
+      PRIV (vms_rec) = PRIV (vms_buf);
     }
-  else         /* Alpha  */
+  else
     {
-      /* extract vms record length  */
+      unsigned int to_read;
 
-      _bfd_vms_get_header_values (abfd, vms_buf + test_start, NULL,
-                                 &PRIV (rec_length));
+      /* Extract record size.  */
+      PRIV (rec_size) = bfd_getl16 (PRIV (vms_rec) + 2);
 
-      if (PRIV (rec_length) <= 0)
+      if (PRIV (rec_size) <= 0)
        {
          bfd_set_error (bfd_error_file_truncated);
          return 0;
        }
 
-      /* that's what the linker manual says  */
-
-      if (PRIV (rec_length) > EOBJ_S_C_MAXRECSIZ)
+      /* That's what the linker manual says.  */
+      if (PRIV (rec_size) > EOBJ_S_C_MAXRECSIZ)
        {
          bfd_set_error (bfd_error_file_truncated);
          return 0;
        }
 
-      /* adjust the buffer  */
+      /* Take into account object adjustment.  */
+      to_read = PRIV (rec_size);
+      if (PRIV (file_format) == FF_FOREIGN)
+       to_read += VMS_OBJECT_ADJUSTMENT;
 
-      if (PRIV (rec_length) > PRIV (buf_size))
+      /* Adjust the buffer.  */
+      if (to_read > PRIV (buf_size))
        {
-         PRIV (vms_buf) = ((unsigned char *)
-                           bfd_realloc (vms_buf,
-                                        (bfd_size_type) PRIV (rec_length)));
-         vms_buf = PRIV (vms_buf);
-         if (vms_buf == 0)
-           return -1;
-         PRIV (buf_size) = PRIV (rec_length);
+         PRIV (vms_buf)
+           = (unsigned char *) bfd_realloc (PRIV (vms_buf), to_read);
+         if (PRIV (vms_buf) == NULL)
+           return 0;
+         PRIV (buf_size) = to_read;
        }
 
-      /* read the remaining record  */
-
-      remaining = PRIV (rec_length) - test_len + test_start;
+      /* Read the remaining record.  */
+      to_read -= read_so_far;
 
 #if VMS_DEBUG
-      vms_debug (10, "bfd_bread remaining %d\n", remaining);
+      vms_debug (8, "vms_get_remaining_obj_record: to_read %d\n", to_read);
 #endif
-      if (bfd_bread (vms_buf + test_len, (bfd_size_type) remaining, abfd) !=
-         (bfd_size_type) remaining)
+
+      if (bfd_bread (PRIV (vms_buf) + read_so_far, to_read, abfd) != to_read)
        {
          bfd_set_error (bfd_error_file_truncated);
          return 0;
        }
-      PRIV (vms_rec) = vms_buf + test_start;
+
+      /* Reset the record pointer.  */
+      PRIV (vms_rec) = PRIV (vms_buf);
+      maybe_adjust_record_pointer_for_object (abfd);
     }
 
 #if VMS_DEBUG
-  vms_debug (11, "bfd_bread rec_length %d\n", PRIV (rec_length));
+  vms_debug (8, "vms_get_remaining_obj_record: size %d\n", PRIV (rec_size));
 #endif
 
-  return PRIV (rec_length);
+  return PRIV (rec_size);
 }
 
-/* get next vms record from file
-   update vms_rec and rec_length to new (remaining) values  */
+/* Implement step #2 of the record reading procedure for images.
+   Return the size of the record or 0 on failure.  */
 
-int
-_bfd_vms_next_record (abfd)
-     bfd *abfd;
+static int
+vms_get_remaining_image_record (bfd *abfd, int read_so_far)
 {
-#if VMS_DEBUG
-  vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n",
-             PRIV (rec_length), PRIV (rec_size));
-#endif
+  unsigned int to_read;
+  int remaining;
 
-  if (PRIV (rec_length) > 0)
-    {
-      PRIV (vms_rec) += PRIV (rec_size);
-    }
-  else
+  /* Extract record size.  */
+  PRIV (rec_size) = bfd_getl32 (PRIV (vms_rec) + EIHD_S_L_SIZE);
+
+  if (PRIV (rec_size) > PRIV (buf_size))
     {
-      if (_bfd_vms_get_record (abfd) <= 0)
-       return -1;
-    }
+      PRIV (vms_buf) = bfd_realloc (PRIV (vms_buf), PRIV (rec_size));
 
-  if (!PRIV (vms_rec) || !PRIV (vms_buf)
-      || PRIV (vms_rec) >= (PRIV (vms_buf) + PRIV (buf_size)))
-    return -1;
+      if (PRIV (vms_buf) == NULL)
+       {
+         bfd_set_error (bfd_error_no_memory);
+         return 0;
+       }
 
-  if (PRIV (is_vax))
-    {
-      PRIV (rec_type) = *(PRIV (vms_rec));
-      PRIV (rec_size) = PRIV (rec_length);
+      PRIV (buf_size) = PRIV (rec_size);
     }
-  else
+
+  /* Read the remaining record.  */
+  remaining = PRIV (rec_size) - read_so_far;
+  to_read = MIN (VMS_BLOCK_SIZE - read_so_far, remaining);
+
+  while (remaining > 0)
     {
-      _bfd_vms_get_header_values (abfd, PRIV (vms_rec), &PRIV (rec_type),
-                                 &PRIV (rec_size));
+      if (bfd_bread (PRIV (vms_buf) + read_so_far, to_read, abfd) != to_read)
+       {
+         bfd_set_error (bfd_error_file_truncated);
+         return 0;
+       }
+
+      read_so_far += to_read;
+      remaining -= to_read;
+
+      /* Eat trailing 0xff's.  */
+      if (remaining > 0)
+       while (PRIV (vms_buf) [read_so_far - 1] == 0xff)
+         read_so_far--;
+
+      to_read = MIN (VMS_BLOCK_SIZE, remaining);
     }
-  PRIV (rec_length) -= PRIV (rec_size);
 
-#if VMS_DEBUG
-  vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n",
-             PRIV (vms_rec), PRIV (rec_size), PRIV (rec_length),
-             PRIV (rec_type));
-#endif
+  /* Reset the record pointer.  */
+  PRIV (vms_rec) = PRIV (vms_buf);
 
-  return PRIV (rec_type);
+  return PRIV (rec_size);
 }
-\f
-/* Copy sized string (string with fixed length) to new allocated area
-   size is string length (size of record)  */
+
+/* Copy sized string (string with fixed size) to new allocated area
+   size is string size (size of record)  */
 
 char *
-_bfd_vms_save_sized_string (str, size)
-     unsigned char *str;
-     int size;
+_bfd_vms_save_sized_string (unsigned char *str, int size)
 {
   char *newstr = bfd_malloc ((bfd_size_type) size + 1);
 
   if (newstr == NULL)
-    return 0;
+    return NULL;
   strncpy (newstr, (char *) str, (size_t) size);
   newstr[size] = 0;
 
   return newstr;
 }
 
-/* Copy counted string (string with length at first byte) to new allocated area
-   ptr points to length byte on entry  */
+/* Copy counted string (string with size at first byte) to new allocated area
+   ptr points to size byte on entry  */
 
 char *
-_bfd_vms_save_counted_string (ptr)
-     unsigned char *ptr;
+_bfd_vms_save_counted_string (unsigned char *ptr)
 {
   int len = *ptr++;
 
   return _bfd_vms_save_sized_string (ptr, len);
 }
 \f
-/* stack routines for vms ETIR commands */
+/* Stack routines for vms ETIR commands.  */
 
-/* Push value and section index  */
+/* Push value and section index.  */
 
 void
-_bfd_vms_push (abfd, val, psect)
-     bfd *abfd;
-     uquad val;
-     int psect;
+_bfd_vms_push (bfd * abfd, uquad val, int psect)
 {
   static int last_psect;
 
 #if VMS_DEBUG
-  vms_debug (4, "<push %016lx(%d) at %d>\n", val, psect, PRIV (stackptr));
+  vms_debug (4, "<push %016lx (%d) at %d>\n", val, psect, PRIV (stackptr));
 #endif
 
   if (psect >= 0)
@@ -541,15 +588,12 @@ _bfd_vms_push (abfd, val, psect)
       (*_bfd_error_handler) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr));
       exit (1);
     }
-  return;
 }
 
-/* Pop value and section index  */
+/* Pop value and section index.  */
 
 uquad
-_bfd_vms_pop (abfd, psect)
-     bfd *abfd;
-     int *psect;
+_bfd_vms_pop (bfd * abfd, int *psect)
 {
   uquad value;
 
@@ -571,104 +615,24 @@ _bfd_vms_pop (abfd, psect)
   return value;
 }
 \f
-/* object file output functions */
-
-/* GAS tends to write sections in little chunks (bfd_set_section_contents)
-   which we can't use directly. So we save the little chunks in linked
-   lists (one per section) and write them later.  */
-
-/* Add a new vms_section structure to vms_section_table
-   - forward chaining -  */
-
-static vms_section *
-add_new_contents (abfd, section)
-     bfd *abfd;
-     sec_ptr section;
-{
-  vms_section *sptr, *newptr;
-
-  sptr = PRIV (vms_section_table)[section->index];
-  if (sptr != NULL)
-    return sptr;
-
-  newptr = (vms_section *) bfd_alloc (abfd,
-                                     (bfd_size_type) sizeof (vms_section));
-  if (newptr == (vms_section *) NULL)
-    return NULL;
-  newptr->contents = (unsigned char *) bfd_alloc (abfd, section->size);
-  if (newptr->contents == (unsigned char *) NULL)
-    return NULL;
-  newptr->offset = 0;
-  newptr->size = section->size;
-  newptr->next = 0;
-  PRIV (vms_section_table)[section->index] = newptr;
-  return newptr;
-}
-
-/* Save section data & offset to a vms_section structure
-   vms_section_table[] holds the vms_section chain.  */
-
-bfd_boolean
-_bfd_save_vms_section (abfd, section, data, offset, count)
-     bfd *abfd;
-     sec_ptr section;
-     const PTR data;
-     file_ptr offset;
-     bfd_size_type count;
-{
-  vms_section *sptr;
-
-  if (section->index >= VMS_SECTION_COUNT)
-    {
-      bfd_set_error (bfd_error_nonrepresentable_section);
-      return FALSE;
-    }
-  if (count == (bfd_size_type)0)
-    return TRUE;
-  sptr = add_new_contents (abfd, section);
-  if (sptr == NULL)
-    return FALSE;
-  memcpy (sptr->contents + offset, data, (size_t) count);
-
-  return TRUE;
-}
-
-/* Get vms_section pointer to saved contents for section # index  */
-
-vms_section *
-_bfd_get_vms_section (abfd, index)
-     bfd *abfd;
-     int index;
-{
-  if (index >=  VMS_SECTION_COUNT)
-    {
-      bfd_set_error (bfd_error_nonrepresentable_section);
-      return NULL;
-    }
-  return PRIV (vms_section_table)[index];
-}
-\f
-/* Object output routines  */
+/* Object output routines.   */
 
 /* Begin new record or record header
    write 2 bytes rectype
    write 2 bytes record length (filled in at flush)
-   write 2 bytes header type (ommitted if rechead == -1)  */
+   write 2 bytes header type (ommitted if rechead == -1).  */
 
 void
-_bfd_vms_output_begin (abfd, rectype, rechead)
-     bfd *abfd;
-     int rectype;
-     int rechead;
+_bfd_vms_output_begin (bfd * abfd, int rectype, int rechead)
 {
 #if VMS_DEBUG
-  vms_debug (6, "_bfd_vms_output_begin(type %d, head %d)\n", rectype,
+  vms_debug (6, "_bfd_vms_output_begin (type %d, head %d)\n", rectype,
              rechead);
 #endif
 
   _bfd_vms_output_short (abfd, (unsigned int) rectype);
 
-  /* save current output position to fill in length later  */
+  /* Save current output position to fill in length later.   */
 
   if (PRIV (push_level) > 0)
     PRIV (length_pos) = PRIV (output_size);
@@ -678,52 +642,45 @@ _bfd_vms_output_begin (abfd, rectype, rechead)
              PRIV (length_pos));
 #endif
 
-  _bfd_vms_output_short (abfd, 0);             /* placeholder for length */
+  /* Placeholder for length.  */
+  _bfd_vms_output_short (abfd, 0);
 
   if (rechead != -1)
     _bfd_vms_output_short (abfd, (unsigned int) rechead);
-
-  return;
 }
 
-/* Set record/subrecord alignment  */
+/* Set record/subrecord alignment  */
 
 void
-_bfd_vms_output_alignment (abfd, alignto)
-     bfd *abfd;
-     int alignto;
+_bfd_vms_output_alignment (bfd * abfd, int alignto)
 {
 #if VMS_DEBUG
-  vms_debug (6, "_bfd_vms_output_alignment(%d)\n", alignto);
+  vms_debug (6, "_bfd_vms_output_alignment (%d)\n", alignto);
 #endif
 
   PRIV (output_alignment) = alignto;
-  return;
 }
 
-/* Prepare for subrecord fields  */
+/* Prepare for subrecord fields.  */
 
 void
-_bfd_vms_output_push (abfd)
-     bfd *abfd;
+_bfd_vms_output_push (bfd * abfd)
 {
 #if VMS_DEBUG
-  vms_debug (6, "vms_output_push(pushed_size = %d)\n", PRIV (output_size));
+  vms_debug (6, "vms_output_push (pushed_size = %d)\n", PRIV (output_size));
 #endif
 
   PRIV (push_level)++;
   PRIV (pushed_size) = PRIV (output_size);
-  return;
 }
 
-/* End of subrecord fields  */
+/* End of subrecord fields  */
 
 void
-_bfd_vms_output_pop (abfd)
-     bfd *abfd;
+_bfd_vms_output_pop (bfd * abfd)
 {
 #if VMS_DEBUG
-  vms_debug (6, "vms_output_pop(pushed_size = %d)\n", PRIV (pushed_size));
+  vms_debug (6, "vms_output_pop (pushed_size = %d)\n", PRIV (pushed_size));
 #endif
 
   _bfd_vms_output_flush (abfd);
@@ -735,21 +692,19 @@ _bfd_vms_output_pop (abfd)
 
   PRIV (pushed_size) = 0;
   PRIV (push_level)--;
-  return;
 }
 
-/* Flush unwritten output, ends current record  */
+/* Flush unwritten output, ends current record.  */
 
 void
-_bfd_vms_output_flush (abfd)
-     bfd *abfd;
+_bfd_vms_output_flush (bfd * abfd)
 {
   int real_size = PRIV (output_size);
   int aligncount;
   int length;
 
 #if VMS_DEBUG
-  vms_debug (6, "_bfd_vms_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n",
+  vms_debug (6, "_bfd_vms_output_flush (real_size = %d, pushed_size %d at lenpos %d)\n",
              real_size, PRIV (pushed_size), PRIV (length_pos));
 #endif
 
@@ -773,19 +728,17 @@ _bfd_vms_output_flush (abfd)
       length++;
     }
 
-  /* put length to buffer  */
+  /* Put length to buffer.  */
   PRIV (output_size) = PRIV (length_pos);
   _bfd_vms_output_short (abfd, (unsigned int) length);
 
   if (PRIV (push_level) == 0)
     {
-#ifndef VMS
-       /* write length first, see FF_FOREIGN in the input routines */
-      fwrite (PRIV (output_buf) + 2, 2, 1, (FILE *) abfd->iostream);
-#endif
-      fwrite (PRIV (output_buf), (size_t) real_size, 1,
-             (FILE *) abfd->iostream);
-
+      /* File is open in undefined (UDF) format on VMS, but ultimately will be
+        converted to variable length (VAR) format.  VAR format has a length
+        word first which must be explicitly output in UDF format.  */
+      bfd_bwrite (PRIV (output_buf) + 2, 2, abfd);
+      bfd_bwrite (PRIV (output_buf), (size_t) real_size, abfd);
       PRIV (output_size) = 0;
     }
   else
@@ -793,63 +746,51 @@ _bfd_vms_output_flush (abfd)
       PRIV (output_size) = real_size;
       PRIV (pushed_size) = PRIV (output_size);
     }
-
-  return;
 }
 
-/* End record output  */
+/* End record output  */
 
 void
-_bfd_vms_output_end (abfd)
-     bfd *abfd;
+_bfd_vms_output_end (bfd * abfd)
 {
 #if VMS_DEBUG
   vms_debug (6, "_bfd_vms_output_end\n");
 #endif
 
   _bfd_vms_output_flush (abfd);
-
-  return;
 }
 
-/* check remaining buffer size
+/* Check remaining buffer size
 
-   return what's left.  */
+   Return what's left.  */
 
 int
-_bfd_vms_output_check (abfd, size)
-    bfd *abfd;
-    int size;
+_bfd_vms_output_check (bfd * abfd, int size)
 {
 #if VMS_DEBUG
-  vms_debug (6, "_bfd_vms_output_check(%d)\n", size);
+  vms_debug (6, "_bfd_vms_output_check (%d)\n", size);
 #endif
 
   return (MAX_OUTREC_SIZE - (PRIV (output_size) + size + MIN_OUTREC_LUFT));
 }
 
-/* Output byte (8 bit) value  */
+/* Output byte (8 bit) value.  */
 
 void
-_bfd_vms_output_byte (abfd, value)
-     bfd *abfd;
-     unsigned int value;
+_bfd_vms_output_byte (bfd * abfd, unsigned int value)
 {
 #if VMS_DEBUG
-  vms_debug (6, "_bfd_vms_output_byte(%02x)\n", value);
+  vms_debug (6, "_bfd_vms_output_byte (%02x)\n", value);
 #endif
 
   bfd_put_8 (abfd, value & 0xff, PRIV (output_buf) + PRIV (output_size));
   PRIV (output_size) += 1;
-  return;
 }
 
-/* Output short (16 bit) value  */
+/* Output short (16 bit) value.  */
 
 void
-_bfd_vms_output_short (abfd, value)
-     bfd *abfd;
-     unsigned int value;
+_bfd_vms_output_short (bfd * abfd, unsigned int value)
 {
 #if VMS_DEBUG
   vms_debug (6, "_bfd_vms_output_short (%04x)\n", value);
@@ -858,15 +799,12 @@ _bfd_vms_output_short (abfd, value)
   bfd_put_16 (abfd, (bfd_vma) value & 0xffff,
              PRIV (output_buf) + PRIV (output_size));
   PRIV (output_size) += 2;
-  return;
 }
 
-/* Output long (32 bit) value  */
+/* Output long (32 bit) value.  */
 
 void
-_bfd_vms_output_long (abfd, value)
-     bfd *abfd;
-     unsigned long value;
+_bfd_vms_output_long (bfd * abfd, unsigned long value)
 {
 #if VMS_DEBUG
   vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value);
@@ -874,36 +812,30 @@ _bfd_vms_output_long (abfd, value)
 
   bfd_put_32 (abfd, (bfd_vma) value, PRIV (output_buf) + PRIV (output_size));
   PRIV (output_size) += 4;
-  return;
 }
 
-/* Output quad (64 bit) value  */
+/* Output quad (64 bit) value.  */
 
 void
-_bfd_vms_output_quad (abfd, value)
-     bfd *abfd;
-     uquad value;
+_bfd_vms_output_quad (bfd * abfd, uquad value)
 {
 #if VMS_DEBUG
-  vms_debug (6, "_bfd_vms_output_quad(%016lx)\n", value);
+  vms_debug (6, "_bfd_vms_output_quad (%016lx)\n", value);
 #endif
 
   bfd_put_64(abfd, value, PRIV (output_buf) + PRIV (output_size));
   PRIV (output_size) += 8;
-  return;
 }
 
-/* Output c-string as counted string  */
+/* Output c-string as counted string.  */
 
 void
-_bfd_vms_output_counted (abfd, value)
-     bfd *abfd;
-     char *value;
+_bfd_vms_output_counted (bfd * abfd, char *value)
 {
-int len;
+  int len;
 
 #if VMS_DEBUG
-  vms_debug (6, "_bfd_vms_output_counted(%s)\n", value);
+  vms_debug (6, "_bfd_vms_output_counted (%s)\n", value);
 #endif
 
   len = strlen (value);
@@ -918,19 +850,18 @@ int len;
       return;
     }
   _bfd_vms_output_byte (abfd, (unsigned int) len & 0xff);
-  _bfd_vms_output_dump (abfd, (unsigned char *)value, len);
+  _bfd_vms_output_dump (abfd, (unsigned char *) value, len);
 }
 
-/* Output character area  */
+/* Output character area.  */
 
 void
-_bfd_vms_output_dump (abfd, data, length)
-     bfd *abfd;
-     unsigned char *data;
-     int length;
+_bfd_vms_output_dump (bfd * abfd,
+                     unsigned char *data,
+                     int length)
 {
 #if VMS_DEBUG
-  vms_debug (6, "_bfd_vms_output_dump(%d)\n", length);
+  vms_debug (6, "_bfd_vms_output_dump (%d)\n", length);
 #endif
 
   if (length == 0)
@@ -938,40 +869,34 @@ _bfd_vms_output_dump (abfd, data, length)
 
   memcpy (PRIV (output_buf) + PRIV (output_size), data, (size_t) length);
   PRIV (output_size) += length;
-
-  return;
 }
 
-/* Output count bytes of value  */
+/* Output count bytes of value.  */
 
 void
-_bfd_vms_output_fill (abfd, value, count)
-     bfd *abfd;
-     int value;
-     int count;
+_bfd_vms_output_fill (bfd * abfd,
+                     int value,
+                     int count)
 {
 #if VMS_DEBUG
-  vms_debug (6, "_bfd_vms_output_fill(val %02x times %d)\n", value, count);
+  vms_debug (6, "_bfd_vms_output_fill (val %02x times %d)\n", value, count);
 #endif
 
   if (count == 0)
     return;
   memset (PRIV (output_buf) + PRIV (output_size), value, (size_t) count);
   PRIV (output_size) += count;
-
-  return;
 }
 
-/* this hash routine borrowed from GNU-EMACS, and strengthened slightly  ERY*/
+/* This hash routine borrowed from GNU-EMACS, and strengthened slightly.  ERY.  */
 
 static int
-hash_string (ptr)
-     const char *ptr;
+hash_string (const char *ptr)
 {
-  register const unsigned char *p = (unsigned char *) ptr;
-  register const unsigned char *end = p + strlen (ptr);
-  register unsigned char c;
-  register int hash = 0;
+  const unsigned char *p = (unsigned char *) ptr;
+  const unsigned char *end = p + strlen (ptr);
+  unsigned char c;
+  int hash = 0;
 
   while (p != end)
     {
@@ -984,12 +909,9 @@ hash_string (ptr)
 /* Generate a length-hashed VMS symbol name (limited to maxlen chars).  */
 
 char *
-_bfd_vms_length_hash_symbol (abfd, in, maxlen)
-     bfd *abfd;
-     const char *in;
-     int maxlen;
+_bfd_vms_length_hash_symbol (bfd * abfd, const char *in, int maxlen)
 {
-  long int result;
+  unsigned long result;
   int in_len;
   char *new_name;
   const char *old_name;
@@ -998,16 +920,16 @@ _bfd_vms_length_hash_symbol (abfd, in, maxlen)
   char *out = outbuf;
 
 #if VMS_DEBUG
-  vms_debug(4, "_bfd_vms_length_hash_symbol \"%s\"\n", in);
+  vms_debug (4, "_bfd_vms_length_hash_symbol \"%s\"\n", in);
 #endif
 
   if (maxlen > EOBJ_S_C_SYMSIZ)
     maxlen = EOBJ_S_C_SYMSIZ;
 
-  new_name = out;              /* save this for later.  */
+  /* Save this for later.  */
+  new_name = out;
 
   /* We may need to truncate the symbol, save the hash for later.  */
-
   in_len = strlen (in);
 
   result = (in_len > maxlen) ? hash_string (in) : 0;
@@ -1015,11 +937,8 @@ _bfd_vms_length_hash_symbol (abfd, in, maxlen)
   old_name = in;
 
   /* Do the length checking.  */
-
   if (in_len <= maxlen)
-    {
-      i = in_len;
-    }
+    i = in_len;
   else
     {
       if (PRIV (flag_hash_long_names))
@@ -1039,7 +958,7 @@ _bfd_vms_length_hash_symbol (abfd, in, maxlen)
     *out = 0;
 
 #if VMS_DEBUG
-  vms_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
+  vms_debug (4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
 #endif
 
   if (in_len > maxlen
@@ -1053,9 +972,7 @@ _bfd_vms_length_hash_symbol (abfd, in, maxlen)
 /* Allocate and initialize a new symbol.  */
 
 static asymbol *
-new_symbol (abfd, name)
-     bfd *abfd;
-     char *name;
+new_symbol (bfd * abfd, char *name)
 {
   asymbol *symbol;
 
@@ -1067,7 +984,7 @@ new_symbol (abfd, name)
   if (symbol == 0)
     return symbol;
   symbol->name = name;
-  symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
+  symbol->section = (asection *)(unsigned long)-1;
 
   return symbol;
 }
@@ -1075,9 +992,7 @@ new_symbol (abfd, name)
 /* Allocate and enter a new private symbol.  */
 
 vms_symbol_entry *
-_bfd_vms_enter_symbol (abfd, name)
-     bfd *abfd;
-     char *name;
+_bfd_vms_enter_symbol (bfd * abfd, char *name)
 {
   vms_symbol_entry *entry;
 
This page took 0.050055 seconds and 4 git commands to generate.