.TITLE VTLPOS - VTL Positioning Routines .IDENT /1.3/ .ENABL LC ;+ ; ; Free software BY ; Project Software & Development, Inc. ; ; This software is furnished for free and may be used and copied as ; desired. This software or any other copies thereof may be provided or ; otherwise made available to any other person. No title to and ; ownership of the software is hereby transferred or allowed. ; ; The information in this software is subject to change without notice ; and should not be construed as a commitment by PROJECT SOFTWARE ; AND DEVELOPMENT, INC. ; ; PROJECT SOFTWARE assumes no responsibility for the use or reliability ; of this software on any equipment whatsoever. ; ; Project Software & Development, Inc. ; 14 Story St. ; Cambridge, Ma. 02138 ; 617-661-1444 ; ; ; Title: VTLPOS.MAC ; Author: Robin Miller ; Date: June 30, 1983 ; ; Description: ; ; These routines do the mark and pointing to records within a file. ; ;- .ENABL AMA .NLIST BEX ;+ ; ; Modification History: ; ; June 5, 1984 by Robin Miller. Edit (04) ; Added routine MARK to do marking of a record position. ; ; June 5, 1984 by Robin Miller. Edit (03) ; Added routine MRKPRV to save the previous record context. ; Added routines MRKFND/PNTFND to reposition to the last search ; string record. ; ; June 2, 1984 by Robin Miller. Edit (02). ; Use common routine to Get/Mark the next input record. Remove ; code from POINTR routine which setup to point to previous record. ; ; June 2, 1984 by Robin Miller. Edit (01). ; Accumulate the total records skipped for debugged. ; ;- .SBTTL MARKER - Mark the current record. ;+ ; ; MARKER - Mark the current record (if needed). ; ; This routine is used to see if the current record position needs to be ; saved in the mark buffer. The record position is recorded so we can ; reposition quickly to a specified record after we've passed it. After ; every O.MARK records (50. by default), we save the record position. ; ; Implicit Inputs: ; IENTRY = The active file entry address. ; O.CREC = The current record number. ; O.HREC = The highest record encountered. ; ; Implicit Outputs: ; O.CREC = The adjusted current record number. ; O.HREC = The updated highest record number. ; ; Every O.MARK record(s): ; O.MRKB - Updated with record virtual block #'s. ; O.MRKP - Points to next mark buffer address. ; O.MRKC - Incremented to reflect # of mark entries. ; ; All registers are preserved. ; ;- MARKER::CALL $SAVAL ; Save all registers. MOV IENTRY,R5 ; Copy the file entry address. MOV O.CREC(R5),R0 ; Copy the current MOV O.CREC+2(R5),R1 ; record number. ; Adjust the current record number and save the highest record. ADD #1,R1 ; Bump the current ADC R0 ; record number. CMP R0,O.HREC(R5) ; Need to update highest record ? BHI 10$ ; If HI, yes (current > highest). CMP R1,O.HREC+2(R5) ; Maybe, need to update ? BLOS 20$ ; If LOS, no. 10$: MOV R0,O.HREC(R5) ; Update the highest MOV R1,O.HREC+2(R5) ; record number so far. ; See if we need to save this record position. 20$: MOV R0,O.CREC(R5) ; Update the current MOV R1,O.CREC+2(R5) ; record number. DIV O.MARK(R5),R0 ; Calculate the mark table entry. ; R0 = The quotient (table entry). ; R1 = The remainder. CMP R0,O.MRKC(R5) ; This record already marked ? BLE 100$ ; If LE, yes (skip marking). CMP O.MRKC(R5),#MRKLEN ; Do we have another entry ? BGE 100$ ; If GE, no (we've run out). MOV O.CREC(R5),O.LREC(R5) ; Save the last MOV O.CREC+2(R5),O.LREC+2(R5) ; record number marked. MOV O.MRKP(R5),R4 ; Get pointer to next mark entry. CALL MARK ; Mark this records' position. (04) ADD #,R4 ; Point to the next table entry.(04) MOV R4,O.MRKP(R5) ; Save the updated mark pointer. INC O.MRKC(R5) ; Count number of mark entries. 100$: RETURN .SBTTL POINTR - Point to a specified record. ;+ ; ; POINTR - Points to a specified record. ; ; This routine is used to position to a specified record number. If the ; record specified has previously been marked, we calculcate the mark buffer ; entry, reposition to that record, and skip the appropriate number of records ; to get the the specified record number. If the specified record hasn't ; been marked, we simply skip records until we get to the specified record. ; ; The actual record number pointed to is one less than the specified record ; number. This must be done so we are positioned for the next read (GET) to ; display the specified record number. ; ; Implicit Inputs: ; WTGREC = Contains the record to point to. ; ; Implicit Outputs: ; O.CREC = The record number pointed to ; or the last record number at EOF. ; ; C bit clear/set = success/error or CTRL/C typed. ; ; All registers are preserved. ; ;- POINTR::CALL $SAVAL ; Save all registers. MOV IENTRY,R5 ; Copy the file entry address. MOV WTGREC,R0 ; Copy the specified record # (02) MOV WTGREC+2,R1 ; to find mark table entry. (02) ; If this is record number zero, don't adjust the record number. TST WTGREC ; Is this possibly record zero ? BNE 10$ ; If NE, no (continue ...) TST WTGREC+2 ; Is it really record zero ? BEQ 15$ ; If EQ, yes (skip the adjustment). 10$: SUB #1,WTGREC+2 ; By -1 to get previous record. SBC WTGREC ; Subtract out borrow (if any). 15$: CMP R0,O.HREC(R5) ; Have we ever been there ? BHI 20$ ; If HI, no. CMP R1,O.HREC+2(R5) ; Maybe, really been there ? BHI 20$ ; If HI, no. ; Calculate the closest table entry to this record. DIV O.MARK(R5),R0 ; Calculate the mark table entry. ; R0 = The quotient (table entry). ; R1 = The remainder (skip count). ; ; If we're at the first table entry, adjust skip count by one. ; WTGREC = 1, entry 0 puts us at top of file, so we must not skip. ; Remember that each table entry positions us to read that record ; so the current record must point to the previous record number. ; TST R0 ; Is this the first entry ? (02) BNE 17$ ; If NE, no. (02) TST R1 ; First record of this entry ? (02) BEQ 17$ ; If EQ, yes (don't adjust). (02) DEC R1 ; Else adjust the skip count. (02) 17$: CLR SKPCNT ; Initialize high part of skip count. MOV R1,SKPCNT+2 ; Save the number of records to skip. CMP R0,#MRKLEN ; Is the table index too big ? BGE 20$ ; If GE, yes (this is bad news). MOV R0,R1 ; Odd register for 16 bit multiply. MUL #,R1 ; Multiply by the mark entry size. ADD O.MRKB(R5),R1 ; Add in the mark buffer base address. MOV R1,R4 ; Copy the table entry address. CALL POINT ; Point to this record number. MOV WTGREC,O.CREC(R5) ; Setup current record MOV WTGREC+2,O.CREC+2(R5) ; with the new record number. SUB SKPCNT+2,O.CREC+2(R5) ; Adjust for skip record count. SBC O.CREC(R5) ; Subtract out the carry (if any). BR 30$ ; Continue ... ; Skip forward to the desired record number. 20$: TST O.MRKC(R5) ; Any entrys left in the table ? BEQ 25$ ; If EQ, no. MOV O.MRKP(R5),R4 ; Yes, get pointer to next entry. SUB #,R4 ; Calculate pointer to last entry. CALL POINT ; And point to that record number. MOV O.LREC(R5),O.CREC(R5) ; Set up the new MOV O.LREC+2(R5),O.CREC+2(R5) ; current record number. SUB #1,O.CREC+2(R5) ; Point to the (02) SBC O.CREC(R5) ; previous record number. (02) 25$: MOV WTGREC,SKPCNT ; Copy the desired MOV WTGREC+2,SKPCNT+2 ; record number. SUB O.CREC+2(R5),SKPCNT+2 ; Calculate the number of SBC SKPCNT ; records to skip to get SUB O.CREC(R5),SKPCNT ; to the desired record. ; Skip records until we get to the desired record number. 30$: MOV SKPCNT,R4 ; Copy the skip MOV SKPCNT+2,R3 ; record count. 40$: TST R4 ; Is there any count ? BNE 50$ ; If NE, yes (start skipping). TST R3 ; Maybe, really have a count ? BEQ 100$ ; If EQ, no (we're finished). 50$: CALL GETM ; Get/Mark the next record. (02) BCS 90$ ; If CS, error or end of file. .IFDF T$SKIP ADD #1,TSKIPS+2 ; Accumulate the total (01) ADC TSKIPS ; number of records skipped. (01) .ENDC ; T$SKIP TST STATUS ; Has CTRL/C been typed to abort ? BMI 90$ ; If MI, yes (stop looping). SUB #1,R3 ; Adjust the low order bits SBC R4 ; and the high order bits. BR 40$ ; Now, see if we're done yet. 90$: SEC ; Show error or CTRL/C typed. 100$: RETURN .SBTTL MARK - Mark a records' position. ;+ ; ; MARK - Mark a records' position. ; ; This routine is called to save the current record position. The ; position saved is actually the next record position. ; ; Inputs: ; R4 = The address to save the record context. ; R5 = The file entry address. ; ; Outputs: ; C bit clear/set = success/failure. ; ; All registers are preserved. ; ;- MARK: CALL $SAVAL ; Save all registers. MOV O.FDB(R5),R0 ; Copy the FDB address. CALL .MARK ; Get the current file context. BCS 90$ ; If CS, we had an error. MOV R1,(R4)+ ; Save the high order bits, MOV R2,(R4)+ ; the low order bits, & MOV R3,(R4)+ ; the next byte in the block. BR 100$ ; Use common return ... 90$: CALL FCSERR ; Else, report the FCS error. 100$: RETURN .SBTTL POINT - Point to a records' VBN. ;+ ; ; POINT - Point to a records' virtual block number. ; ; Inputs: ; R4 = The address of the positioning information: ; word 0 = The high-order bits of the VBN. ; word 1 = The low-order bits of the VBN. ; word 2 = The byte offset within the block. ; R5 = The active file entry address. ; ; Outputs: ; C bit clear/set = success/failure. ; ; All registers are preserved, ; ;- POINT: CALL $SAVAL ; Save all registers. MOV O.FDB(R5),R0 ; Copy the FDB address. BIC #S.EOF,(R5) ; Presume not at end of file. CLR O.BADR(R5) ; Show no continuation record. MOV (R4)+,R1 ; Copy the high VBN, MOV (R4)+,R2 ; the low VBN, and MOV (R4)+,R3 ; offset into the block. CALL .POINT ; Now, point to that record. BCC 10$ ; If CC, positioned successfully. CALL FCSERR ; Else, report the error message. 10$: RETURN .SBTTL MRKFND - Mark the search record position. ;+ ; ; MRKFND - Mark the search record position. ; ; This routine copies the current record number and the previous record ; context to the search record area of this file entry. By saving the ; previous records' context, we can reposition to the search record in ; preparation to reread that record. Note that the search string record ; is actually one more that the record context. This is because the ; format routine compares the current record with the search record when ; formatting the search string found. ; ; Inputs: ; R5 = The file entry address. ; PRVREC = The previous record number/context. ; ; Outputs: ; O.FREC = The current record number. ; O.FDOT = The previous record context. ; ; All registers are preserved. ; ;- MRKFND::JSR R2,$SAVVR ; Save R0 - R2. MOV #PRVDOT,R0 ; Set address of previous context. MOV R5,R1 ; Copy the file entry address. ADD #O.FREC,R1 ; Point to search record area. MOV O.CREC(R5),(R1)+ ; Copy the high and low MOV O.CREC+2(R5),(R1)+ ; current record number. MOV (R0)+,(R1)+ ; Copy the MOV (R0)+,(R1)+ ; previous MOV (R0)+,(R1)+ ; record context. RETURN .SBTTL PNTFND - Point to the last search record. ;+ ; ; PNTFND - Point to the last search record. ; ; This routine is used to reposition to the last record where the search ; string was found. Also see notes in MRKFND routine above. ; ; Inputs: ; R5 = The file entry address. ; ; Outputs: ; O.CREC = Search record number - 1. ; ; All registers are preserved. ; ;- PNTFND::JSR R5,$SAVRG ; Save R3 - R5. MOV R5,R4 ; Copy the file entry address. ADD #O.FREC,R4 ; Point to search record area. MOV (R4)+,O.CREC(R5) ; Copy the search MOV (R4)+,O.CREC+2(R5) ; record number. SUB #1,O.CREC+2(R5) ; Point to previous SBC O.CREC(R5) ; record number. CALL POINT ; Point to previous record context. RETURN .SBTTL MRKPRV - Save the previous record position. ;+ ; ; MRKPRV - Mark the previous record position. ; ; The routine is called before doing the next GET to save the previous ; record position. When searching backwards, this allows us to reposition ; to the last record found very quickly instead of skipping records to ; get to the desired record via the POINTR routine. ; ; Inputs: ; R5 = The file entry address. ; ; Outputs: ; All registers are preserved. ; ;- MRKPRV::JSR R5,$SAVRG ; Save R3 - R5. MOV #PRVREC,R4 ; Previous record save area. MOV O.CREC(R5),(R4)+ ; Copy the high and MOV O.CREC+2(R5),(R4)+ ; low record numbers. CALL MARK ; Mark the record position. (04) RETURN .SBTTL MRKSAV - Save the current record position. ;+ ; ; MRKSAV - Save the current record position. ; ; Implicit inputs: ; O.CREC = The current record number. ; ; Implicit outputs: ; O.SREC = The saved current record number. ; O.SDOT = The saved current record context. ; ; All registers are preserved. ; ;- MRKSAV::CALL $SAVAL ; Save all registers. MOV IENTRY,R5 ; Copy the file entry address. MOV R5,R4 ; Copy the file entry address. ADD #O.SREC,R4 ; Point to start of context area. MOV O.CREC(R5),(R4)+ ; Save the current MOV O.CREC+2(R5),(R4)+ ; record number. CALL MARK ; Mark the record position. (04) RETURN .SBTTL PNTSAV - Point to saved record number. ;+ ; ; PNTSAV - Point to the saved record number. ; ; This routine is used to reposition to a previously saved record number. ; This routine is called after the MRKSAV routine to restore the current ; record number and record context. ; ; Implicit inputs: ; O.SREC = The saved record number. ; O.SDOT = The saved record context. ; ; Implicit outputs: ; O.CREC = Filled in with the saved record number. ; ; All registers are preserved. ; ;- PNTSAV::CALL $SAVAL ; Save all registers. MOV IENTRY,R5 ; Copy the file entry address. MOV R5,R4 ; Copy the file entry address. ADD #O.SREC,R4 ; Set address of saved context. MOV (R4)+,O.CREC(R5) ; Copy the high and MOV (R4)+,O.CREC+2(R5) ; low record number. CALL POINT ; Now point to the saved record. RETURN .SBTTL SETTOP - Setup top of page record number. ;+ ; ; SETTOP - Setup the top of page record number. ; ; This routine is used to setup the top of page record number which is ; used when we need to refresh the screen. ; ; Implicit inputs: ; If S.STOP is set, the top of page record number is setup. ; ; Outputs: ; All registers are preserved. ; ;- SETTOP::CALL $SAVAL ; Save all registers. MOV IENTRY,R5 ; Copy the file entry address. BIT #S.STOP,(R5) ; Top of page record already setup ? BEQ 100$ ; If EQ, yes (don't use current). MOV O.CREC(R5),R0 ; Copy the current MOV O.CREC+2(R5),R1 ; record number. ADD #1,R1 ; Adjust so we're pointing ADC R0 ; to first record on page. MOV R0,O.TOPR(R5) ; Set the top of MOV R1,O.TOPR+2(R5) ; page record number. 100$: RETURN .SBTTL PNTTOP - Point to top of page record. ;+ ; ; PNTTOP - Point to the top of page record number. ; ; This routine is used to point to the top of page record number when we ; need to redisplay the screen. ; ; Implicit inputs: ; O.TOPR = The top of page record number. ; ; Implicit outputs: ; O.CREC = The current record filled on with O.TOPR-1. ; ; All registers are preserved. ; ;- PNTTOP::CALL $SAVAL ; Save all registers. MOV IENTRY,R5 ; Copy the file entry address. MOV O.TOPR(R5),WTGREC ; Else, copy the top of MOV O.TOPR+2(R5),WTGREC+2 ; page record number. CALL POINTR ; Point to the top of page record. RETURN .END