[Info-vax] Compatibility and 64-bit

David Froble davef at tsoft-inc.com
Sun Mar 15 18:58:48 EDT 2015


JF Mezei wrote:
> On 15-03-15 03:08, David Froble wrote:
> 
>> About the string descriptors ....
> 
> 
> Question:
> 
> Say i have a C program.
> 
> I define
> 
> mydescriptor struct dsc$descriptor ;  (forgot the actial precise name).
> 
> That descriptor contains (from memory, pardon lack of precision)
> 
> char type;
> char class;
> short lenght;
> void *pointer ;   (or is it unsignec char *pointer ?)
> 
> 
> Why would my program care whether "pointer" was allocated as 4 or 8 bytes ?
> 
> If the program is compiled with a switch that makes all pointers 64
> bits, then all my operations to move pointers around should be 64 bits
> and this is transparent to me.
> 
> If I dynamically allocate memory to make an array of descriptors, then I
> will likely use  sizeof(struct dsc$descriptor) when calculating how much
> memory to allocate, so whether compiled in 32 or 64 bits, the code will
> still work.
> 
> And when I manipulate a pointer, I am expected to always use pointer
> variables, right ?  I am NOT supposed to move a pointer to an integer,
> have fun with it as integer and then move it back to a pointer variable,
> right?
> 
> Ever since VMS started to support both 32 and 64 bits, I have been weary
> of assuming the size of any variable and always use sizeof when I need
> to knwo it size.
> 
> Yeah, when dealing with integers, you want to make sure you have the
> right incantation to have the right bit size. For instance, for VMS
> time, you can safely use a quadword, but if you know the language well
> enough, you can also allocate a 64 bit integer and do the math directly
> to it , instead of calling the routines that add/subtract time.
> 
> But for pointers, I am not sure I understand where the problem is.

Some people do weird stuff ...

Consider:

         .TITLE  DAS_RECREAD Read record by record number
         .IDENT  /1-001/

;++
;
; Copyright (C) 1984 by Dave Froble Enterprises, Inc.
;
; Facility:     Database Access System (DAS)
;
; Abstract:
;
;       This subroutine reads the data record specified from a DAS file.
; The record is labelled by a dynamic string array specified.
;
; Modifications:
;
; 10-MAY-1984 DAS Original
;
; Argument list format:
;
;         (AP) = Argument count
;        4(AP) = Address of a longword containing a user channel #
;        8(AP) = Address of a longword specifying the record # to read
;       12(AP) = Address of a longword containing processing options:
;                       Bit 0: Set to leave record locked after read
;                       Bit 1: Set to force disk seek
;                       Bit 2: Set to inhibit record labeling
;       16(AP) = Address of the descriptor of the dynamic string array to
;                use to label the record. This parameter may be omitted
;                when the processing options inhibit labeling.

Ok, here is something non-standard.  The address of an array descriptor, 
for an array of string descriptors.  These things are going to be used 
as labels in an I/O buffer.


;       20(AP) = Address of a longword to receive completion status
;--

         .PSECT  DAS_PURECODE,CON,EXE,GBL,NOWRT,PIC,RD,REL,SHR,PAGE

         .ENTRY  DAS_RECREAD,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>

         TSTL    (AP)+                   ; Skip argument count
         MOVL    @(AP)+,R2               ; Channel number
         MOVL    @(AP)+,R3               ; Record number
         MOVL    @(AP)+,R4               ; Processing options
         MOVL    (AP)+,R5                ; Address of labeling descriptor
                                         ; AP -> Address for completion code

         .GETIFDA CHAN=R2, IFDA=R9       ; Validate channel & get IFDA 
address

         MOVL    #DAS_IVRECNUM,R0        ; Assume failure
         TSTL    R3                      ; Record index zero?
         BEQLU   000$                    ; Yes, return with error
         CMPL    IFDA_L_MAXREC(R9),R3    ; Within file's limitations 
(records)?
         BGEQU   010$                    ; Yes, continue
000$:   BRW     RETURN                  ; Branch aid to 'RETURN'

;+
;       Calculate the block # containing the record
;       & base of segment for MBC
;       & offset in buffer (blocks) to block containing record
;       & offset if block (records) to record
;-

