Individual Entry

Date(time) to Quadword

I was recently Googling for something completely unrelated when one of Google's finds pointed me to this thread; titled: Date to quadword in DCL???? I perused the thread's entries wondering why Google returned this link as matching my query. However, I was quickly drawn into the quagmire of the thread because the original question was never actually answered. Numerous <quote>solutions<unquote> were offered in the course of the thread but they all involved a high-level language or C. While each offered a means to the end, none of them offered a DCL solution. This particular comp.os.vms thread is over half a decade old, so it doesn't make much sense to reopen it. Instead, I will provide an answer to the question here.

OpenVMS DCL has numerous lexical functions to manipulate time but these are for manipulating time as a date(time) string. However, there is nothing to convert a date(time) string in DCL to the equivalent OpenVMS time quadword like the system service SYS$BINTIM would provide. There are ways, with a little DCL understanding, to take an OpenVMS quadword time value and present it, in DCL, as a date(time) string a la the system service SYS$ASCTIM. The under-used and under-appreciated lexical F$FAO is well-suited for this purpose. Regardless, while it is possible to go from OpenVMS time quadword to a date(time) string, the converse operation remains elusive, at least, with current OpenVMS DCL lexical functions.

The problem can be solve with only OpenVMS DCL but one has to delve into aspects of OpenVMS which can, natively, provide the date(time) string to OpenVMS quadword translation in a wah in which it can then be extracted using DCL. I originally though about doing this translation myself by calculating the OpenVMS quadword time by doing some quadword math using DCL. While it's possible to do things like simple addition, subtraction and bit-shift operations on a quadword using DCL, the thought of going multiplication on a quadword in DCL was not something I wanted to tackle. Also, the idea of having to lookup the day count per month and the leap-year rule variations quickly turned me of to the whole idea. So, I struck out on another path.

The idea is to use OpenVMS in such a way as to provide the date(time) string and let it store its quadword time translation. Then, use DCL to extract the translated quadword time. Simple in theory, but where and how to do this may not seem so obvious — the file system. OpenVMS stores several date(time) values for files: creation date, revision date, backup date and expiration date. It's possible to use one of these fields, as long as it can be set using standard OpenVMS DCL accessible utilities, for translating the date(time) string. OpenVMS has the creation date and revision date pretty well tied down but the backup date and expiration date can be easily manipulated. These fields can be easily modified by applying FDL (File Definition Language) syntax. So, I set out to write a strictly DCL date(time)-string to quadword-time converter.

The first thing to do was, of course, take in the date(time) string and apply it to a file as the backup date or expiration date. I chose the backup date. Also, since the file is only a means to an end, its name as well as its contents are of no consequence. All that was needed was a temporary file. I chose to place this file into SYS$SCRATCH and devised a name for it using F$UNIQUE. Thus, I shouldn't have to worry about tripping over any other files. With the filename issue settled, I needed to modify the backup time of the file. More recent versions of OpenVMS will allow the command $ CREATE/FDL to accept FDL syntax as a string on the command line; however, I decided to code this for versions of OpenVMS without this new feature. To do so, the uniquely named file is used as both the FDL definition file and the target of the $ CREATE/FDL.

$ FNM := "SYS$SCRATCH:''F$unique()'.;"
$!CREATE/FDL="DATE; BACKUP ''P1'" &FNM ! an OpenVMS V8.x syntax only
$ OPEN/WRITE FDL &FNM
$ WRITE FDL "DATE; BACKUP ''P1'"
$ CLOSE/NOLOG FDL
$ CREATE/FDL=&FNM &FNM
$ DELETE/NOLOG &FNM-1

Now, with the file created with the date(time) string now defined as the file's backup date, it's time to extract the quadword time from the file. This information is stored in the file's header. File headers are stored in the volume's INDEXF.SYS file in the master file directory. This is easily vied with the OpenVMS command $ DUMP/HEADER. However, to extract the quadword time, direct access to the file's header and the quadword within it holding the backup date is needed. This is an easy task, if one is familiar with how OpenVMS maintains file headers on its volumes.

