diff options
author | Arnold D. Robbins <arnold@skeeve.com> | 2010-07-16 13:09:56 +0300 |
---|---|---|
committer | Arnold D. Robbins <arnold@skeeve.com> | 2010-07-16 13:09:56 +0300 |
commit | bc70de7b3302d5a81515b901cae376b8b51d2004 (patch) | |
tree | d36d6743e65697f6923b79d0ea8f9f9bf4ef7398 /vms/vms_misc.c | |
parent | b9e4a1fd4c8c8753ab8a9887bab55f03efe1e3e2 (diff) | |
download | egawk-bc70de7b3302d5a81515b901cae376b8b51d2004.tar.gz egawk-bc70de7b3302d5a81515b901cae376b8b51d2004.tar.bz2 egawk-bc70de7b3302d5a81515b901cae376b8b51d2004.zip |
Move to gawk-3.1.0.
Diffstat (limited to 'vms/vms_misc.c')
-rw-r--r-- | vms/vms_misc.c | 167 |
1 files changed, 161 insertions, 6 deletions
diff --git a/vms/vms_misc.c b/vms/vms_misc.c index 1b1a2239..439790d5 100644 --- a/vms/vms_misc.c +++ b/vms/vms_misc.c @@ -1,6 +1,6 @@ /* vms_misc.c -- sustitute code for missing/different run-time library routines. - Copyright (C) 1991-1993, 1996, 1997 the Free Software Foundation, Inc. + Copyright (C) 1991-1993, 1996-1997, 2001 the Free Software Foundation, Inc. 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 @@ -18,6 +18,7 @@ #define creat creat_dummy /* one of gcc-vms's headers has bad prototype */ #include "awk.h" +#include "vms.h" #undef creat #include <fab.h> #ifndef O_RDONLY @@ -111,6 +112,15 @@ vms_open( const char *name, int mode, ... ) { int result; + if (STREQN(name, "/dev/", 5)) { + /* (this used to be handled in vms_devopen(), but that is only + called when opening files for output; we want it for input too) */ + if (strcmp(name + 5, "null") == 0) /* /dev/null -> NL: */ + name = "NL:"; + else if (strcmp(name + 5, "tty") == 0) /* /dev/tty -> TT: */ + name = "TT:"; + } + if (mode == (O_WRONLY|O_CREAT|O_TRUNC)) { /* explicitly force stream_lf record format to override DECC$SHR's defaulting of RFM to earlier file version's when one is present */ @@ -146,11 +156,7 @@ vms_devopen( const char *name, int mode ) { FILE *file = NULL; - if (STREQ(name, "/dev/null")) - return open("NL:", mode, 0); /* "/dev/null" => "NL:" */ - else if (STREQ(name, "/dev/tty")) - return open("TT:", mode, 0); /* "/dev/tty" => "TT:" */ - else if (strncasecmp(name, "SYS$", 4) == 0) { + if (strncasecmp(name, "SYS$", 4) == 0) { name += 4; /* skip "SYS$" */ if (strncasecmp(name, "INPUT", 5) == 0 && (mode & O_WRONLY) == 0) file = stdin, name += 5; @@ -165,6 +171,41 @@ vms_devopen( const char *name, int mode ) } +#define VMS_UNITS_PER_SECOND 10000000L /* hundreds of nanoseconds, 1e-7 */ +#define UNIX_EPOCH "01-JAN-1970 00:00:00.00" + +extern U_Long sys$bintim(), sys$gettim(); +extern U_Long lib$subx(), lib$ediv(); + + /* + * Get current time in microsecond precision. + */ +/* vms_gettimeofday() - get current time in `struct timeval' format */ +int +vms_gettimeofday(struct timeval *tv, void *timezone__not_used) +{ + /* + Emulate unix's gettimeofday call; timezone argument is ignored. + */ + static const Dsc epoch_dsc = { sizeof UNIX_EPOCH - sizeof "", UNIX_EPOCH }; + static long epoch[2] = {0L,0L}; /* needs one time initialization */ + const long thunk = VMS_UNITS_PER_SECOND; + long now[2], quad[2]; + + if (!epoch[0]) sys$bintim(&epoch_dsc, epoch); /* 1 Jan 0:0:0 1970 */ + /* get current time, as VMS quadword time */ + sys$gettim(now); + /* convert the quadword time so that it's relative to Unix epoch */ + lib$subx(now, epoch, quad); /* quad = now - epoch; */ + /* convert 1e-7 units into seconds and fraction of seconds */ + lib$ediv(&thunk, quad, &tv->tv_sec, &tv->tv_usec); + /* convert fraction of seconds into microseconds */ + tv->tv_usec /= (VMS_UNITS_PER_SECOND / 1000000); + + return 0; /* success */ +} + + #ifndef VMS_V7 /* * VMS prior to V7.x has no timezone support unless DECnet/OSI is used. @@ -196,6 +237,7 @@ void vms_bcopy( const char *src, char *dst, int len ) } #endif /*!__GNUC__*/ + /*----------------------------------------------------------------------*/ #ifdef NO_VMS_ARGS /* real code is in "vms/vms_args.c" */ void vms_arg_fixup( int *argc, char ***argv ) { return; } /* dummy */ @@ -215,3 +257,116 @@ int fork( void ) { return -1; } #endif /*NO_VMS_PIPES*/ +/*----------------------------------------------------------------------*/ + + +/* + * The following code is taken from the GNU C preprocessor (cccp.c, + * 2.8.1 vintage) where it was used #if VMS. It is only needed for + * VAX C and GNU C on VAX configurations; DEC C's run-time library + * doesn't have the problem described. + * + * VMS_fstat() and VMS_stat() were static in cccp.c but need to be + * accessible to the whole program here. Also, the special handling + * for the null device has been introduced for gawk's benefit, to + * prevent --lint mode from giving spurious warnings about /dev/null + * being empty if it's used as an input file. + */ + +#if defined(VAXC) || (defined(__GNUC__) && !defined(__alpha)) + +/* more VMS hackery */ +#include <fab.h> +#include <nam.h> + +extern unsigned long sys$parse(), sys$search(); + +/* Work around a VAXCRTL bug. If a file is located via a searchlist, + and if the device it's on is not the same device as the one specified + in the first element of that searchlist, then both stat() and fstat() + will fail to return info about it. `errno' will be set to EVMSERR, and + `vaxc$errno' will be set to SS$_NORMAL due yet another bug in stat()! + We can get around this by fully parsing the filename and then passing + that absolute name to stat(). + + Without this fix, we can end up failing to find header files, which is + bad enough, but then compounding the problem by reporting the reason for + failure as "normal successful completion." */ + +#undef fstat /* Get back to the library version. */ + +int +VMS_fstat (fd, statbuf) + int fd; + struct stat *statbuf; +{ + int result = fstat (fd, statbuf); + + if (result < 0) + { + FILE *fp; + char nambuf[NAM$C_MAXRSS+1]; + + if ((fp = fdopen (fd, "r")) != 0 && fgetname (fp, nambuf) != 0) + result = VMS_stat (nambuf, statbuf); + /* No fclose(fp) here; that would close(fd) as well. */ + } + + if (result == 0 /* GAWK addition; fixup /dev/null flags */ + && (statbuf->st_mode & S_IFREG) + && STREQ(statbuf->st_dev, "_NLA0:")) + { + statbuf->st_mode &= ~S_IFREG; + statbuf->st_mode |= S_IFCHR; + } + + return result; +} + +int +VMS_stat (name, statbuf) + const char *name; + struct stat *statbuf; +{ + int result = stat (name, statbuf); + + if (result < 0) + { + struct FAB fab; + struct NAM nam; + char exp_nam[NAM$C_MAXRSS+1], /* expanded name buffer for sys$parse */ + res_nam[NAM$C_MAXRSS+1]; /* resultant name buffer for sys$search */ + + fab = cc$rms_fab; + fab.fab$l_fna = (char *) name; + fab.fab$b_fns = (unsigned char) strlen (name); + fab.fab$l_nam = (void *) &nam; + nam = cc$rms_nam; + nam.nam$l_esa = exp_nam, nam.nam$b_ess = sizeof exp_nam - 1; + nam.nam$l_rsa = res_nam, nam.nam$b_rss = sizeof res_nam - 1; + nam.nam$b_nop = NAM$M_PWD | NAM$M_NOCONCEAL; + if (sys$parse (&fab) & 1) + { + if (sys$search (&fab) & 1) + { + res_nam[nam.nam$b_rsl] = '\0'; + result = stat (res_nam, statbuf); + } + /* Clean up searchlist context cached by the system. */ + nam.nam$b_nop = NAM$M_SYNCHK; + fab.fab$l_fna = 0, fab.fab$b_fns = 0; + (void) sys$parse (&fab); + } + } + + if (result == 0 /* GAWK addition; fixup /dev/null flags */ + && (statbuf->st_mode & S_IFREG) + && STREQ(statbuf->st_dev, "_NLA0:")) + { + statbuf->st_mode &= ~S_IFREG; + statbuf->st_mode |= S_IFCHR; + } + + return result; +} +#endif /* VAXC || (__GNUC__ && !__alpha) */ |