gdb: defer commit resume until all available events are consumed
[deliverable/binutils-gdb.git] / bfd / vms-misc.c
index 67cc25adc065efa5d593fcdd67fb6348cd0dccf1..d040c79de16ce761e5705eefe951d97160657fd6 100644 (file)
@@ -1,7 +1,6 @@
 /* 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, 2005,
-   2007, 2008, 2009  Free Software Foundation, Inc.
+   Copyright (C) 1996-2020 Free Software Foundation, Inc.
 
    Miscellaneous functions.
 
 #include "safe-ctype.h"
 
 #ifdef VMS
+#define __NEW_STARLET
 #include <rms.h>
 #include <unixlib.h>
+#include <gen64def.h>
 #include <starlet.h>
 #define RME$C_SETRFM 0x00000001
 #include <unistd.h>
@@ -134,31 +135,39 @@ _bfd_hexdump (int level, unsigned char *ptr, int size, int offset)
 #endif
 \f
 
-/* Copy sized string (string with fixed size) to new allocated area
-   size is string size (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 (unsigned char *str, int size)
+_bfd_vms_save_sized_string (bfd *abfd, unsigned char *str, size_t size)
 {
-  char *newstr = bfd_malloc ((bfd_size_type) size + 1);
+  char *newstr;
 
+  if (size == (size_t) -1)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return NULL;
+    }
+  newstr = bfd_alloc (abfd, size + 1);
   if (newstr == NULL)
     return NULL;
-  memcpy (newstr, (char *) str, (size_t) size);
+  memcpy (newstr, str, size);
   newstr[size] = 0;
 
   return newstr;
 }
 
-/* Copy counted string (string with size at first byte) to new allocated area
-   ptr points to size 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 (unsigned char *ptr)
+_bfd_vms_save_counted_string (bfd *abfd, unsigned char *ptr, size_t maxlen)
 {
-  int len = *ptr++;
+  unsigned int len = *ptr++;
 
-  return _bfd_vms_save_sized_string (ptr, len);
+  if (len > maxlen)
+    return NULL;
+  return _bfd_vms_save_sized_string (abfd, ptr, len);
 }
 \f
 /* Object output routines.   */
@@ -249,7 +258,7 @@ _bfd_vms_output_end_subrec (struct vms_rec_wr *recwr)
 
   /* Put length to buffer.  */
   bfd_putl16 ((bfd_vma) (recwr->size - recwr->subrec_offset),
-              recwr->buf + recwr->subrec_offset + 2);
+             recwr->buf + recwr->subrec_offset + 2);
 
   /* Close the subrecord.  */
   recwr->subrec_offset = 0;
@@ -346,7 +355,7 @@ _bfd_vms_output_quad (struct vms_rec_wr *recwr, bfd_vma value)
 /* Output c-string as counted string.  */
 
 void
-_bfd_vms_output_counted (struct vms_rec_wr *recwr, char *value)
+_bfd_vms_output_counted (struct vms_rec_wr *recwr, const char *value)
 {
   int len;
 
@@ -355,22 +364,22 @@ _bfd_vms_output_counted (struct vms_rec_wr *recwr, char *value)
   len = strlen (value);
   if (len == 0)
     {
-      (*_bfd_error_handler) (_("_bfd_vms_output_counted called with zero bytes"));
+      _bfd_error_handler (_("_bfd_vms_output_counted called with zero bytes"));
       return;
     }
   if (len > 255)
     {
-      (*_bfd_error_handler) (_("_bfd_vms_output_counted called with too many bytes"));
+      _bfd_error_handler (_("_bfd_vms_output_counted called with too many bytes"));
       return;
     }
   _bfd_vms_output_byte (recwr, (unsigned int) len & 0xff);
-  _bfd_vms_output_dump (recwr, (unsigned char *) value, len);
+  _bfd_vms_output_dump (recwr, (const unsigned char *)value, len);
 }
 
 /* Output character area.  */
 
 void