The file INDEXF.SYS is a manifestation of file system information — home block, file bitmap, allocation bitmap, and the file headers. To access a specific given file's header, one needs to know where these headers begin in INDEXF.SYS and how to determine which header represents the specific given file. The first file header within INDEXF.SYS is found using the equation:
4 * cluster-factor + file-header-bitmap-size

The values which comprise this equation are easily derived using the F$GETDVI lexical function. The file header bitmap size, in blocks, can be computed from the maximum permissible files on the volume divided by the number of bits in a block (4096). The file's header is at an offset from this value. To compute the offset, one needs the file's FID (File IDentification). The FID is a tuple of 3 word-size values. This tuple contains: (num,seq,nmx«8+rvn). The offset is the num value plus the nmx value*65536 — effectively, shifting the nmx value up one 16 bit word. Putting this all together, the DCL code is:

$ FID = F$element(0,")",F$element(1,"(",F$file_attributes(FNM,"FID")))
$ HDR = F$getdvi(FNM,"CLUSTER")*4+(F$getdvi(FNM,"MAXFILES")/(512*8))+1
$ BLK[0,32] = HDR + F$integer(F$element(0,",",FID))+
(F$integer(F$element(2,",",FID))/%x100)*%x10000

The next step or challenge is to read the file header from code class="line">INDEXF.SYS. DCL can do this using its OPEN, READ and CLOSE commands. One thing that may not be obvious is that it is possible to instruct DCL to read a particular block from a file using READ/KEY.

$ OPEN/READ/SHARE=WRITE/ERROR=100$ INDEXF$SYS
'F$getdvi(FNM,"DEVNAM")[000000]INDEXF.SYS
$ READ/ERROR=100$/KEY=&BLK INDEXF$SYS HDR
$ 100$: CLOSE/NOLOG INDEXF$SYS

The only thing now left to do is to extract the backup date quadword time value from the header. However, there's one slight twist. The backup date quadword time value is stored in different locations depending upon the volume structure (ODS-2 or ODS-5) of the target volume. Nothing difficult to overcome with DCL, it just has to be coded to handle these two cases.



$ FH2$B_IDOFFSET = 0 ! offset to the identification segment
$ FH2$W_STRUCLEV = 6 ! offset to the disk structure identification
$ FI2$Q_BAKDATE = 46 ! ODS-2 offset in ID segment to backup date
$ FI5$Q_BAKDATE = 28 ! ODS-5 offset in ID segment to backup date



$ BAKDATE[ 0,32] = F$cvui((F$cvui(FH2$B_IDOFFSET*8,8,HDR)*2+
FI'F$cvui(FH2$W_STRUCLEV*8+8,8,HDR)'$Q_BAKDATE)*8, 32,HDR)
$ BAKDATE[32,32] F$cvui((F$cvui(FH2$B_IDOFFSET*8,8,HDR)*2+
FI'F$cvui(FH2$W_STRUCLEV*8+8,8,HDR)'$Q_BAKDATE)*8+32,32,HDR)

That's it.

There are a few more odd piece added to complete this exercise. First, some code to allow the specification of a DELTA date(time) string and accept the relative date(time) keywords of TODAY, YESTERDAY and TOMORROW. For demonstration purposes, the date(time) string and the quadword time value are displayed.

Here is the download link for the complete DCL source code of the described DATE-to-QUADWORD.COM procedure.

Reader Comment

I have a tendancy to be lazy with commenting, but i adore your blog and i may well also say it correct now.

by: Queuemnnady (Email ) on 28-May-2012 01:01


Comments?


To thwart automated comment SPAM, you must answer this question to post.

Comment moderation is enabled. Your comment(s) will not be visisble until approved.
Remember personal info?
Notify?
Hide email?
All html tags, with the exception of <b> and <i>, will be removed from your comment. You can make links by simply typing the url or email-address.
Powered by…