010$:   SUBL3   #1,R3,R6                ; Offset (records) to record
         DIVL2   IFDA_L_RECBLK(R9),R6    ; Offset (blocks) to record
         DIVL3   IFDA_L_ORGMBC(R9),R6,R7 ; Offset (buffers) to block
         MULL2   IFDA_L_ORGMBC(R9),R7    ; Base of segment-1
         SUBL3   R7,R6,R8                ; Block offset in buffer to record
         MULL3   IFDA_L_RECBLK(R9),R6,R10 ; Offset in blocked record to 
record
         SUBL3   R10,R3,R6               ; Offset+1 in block to record 
(records)
         DECL    R6                      ; Offset in block to record 
(records)
         INCL    R7                      ; Base VBN of segment
         ADDL2   IFDA_L_DATOFF(R9),R7    ; Don't forget data offset
         ASHL    #9,R8,R8                ; Make block offset bytes
         MULL2   IFDA_L_RECLEN(R9),R6    ; Make record offset bytes
         ADDL2   R8,R6                   ; Total byte offset in buffer 
to record
         MOVL    R6,IFDA_L_RECOFF(R9)    ; Set current record offset
;+
;       A seek must be done if:
;
;       * The processing options force a seek
;       * The record requested is not in the incore segment
;       * The record requested is in the incore segment, the incore segment
;         is unlocked by the current process, and the processing options
;         specify that the record should be left locked.
;-
100$:   BBS     #1,R4,200$              ; Force seek
         CMPL    R7,IFDA_L_CURDBK(R9)    ; Is the required segment incore?
         BNEQU   200$                    ; No, seek
         BBC     #0,R4,110$              ; Use incore buffer if no lock req.
         .VDACHLK CHAN=R2, VBN=R7, NBLOCKS=IFDA_L_ORGMBC(R9)
         BLBC    R0,200$                 ; Incore segment not locked, seek
110$:   BRW     230$                    ; Skip over seek stuff
                                         ; Also branch aid to skip seek
;+
;       Do a disk read for the buffer required:
;
;       * Write the current incore buffer if the pending write flag is set
;       * Unlock the current segment (always)
;       * Lock the segment if requested
;       * Read the required segment
;
;-
200$:   BBC     #0,IFDA_L_CFLAGS(R9),210$
         MOVL    R2,WRK_L_CURCHN         ; Set channel number
         PUSHL   (AP)                    ; Address of completion code
         PUSHAL  WRK_L_CURCHN            ; Address of channel number
         CALLS   #2,G^DAS_RECUPD         ; Write incore segment
         TSTL    R0                      ; Error?
         BNEQU   000$                    ; Return on error
210$:   .VDAUNLK CHAN=R2                ; Unlock current segment
         BLBS    R0,215$                 ; Continue if successful
         BRW     ERRORS                  ; Return on error
215$:   BBC     #0,R4,220$              ; Skip locking if not requested
         .VDALOCK CHAN=R2, VBN=R7, NBLOCKS=IFDA_L_ORGMBC(R9)
         BLBS    R0,220$                 ; Continue unless error
         BRW     RETURN                  ; Else return
220$:   .VGET   CHAN=R2, VBN=R7, NBLOCKS=IFDA_L_ORGMBC(R9), -
                 BUFADR=@IFDA_L_DABADR(R9), RCOUNT=IFDA_L_RCOUNT(R9)
         BLBS    R0,230$                 ; Continue if no errors
         PUSHL   R0                      ; Preserve error code
         .VDAUNLK CHAN=R2                ; Else unlock D/A on error
         POPL    R0                      ; Restore error code
225$:   BRW     RETURN                  ; Return error
230$:   MOVL    R7,IFDA_L_CURDBK(R9)    ; Remember current data block
         MOVL    R3,IFDA_L_CURREC(R9)    ; Remember current record
         ADDL2   IFDA_L_DABADR(R9),R6    ; Virtual address of record in 
memory
         BBS     #2,R4,400$              ; Don't do labeling
;+
;       Label the data record
;-

At this point the descriptors are tested, and if they pass the tests, 
then the code steps through each field in the data record, and sets the 
address and length into each respective string descriptor int he array 
of descriptors.

