summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Gingold <gingold@adacore.com>2010-05-27 13:43:44 +0000
committerTristan Gingold <gingold@adacore.com>2010-05-27 13:43:44 +0000
commit953b49ed1301bc695c44c9981bc3739c4f60a6af (patch)
tree9fed5560ed19299d8fe69bcc6f7e88d7dd92f582
parentc3a6ea62fc4464995f8f62c41676b2eda161967e (diff)
downloadbinutils-gdb-953b49ed1301bc695c44c9981bc3739c4f60a6af.tar.gz
2010-05-27 Tristan Gingold <gingold@adacore.com>
* vms-misc.c: Define __NEW_STARLET. Remove trailing spaces. (VMS_TIME_FACTOR, VMS_TIME_OFFSET): New macros. (vms_time_to_time_t): Use them instead of local const. (vms_time_t_to_vms_time): New function. (vms_get_time): Likewise. (vms_raw_get_time): Likewise. * vms.h (vms_time_t_to_vms_time): New declaration. (vms_get_time): Likewise. (vms_raw_get_time): Likewise.
-rw-r--r--bfd/ChangeLog12
-rw-r--r--bfd/vms-misc.c131
-rw-r--r--bfd/vms.h3
3 files changed, 131 insertions, 15 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 471d1f31f3e..05a16563241 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,15 @@
+2010-05-27 Tristan Gingold <gingold@adacore.com>
+
+ * vms-misc.c: Define __NEW_STARLET. Remove trailing spaces.
+ (VMS_TIME_FACTOR, VMS_TIME_OFFSET): New macros.
+ (vms_time_to_time_t): Use them instead of local const.
+ (vms_time_t_to_vms_time): New function.
+ (vms_get_time): Likewise.
+ (vms_raw_get_time): Likewise.
+ * vms.h (vms_time_t_to_vms_time): New declaration.
+ (vms_get_time): Likewise.
+ (vms_raw_get_time): Likewise.
+
2010-05-26 Tristan Gingold <gingold@adacore.com>
* vms-alpha.c: Update comments.
diff --git a/bfd/vms-misc.c b/bfd/vms-misc.c
index be6d5094b17..c7bd3468370 100644
--- a/bfd/vms-misc.c
+++ b/bfd/vms-misc.c
@@ -33,11 +33,10 @@
#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>
@@ -497,19 +496,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 +525,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. */
+
+/* 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;
/* 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 (lo > VMS_TIME_OFFSET && hi > 1)
+ return 0;
+
+ /* Return 0 in case of underflow. */
+ if (lo < VMS_TIME_OFFSET)
return 0;
- return lo - off;
+ return lo - VMS_TIME_OFFSET;
+}
+
+/* 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;
+ if (sizeof (ut) > 4)
+ {
+ val[2] = (ut >> 32) & 0xffff;
+ val[3] = (ut >> 48) & 0xffff;
+ }
+ else
+ {
+ val[2] = 0;
+ val[3] = 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 +640,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);
+}
diff --git a/bfd/vms.h b/bfd/vms.h
index 762c8b53984..c95487d5d4d 100644
--- a/bfd/vms.h
+++ b/bfd/vms.h
@@ -115,6 +115,9 @@ extern char * vms_get_module_name (const char *, bfd_boolean);
extern unsigned char *get_vms_time_string (void);
extern time_t vms_time_to_time_t (unsigned int hi, unsigned int lo);
extern time_t vms_rawtime_to_time_t (unsigned char *);
+extern void vms_time_t_to_vms_time (time_t ut, unsigned int *hi, unsigned int *lo);
+extern void vms_get_time (unsigned int *hi, unsigned int *lo);
+extern void vms_raw_get_time (unsigned char *buf);
extern char * _bfd_vms_save_sized_string (unsigned char *, int);
extern char * _bfd_vms_save_counted_string (unsigned char *);