Use size_t rather than bfd_size_type
[deliverable/binutils-gdb.git] / bfd / vms-misc.c
index be6d5094b17541f235489d8c7ee1d051196c8108..94a13c736b7c858004e732b71e6045cab6b23611 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, 2010  Free Software Foundation, Inc.
+   Copyright (C) 1996-2016 Free Software Foundation, Inc.
 
    Miscellaneous functions.
 
 #include "safe-ctype.h"
 
 #ifdef VMS
-#if defined(__GNUC__) && !defined(globalref)
-#define globalref extern
-#endif
+#define __NEW_STARLET
 #include <rms.h>
 #include <unixlib.h>
+#include <gen64def.h>
 #include <starlet.h>
 #define RME$C_SETRFM 0x00000001
 #include <unistd.h>
@@ -349,7 +347,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;
 
@@ -367,13 +365,13 @@ _bfd_vms_output_counted (struct vms_rec_wr *recwr, char *value)
       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));
 
@@ -402,8 +400,8 @@ _bfd_vms_output_fill (struct vms_rec_wr *recwr, int value, int count)
    using undocumented system call sys$modify().
    Pure VMS version.  */
 
-void
-_bfd_vms_convert_to_var (char * vms_filename)
+static void
+vms_convert_to_var (char * vms_filename)
 {
   struct FAB fab = cc$rms_fab;
 
@@ -434,8 +432,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;
@@ -497,19 +495,19 @@ 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;
@@ -526,36 +524,109 @@ vms_get_module_name (const char *filename, bfd_boolean upcase)
   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 lo - off;
+  /* Return 0 in case of underflow.  */
+  if (hi == 0 && lo < VMS_TIME_OFFSET)
+    return 0;
+
+  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.  */
@@ -568,3 +639,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.026597 seconds and 4 git commands to generate.