Now, could the descriptors be analyzed to determine what and where the 
appropriate data is in the descriptor, and the size of the pointer? 
Don't know, never researched it.  But you can see, some pretty strong 
assumptions are made.  Length of the pointer.  Location of the pointer.

         MOVL    #DAS_IVLABARR,R0        ; Assume failure
         CMPB    #DSC$K_CLASS_A,DSC$B_CLASS(R5) ; Array descriptor?
         BNEQU   225$                    ; No, return
         CMPB    #DSC$K_DTYPE_DSC,DSC$B_DTYPE(R5) ; Array of descriptors?
         BNEQU   225$                    ; No, return
         CMPB    #1,DSC$B_DIMCT(R5)      ; One dimensional?
         BNEQU   225$                    ; Exit if not
         CMPL    IFDA_L_NUMFLD(R9),DSC$L_M1(R5) ; Large enough?
         BGEQU   RETURN                  ; No, return

         MOVL    IFDA_L_NUMFLD(R9),R7    ; # of fields to label
         MOVAW   IFDA_W_FLDOFF(R9),R10   ; Field offsets
         MOVAW   IFDA_W_FLDLEN(R9),R11   ; Fields lengths
         MOVL    DSC$A_POINTER(R5),R8    ; Address of first descriptor
;+
;       Field element zero of the array
;-
         CMPB    #DSC$K_CLASS_S,DSC$B_CLASS(R8) ; Scalar string?
         BEQLU   250$                    ; Yes, continue
         TSTW    DSC$W_LENGTH(R8)        ; Space allocated to this string?
         BEQLU   240$                    ; No, continue
         MOVL    #DAS_IVLABARR,R0        ; Set completion code
         BRW     RETURN                  ; Return
240$:   MOVB    #DSC$K_CLASS_S,DSC$B_CLASS(R8) ; Mark string as scalar
250$:   MOVL    R6,DSC$A_POINTER(R8)    ; Offset in record this field
         MOVW    IFDA_L_RECLEN(R9),DSC$W_LENGTH(R8) ; Set length of 
field into dr
         ADDL2   #8,R8                   ; Point to next descriptor
300$:   CMPB    #DSC$K_CLASS_S,DSC$B_CLASS(R8) ; Scalar string?
         BEQLU   320$                    ; Yes, continue
         TSTW    DSC$W_LENGTH(R8)        ; Space allocated to this string?
         BEQLU   310$                    ; No, continue
         MOVL    #DAS_IVLABARR,R0        ; Set completion code
         BRW     RETURN                  ; Return
310$:   MOVB    #DSC$K_CLASS_S,DSC$B_CLASS(R8) ; Mark string as scalar
320$:   MOVZWL  (R10)+,DSC$A_POINTER(R8) ; Offset in record this field
         ADDL2   R6,DSC$A_POINTER(R8)    ; From start of record
         MOVW    (R11)+,DSC$W_LENGTH(R8) ; Set length of field into 
descriptor
         ADDL2   #8,R8                   ; Point to next descriptor

Consider that assumption, the total size of the descriptor ...

         SOBGTR  R7,300$                 ; Loop for the count
400$:   CLRL    R0                      ; Set completion code
         MOVL    IFDA_L_DELFLD(R9),R7    ; Delete field index
         BEQLU   RETURN                  ; None, exit
         DECL    R7                      ; Adjust for indexing
         MOVZWL  IFDA_W_FLDOFF(R9)[R7],R7 ; Offset in record to delete field
         CMPB    #255,(R6)[R7]           ; Deleted record?
         BNEQU   RETURN                  ; No, return
         MOVL    #DAS_RECDEL,R0          ; Yes, set error code
         BRB     RETURN                  ; Return

ERRORS:

RETURN: MOVL    R0,@(AP)                ; Return completion code
         RET


         .END

This is just one example.  The people still on VMS just may have similar 
things, that made any idea of a port, a hard sell, and, make the loss of 
compatibility a serious issue.

Probably the biggest and first offender was the MACRO-32 compiler.  We 
know why it was developed.  But it extended the life of the VAX 
environment and software.

I know what Steve is saying, and I understand.  But the other side of 
the issue is the many VMS systems running production with stuff like the 
above, and how useless those systems become if their applications stop 
running.

Things like DAS were a decent product in 1984.  That doesn't hold for 
2015, and I myself can make a good argument for replacing it with a 
modern database.  But, that isn't an easy, nor inexpensive, thing to do. 
  And the current users are still getting what they need.  There is no 
business argument for such a change.

Now extend that to many other VMS sites, and perhaps you can see the 
problem with throwing out the baby with the bath water.



More information about the Info-vax mailing list