.TITLE DIRSUB - DIR Subroutines. .IDENT /1.2/ .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: DIRSUB.MAC ; Author: Robin Miller ; Date: February 19, 1985 ; ; Description: ; ; This module contains various subroutines for the DIR program. ; ; Modification History: ; ; April 17, 1986 by F.borger, change terminal check to be for 81 columns ; so that 4/6 column default works correctly ; ; April 11, 1985 by Robin Miller. Edit (02), Version 1.2 ; Add the offset to the indentification area of the file header ; when accessing file dates and/or times. ; ; March 1, 1985 by Robin Miller. Edit (01), Version 1.1 ; Don't check the error return from getting the terminal width ; in routine CTTYPE. This is failing on VAX/VMS. ; ;- .ENABL AMA .NLIST BEX .MCALL ASTX$S, CMKT$S, DIR$, GTIM$S, MRKT$S, QIOW$, TTSYM$ .MCALL CSI$, FCSBT$, NBOFF$ ; Bit and offset definitions: CSI$ ; Define the CSI offsets. FCSBT$ DEF$L ; Define the FCS bits locally. NBOFF$ DEF$L ; Define the FNB offsets locally. TTSYM$ ; Define the terminal symbols. NB.SFL = NB.SD1!NB.SD2!NB.SNM!NB.STP!NB.SVR ; All wildcard bits. ; QIOW's to get and set the terminal characteristics. GETCHA: QIOW$ SF.GMC,TOLUN,TOEFN,,TIOSB,, ; Get term. char. GETCTO::QIOW$ SF.GMC,TOLUN,TOEFN,,,, ; Get CTRL/O status. ; Local storage: S.CTRO = 2 ; CTRL/O status bit. CTRLO: .BYTE TC.CTS,0 ; Get the CTRL/O status. CTOSIZ = .-CTRLO DATTIM::.BLKW 8. ; Buffer for date / time. CURYR == DATTIM+0 ;(G.TIYR) The current year. CURMON == DATTIM+2 ;(G.TIMO) The current month. CURDAY == DATTIM+4 ;(G.TIDA) The current day. TTYBUF: .BYTE TC.WID ; Get the terminal width. TTYWID: .BYTE 0 ; And store the value here. TTYSIZ = .-TTYBUF ; Size of status table. ; ASCII month table. MONTAB: .ASCIZ "JAN" MONSIZ = .-MONTAB ; Size of each month entry. .ASCIZ "FEB" .ASCIZ "MAR" .ASCIZ "APR" .ASCIZ "MAY" .ASCIZ "JUN" .ASCIZ "JUL" .ASCIZ "AUG" .ASCIZ "SEP" .ASCIZ "OCT" .ASCIZ "NOV" .ASCIZ "DEC" .EVEN .SBTTL CCTRLO - Check the CTRL/O state. ;+ ; ; CCTRLO - Check the CTRL/O state. ; ; This routine is used to determine if CTRL/O has been typed. ; ; Inputs: ; None. ; ; Outputs: ; Bit B.CTRO is also set in the STATUS if CTRL/O typed. ; ; All registers are preserved. ; ;- CCTRLO::BIT #B.OFIL,STATUS ; Outputting to a file ? BNE 100$ ; If NE, yes. DIR$ #GETCTO ; Get the CTRL/O status. CALL CHKDIR ; Check for directive error. BCS 100$ ; IF CS, we had an error. BITB #S.CTRO,CTRLO+1 ; Was CTRL/O typed ? BEQ 100$ ; If EQ, no (return C clear). BIS #B.CTRO,STATUS ; Show CTRL/O was typed. 100$: RETURN .SBTTL CTTYPE - Check the terminal type. ;+ ; ; CTTYPE - Check the terminal type. ; ; This routine is used to get the terminal width and lines per page. ; ; Inputs: ; None. ; ; Outputs: ; C bit clear/set = success/failure. ; ; All registers are preserved. ; ;- CTTYPE::DIR$ #GETCHA ; Get the terminal type. ;*** CALL CHKERR ; Check for any errors. (01) ;*** BCS 100$ ; If CS, it failed. (01) CMPB TTYWID,#81. ; Are we on a wide screen ? BLOS 10$ ; If LOS, no (narrow). MOV #6,NUMCOL ; Adjust number of columns. 10$: CLC ; Show success. 100$: RETURN .SBTTL CHKDID - Check for a different directory. ;+ ; ; CHKDID - Check for a different directory. ; ; This routine compares the current directory ID and device/unit number ; with the saved to determine if this is a different directory/device. ; ; Inputs: ; R5 = The file entry address. ; ; Outputs: ; C bit clear/set = same/different. ; ; All registers are preserved. ; ;- CHKDID::JSR R2,$SAVVR ; Save R0 - R2. MOV R5,R0 ; Copy the file entry address. ADD #O.DID,R0 ; Point to directory ID/device. MOV O.FNB(R5),R1 ; Copy the FNB address. ADD #N.DID,R1 ; Point to the directory ID. MOV #5,R2 ; Set the loop count. 10$: CMP (R0)+,(R1)+ ; Is this the same directory ? BNE 90$ ; If NE, no. SOB R2,10$ ; Check the next word. CLC ; Show directory is the same. BR 100$ ; Use common return ... 90$: SEC ; Show directory is different. 100$: RETURN .SBTTL CLRDID - Clear the saved directory ID. ;+ ; ; CLRDID - Clear the saved directory ID. ; ; Inputs: ; R5 = The file entry address. ; ; Outputs: ; All registers are preserved. ; ;- CLRDID::JSR R2,$SAVVR ; Save R0 - R2. MOV R5,R0 ; Copy the file entry address. ADD #O.DID,R0 ; Point to saved directory ID. MOV #3,R2 ; Set the loop count. 10$: CLR (R0)+ ; Clear the directory ID. SOB R2,10$ ; Loop until done. RETURN .SBTTL SAVDID - Save the current directory ID. ;+ ; ; SAVDID - Save the current directory ID and device/unit. ; ; This routine saves the current directory ID and device/unit in the ; file name block into the file entry table. ; ; Inputs: ; R5 = The file entry address. ; ; Outputs: ; All registers are preserved. ; ;- SAVDID::JSR R2,$SAVVR ; Save R0 - R2. MOV R5,R0 ; Copy the file entry address. ADD #O.DID,R0 ; Point to directory ID/device. MOV O.FNB(R5),R1 ; Copy the FNB address. ADD #N.DID,R1 ; Point to the directory ID. MOV #5,R2 ; Set the loop count. 10$: MOV (R1)+,(R0)+ ; Copy the directory ID. SOB R2,10$ ; Loop until done. RETURN .SBTTL CHKBEF - Check against the /BEFORE date. ;+ ; ; CHKBEF - Check the current file against the /BEFORE date. ; ; Inputs: ; None. ; ; Outputs: ; C bit clear/set = match/nomatch. ; ; All registers are preserved. ; ;- CHKBEF::CMP BEFYR,FILYR ; Is the year in range ? BLO 100$ ; If LO, no. BHI 90$ ; If HI, date is in range. CMP BEFMON,FILMON ; Is the month in range ? BLO 100$ ; If LO, no BHI 90$ ; If HI, date is in range. CMP BEFDAY,FILDAY ; Is the day in range ? BLO 100$ ; If LO, no. BHI 90$ ; If HI, date is in range. CMP BEFHR,FILHR ; Is the hour in range ? BLO 100$ ; If LO, no. BHI 90$ ; If HI, date is in range. CMP BEFMIN,FILMIN ; Is the minute in range ? BLO 100$ ; If LO, no. 90$: CLC ; Yes, show we have a match. 100$: RETURN .SBTTL CHKSIN - Check against the /SINCE date. ;+ ; ; CHKSIN - Check the current file against the /SINCE date. ; ; Inputs: ; None. ; ; Outputs: ; C bit clear/set = match/nomatch. ; ; All registers are preserved. ; ;- CHKSIN::CMP FILYR,SINYR ; Is the year in range ? BLO 100$ ; If LO, no. BHI 90$ ; If HI, date is in range. CMP FILMON,SINMON ; Is the month in range ? BLO 100$ ; If LO, no BHI 90$ ; If HI, date is in range. CMP FILDAY,SINDAY ; Is the day in range ? BLO 100$ ; If LO, no. BHI 90$ ; If HI, date is in range. CMP FILHR,SINHR ; Is the hour in range ? BLO 100$ ; If LO, no. BHI 90$ ; If HI, date is in range. CMP FILMIN,SINMIN ; Is the minute in range ? BLO 100$ ; If LO, no. 90$: CLC ; Yes, show we have a match. 100$: RETURN .SBTTL GETDAT - Get and format today's date. ;+ ; ; GETDAT - Get and format todays date. ; ; Inputs: ; None ; ; Outputs: ; All registers are preserved. ; ;- GETDAT::JSR R2,$SAVVR ; Save R0 - R2. MOV #DATTIM,R2 ; Address of date/time buffer. GTIM$S R2 ; Get the binary date/time. CALL CHKDIR ; Check for directive errors. BCS 100$ ; If CS, we had an error. ; Format as "ddmmmyy" (stored in file header in this format). MOV #DATBUF,R0 ; Buffer for ASCII date. MOV G.TIDA(R2),R1 ; Copy the binary date. CALL CVTTWO ; Convert to decimal ASCII. MOV G.TIMO(R2),R1 ; Copy the binary month. DEC R1 ; Bias the month by one. MUL #MONSIZ,R1 ; Calculate index into table. ADD #MONTAB,R1 ; Position to the ASCIZ string. CALL MOVEC ; Append to the output buffer. MOV G.TIYR(R2),R1 ; Copy the binary year. CALL CVTTWO ; Convert to decimal ASCII. 100$: RETURN .SBTTL SETDAT - Setup the file date/time. ;+ ; ; SETDAT - Setup the file date/time. ; ; Inputs: ; None. ; ; Outputs: ; All registers are preserved. ; ;- SETDAT::CALL $SAVAL ; Save all registers. MOV #HDRBUF+V.CDAT,R5 ; Presume creation date. BIT #B.CDAT,SWMASK ; Compare creation date ? BNE 10$ ; If NE, yes. MOV #HDRBUF+V.RDAT,R5 ; Presume revision date. BIT #B.MDAT,SWMASK ; Compare revision date ? BNE 10$ ; If NE, yes. MOV #HDRBUF+V.EDAT,R5 ; Must be expiration date. ; The format of the ASCII date is "ddmmmyyhhmmss". 10$: ADD IOFSET,R5 ; Add offset to indent area. (02) MOV #TMPBUF,R0 ; Set temporary buffer address. ; Convert the ASCII day. MOV R0,R3 ; Save this buffer address. MOV R0,R4 ; Copy temporary address. MOVB (R5)+,(R4)+ ; Copy the MOVB (R5)+,(R4)+ ; ASCII day. CLRB (R4) ; Set termination character. CALL $CDTB ; Convert decimal to binary. ; R0 = Updated buffer address. ; R1 = The binary number. ; R2 = Terminating character. MOV R1,FILDAY ; Save the binary day. ; Convert the ASCII month. CALL GETMON ; Get the binary month. MOV R1,FILMON ; Save the binary month. ADD #3,R5 ; Point past the ASCII month. ; Convert the ASCII year. MOV R3,R0 ; Reset starting buffer address. MOV R0,R4 ; Copy the temporary buffer. MOVB (R5)+,(R4)+ ; Copy the MOVB (R5)+,(R4)+ ; ASCII year. CLRB (R4) ; Set termination character. CALL $CDTB ; Convert decimal to binary. MOV R1,FILYR ; Save the binary year. ; Convert the ASCII hour. MOV R3,R0 ; Reset starting buffer address. MOV R0,R4 ; Copy the temporary buffer. MOVB (R5)+,(R4)+ ; Copy the MOVB (R5)+,(R4)+ ; ASCII hour. CLRB (R4) ; Set termination character. CALL $CDTB ; Convert decimal to binary. MOV R1,FILHR ; Save the binary hour. ; Convert the ASCII minute. MOV R3,R0 ; Reset starting buffer address. MOV R0,R4 ; Copy the temporary buffer. MOVB (R5)+,(R4)+ ; Copy the MOVB (R5)+,(R4)+ ; ASCII minute. CLRB (R4) ; Set termination character. CALL $CDTB ; Convert decimal to binary. MOV R1,FILMIN ; Save the binary minute. RETURN .SBTTL GETMON - Get the binary month. ;+ ; ; GETMON - Get the binary month. ; ; This routine converts the ASCII month into the binary value. ; ; Inputs: ; R5 = Address of ASCII month. ; ; Outputs: ; R2 is destroyed. ; R1 = The binary month. ; ; All other registers are preserved. ; ;- GETMON::JSR R5,$SAVRG ; Save R3 - R5. MOV #1,R1 ; Set for the first month. MOV #MONTAB,R2 ; Set address of month table. MOV #12.,R3 ; Number of month entrys. 10$: CMPB (R2),(R5) ; The first character match ? BNE 20$ ; If NE, no. CMPB 1(R2),1(R5) ; The second character match ? BNE 20$ ; If NE, no. CMPB 2(R2),2(R5) ; The third character match ? BEQ 100$ ; If EQ, yes. 20$: INC R1 ; Adjust the binary month. ADD #MONSIZ,R2 ; Point to the next entry. SOB R3,10$ ; Compare the next entry. 100$: RETURN .SBTTL CVTDBL - Convert double precision decimal. ;+ ; ; CVTDBL - Convert double precision decimal to ASCII. ; ; This routine is used to convert a double precision decimal number to ; ASCII with blank fill. The field width is fixed at 6 characters. ; ; Inputs: ; R0 = The output buffer. ; R1 = Address of double word. ; FLDSIZ = The current field size. ; ; Outputs: ; R0 = The updated buffer address. ; FLDSIZ = The adjust field size. ; ; All other registers are preserved. ; ;- .ENABL LSB CVTDBL::JSR R5,.SAVR1 ; Save R1 - R5. MOV R0,R5 ; Save the output buffer. MOV #TMPBUF,R0 ; Set temporary buffer address. MOV R0,R4 ; Save temp buffer address. CALL CVTDTD ; Convert decimal to ASCII. MOV R4,R0 ; Restore temp buffer address. CALL GETLEN ; Calculate the length into R1. MOV R1,R3 ; Copy the temp buffer size. MOV R0,R1 ; Copy temp buffer address. MOV R5,R0 ; Restore real output buffer. MOV #6,R2 ; Set the maximum field size. CMP R3,R2 ; Is the buffer size too big ? BLOS 10$ ; If LOS, no. MVS <******> ; Show the field is too small. BR 100$ ; Use common return ... 10$: SUB R3,R2 ; Calculate leading space count. BEQ 30$ ; If EQ, don't need any spaces. ADD R2,FLDSIZ ; Adjust the field size. 20$: MOVB #SPACE,(R0)+ ; Prefix field with spaces. SOB R2,20$ ; Loop until done. 30$: CALL MOVEC ; Copy number to output buffer. 100$: RETURN .DSABL LSB .SBTTL MOVE - Move an ASCIZ string. ;+ ; ; MOVE - Move an ASCIZ message and bump the field size. ; ; INPUTS: ; R1 = Address of ASCIZ string to move. ; R0 = Address of output buffer. ; ; OUTPUTS: ; R0 = Updated (ready for next character). ; ;- MOVE:: INC FLDSIZ ; Bump the current field size. MOVB (R1)+,(R0)+ ; Copy the first/next byte. BNE MOVE ; If NE, more to copy. DEC R0 ; Point to the null byte. DEC FLDSIZ ; Adjust the field size. RETURN ; ; Append to buffer pointed to by R0. ; NEWLIN::MOVB #CR,(R0)+ ; Append a carriage return MOVB #LF,(R0)+ ; and line feed sequence. CLRB (R0) ; Terminate the output buffer. CLF ; Reset the field size. RETURN .SBTTL PADFLD - Pad the field with spaces. ;+ ; ; PADFLD - Pad the field with spaces. ; ; Inputs: ; R0 The output buffer address. ; FLDSIZ The current field size. ; FLDMAX The maximum field size. ; ; Outputs: ; R0 The updated buffer address. ; FLDSIZ Reinitialized to zero. ; ;- PADFLD::CMP FLDSIZ,FLDMAX ; Have we reached the maximum size ? BHIS 100$ ; If HIS, yes. MOVB #SPACE,(R0)+ ; No, append a space. INC FLDSIZ ; Adjust the field size. BR PADFLD ; And check against maximum again. 100$: CLF ; Reset the field size. RETURN .SBTTL WRTMSG - Write a message to the terminal. ;+ ; ; TYPMSG - Entry point to finish buffer and write the message. ; WRTMSG - Append message to buffer then display the message. ; ; Inputs: ; R0 = The output buffer address (entry at TYPMSG). ; R1 = The message string address (entry at WRTMSG). ; ; Outputs: ; R0 = The starting output buffer address. ; ; All other registers are preserved. ; ;- .ENABL LSB WRTMSG::JSR R5,.SAVR1 ; Save R1 - R5. MOV BUFADR,R0 ; Set the buffer address. CALL MOVEC ; Append the message string. TYPMSG::BIT #B.STUP,STATUS ; Are we in the startup code ? BNE 20$ ; If NE, yes. CRLF ; Else, append carriage control. 20$: BR VTYPE ; Write it to the terminal. .DSABL LSB .SBTTL VTYPE - Write the format buffer. ;+ ; ; VTYPE - Write the format buffer to the terminal. ; ; Inputs: ; R0 = The updated output buffer address. ; ; Outputs: ; R0 = The starting output buffer address. ; ; All other registers are preserved. ; ;- VTYPE:: JSR R5,.SAVR1 ; Save R1 - R5. MOV R0,R1 ; Copy the buffer address. MOV BUFADR,R0 ; Copy starting buffer address. SUB R0,R1 ; Calculate the byte count. BEQ 100$ ; If EQ, nothing to write. CALL WRITIT ; And go write it. MOV BUFALT,BUFADR ; Switch to alternate buffer. MOV R0,BUFALT ; Save previous buffer address. MOV BUFADR,R0 ; Set alternate buffer address. 100$: RETURN .END