-_bfd_vms_output_dump (struct vms_rec_wr *recwr, unsigned char *data, int len)
+_bfd_vms_output_dump (struct vms_rec_wr *recwr, const unsigned char *data, int len)
 {
   vms_debug2 ((6, "_bfd_vms_output_dump (%d)\n", len));
 
@@ -400,7 +409,7 @@ _bfd_vms_output_fill (struct vms_rec_wr *recwr, int value, int count)
    Pure VMS version.  */
 
 static void
-vms_convert_to_var (char *vms_filename)
+vms_convert_to_var (char * vms_filename)
 {
   struct FAB fab = cc$rms_fab;
 
@@ -431,8 +440,8 @@ vms_convert_to_var_1 (char *filename, int type)
    using undocumented system call sys$modify().
    Unix filename version.  */
 
-static int
-vms_convert_to_var_unix_filename (const char *unix_filename)
+int
+_bfd_vms_convert_to_var_unix_filename (const char *unix_filename)
 {
   if (decc$to_vms (unix_filename, &vms_convert_to_var_1, 0, 1) != 1)
     return FALSE;
@@ -494,65 +503,138 @@ vms_get_module_name (const char *filename, bfd_boolean upcase)
     fout++;
   else
     fout = filename;
-      
+
   /* Strip UNIX path.  */
   fptr = strrchr (fout, '/');
   if (fptr != NULL)
     fout = fptr + 1;
-  
+
   fname = strdup (fout);
 
   /* Strip suffix.  */
   fptr = strrchr (fname, '.');
   if (fptr != 0)
     *fptr = 0;
-  
+
   /* Convert to upper case and truncate at 31 characters.
      (VMS object file format restricts module name length to 31).  */
   fptr = fname;
   for (fptr = fname; *fptr != 0; fptr++)
     {
       if (*fptr == ';' || (fptr - fname) >= 31)
-        {
-          *fptr = 0;
-          break;
-        }
+       {
+         *fptr = 0;
+         break;
+       }
       if (upcase)
-        *fptr = TOUPPER (*fptr);
+       *fptr = TOUPPER (*fptr);
     }
   return fname;
 }
 
-/* Convert a raw VMS time to a unix time.  */
+/* Compared to usual UNIX time_t, VMS time has less limits:
+   -  64 bit (63 bits in fact as the MSB must be 0)
+   -  100ns granularity
+   -  epoch is Nov 17, 1858.
+   Here has the constants and the routines used to convert VMS from/to UNIX time.
+   The conversion routines don't assume 64 bits arithmetic.
+
+   Here we assume that the definition of time_t is the UNIX one, ie integer
+   type, expressing seconds since the epoch.  */
+
+/* UNIX time granularity for VMS, ie 1s / 100ns.  */
+#define VMS_TIME_FACTOR 10000000
+
+/* Number of seconds since VMS epoch of the UNIX epoch.  */
+#define VMS_TIME_OFFSET 3506716800U
+
+/* Convert a VMS time to a unix time.  */
 
 time_t
 vms_time_to_time_t (unsigned int hi, unsigned int lo)
 {
-  const unsigned int off = 3506716800U;
-  const unsigned int factor = 10000000;
   unsigned int tmp;
   unsigned int rlo;
   int i;
+  time_t res;
 
   /* First convert to seconds.  */
-  tmp = hi % factor;
-  hi = hi / factor;
+  tmp = hi % VMS_TIME_FACTOR;
+  hi = hi / VMS_TIME_FACTOR;
   rlo = 0;
   for (i = 0; i < 4; i++)
     {
       tmp = (tmp << 8) | (lo >> 24);
       lo <<= 8;
 
-      rlo = (rlo << 8) | (tmp / factor);
-      tmp %= factor;
+      rlo = (rlo << 8) | (tmp / VMS_TIME_FACTOR);
+      tmp %= VMS_TIME_FACTOR;
     }
   lo = rlo;
 
   /* Return 0 in case of overflow.  */
-  if (lo > off && hi > 1)
+  if (hi > 1
+      || (hi == 1 && lo >= VMS_TIME_OFFSET))
+    return 0;
+
+  /* Return 0 in case of underflow.  */
+  if (hi == 0 && lo < VMS_TIME_OFFSET)
     return 0;
 
-  return lo - off;
+  res = lo - VMS_TIME_OFFSET;
+  if (res <= 0)
+    return 0;
+  return res;
+}
+
+/* Convert a time_t to a VMS time.  */
+
+void
+vms_time_t_to_vms_time (time_t ut, unsigned int *hi, unsigned int *lo)
+{
+  unsigned short val[4];
+  unsigned short tmp[4];
+  unsigned int carry;
+  int i;
+
+  /* Put into val.  */
+  val[0] = ut & 0xffff;
+  val[1] = (ut >> 16) & 0xffff;
+  val[2] = sizeof (ut) > 4 ? (ut >> 32) & 0xffff : 0;
+  val[3] = sizeof (ut) > 4 ? (ut >> 48) & 0xffff : 0;
+
+  /* Add offset.  */
+  tmp[0] = VMS_TIME_OFFSET & 0xffff;
+  tmp[1] = VMS_TIME_OFFSET >> 16;
+  tmp[2] = 0;
+  tmp[3] = 0;
+  carry = 0;
+  for (i = 0; i < 4; i++)
+    {
+      carry += tmp[i] + val[i];
+      val[i] = carry & 0xffff;
+      carry = carry >> 16;
+    }
+
+  /* Multiply by factor, well first by 10000 and then by 1000.  */
+  carry = 0;
+  for (i = 0; i < 4; i++)
+    {
+      carry += val[i] * 10000;
+      val[i] = carry & 0xffff;
+      carry = carry >> 16;
+    }
+  carry = 0;
+  for (i = 0; i < 4; i++)
+    {
+      carry += val[i] * 1000;
+      val[i] = carry & 0xffff;
+      carry = carry >> 16;
+    }
+
+  /* Write the result.  */
+  *lo = val[0] | (val[1] << 16);
+  *hi = val[2] | (val[3] << 16);
 }
 
 /* Convert a raw (stored in a buffer) VMS time to a unix time.  */
@@ -565,3 +647,32 @@ vms_rawtime_to_time_t (unsigned char *buf)
 
   return vms_time_to_time_t (hi, lo);
 }
+
+void
+vms_get_time (unsigned int *hi, unsigned int *lo)
+{
+#ifdef VMS
+  struct _generic_64 t;
+
+  sys$gettim (&t);
+  *lo = t.gen64$q_quadword;
+  *hi = t.gen64$q_quadword >> 32;
+#else
+  time_t t;
+
+  time (&t);
+  vms_time_t_to_vms_time (t, hi, lo);
+#endif
+}
+
+/* Get the current time into a raw buffer BUF.  */
+
+void
+vms_raw_get_time (unsigned char *buf)
+{
+  unsigned int hi, lo;
+
+  vms_get_time (&hi, &lo);
+  bfd_putl32 (lo, buf + 0);
+  bfd_putl32 (hi, buf + 4);
+}
This page took 0.027438 seconds and 4 git commands to generate.