.MCALL .MODULE .MODULE BINCOM,VERSION=34,COMMENT=,AUDIT=YES ; Copyright (c) 1998 by Mentec, Inc., Nashua, NH. ; All rights reserved ; ; This software is furnished under a license for use only on a ; single computer system and may be copied only with the ; inclusion of the above copyright notice. This software, or ; any other copies thereof, may not be provided or otherwise ; made available to any other person except for use on such ; system and to one who agrees to these license terms. Title ; to and ownership of the software shall at all times remain ; in Mentec, Inc. ; ; The information in this document is subject to change without ; notice and should not be construed as a commitment by Digital ; Equipment Corporation, or Mentec, Inc. ; ; Digital and Mentec assume no responsibility for the use or ; reliability of its software on equipment which is not supplied ; by Digital or Mentec, and listed in the Software Product ; Description. .SBTTL Edit History ;+ ; BINARY COMPARE UTILITY PROGRAM ; VERSION 4 AUTHOR: SCOTT DAVIS ; VERSION 5 AUTHOR: LINDA BANCHE ; ; Edit History: ; 15-FEB-85 George Thissell Jr. ; Keep significant zeroes from being "eaten" ; on address past 7776 ; ; 25-FEB-85 George Thissell Jr. ; Check for possible date rollover ; ; 003 09-JUL-87 RHH Fix wildcard-on-magtape crashes ; ; 004 11-NOV-87 CS Fix blank lines on wildcard compares ; ; 005 11-FEB-88 IHZ Isssue Invalid device error (not Input file ; not found) when bad device in user command. ; ; 006 23-Jun-89 RHH Change output for DIF/BIN/QUIET (wildcards) ; ; 013 21-JUL-89 MSS Make WCDISP check that it will not overwrite ; the USR when it copies a filename into the ; filename buffer. If the check fails, BINCOM ; will return Insufficient Memory ; ; 015 21-JUL-89 MSS Make WCDLKO do .ENTER on the output file. ; Previously, it would first do A .LOOKUP to ; see if it could reuse an existing file; this ; is not desireable because if the desired file ; exists but is very small, we can could get ; an output error if there will be lots of ; differences. ; ; 017 22-JUL-89 MSS Add KPCHECK to handle invalid operations on ; on KP: type devices ; ; 019 23-JUL-89 MSS Change the Magic Mumbers 10070 and 6050 to ; 6070 and 4050, respectively. This lowers ; the imposed mininum lengths for read buf1 and ; and read buf2 from two blocks each down to ; one block each. The goal is to make more room ; for wildcarding. ; ; 021 24-JUL-89 MSS Make DEVDEV see if there are two variable size ; volumes and if so, use .Spfun 373 to obtain ; the sizes, then compare them and set MOD ; flags accordingly ; ; 023 24-JUL-89 MSS Eliminate direct access of USR address through ; an RMON offset for making argument to .SETTOP. ; Use .SETTOP #-2 instead. ; ; 024 04-Aug-89 RHH Fix wildcard anomolies when both inputs ; specify wildcards. Impose wildcard rules, ; correctly handle %%'s and embedded '*'s ; Fix end-block maximum (was 77777, now 177777) ; Fix crash when /O entered without 2nd out file ; Use SOB macro instead of raw SOBs. ; ; 025 31-Oct-1990 JFW bracket error messages with ;+/;ERROR/.../;- ; ; 026 7-Jan-1991 WFG Fix wildcard problem with filnames of different ; length. ; 027 01-Apr-91 WFG ACT #7438 - Fix incorrect 'File is Longer' ; msg when comparing file to device. ; 028 14-May-91 WFG ACT #6741 - Fix magtape-related problems ; - Check for device size = 0 (unknown size) ; - Don't DEC size, adjust BHIS's to BHI's ; - Clear buffers to fix mismatch on block 0 ; 029 7-Jun-91 WFG Change JSR PC and RTS PC to CALL and RETURN ; 030 7-Jun-91 WFG Set EOF at /END to display correct msgs ; ; (031) 01-Aug-91 MBG Turned on code developed by Rob.H. Suggestion that ; conditionals be removed in a future release. ; ; (032) 09-Aug-91 MBG Made nonquiet comparison similar to /QUIET, removed ; conditionals for RHH$QT, added some additional ; magtape error checking ; ; (033) 22-Nov-91 MBG Corrected problem with end-of-volume comparisons on ; large volumes during multi-block read-compares. ; ; 034 16-Jun-1998 TDS Fixes for 65535-block DU: devices: ; * Make default END be 177776, so no attempt will be ; made to compare block 177777. ; * Check for overflow when incrementing block number ; so we won't go into infinite loop. ;- .SBTTL System definitions .LIBRARY "SRC:SYSTEM.MLB" ;Declare our library .MCALL .ERMDF ;Magtape error codes .MCALL .SFMDF ;Magtape special functions .ERMDF .SFMDF .SBTTL Conditionals ;+ ;COND ; Conditionals .IIF NDF MSS$DB MSS$DB = 0 ; Debug messages ;- .SBTTL System Macros .MCALL .BR .CLOSE .CSIGEN .CSISPC .DSTATU .ENTER .MCALL .EXIT .FETCH .GTIM .GVAL .LOOKUP .PRINT .MCALL .RCTRLO .READW .RELEAS .SETTOP .SPFUN SOB .MCALL .SRESET .WAIT .WRITW .SBTTL Local Macros .MACRO EVN SRC,?L1 BIT #1,SRC BEQ L1 CLRB (SRC)+ L1: .ENDM EVN .MACRO XOR SRC,DEST MOV @DEST,-(SP) BIC @SRC,@SP MOV @SRC,-(SP) COM @SP COM @DEST BIC (SP)+,@DEST BIS (SP)+,@DEST .ENDM XOR .MACRO XORB SRC,DEST MOVB @DEST,-(SP) BICB @SRC,@SP MOVB @SRC,-(SP) COMB @SP COMB @DEST BICB (SP)+,@DEST BISB (SP)+,@DEST .ENDM XORB .SBTTL STORAGE AREA FOR BINCOM .PSECT DATA .ENABL GBL .NLIST BEX DFTYP:: .WORD 0 ;DEFAULT FILE TYPES .RAD50 /DIF/ .RAD50 /COM/ .WORD 0 LMT: .LIMIT SWTAB: .ASCIZ /BEHOQSD/ ;SWITCH TABLE .EVEN ACTAB: .WORD BYT ;ACTION ROUTINE ADDRESSES FOR SWITCHES .WORD ENB .WORD HEL .WORD CRF .WORD SUP .WORD STB .WORD DEV .WORD 0 STBL:: .WORD 0 ;STARTING BLOCK # ENBL:: .WORD 0 ;ENDING BLOCK # MOD:: .WORD 0 ;WORD TO INDICATE SWITCHES IND:: .WORD 0 ;INDICATOR WORD NMBL:: .WORD 0 ;WORD TO HOLD SHORT READ BLOCK# SAV1:: .WORD 0 ;SAVE BLOCK # FOR SIPP SAV2:: .WORD 0 ;SAVE OFFSET FOR SIPP MOD2:: .WORD 0 ;2ND WORD TO INDICATE SWITCHES SAVERB::.WORD 0 ;SAVE $ERRBY FOR INVALID DEV. TST. FN.SUP==1 ;BITS FOR SWITCH/Q FN.FL1==2 ;FILE 1 SHORTER BIT FN.FL2==4 ;FILE 2 SHORTER BIT FN.CRF==10 ;BITS FOR SWITCH/O FN.CRP==20 ;BIT FOR SWITCH/O PATCH FN.DEV==40 ;BIT FOR SWITCH/D FN.PAT==100 ;SIPP FILE FN.DFT==200 ;BIT FOR DIF FILES FN.ADF==400 ;ANY FILES DIFFERENT (FOR WILDCARDS) FN.DIF==1000 ;BIT FOR SHORT FILE FN.BYT==100000 ;BITS FOR SWITCH/B F2.ENB==1 ;BIT FOR SWITCH/E F2.STB==2 ;BIT FOR SWITCH/S F2.WCD==10 ;BIT FOR WILDCARDING AREA1: .BLKW 10 ;FILE INFO ON INPUT 1 AREA2: .BLKW 10 ;FILE INFO ON INPUT 2 CNT:: .WORD 0 ;NUMBER READ IN AT A TIME SVSP: .WORD 0 ;WORD TO SAVE SP ON ;+ ;ERROR ; MESSAGES MSGLST MSGTAB ERRMSG EM0 ERRMSG EM1 ERRMSG EM2 ERRMSG EM3 ERRMSG EM4 ERRMSG EM5 ERRMSG EM6 ERRMSG EM7 ERRMSG EM8 ERRMSG EM9 ERRMSG ER10 ERRMSG ER20 ERRMSG ER30 ERRMSG ER40 ERRMSG ER50 ERRMSG ER60 ERRMSG ER70 ERRMSG ER80 ERRMSG ER90 ;IHZ MSGEND ;- BIN:: .ASCII \?BINCOM-\ LEV:: .ASCII \X-\<200> .EVEN ERAR:: .BYTE 0 .BYTE 200 .WORD BIN .WORD LEV .WORD MSGTAB .WORD 0 .WORD NEXT1 HELPFL: .ASCIZ \Bincom options currently available: \ HLP: .ASCIZ \/B -- Compares the input files byte by byte \ .ASCIZ \ default is word mode \ .ASCIZ \/D -- Compares two different devices \ .ASCIZ \ starting with block 0 \ .ASCIZ \/E:n -- Ends comparison at block # n \ .ASCIZ \ default is until eof on either file \ .ASCIZ \/H -- Prints list of switches \ .ASCIZ \/O -- Always creates an output file or patch \ .ASCIZ \ file regardless of whether the files \ .ASCIZ \ are the same or different \ .ASCIZ \/Q -- Suppresses the difference listing, only\ .ASCIZ \ tells you if files are the same or \ .ASCIZ \ different \ .ASCIZ \/S:n -- Starts the comparison at block # n \ .ASCIZ \ default is beginning of file \ ENHELP: .EVEN SPHD: .ASCII \R SIPP\;START OF SIPP FILE LINE OUTSP:: .BLKW 5 ;FILE DESCRIPTOR BLOCKS PATSP:: .BLKW 12 ;PATCH FILE DESCRIPTOR BLOCK IN1:: .BLKW 4 ;INPUT FILE 1 DESCRIPTOR BLOCK IN2:: .BLKW 20. ;INPUT FILE 2 CMLB:: .BLKB 81. ;STORE CML VERSN: .NLCSI PATLEV=:.-2 .EVEN LIM: .WORD 0 ;PROGRAM LIMIT TTNAM: .RAD50 \TT \ ;DEFAULT DEVICE FOR OUTPUT OUTF== 0 ;OUTPUT CHANNEL PATF== 1 ;PATCH CHANNEL INF1== 3 ;INPUT FILE 1 INF2== 4 ;INPUT FILE 2 AREA: .BLKW 5 ;EMT FOR LOOKUP $ERRBY =: 52 $USRRB =: 53 WARN$ =: 2 ERCMD==0 ;INVALID COMMAND ;IHZ ERDNC==1 ;DEVICE NOT FOUND ;IHZ ERPRE==2 ;PROTECTED FILE EXISTS ;IHZ ERFUC==3 ;DEVICE FULL ;IHZ ERFNC==4 ;FILE NOT FOUND ;IHZ RMON== 54 ;START OF RMON USRBUF==266 ;OFFSET FOR USR OUTBUF: .WORD 0 ;POINTER TO OUTPUT BUFFER OUTBF: .WORD 0 ;INDEX TO OUTPUT BUFFER PATBUF: .WORD 0 ;POINTER TO SIPP BUFFER PATBF: .WORD 0 ;INDEX TO SIPP BUFFER NMBLK:: .WORD 0 ;#BLOCKS READ ON READ BUF1: .WORD 0 ;POINTER TO INPUT BUFFER 1 BUF2: .WORD 0 ;POINTER TO INPUT BUFFER 2 PBLK: .WORD 0 ;BLOCK # IN SIPP WBLK:: .WORD 0 ;BLOCK # IN OUTPUT BLK:: .WORD 0 ;CURRENT BLOCK # SBLK:: .WORD 0 ;SAVE BLOCK WORD SAV:: .WORD 0 ;SAV R0 NBUF1: .WORD 0 ;# READ INTO BUF1 NBUF2: .WORD 0 ;#READ INTO BUF 2 SPCON:: .WORD 0 ;FLAG FOR TELLING WHICH SPEC YOU'RE WORKING ON ASCB: .ASCII \ \ ;ASCII BLANKS NLZCNT::.WORD 0 ;SIPP NON-LEADING ZERO CHAR COUNT DSPC1:: .WORD 0,0,0 ;VALID FILESPEC FOR /D DSPC2:: .ASCII /* / ;VALID FILESPEC FOR /D DSPC3:: .ASCII /* * / ;VALID FILESPEC FOR /D C.TAB =: 11 ;Tab C.LF =: 12 ;Line feed C.CR =: 15 ;Carriage return C.SPAC =: 40 ;Space FILLEN == 13 ;LENGTH OF ASCII FILENAME RETURNED BY RTOA .EVEN HD: .ASCIZ \BINCOM comparing/ \ SEPAR: .ASCIZ \ -- \ ;+ ;ERROR CRLF: HD2: .ASCIZ // SEPAR2: .ASCIZ / with / LOGHED: .ASCIZ / Files compared:/ NFC: .ASCII /?BINCOM-I-Number of comparisons = / NFCVAL: .ASCIZ / / NFD: .ASCII /?BINCOM-W-Files with differences = / NFDVAL: .ASCIZ / / ;- .EVEN HFMT1: .WORD HD,SEPAR,<+14.> HFMT2: .WORD HD2,SEPAR2,<+12.> S$JSW== 44 JS.REE==20000 S.VER == 276 ;Offset from RMON to monitor version number .SBTTL WILDCARD VARIABLES AND CONSTANTS .EVEN WC.FLG::.WORD 0 ;WILDCARD FLAG ; VALUES FOR WC.FLG WC.ENB == 000001 ;WILDCARDING SPECIFIED WC.1FL == 000002 ;WILDCARDING ON INPUT SPEC 1 WC.2FL == 000004 ;WILDCARDING ON INPUT SPEC 2 WC.BOT == WC.1FL+WC.2FL ;WILDCARDING ON BOTH SPECS WC.NXT == 000100 ;WILDCARDING NOT-FIRST-LOOP WCSAV1::.WORD 0 ;ADDRESS OF WCD BUFFER 1 WC1PTR::.WORD 0 ;PTR TO CURRENT LOCATION IN WCSAV1 WCEND:: .WORD 0 ;1ST FREE BYTE AFTER WCSAV1 WCSAV2::.WORD 0 ;ADDRESS OF WCD BUFFER 2 WC2PTR::.WORD 0 ;PTR TO CURRENT LOCATION IN WCSAV2 WDEV1:: .WORD 0 ;WILDCARD DEV 1 TYPE WDEV2:: .WORD 0 ;WILDCARD DEV 2 TYPE DIFCNT: .WORD 0 ;Counts different files NOFILS: .WORD 0 ;Counts number of files compared DEVIN:: .WORD 0 ;Flag to indicate device type (wildcarding) DEVMT == 000001 ;Flag to indicate magtape input LSTFIL::.WORD 0 ;FLAG TO INDICATE OUTPUT FILE SPECIFIED MATFND::.WORD 0 ;FLAG TO INDICATE IF A MATCH WAS FOUND ONEMAT == 000001 ;AT LEAST ONE MATCH WAS FOUND (WC ON 2 SPECS) MATPAS == 000002 ;MATCH FOUND THIS PASS (WC ON 2 SPECS) MAT == ONEMAT+MATPAS ;BOTH OF THE ABOVE FLAGS STR1A:: .BLKW 4 ;FILENAME 1 SAVE AREA (WC ON 2 SPECS) STR1B:: .BLKW 4 ;FILE TYPE 1 SAVE AREA STR2A:: .BLKW 4 ;FILENAME 2 SAVE AREA STR2B:: .BLKW 4 ;FILETYPE 2 SAVE AREA SAVR1:: .WORD 0 ;SAVE AREA FOR R1 SAVR5:: .WORD 0 ;SAVE AREA FOR R5 SAVPTR::.WORD 0 ;SAVE AREA FOR FILENAME START SAVPT2::.WORD 0 ;SAVE AREA FOR WCSAV2 START CHARS:: .BLKW 6 ;AREA FOR ASCII OF FILENAME BUFSTR::.WORD 0 ;SAVE READ BUFFER START ENBSAV::.WORD 0 ;SAVE END BLOCK FOR /E FIXSPC::.WORD 0 ;ASCII OF INPUT SPEC 1 OR 2 LASTFR::.WORD 0 ;HIGHEST FREE WORD USRLIM::.WORD 0 ;Last Word Before the USR IN1ASC::.BLKW 6 ;ASCII OF IN1 IN2ASC::.BLKW 6 ;ASCII OF IN2 MATTMP::.BLKW 6 ;TEMP SAVE AREA FOR FILENAME 2 SAVR50::.BLKW 3 ;STORAGE AREA FOR RAD50 FILENAME STBSAV::.WORD 0 ;SAVE START BLOCK FOR /S SEQDEV == 100000 ;.DSTATUS status word. 0 => sequential device NRTDIR == 10000 ;.DSTATUS status word. 1 => non RT-11 ; directory structured device (MT) KPTYPE == 110000 ; code for KP: type device MMIDEN == 11 ;.DSTATUS MM identification number MTIDEN == 20 ;.DSTATUS MT identification number MSIDEN == 35 ;.DSTATUS MS identification number MUIDEN == 60 ;.DSTATUS MU identification number DEFTYP::.WORD 0 ;Default listing type for file sizes DEVSEQ::.WORD 0 ;Flag to indicate sequential output device ASTERK == 52 ;ASCII '*' PRCENT == 45 ;ASCII '%' COMMA == 54 ;ASCII ',' EQUALS == 75 ;ASCII '=' DOT == 56 ;ASCII '.' IOAREA::.BLKW 12 ;EMT BLOCK ICHAN:: .WORD 0 ;INPUT FILE CHANNEL NUMBER MABBAD::.WORD 0 ;Flag to indicate maybe-bad-block ; DISK CONSTANTS DH.AVL == 0 ;Number of available directory segments DH.NXT == 2 ;Pointer to next directory segment DH.HI == 4 ;Highest directory segment open DH.EXB == 6 ;Number of extra bytes in directory entries DH.STB == 10 ;Starting block number for files in segment DH.SIZ == 12 ;Size of directory header words HOMBLK == 1 ;Disk home block DK.VID == 730 ;Offset to volume id DK.VLN == 14 ;Length of volume id DK.OWN == 744 ;Offset to owner name DK.OLN == 14 ;Length of owner name DK.VAL == 726 ;Offset to volume validation pattern ; Disk directory entry offsets and symbolics DE.ST == 0 ;Entry status DS.TNT == 400 ; 1 => tentative entry DS.EMP == 1000 ; 1 => empty entry DS.PRM == 2000 ; 1 => permanent entry DS.EOS == 4000 ; 1 => end-of-segment entry DE.FN1 == 2 ;Offset to first word of filename DE.FN2 == 4 ;Offset to second word of filename DE.TYP == 6 ;Offset to filetype DE.LEN == 10 ;Offset to filesize DE.DAT == 14 ;Offset to file creation date DE.SIZ == 16 ;Size of directory entry ;MAGTAPE CONSTANTS MT.SEQ = 31. ;Offset to file sequence number MT.FSZ = 54. ;Offset to file size (records) MT.FID = 4 ;Offset to filename ; Magtape directory offsets and symbolics MT.VOL == "VO ;VOL label identification MT.VID == 4 ;Offset to magtape volume id MT.VLN == 6 ;Length of magtape volume id MT.OWN == 37. ;Offset to magtape owner name MT.VP1 == 'D ;First part of owner validation pattern MT.VP2 == "%B ;Second part. MT.OLN == 12 ;Length of magtape owner name MT.HDR == "HD ;HDR label identification MT.HFI == 4 ;Offset to file identifier MT.HDT == 41. ;Offset to file creation date MT.EOF == "EO ;EOF label identification LABSIZ == 400 ;Size of RT-11 labels in words INBFSZ == 2000 ;Size of input buffer in bytes R50V3A == ^RV3A ;RAD50 'V3A' AVAIL:: .WORD 0 ;Number of available directory segments EOSFLG::.WORD 0 ;Flag to indicate end-of-segment encountered HISEG:: .WORD 0 ;Highest directory segment in use NXTDSG::.WORD 0 ;Next directory segment to read NXTFIL::.WORD 0 ;Pointer to next directory entry RBLK:: .WORD 0 ;Physical block to read SBLOCK::.WORD 0 ;Starting block number of current file XTRABY::.WORD 0 ;Number of extra bytes in directory entry MBUF:: .WORD 0 ;Magtape input buffer address MVAL:: .WORD 0 ;Flag for which magtape buffer to use DBUF:: .BLKW 1000 ;Disk Input buffer IBUF:: .BLKW 1000 ;Magtape Input buffer LKBLK:: .BLKW 4 ;Used in .LOOKUP's and magtape .SPFUN's DUMPIT::.BLKW 6 ;DUMP AREA FOR .SPFUN STOST:: .BLKW 4 ;DUMP AREA FOR .DSTATUS BLOK:: .WORD 0 ;STORAGE FOR BLOCK NUMBER BLOK1:: .WORD 0 ; FIL1 block number BLOK2:: .WORD 0 ; FIL2 block number EOF1:: .WORD 0 ; End of file on FIL1 EOF2:: .WORD 0 ; End of file on FIL2 EOD1:: .WORD 0 ; End of device on FIL1 EOD2:: .WORD 0 ; End of device on FIL2 $JSX =: 4 ;JSW extension VBGEX$ =: 200 ;may be run under VBGEXE ALL64$ =: 020 ;may crush simulated RMON $VBGTO =: 6 ;max settop value under VBGEXE .ASECT .=$JSX .WORD VBGEX$!ALL64$ .=$VBGTO .WORD 177774 ;BINCOM can't handle all of memory .=S$JSW .WORD JS.REE ;REENTER .SBTTL REGISTER PRESERVE ROUTINES ;+ ;SAVRG -- ROUTINE TO SAVE ALL REGISTERS .ENABLE GBL ;- .PSECT MAIN SAVRG: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV R4,-(SP) MOV 12(SP),-(SP) RTS R5 ;+ ;RSTRG -- ROUTINE TO RESTORE REGISTERS ;- RSTRG: TST (SP)+ MOV (SP)+,R4 MOV (SP)+,R3 MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 RTS R5 .SBTTL START UP AND RETRY CODE ;+ ; INITIALIZE AND PROCESS A COMMAND LINE. ;- BR RSTRT ;RE ENTRY POINT START:: MOV SP,SVSP ;FIRST TIME MUST PRESERVE STACK RSTRT:: MOV SVSP,SP ;RESTORE STACK .GTIM #IOAREA,#IOAREA ;CHECK FOR POSSIBLE DATE ROLLOVER .GVAL #IOAREA,#S.VER ;GET THE SYSTEM VERSION NUMBER BIC #^C377,R0 ;CLEAR THE UPDATE NUMBER CMP R0,#5 ;IS IT THE RIGHT VERSION? BGE 3$ ;BRANCH IF SO ;+ ;ERROR .ERR #ERAR,#ER80,LEVEL=E,RETURN=YES ;- CLR R0 ;HARD EXIT .EXIT ;GET OUT QUICK 3$: CLR WC.FLG ;CLEAR WILDCARDING FLAG CALL INIT ;GO CLEAN UP FOR A RESTART .CSISPC #OUTSP,#DFTYP,#0,#CMLB ;FETCH COMMAND LINE AND OPEN FILES BCC 5$ ;IF ERROR RETRY JMP INVCMD ; .ERR #ERAR,#EM5,LEVEL=E,RETURN=NO 5$: TSTB CMLB ;DID WE GET INPUT BNE 10$ ;IF NE YES .PRINT #VERSN ;ELSE PRINT VERSION # BR RSTRT ; AND START AGAIN 10$: MOV (SP)+,R2 ;GET # OF SWITCHES BEQ 33$ ;IF EQ NONE 15$: MOV #SWTAB,R3 ;POINT TO START OF SWITCH TABLE MOV #ACTAB,R4 ;POINT TO ACTION ROUTINE ADDRESS MOV (SP)+,R5 ;GET SWITCH BMI 20$ ;IF MI AN ARGUMENT IS NEXT ON STACK CLR -(SP) ;ELSE PRETEND THERE IS ONE 20$: BICB #40,R5 ;Convert it to uppercase ;DBF CMPB (R3)+,R5 ;IS THIS ONE THE SWITCH? BEQ 30$ ;IF EQ YES TST (R4)+ ;POINT TO NEXT ROUTINE BNE 20$ ;IF NE MORE SWITCHES IN TABLE TST R5 ;VALUE? BMI 25$ ;IF MI YES JMP $ER ;ELSE NO 25$: MOV (SP)+,R0 ;R0=VALUE JMP $ERR ;SPLIT 30$: MOV (SP)+,R0 ;GET ARGUMENT CALL @(R4)+ ;PROCESS IT SOB R2,15$ ;MORE SWITCHES?BR IF YES 33$: CLR DIFCNT ; initialize differences counter CLR LOGFLG ; clear the "Files compared" flag CLR NOFILS ; clear "number of files" counter BIT #FN.DEV,MOD ;/D USED? BEQ 34$ ;IF NOT, BRANCH CALL KPCHECK ;cannot do device operations on KP: CALL DEVDEV ;YES, PROCESS IT BR 47$ ;NO WILDCARDING FOR /D 34$: CALL WILCRD ;TEST FOR WILDCARDING TST WC.FLG ;ANY WILDCARDING? BEQ 35$ ;IF NOT, BRANCH CALL KPCHECK ;cannot do wildcard operations on KP: CALL WCDIO ;YES, SET UP FOR WILDCARDING BR 47$ ;BYPASS NON-WC PROCESSING 35$: .CSIGEN ,#DFTYP,#CMLB ;GO OPEN FILES MOVB @#$ERRBY,SAVERB ;SAVE FOR INVALID DEVICE CHECK ;IHZ BCC 45$ ;IF CC GOOD TSTB @#$ERRBY ;SEE IF ILLEGAL COMMAND LINE ; BNE 40$ ;IF NE NO ; .ERR #ERAR,#EM5,RETURN=NO,LEVEL=E BEQ 56$ ;?BINCOM-F-Invalid command 40$: CMPB @#$ERRBY,#ERFUC ;OUTPUT DEVICE FULL? BNE 45$ ;IF NE NO ;+ ;ERROR .ERR #ERAR,#EM1,RETURN=NO,LEVEL=E ;- 45$: MOV R0,LIM ;SAVE PROGRAM LIMIT 47$: MOV SVSP,SP ;GET RID OF SWITCHES TST WC.FLG ;WILDCARDING IN PROGRESS? BNE 60$ ;IF YES, BRANCH .WAIT #OUTF ;DO WE HAVE OUT FILE? BCC 55$ ;IF CC YES .FETCH LIM,#TTNAM ;SET CHANNEL TO DEFAULT TT BCS 50$ ;IF CC SUCCESSFUL MOV R0,LIM ;UPDATE LIMIT .LOOKUP #AREA,#OUTF,#TTNAM ;SET UP FOR OUTPUT TO TT BCC 55$ ;IF CC GOOD ;+ ;ERROR 50$: .ERR #ERAR,#EM1,LEVEL=E,RETURN=NO,FILE=#TTNAM ;- 55$: .WAIT #PATF ;DO WE HAVE PATCH FILE? BCS 60$ ;IF CS NO BIT #FN.DEV,MOD ;/D SPECIFIED? BEQ 58$ ;BRANCH IF NOT 56$: JMP INVCMD ; .ERR #ERAR,#EM5,RETURN=NO,LEVEL=E ;NO SIPP FILE WITH /D 58$: BIS #FN.PAT,MOD ;INDICATE PATCH FILE 60$: CMPB SAVERB,#ERDNC ;DEVICE IN SYSTEM TABLES? ;IHZ BNE 61$ ;IF NE YES ;IHZ ;+ ;ERROR .ERR #ERAR,#ER90,RETURN=NO,LEVEL=F ;IHZ ;- 61$: .WAIT #INF1 ;CHECK TO MAKE SURE FOR 2 INPUT FILES BCC 65$ ;IF CS ERROR ;+ ;ERROR .ERR #ERAR,#EM6,RETURN=NO,FILE=#IN1,LEVEL=E ;- 65$: .WAIT #INF2 ;CHECK FOR INPUT FILES BCC 70$ ;IF CS ERROR ;+ ;ERROR .ERR #ERAR,#EM6,RETURN=NO,FILE=#IN2,LEVEL=E ;- 70$: TST WC.FLG ;If wildcarding is in progress, USRLIM is BEQ 71$ ;already set up by WCDFET MOV WCEND,R1 ;GET BUFFER START FOR LISTFILE EVN R1 ;PUT ON A WORD BOUNDARY MOV USRLIM,R0 BR 74$ 71$: .SETTOP #-2 ;get as much memory as possible for dynamic TST (R0)+ ;buffers. MOV R0,USRLIM ;set up USRLIM MOV #LIM,R3 ;R3 -> WORD CONTAINING PROG LIMIT MOV (R3)+,R1 ;R1 -> FIRST BUFFER AREA WORD 74$: MOV R0,R5 ;SAVE LAST FREE WORD MOV R5,LASTFR ;SAVE FOR WILDCARDING SUB R1,R0 ;GET TOTAL BUFFER SIZE CMP R0,#6070 ;DO WE HAVE ENOUGH SPACE? used to be 10070 MSS BHI 85$ ;IF HI YES BIT #FN.PAT,MOD ;MAYBE WE DON'T NEED THAT MUCH BEQ 80$ ;IF EQ CHECK ;+ ;ERROR 75$: .ERR #ERAR,#ER10,LEVEL=E,RETURN=NO ;- 80$: CMP R0,#4050 ;NO PATCH BUFFER NEEDED - used to use 6050 MSS BHI 85$ ;IF HI WE'RE OK BR 75$ ;ELSE STILL TOO LITTLE CORE 85$: MOV R1,OUTBUF ;OUTBUF=OUTPUT BUFFER MOV R1,OUTBF ;OUTBF=1ST FREE LOCATION IN BUFFER ;what the heck are "2050" and "2020"? They ;must come from a calculation of the most that ;can ever be written in one shot from the ;ouput buffer to the output device.... MSS ADD #2050,R1 ;R1-> NEXT AVAILABLE BUFFER MOV R1,BUFSTR ;SAVE BUFFER START BIT #FN.PAT,MOD ;DO WE NEED A PATCH BUFFER? BEQ WCDSTR ;IF EQ NO MOV R1,PATBUF ;PATBUF->PATCH BUFFER ADD #2020,R1 ;R1-> NEXT AVAILABLE BUFFER MOV R1,BUFSTR ;SAVE BUFFER START .SBTTL WCDSTR - WILDCARD RESTART ;+ ; AFTER THE FIRST WILDCARD COMPARE, WILDCARDING WILL ; RETURN HERE TO PICK UP SUBSEQUENT FILE PAIRS ; FOR PROCESSING ;- WCDSTR:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$1 MOV (SP)+,R0 .ENDC ;NE MSS$DB TST WC.FLG ;WILDCARDING IN PROGRESS? BEQ 90$ ;IF NOT, BRANCH BIT #WC.NXT,WC.FLG ;FIRST TIME THROUGH WC? BNE 10$ ;NO, BRANCH BIS #WC.NXT,WC.FLG ;SAY FIRST TIME DONE BR 90$ ;CONTINUE 10$: CALL WCDINT ;WILDCARD INITIALIZATION CALL WCDLKI ;GO LOOKUP NEXT TWO INPUT FILES BIT #F2.WCD,MOD2 ;STILL WILDCARDING? BNE 20$ ;IF YES, BRANCH .CLOSE #OUTF ;NO, CLOSE LIST FILE JMP NEXT1 ;AND END 20$: TST LSTFIL ;LIST FILE SPECIFIED? BEQ 30$ ;IF NO, BRANCH CALL WCDPRT ;PRINT COMPARING MESSAGE 30$: MOV OUTBUF,OUTBF ;GET START OF OUTPUT BUFFER MOV BUFSTR,R1 ;GET START OF READ BUFS MOV LASTFR,R5 ;RESTORE LAST FREE WORD TO R5 90$: .DSTATU #AREA,#IN1 ;SEQUENTIAL ACCESS? TST AREA ;IF SO USE SINGLE BLOCK OPERATIONS BPL 100$ ;SINGLE BLOCKS 95$: .DSTATU #AREA,#IN2 ;SEQUENTIAL ACCESS? TST AREA ;IF SO SINGLE READS BMI 105$ ;IF NE NO 100$: MOV #1000,R2 ;BUFF SIZE BR 110$ ;MERGE BELOW 105$: MOV R1,R2 ;CALCULATE SIZE OF EACH READ BUF NEG R2 ;(LIM-R1)/2 ADD R5,R2 ;CALCULATE ASR R2 ;R2=SIZE BIC #100000,R2 ;COMPENSATE SIGN BIT 110$: MOV R1,BUF1 ;BUF1->READ BUFFER 1 CLRB R2 ;CALCULATE #BLOCKS SWAB R2 ;CALC ASR R2 ;R2 NOW =BLOCKS MOV R2,NMBLK ; MOV R2,NMBL ;BLOCK CALC NMBLK SWAB R2 ;R2=# IN BLOCKS ASL R2 ;R2 = # BYTES IN BLOCK ADD R2,R1 ;R1->ADDRESS OF BUFFER 2 MOV R1,BUF2 ;BUF2->BUFFER 2 MOV R1,R0 ;SET UP TO RELEASE ANY XTRA SPACE ADD R2,R0 ;R0 = LAST USED WORD ASR R2 ;WORDS NOT BYTES MOV R2,CNT ;CNT =SIZE TST (R0)+ ; .SETTOP MOV STBL,BLK ;FILL IN STARTING BLOCK # SUB NMBLK,BLK ;ADJUST MOV NMBLK,SAV ;SAV NMBLK FOR LATER USE MOV OUTBF,R1 ;R1->BUFFER CALL $HEAD ;PUT HEADER IN OUTPUT BUFFER MOV R1,OUTBF ;UPDATE BUFFER POINTER BIT #FN.PAT,MOD ;PATCH FILE? BEQ 115$ ;IF EQ NO CALL $SPPIN ;INITIALIZE BUFFER MOV R1,PATBF ;UPDATE PATBF 115$: CALL READ ;GO START READING .SBTTL FINISH UP ROUTINE ;+ ; THIS ROUTINE FINISHES THE CURRENT OPERATION AND ; SOLICITS A NEW COMMAND LINE. ;- DONE:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$2 MOV (SP)+,R0 .ENDC ;NE MSS$DB CMP OUTBUF,OUTBF ;IS WRITE BUFFER EMPTY? BEQ 10$ ;IF EQ YES TSTB MOD ;SEE IF FILES ARE DIFFERENT BPL 10$ ;IF PL NO,SO DON'T WRITE ANYTHING BIT #FN.SUP,MOD ;SUPPRESS LISTING? BNE 5$ ;IF NE YES CALL PROUT ;GO WRITE IT BR 10$ 5$: BIT #F2.WCD,MOD2 ;WILDCARDING IN PROGRESS? BEQ 10$ ;IF NO, BRANCH CALL WCDPRT ;YES, PRINT COMPARING MSG 10$: BIT #FN.FL1,MOD ;FILE 2 LONGER? BEQ 15$ ;IF EQ NO BIT #FN.DEV,MOD ;/D USED? BEQ 12$ ;IF NOT, BRANCH ;+ ;ERROR .ERR #ERAR,#ER40,LEVEL=W,RETURN=YES,FILE=#IN2 ;- BR 20$ ;+ ;ERROR 12$: .ERR #ERAR,#EM7,LEVEL=W,RETURN=YES,FILE=#IN2 ;- BR 20$ ;MERGE BELOW 15$: BIT #FN.FL2,MOD ;IS FILE 1 LONGER? BEQ 20$ ;IF EQ NO BIT #FN.DEV,MOD ;/D USED? BEQ 17$ ;IF NOT, BRANCH ;+ ;ERROR .ERR #ERAR,#ER40,LEVEL=W,RETURN=YES,FILE=#IN1 ;- BR 20$ ;+ ;ERROR 17$: .ERR #ERAR,#EM7,LEVEL=W,RETURN=YES,FILE=#IN1 ;- 20$: BIT #FN.PAT,MOD ;PATCH FILE? BEQ CLS ;IF EQ NO TSTB MOD ;DIFFERENCES? BPL CLS ;IF PL NO MOV PATBF,R1 ;R1 -> NEXT FREE SPOT MOVB #'Y,-3(R1) ;INSERT TERMINATOR MOVB #'^,(R1)+ ;Put in the '^' MOVB #'C,(R1)+ ; followed by a 'C' MOVB #C.CR,(R1)+ ; MOVB #C.LF,(R1)+ ; MOV R1,PATBF ;GO WRITE THE BUFFER CALL PRESP ;GO WRITE THE BUFFER CLS: INC NOFILS ;Count files compared TSTB MOD ;DIFFERENCES? BPL 10$ ;IF PL NO INC DIFCNT BIT #FN.DEV,MOD ;/D USED? BEQ 3$ ;IF NOT, BRANCH ;+ ;ERROR .ERR #ERAR,#ER30,LEVEL=W,RETURN=YES ;- BR 4$ ;+ ;ERROR 3$: .ERR #ERAR,#EM8,LEVEL=W,RETURN=YES ;- 4$: BIT #FN.SUP,MOD ;SUPPRESS OUT FILE? BNE 51$ ;IF NE YES TST WC.FLG ;WILDCARDING IN PROGRESS? BNE 5$ ;IF YES, BRANCH .CLOSE #OUTF ;CLOSE FILE BCC 5$ ;IF ERROR MUST BE PROTECTION CMPB @#$ERRBY,#3 ;PROTECTION? BNE 5$ ;IF NE NO ;+ ;ERROR .ERR #ERAR,#ER20,LEVEL=W,RETURN=YES,FILE=#OUTSP ;- 5$: .SETTOP LIM ;FREE CORE 51$: BR NXT ;FINISH UP 10$: BIT #F2.WCD,MOD2 ;WILDCARDING IN PROGRESS? BEQ 11$ ;IF NO, BRANCH TST LSTFIL ;LIST FILE WANTED? BNE 11$ ;IF YES, BRANCH CALL WCDPRT ;PRINT COMPARING MESSAGE ;+ ;ERROR 11$: .ERR #ERAR,#EM9,LEVEL=I,RETURN=YES ;- 12$: BIT #FN.CRF,MOD ;create output file no matter what? BEQ 20$ ;Branch if not... BIT #FN.ADF,MOD ;Were any files already different? BNE 21$ ;Branch if so MOV OUTBUF,R1 ;GET BUFFER ADDRESS CLR @R1 ;NULL 1 WORD MOV #OUTSP,R2 ;R2->FILE SPEC .WRITW #AREA,#OUTF,R1,#1,WBLK BCC 21$ ;BRANCH IF NO ERROR 15$: JMP $WER ;PRINT ERROR 20$: BIT #FN.ADF,MOD ;Any file different? BEQ NEXT ;Branch if not 21$: TST WC.FLG ;WILDCARDING IN PROGRESS? BNE NEXT ;IF YES, BRANCH .CLOSE #OUTF ;SAVE IT BCC 25$ ;IF CC NO ERROR CMPB @#$ERRBY,#3 ;PROTECTION? BNE 25$ ;IF NE NO ;+ ;ERROR .ERR #ERAR,#ER20,LEVEL=W,RETURN=YES,FILE=#OUTSP ;- 25$: BIT #FN.CRP,MOD ;CREATE PATCH ANYWAY? BEQ NEXT ;IF EQ NO MOV PATBUF,R1 ;GET BUFFER CLR @R1 ;NULL 1 WORD MOV #PATSP,R2 ;R2 -> FILE SPEC .WRITW #AREA,#PATF,R1,#1,PBLK BCS 15$ ;IF CS ERROR NXT: .CLOSE #PATF ;CLOSE PATCH FILE TOO BCC NEXT ;IF CC NO ERROR CMPB @#$ERRBY,#3 ;PROTECTION? BNE NEXT ;IF NE NO ;+ ;ERROR .ERR #ERAR,#ER20,LEVEL=W,RETURN=YES,FILE=#PATSP ;- NEXT: TST WC.FLG ;WILDCARDING IN PROGRESS? BEQ NEXT1 ;NO, BRANCH JMP WCDSTR ;YES, RETURN TO WC START NEXT1: TST DIFCNT ;Any files different? BEQ 10$ ;Nope... BISB #WARN$,@#$USRRB ;Yes, set warning level 10$: .CLOSE #INF1 ;CLOSE INPUT FILES .CLOSE #INF2 ;(NON-WC) JMP RSTRT ;SOLICIT CML .SBTTL ACTION ROUTINES FOR SWITCHES ;+ ; ; THESE ROUTINES WILL TAKE CARE OF INDICATING ; WHAT OPTIONS WERE SPECIFIED. ; ;- BYT: BIS #FN.BYT,MOD ;/B -- SO INDICATE BYTE MODE TST R5 ;VALUE? BMI $ERR ;IF MI YES--ERROR RETURN ;AND SPLIT ENB: MOV R0,ENBL ;/E -- SO FILL IN END BLOCK TST R5 ;VALUE? BPL $ER ;IF PL NO--ERROR BIS #F2.ENB,MOD2 ;INDICATE /E USED MOV ENBL,ENBSAV ;SAVE END BLOCK RETURN ;AND SPLIT HEL: MOV #HELPFL,R0 ;R0 -> HELP FILE MOV #HLP,R1 ;R1 -> 2ND LINE IN HELPFILE SUB R0,R1 ;R1 = LENGTH OF LINE MOV #16.,R2 ;R2 = LOOP COUNT 10$: .PRINT ;OPTION LIST ADD R1,R0 ;POINT TO NEXT LINE SOB R2,10$ ;LOOP CALL RSTRT ;GET NEXT CML CRF: TST R5 ;VALUE? BMI $ERR ;IF MI YES--ERROR SWAB R5 ;CHECK WHICH FILE TSTB R5 ;OUT FILE BNE 5$ ;IF NE NO BIS #FN.CRF,MOD ;SAY SO BR 15$ ;AND SPLIT 5$: CMPB #1,R5 ;/O associated with PATCH FILE? BEQ 10$ ;Branch if yes. BIS #FN.CRF,MOD ;If not, must want both 10$: BIT #FN.PAT,MOD ; SIPP filespec exists? BEQ 15$ BIS #FN.CRP,MOD ;SET PATCH FILE BIT 15$: RETURN ;SPLIT SUP: BIS #FN.SUP,MOD ;/Q -- INDICATE IN MODE TST R5 ;VALUE? BMI $ERR ;IF MI YES--ERROR RETURN ;AND SPLIT STB: MOV R0,STBL ;/S -- FILL IN START BLOCK# TST R5 ;VALUE? BPL $ER ;IF PL NO--ERROR BIS #F2.STB,MOD2 ;INDICATE /S USED MOV STBL,STBSAV ;SAVE START BLOCK RETURN ;AND SPLIT DEV: TST R5 ;/D -- VALUE? BMI $ERR ;IF MI, ERROR BIS #FN.DEV,MOD ;INDICATE /D USED RETURN ;RETURN $ERR: MOV #16.+EM.EM0,R1 ;FIX UP ERROR MESSAGE MOVB R5,(R1)+ ;PUT IN SWITCH MOVB #':,(R1)+ ;PUT IN : MOV R1,R3 ;SAVE ADDRESS CLR (R3)+ ;BLANK OUT # FIELD FIRST CLR (R3)+ ;BLANK OUT # FIELD FIRST CLR (R3)+ ;BLANK OUT # FIELD FIRST MOV R1,R3 ;SAVE ADDRESS MOV #CMLB,R1 ;SCRATCH AREA CALL OCTOUT ;CONVERT VALUE AND PUT IT IN MOV #CMLB,R1 ;R1 ->SCRATCH MOV #5,R2 ;SET UP LOOP 5$: CMPB #60,(R1)+ ;A LEADING 0 BNE 10$ ;IF NE NO SOB R2,5$ ;LOOP TSTB (R2)+ ;ADJUST R2 BR 15$ ;GO LOOP 10$: CMPB -(R1),(R2)+ ;ADJUST R1,R2 15$: MOVB (R1)+,(R3)+ ;PUT IN DIGIT SOB R2,15$ ;LOOP ;+ ;ERROR ER: .ERR #ERAR,#EM0,LEVEL=E,RETURN=NO ;- $ER: MOV #16.+EM.EM0,R1 ;R1 POINTS TO SPOT IN MESSAGE MOVB R5,(R1)+ ;PUT IN SWITCH CLRB (R1)+ ;NULL OUT REST CLR (R1)+ ;NULL CLR (R1)+ ;NULL CLR (R1)+ ;NULL BR ER ;SPLIT .SBTTL INITIALIZATION FOR NEXT CSIGEN ;+ ; ; THIS ROUTINE WILL REINITIALIZE FOR ; THE NEXT COMMAND LINE THE USER TYPES IN ; ;- INIT:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$3 MOV (SP)+,R0 .ENDC ;NE MSS$DB .SRESET ;UNLOAD DEVICE HANDLERS (NON-WC) MOV #STBL,R0 ;FILL IN FIRST ADDRESS CLR (R0)+ ;STARTING BLOCK # (STBL) MOV #177776,(R0)+ ;ENDING BLOCK # (ENBL) ;034 CLR (R0)+ ;SWITCH WORD (MOD) CLR (R0)+ ;INDICATOR WORD (IND) CLR (R0)+ ;SHORT READ BLOCK #'S (NMBL) CLR (R0)+ ;SIPP SAVE BLOCK # (SAV1) MOV #-1,(R0)+ ;SIPP SAVE OFFSET (SAV2) CLR (R0)+ ;SWITCH WORD 2 (MOD2) MOV #PBLK,R0 ;SIPP DATA CLR (R0)+ ;SIPP BLOCK NUMBER (PBLK) CLR (R0)+ ;OUTPUT BLOCK # (WBLK) CLR (R0)+ ;CURRENT BLOCK NUMBER (BLK) MOV #-1,(R0)+ ;SAVE BLOCK (SBLK) RETURN ;SPLIT .SBTTL READ - BINCOM READ routine ;+ ; THIS ROUTINE READS FROM THE FILES ; AND CALLS THE COMPARE ROUTINE ;- READ:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$4 MOV (SP)+,R0 .ENDC ;NE MSS$DB CLR EOF1 CLR EOF2 ; Get device size for FIL1 .DSTATU #STOST,#IN1 ;GET DEVICE INFORMATION MOV STOST+6,BLOK1 ;SAVE DEVICE SIZE BIT #400,STOST ;VAR SIZED VOLUME ? BEQ 2$ ; No, BLOK is OK .SPFUN #DUMPIT,#INF1,#373,#BLOK1,CNT,BLK 2$: .DSTATU #STOST,#IN2 ;GET DEVICE INFORMATION MOV STOST+6,BLOK2 ;SAVE DEVICE SIZE BIT #400,STOST ;VAR SIZED VOLUME ? BEQ 10$ ; No, BLOK is OK .SPFUN #DUMPIT,#INF2,#373,#BLOK2,CNT,BLK 10$: BIT #FN.DEV,MOD ;If this is a device BNE 15$ ;comparison, ignore length ;difference until later. BIT #FN.FL1!FN.FL2!FN.DIF,MOD ;IS THERE A LENGTH DIFFERENCE? BEQ 15$ ;IF EQ NO RETURN ;BYE BYE 15$: ADD NMBLK,BLK ;POINT TO NEXT BLOCK CMP BLK,ENBL ;PAST LAST BLOCK? BLOS 16$ ;BR IF NOT MOV #1,EOF1 ;SAY EOF IN FILE 1 MOV #1,EOF2 ;SAY EOF IN FILE 2 JMP 60$ ;IF TOO BIG 16$: MOV BLK,R5 ;R5=BLK# ADD NMBLK,R5 ;UPDATE BCS 17$ ;If we overflow, then we'll pass ENBL ;034 CMP R5,ENBL ;SEE IF NEXT READ WILL PASS ENBL BLOS 20$ ;IF MI NO 17$: MOV ENBL,R5 ;CALCULATE NEW CNT ;034 SUB BLK,R5 ;R5=ENBL-BLK INC R5 ; +1 MOV R5,NMBLK ;UPDATE NMBLK SWAB R5 ;CALCULATE MOV R5,CNT ;UPDATE CNT 20$: CLR NBUF1 ; Init word count for this READ TST EOF1 ; Is FIL1 already at EOF ? BNE 30$ ; Yes, don't READ past EOF TST EOD1 ; Is FIL1 already at EOD ? BNE 30$ ; Yes, set EOF1 MOV BUF1,R0 ; Get addr of FIL1 buffer CALL CLRBFR ; Clear buffer in case of short READ .READW #AREA,#INF1,BUF1,CNT,BLK MOV R0,NBUF1 ; NBUF1 = # WORDS READ IN BCC 35$ ;IF CC READ IS PROGRESSING TSTB @#$ERRBY ;Are we at EOF ? BEQ 30$ ; Yes, check status of other file CMPB @#$ERRBY,#1 ; Are we at EOD (End Of Device) ? BNE ERR01 ; No, must be an I/O error TST BLOK1 ; Do we know the size of this volume ? BEQ 25$ ; No, accept EOD MOV CNT,R0 ; R0 = WORD COUNT JUST ATTEMPTED TO READ SWAB R0 ; R0 = BLOCK COUNT JUST ATTEMPTED TO READ ADD BLK,R0 ; R0 = HIGH BLOCK JUST ATTEMPTED TO ACCESS BCS 25$ ;If sign changed, we're past end-of-volume CMP BLOK1,R0 ; Did we go past end of device ? BHIS ERR01 ; No, must be I/O error 25$: MOV #1,EOD1 ; Say we reached EOD BR 35$ ; proceed ; EOF on FIL1 30$: MOV #1,EOF1 ;SAY EOF IN FILE 1 ; READ of FIL1 completed OK 35$: 40$: CLR NBUF2 ; Init word count for this READ TST EOF2 ; Is FIL2 already at EOF ? BNE 50$ ; Yes, don't READ past EOF TST EOD2 ; Is FIL2 already at EOD ? BNE 50$ ; Yes, Set EOF2 MOV BUF2,R0 ; Get addr of FIL2 buffer CALL CLRBFR ; Clear buffer in case of short READ .READW #AREA,#INF2,BUF2,CNT,BLK MOV R0,NBUF2 ; NBUF2 = # of words READ BCC 55$ ; OK, compare buffers TSTB @#$ERRBY ; Have we reached EOF ? BEQ 50$ ; Yes, set EOF2 CMPB @#$ERRBY,#1 ; Have we reached EOD (END OF DEVICE) ? BNE ERR02 ; No, must be I/O error TST BLOK2 ; Do we know the size of this volume ? BEQ 45$ ; No, accept EOD MOV CNT,R0 ; R0 = # words just attempted to READ SWAB R0 ; R0 = # blocks just attempted to READ ADD BLK,R0 ; R0 = Block # just attempted to access BCS 45$ ;If sign changed, we're past end-of-volume CMP BLOK2,R0 ; Did we go past end of device ? BHIS ERR02 ; No, must be real error 45$: MOV #1,EOD2 ; FIL2 is at EOD BR 55$ ; EOF on FIL2 50$: MOV #1,EOF2 ; Show EOF on FIL2 ; READ of FIL2 completed OK 55$: ; Compare the buffers TST NBUF1 ; Anything from FIL1 to compare ? BEQ 60$ ; No, take EXIT path TST NBUF2 ; Anything from FIL2 to compare ? BEQ 60$ ; No, take EXIT path CALL WRF ; Compare the buffers JMP 10$ ; READ until EOF'S ; EXIT path, at least one file has run dry 60$: MOV #FN.FL2,R0 ; Assume FIL2 is shorter TST EOF1 ; Is FIL1 at EOF ? BEQ 70$ ; No, FIL2 must be MOV #FN.FL1,R0 ; Assume FIL1 is shorter TST EOF2 ; Is FIL2 at EOF ? BEQ 70$ ; No, FIL1 is shorter CLR R0 ; FIL1 = FIL2 70$: BIS R0,MOD ; Set FIL1/FIL2 bits SUB NMBLK,BLK ; ADJUST TO FINISH SIPP RETURN ;+ ;ERROR ERR01: .ERR #ERAR,#EM3,LEVEL=E,RETURN=NO,FILE=#IN1 ; INPUT ERROR ERR02: .ERR #ERAR,#EM3,LEVEL=E,RETURN=NO,FILE=#IN2 ; INPUT ERROR ;- .SBTTL COMPARISON ROUTINE ;+ ; ; THIS ROUTINE DOES THE COMPARISONS ; AND WHEN IT FINDS A DIFFERENCE, ; IT CALLS THE DIFFERENCE AND SIPP ; ROUTINES. ; ;- WRF:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$5 MOV (SP)+,R0 .ENDC ;NE MSS$DB JSR R5,SAVRG ;SAVE REGISTERS CALL $SETUP ;GO SET UP LOOP MOV BUF1,R5 ;GET ADDRESS OF BUFFER 1 MOV BUF2,R3 ;GET ADDRESS OF BUFFER 2 TST MOD ;BYTE MODE? BMI OLP2 ;IF MI YES LOOP1: CMP (R5)+,(R3)+ ;IS WORD THE SAME? BEQ 10$ ;IF EQ YES BIT #FN.PAT,MOD ;PATCH FILE? BEQ 5$ ;IF EQ NO CALL $SIPP ;GO WRITE OUT THE DIFFERENCE 5$: CALL DIFF ;GO AND PREPARE OUTPUT LINES 10$: SOB R4,LOOP1 ;LOOP BACK UP MOV #400,R4 ;RESET R4 SOB R2,LOOP1 ; AND LOOP BR FIN ;NEXT READ OLP2: ASL R4 ;SET LOOP COUNT FOR BYTE MODE LOOP2: CMPB (R3)+,(R5)+ ;COMPARE BYTES BEQ 30$ ;IF EQ SAME BIT #FN.PAT,MOD ;PATCH FILE? BEQ 20$ ;IF EQ NO CALL $SIPP ;GO WRITE OUT THE DIFFERENCE 20$: CALL DIFF ;OUTPUT LINES 30$: SOB R4,LOOP2 ;LOOP MOV #400,R4 ;RESET R4 SOB R2,OLP2 ; AND LOOP FIN: MOV R3,STBL ;SAVE POINTER FOR FUTURE GENERATIONS JSR R5,RSTRG ;RESTORE REGISTERS RETURN ;AND SPLIT .SBTTL SET UP OUTPUT LINE ROUTINE ;+ ; ; THIS ROUTINE WILL SET UP THE OUTPUT LINE ; ;- DIFF:: .IF NE MSS$DB MOV R0,-(SP) ; .PRINT #MSS$6 MOV (SP)+,R0 .ENDC ;NE MSS$DB JSR R5,SAVRG ;SAVE REGISTERS MOV OUTBF,R1 ;R1->OUTPUT BUFFER EVN R1 ;ALIGN LAB: .IF NE MSS$DB MOV R0,-(SP) ; .PRINT #MSS$7 MOV (SP)+,R0 .ENDC ;NE MSS$DB MOV BLK,-(SP) ;PUSH BLK ADD NMBL,@SP ;ADD NMBLK SUB R2,@SP ;-LOOP COUNT BIT #FN.SUP,MOD ;SUPPRESS OUTPUT? BNE $FN ;IF NE YES CMP @SP,SBLK ;SAME BLOCK# BNE 50$ ;IF NE NO MOV #ASCB,R0 ;BLOCK OUT BLOCK# MOV @R0,(R1)+ ;BLANK OUT THE FIELD MOV @R0,(R1)+ MOV @R0,(R1)+ MOVB @R0,(R1)+ BR 60$ ;AND MERGE BELOW 50$: MOV @SP,R0 ;R0=BLOCK # CALL OCTOUT ;CONVERT 60$: MOVB #C.TAB,(R1)+ ;LEAVE BLANK IN STRING MOV R1,-(SP) ;SAVE POSITION IN OUTPUT STRING TST MOD ;BYTE MOD? BMI 70$ ;IF MI YES MOV #400,R0 ;COMPUTE OFFSET SUB R4,R0 ;R0=WORD OFFSET ASL R0 ;R0=ACTUAL BYTE OFFSET BR 80$ ;MERGE BELOW 70$: MOV #1000,R0 ;CALCULATE OFFSET SUB R4,R0 ;CALCULATE 80$: MOV #CMLB,R1 ;POINT TO SCRATCH AREA CALL OCTOUT ;CONVERT TO ASCII MOV #CMLB+3,R2 ;ONLY WANT LOW BYTE MOV (SP)+,R1 ;RESET R1 MOVB (R2)+,(R1)+ ;GET LAST 2 DIGITS MOVB (R2)+,(R1)+ ;GET LAST 2 DIGITS MOVB (R2)+,(R1)+ ;GET LAST 2 DIGITS MOVB #'/,(R1)+ ;FILL IN '/ ' IN OUTPUT STRING MOVB #C.TAB,(R1)+ ;TAB CLRB (R1)+ TST MOD ;ARE WE IN BYTE MODE? BMI BTM ;IF NE YES MOV -(R5),R0 ;GET WORD IN FILE 1 CALL OCTOUT ;CONVERT MOVB #C.TAB,(R1)+ ;KEEP BLANK MOV -(R3),R0 ;GET WORD IN FILE 2 CALL OCTOUT ;CONVERT MOVB #C.TAB,(R1)+ ;KEEP BLANK XOR R3,R5 ;GET THE XOR MOV (R5),R0 ;PREPARE TO CONVERT CALL OCTOUT ;CONVERT EVN R1 ;ALIGN MOVB #C.CR,(R1)+ ;INSERT A MOVB #C.LF,(R1)+ ;INSERT A OUT: MOV R1,-(SP) ;FIND OUT IF BUFFER IS FULL SUB OUTBUF,@SP ;@SP=AMOUNT USED CMP (SP)+,#2000 ;BUFFER FULL? BMI $FN ;IF MI NO MOV #CMLB,R2 ;SAVE IN CMLB MOV OUTBF,R4 ;R4->START OF LINE CALL SVLN ;SAVE LAST LINE CALL PROUT ;GO WRITE IT MOV #CMLB,R4 ;R4=FROM MOV OUTBUF,R2 ;R2=TO CALL SVLN ;UPDATE LINE MOV R2,R1 ;FIX POINTER $FN: MOV R1,OUTBF ;UPDATE OUTBF BIS #FN.DFT,MOD ;INDICATE FILES ARE DIFFERENT BIS #FN.ADF,MOD ;INDICATE FILES ARE DIFFERENT MOV (SP)+,SBLK ;UPDATE SAVED BLOCK # JSR R5,RSTRG ;RESTORE REGISTERS RETURN ;AND RETURN WITH A JOB WELL DONE SVLN: MOV R1,R5 ;SET UP TO SAVE LAST LINE SUB OUTBF,R5 ;R5 =#OF BYTES TOSAVE 10$: MOVB (R4)+,(R2)+ ;SAVE IT SOB R5,10$ ;LOOP RETURN ;RETURN BTM: MOVB -(R5),R0 ;GET FILE 1 BYTE BIC #400,R0 ;ALLOW FOR SIGN EXTEND MOV R1,R4 ;SAVE STRING POINTER CALL PRBYT ;CONVERT BYTE MOVB -(R3),R0 ;GET FILE 2 BYTE BIC #400,R0 ;ALLOW FOR SIGN EXTEND CALL PRBYT ;CONVERT BYTE XORB R3,R5 ;GET XOR MOVB (R5),R0 ;SET UP TO CONVERT BIC #400,R0 ;ALLOW FOR SIGN EXTEND CALL PRBYT ;CONVERT IT MOVB #C.CR,(R4)+ ;INSERT A MOVB #C.LF,(R4)+ ; and MOV R4,R1 ;UPDATE R1 BR OUT ;AND SPLIT WITH A JOB WELL DONE PRBYT: MOV #CMLB,R1 ;GET SCRATCH AREA CALL OCTOUT ;CONVERT MOV #CMLB+3,R2 ;POINT TO FIRST CHARACTER OF BYTE MOVB (R2)+,(R4)+ ;PUT IT IN OUTPUT STRING MOVB (R2)+,(R4)+ ;PUT IT IN OUTPUT STRING MOVB (R2)+,(R4)+ ; MOVB (R2)+,(R4)+ ;FILL ER UP RETURN ;SPLIT .SBTTL OCTAL TO ASCII OUTPUT ROUTINE ;+ ; R0 = UNSIGNED # TO BE CONVERTED ; R1 -> ADDR OF AREA TO PLACE THE 6 ASCII DIGITS ; A TAB IS LEFT AFTER THE NUMBER & R1 -> TAB CHARACTER ;- OCTOUT: .IF NE MSS$DB MOV R0,-(SP) ; .PRINT #MSS$8 MOV (SP)+,R0 .ENDC ;NE MSS$DB MOVB #30,@R1 SEC ;NOT NEEDED IF C=1 ON ENTRY 5$: ROL R0 ROLB (R1)+ MOVB #206,@R1 10$: ASL R0 BEQ 15$ ;IF 0 THEN DONE ROLB @R1 BCS 10$ BR 5$ 15$: MOVB #C.TAB,@R1 ;CHANGE 206 TO A TAB RETURN .SBTTL CLRBFR Clear a file buffer ; Call with: ; R0 -> Start of buffer ; CNT = Length of buffer (words) ; Returns: ; Buffer cleared ; Registers preserved CLRBFR: MOV R0,-(SP) MOV R1,-(SP) MOV CNT,R1 10$: CLR (R0)+ SOB R1,10$ MOV (SP)+,R1 MOV (SP)+,R0 RETURN .SBTTL WRITE A BUFFER ROUTINE ;+ ; ; THIS ROUTINE WILL WRITE THE SPECIFIED BUFFER TO ; THE SPECIFIED CHANNEL. ; ; INPUT: R2 -> FILE SPEC ; R0 -> FIRST FREE BYTE IN OUTPUT BUFFER ; R3 -> START OF BUFFER ; R4 -> BLOCK # TO BE WRITTEN TO ; R5 = CHANNEL TO WRITE TO ; OUTPUT: R1 = #WORDS WRITTEN ; ;- .ENABL LSB WRITBF: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$9 MOV (SP)+,R0 .ENDC ;NE MSS$DB EVN R0 ;CAN'T WRITE AN ODD BYTE MOV R0,-(SP) ;SAVE R0 MOV R3,R1 ;R1 = WORD COUNT ADD #2000,R1 ;R1=END OF BUFFER ADDRESS SUB R0,R1 ;R1 = WORD COUNT BEQ 21$ 20$: CLRB (R0)+ ;CLEAR OUT REST OF BUFFER SOB R1,20$ ;LOOP UNTIL DONE 21$: MOV (SP)+,R1 ;RESTORE R1 SUB R3,R1 ;R1=#BYTES TO WRITE ASR R1 ;R1=WORDS BIT #F2.WCD,MOD2 ;WILDCARDING IN PROGRESS? BEQ 30$ ;IF NOT, BRANCH CMP R1,#1000 ;IS BUFFER FILLED? BEQ 30$ ;IF YES, BRANCH MOV #1000,R1 ;NO, FILL IT 30$: .WRITW #AREA,R5,R3,R1,(R4) BCC 10$ ;IF CC GOOD $WER: TSTB @#$ERRBY ;EOF? BNE 5$ ;IF EQ YES ;+ ;ERROR .ERR #ERAR,#EM2,LEVEL=E,FILE=R2,RETURN=NO 5$: .ERR #ERAR,#EM4,LEVEL=E,FILE=R2,RETURN=NO ;- 10$: ADD #2,(R4) ;UPDATE BLOCK WRITTEN TO RETURN ;AND SPLIT .DSABL LSB .SBTTL HEADER ROUTINE ;+ ; ; THIS ROUTINE WILL INITIALIZE THE OUTPUT BUFFER ; SO THAT THE FIRST LINE PRINTED IS OF THE FORM: ; BINCOM COMPARING DD:FILENAM.TYP -- DD:FILENAM .TYP ; ; INPUT: R1 -> THE FIRST CHARACTER IN THE OUTPUT BUFFER ; R0 AND R2 ARE ALTERED ; ; OUTPUT: R1 -> POINT TO NEXT AVAILABLE CHARACTER IN BUFFER ; ;- .ENABL LSB $HEAD:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$10 MOV (SP)+,R0 .ENDC ;NE MSS$DB MOV R3,-(SP) MOV R4,-(SP) MOV R1,R3 ; save original output pointer MOV #HFMT1,R4 ; point to output format info BIT #FN.SUP,MOD ; /QUIET? BNE 10$ MOVB #C.CR,(R1)+ ;END WITH MOVB #C.LF,(R1)+ ;BLANK LINE BR 12$ 10$: MOV #HFMT2,R4 ; point to alternate format info 12$: MOV @R4,R0 ;R0->HEADER 20$: TSTB @R0 ;TERMINATED BY NULL BEQ 22$ MOVB (R0)+,(R1)+ ;MOVE FIRST PART OF HEADER TO BUFFER BR 20$ 22$: MOV #IN1,R0 ;R0->FIRST RAD50 FILE BLOCK CALL $FNASC ;CONVERT IT TO ASCII 30$: MOV R1,-(SP) ; current output pointer SUB R3,@SP ; compute how many chars out so far CMP (SP)+,4(R4) ; enough? BHI 40$ ; if so, proceed. MOVB #C.SPAC,(R1)+ ; Otherwise, pad with some blanks BR 30$ 40$: MOV 2(R4),R0 ;POINT TO SEPARATOR STRING 50$: MOVB (R0)+,(R1)+ ;AND MOVE IT INTO THE BUFFER TSTB @R0 BNE 50$ MOV #IN2,R0 ;R0->SECOND RAD50 FILE BLOCK CALL $FNASC ;CONVERT IT TO ASCII BIT #FN.SUP,MOD ; /QUIET? BNE 60$ MOVB #C.CR,(R1)+ ;BLANK LINE MOVB #C.LF,(R1)+ ;BLANK LINE 60$: CLRB (R1)+ ;Null terminate it MOV (SP)+,R4 MOV (SP)+,R3 RETURN ;AND SPLIT WITH A JOB WELL DONE .DSABL LSB .SBTTL SIPP LINE ROUTINE ;+ ; ; THIS ROUTINE WILL PROCESS A WORD OR BYTE DIFFERENCE ; INTO A SIPP COMMAND LINE AND PLACE IT IN THE SIPP ; BUFFER AREA. IN ADDITION IT WILL CHECK IF THE BUFFER ; IS FULL AND IF SO WILL WRITE IT OUT. ; ; INPUTS: R5 -> WORD OR BYTE IN FILE 1 ; R3 -> WORD OR BYTE IN FILE 2 ; R4 -> LOOP COUNTER FROM WHICH ; CAN BE CALCULATED. ; OUTPUT: ALL REGISTERS ARE SAVED AND RESTORED ; ;- $SIPP:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$11 MOV (SP)+,R0 .ENDC ;NE MSS$DB JSR R5,SAVRG ;SAVE REGISTERS MOV PATBF,R1 ;R1 -> NEXT SPOT IN BUFFER MOV BLK,R0 ;CALC BLOCK# ADD NMBL,R0 ;CALC SUB R2,R0 ;R0=BLK# MOV #400,-(SP) ;CALCULATE OFFSET TST MOD ;BYTE MODE? BMI 5$ ;IF MI YES SUB R4,@SP ;CALCULATE OFFSET FOR WORDS ASL @SP ;SP -> OFFSET BR 10$ ;MERGE BELOW 5$: ASL @SP ;ADJUST FOR BYTE CALC SUB R4,@SP ;R0=OFFSET 10$: SWAB @SP ;HIGH ORDER BYTE IS OFFSET ASL R0 ;ADJUST FOR BYTES BISB R0,@SP ;MAKE LOW ORDER BYTES THE SAME CLRB R0 ;CLEAR LOW BYTE SWAB R0 ;R0=HIGH BYTE OF BLOCK # SWAB @SP ;@SP=LOW BYTE OF BLOCK FOLLOWED BY OFFSET ROL @SP ;GET LAST BIT OF LOW ORDER WORD ROL R0 ;AND SHIFT IT INTO HIGH WORD CLC ;CLEAR CARRY SO WE CAN ROR @SP ;GET RID OF LAST BIT IN LOW WORD CMP R0,SAV1 ;NEXT LOCATION CONSECUTIVE? BNE 15$ ;IF NE NO CMP @SP,SAV2 ;NEXT LOCATION CONSECUTIVE? BNE 15$ ;IF NE NO ADD #2,SAV2 ;UPDATE SAVED OFFSET TST (SP)+ ;POP OFFSET SUB #4,R1 ;ERASE ^Z MOV R1,PATBF ;UPDATE PATBF IN CASE WE WRITE BUFFER TST MOD ;BYTE? BMI 35$ ;IF MI YES BR 25$ ;MERGE BELOW 15$: MOV R1,-(SP) ;PUSH R1 MOV #CMLB,R1 ;R1->SCRATCH AREA MOV R0,SAV1 ;SAVE BLOCK# CALL OCTOUT ;GO CONVERT MOV #CMLB+3,R0 ;MOVE ONLY THE LOW BYTE TO BUFFER MOV (SP)+,R1 ;RESTORE R1 MOV R3,-(SP) ;SAVE R3 MOV R1,R3 ;SAVE R1 CLR NLZCNT ;CLEAR NLZ CHAR COUNT CALL SLZERO ;SUPPRESS LEADING ZEROES,IF ANY CALL SLZERO ;AND MOVE THREE BYTES INTO CALL SLZERO ;THE BUFFER MOV R3,R1 ;RESTORE BUFFER POINTER MOV (SP)+,R3 ;RESTORE R3 MOV (SP)+,R0 ;R0=VALUE TO CONVERT MOV R0,SAV2 ;SAVE OFFSET ADD #2,SAV2 ;AND ADJUST FOR NEXT TIME MOV R1,-(SP) ;SAVE BUFFER POINTER CALL OCTOUT ;CONVERT AND PUT IN BUFFER MOV (SP)+,R0 ;RESTORE BUFFER POINTER TO R0 (NOT R1) MOV R3,-(SP) ;SAVE R3 ON THE STACK MOV R0,R3 ;SAVE BUFFER START ADDRESS TSTB (R0)+ ;POINT TO SECOND CHAR IN BUFFER 14$: CALL SLZERO ;SUPPRESS LEADING ZEROES CMP R0,R1 ;DONE YET? BNE 14$ ;IF NE, NO CMP NLZCNT,#0 ;ALL ZEROES? BGT 17$ ;IF NO, BRANCH MOVB #'0,(R3)+ ;YES, SO PUT ONE ZERO IN 17$: MOV R3,R1 ;RESTORE BUFFER PTR TO R1 MOV (SP)+,R3 ;RESTORE R3 MOVB #C.CR,(R1)+ ;PUT IN A CR MOVB #C.LF,(R1)+ ;AND LF 20$: TST MOD ;BYTE MODE? BMI 30$ ;IF MI YES 25$: MOV -(R3),R0 ;R0=PATCHED WORD BR 40$ ;MERGE BELOW 30$: MOVB #'\,(R1)+ ;MAKE SURE BYTE MODE MOVB #C.CR,(R1)+ ;PUT IN CR MOVB #C.LF,(R1)+ ;AND LF BITB #1,R3 ;IS THE ADDRESS ODD? BNE 35$ ;IF NE YES (NOTE WE WANT TO CHECK @<-1+R3>) SUB #3,R1 ;DON'T NEED SLASH 35$: SUB #1,SAV2 ;ADJUST SAVED COUNTER MOVB -(R3),R0 ;R0 =PATCHED BYTE BIC #400,R0 ;ALLOW FOR SIGN EXTEND MOV R3,-(SP) ;SAVE R3 MOV R1,R3 ;SAVE R1 CALL OCTOUT ;CONVERT IT MOV R0,-(SP) ;SAVE R0 MOV #CMLB+3,R0 MOVB -(R1),-(R0) ;PUT CHARS IN TEMP BUF MOVB -(R1),-(R0) MOVB -(R1),-(R0) CLR NLZCNT ;CLEAR NON-LEADING ZERO COUNT CALL SLZERO ;REMOVE LEADING ZEROES CALL SLZERO ;FROM THE 3 CHARS CALL SLZERO CMP NLZCNT,#0 ;ALL ZEROES? BGT 38$ ;IF NO, BRANCH MOVB #'0,(R3)+ ;YES, SO PUT ONE IN BUFFER 38$: MOV R3,R1 ;ADJUST BUFFER PTR MOV (SP)+,R0 ;RESTORE R0 MOV (SP)+,R3 ;AND R3 BR 50$ ;MERGE BELOW 40$: MOV R1,-(SP) ;SAVE BUFFER START ON THE STACK CALL OCTOUT ;CONVERT PATCHED WORD,PUT IN BUFFER MOV (SP)+,R4 ;RESTORE BUFFER START TO R4 (NOT R1) MOV R3,-(SP) ;SAVE R3 AND MOV R0,-(SP) ;R0 ON THE STACK MOV R4,R3 ;SAVE R4 MOV R3,R0 ;AND R3 CLR NLZCNT ;CLEAR NON-LEADING ZERO COUNT 44$: CALL SLZERO ;SUPPRESS LEADING ZEROES CMP R0,R1 ;END OF BUFFER? BNE 44$ ;IF NOT, BR CMP NLZCNT,#0 ;ALL ZEROES? BGT 47$ ;IF NO, BRANCH MOVB #'0,(R3)+ ;YES, SO PUT ONE IN BUFFER 47$: MOV R3,R1 ;ADJUST BUFFER PTR MOV (SP)+,R0 ;RESTORE R0 AND MOV (SP)+,R3 ;R3 50$: MOVB #C.CR,(R1)+ ;CR MOVB #C.LF,(R1)+ ;LF MOVB #'^,(R1)+ ;FINISH LINE MOVB #'Z,(R1)+ ;FINISH LINE MOVB #C.CR,(R1)+ ;CR MOVB #C.LF,(R1)+ ;LF MOV R1,-(SP) ;CALC BUF SIZE SUB PATBUF,@SP ;CALC CMP (SP)+,#2000 ;OUTPUT BUFFER FULL? BMI UVW ;IF MI NO MOV #CMLB,R2 ;SETUP TO SAVE LAST LINE MOV PATBF,R4 ;SETUP CALL SVP ;GO SAVE IT CALL PRESP ;OUTPUT MOV #CMLB,R4 ;SET UP TO RESTORE LAST LINE MOV PATBUF,R2 ;SETUP CALL SVP ;RESTORE MOV R2,R1 ;R1->NEXT SPOT IN BUFFER UVW: MOV R1,PATBF ;UPDATE PATBF JSR R5,RSTRG ;RESTORE REGISTERS RETURN ;AND SPLIT SVP: MOV R1,R5 ;SETUP LOOP COUNT SUB PATBF,R5 ; 10$: MOVB (R4)+,(R2)+ ;MOV IT IN SOB R5,10$ ;LOOP RETURN ;RETURN .SBTTL OUTPUT OF SIPP BUFFER ROUTINE ;+ ; ; THIS ROUTINE OUTPUTS THE PATCH COMMAND FILE BUFFER ; WHEN FULL. ; INPUT: NONE ; OUTPUT: ALL REGISTERS ARE SAVED ;- PRESP:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$12 MOV (SP)+,R0 .ENDC ;NE MSS$DB JSR R5,SAVRG ;SAVE REGISTERS MOV #PATSP,R2 ;R2 -> CHANNEL MOV PATBUF,R3 ;R3 -> PATCH BUFFER MOV PATBF,R0 ;R0 -> FIRST FREE CHARACTER IN BUFFER MOV #PBLK,R4 ;R4 -> OUTPUT BLOCK # MOV #PATF,R5 ;R5 -> FILE DESCRIPTOR FOR ERROR MESSAGE CALL WRITBF ;GO WRITE JSR R5,RSTRG ;RESTORE REGISTERS RETURN ;RETURN TO CALLER .SBTTL SIPP FILE INIT ROUTINE ;+ ; ; THIS ROUTINE PLACES THE REQUIRED INITIAL ; COMMANDS IN THE SIPP BUFFER. ; ; INPUT: R1 -> FIRST FREE SLOT IN SIPP BUFFER ; OUTPUT: R1 -> NEXT FREE LOCATION IN SIPP BUFFER ; R0 = 0 ;- $SPPIN:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$13 MOV (SP)+,R0 .ENDC ;NE MSS$DB MOV PATBUF,R1 ;R1 -> START OF BUFFER MOV #SPHD,R0 ;R0 POINTS TO FIRST LINE MOV (R0)+,(R1)+ ;PUT IN "R SIPP" MOV (R0)+,(R1)+ ; MOV (R0)+,(R1)+ ;DONE MOVB #C.CR,(R1)+ ;CR MOVB #C.LF,(R1)+ ;LF MOV #IN1,R0 ;R0 -> FILE 1 DESCRIPTOR BLOCK CALL $FNASC ;FORMAT FILE NAME MOVB #'/,(R1)+ ;Put in a '/' MOVB #'A,(R1)+ ; with an 'A' MOVB #C.CR,(R1)+ ;PUT IN A MOVB #C.LF,(R1)+ ;PUT IN A MOV R1,-(SP) ;SAVE R1 CLR R0 ;INITIAL BASE CALL OCTOUT ;CONVERT BASE MOV (SP)+,R1 ;RESTORE R1 TSTB (R1)+ ;PUT 1 ZERO IN FOR THE BASE MOVB #C.CR,(R1)+ ;PUT IN A MOVB #C.LF,(R1)+ ;PUT IN A RETURN ;RETURN TO CALLER .SBTTL SUPPRESS LEADING ZEROES ;+ ; THIS ROUTINE IS USED BY $SIPP TO SUPPRESS LEADING ZEROES ; IN THE SIPP OUTPUT FILE ; ; INPUTS: R0 = CHARACTER TO BE COMPARED TO ZERO ; R3 = BUFFER TO PLACE A VALID CHARACTER ; ;- SLZERO:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$14 MOV (SP)+,R0 .ENDC ;NE MSS$DB 1$: TST NLZCNT ;DONE WITH LEADING ZEROES? BNE 10$ ;IF YES, BR CMPB @R0,#'0 ;IS CHAR A ZERO? BEQ 20$ ;IF YES, BR 10$: INC NLZCNT ;INC NLZ CHAR COUNT MOVB @R0,(R3)+ ;MOVE CHAR INTO BUFFER 20$: TSTB (R0)+ ;POINT TO NEXT CHAR RETURN .SBTTL OUTPUT BUFFER WRITE ROUTINE ;+ ; ; THIS ROUTINE WILL WRITE THE OUTPUT BUFFER WHEN FULL ; ; INPUT: NONE ; OUTPUT: NONE AS ALL REGISTERS ARE SAVED AND RESTORED ; ;- PROUT:: .IF NE MSS$DB .PRINT #MSS$15 .ENDC ;NE MSS$DB JSR R5,SAVRG ;SAVE REGISTERS MOV #OUTF,R5 ;R5 -> CHANNEL # MOV OUTBUF,R3 ;R3 -> OUTPUT BUFFER MOV OUTBF,R0 ;R0 -> NEXT FREE WORD IN BUFFER MOV #WBLK,R4 ;R4 -> OUTPUT BLOCK # MOV #OUTSP,R2 ;R2 -> OUT FILE SPEC IN CASE OF ERROR CALL WRITBF ;WRITE IT OUT JSR R5,RSTRG ;RESTORE REGISTERS RETURN ;RETURN .SBTTL SET UP COMPARE ROUTINE ;+ ; THIS ROUTINE IS CALLED TO SET UP ; THE LOOP COUNTERS FOR THE COMPARE ; SO THAT THE BLOCK # AND OFFSET CAN ; BE CALCULATED WHEN A DIFFERENCE IS ; FOUND. ; ; INPUT: NONE ; OUTPUT: R2 = OUTER LOOP COUNTER ; R4 = INNER LOOP COUNTER ; ; NOTE UPON RETURN = BLOCK # ; <#1000-R4> = OFFSET ; ;- $SETUP:: .IF NE MSS$DB .PRINT #MSS$16 .ENDC ;NE MSS$DB BIT #FN.FL1,MOD ;IS FILE 1 SHORTER? BNE 10$ ;IF NE YES BIT #FN.FL2,MOD ;IS FILE 2 SHORTER? BEQ 5$ ;IF NE NO MOV NBUF2,R2 ;R2 = # WORDS READ MOV R2,R4 ;SET UP DEFAULT COUNT BR 15$ ;MERGE BELOW 5$: CMP CNT,NBUF1 ;IS THE LAST BLOCK READ SHORT? BEQ 20$ ;IF EQ NO 10$: MOV NBUF1,R2 ;R2 = # WORDS READ IN MOV R2,R4 ;SET UP DEFAULT COUNT 15$: CLRB R2 ;R2 =# COMPLETE BLOCKS READ SWAB R2 ;CALC BIS #FN.DIF,MOD ;SAY FILES CONTAIN A SHORT BLOCK BR 25$ ; MERGE BELOW 20$: MOV NMBLK,R2 ;R2 = # BLOCKS READ IN 25$: MOV #400,R4 ;R4 = INNER LOOP COUNT 30$: MOV R2,NMBL ;UPDATE CALC NMBLK RETURN ; SPLIT .SBTTL /D ROUTINES ;+ ; ; THESE TWO ROUTINES ; 1) DETERMINE IF THE COMMAND LINE IS CORRECT ; 2) LOAD THE HANDLERS FOR THE TWO INPUT DEVICES ; 3) LOAD THE HANDLER FOR THE LISTING DEVICE (OTHER THAN TT:) ; ; THERE CANNOT BE A SIPP FILE WITH /D ; ; If both of the devices are variable size volumes, then we ; use .SPFUN 373 to get the devices' size; then we compare the ; two volume sizes and set MOD accordingly ; ;- DEVDEV:: .IF NE MSS$DB .PRINT #MSS$17 .ENDC ;NE MSS$DB MOV #IN1,R0 ;GET FIRST FILESPEC CALL SPCTST ;TEST FOR VALID FILESPEC MOV #IN2,R0 ;GET SECOND FILESPEC CALL SPCTST ;TEST FOR VALID FILESPEC .FETCH ,#IN1 ;GET DEVICE 1 HANDLER BCC 10$ ;IF NO ERROR, BRANCH ;+ ;ERROR .ERR #ERAR,#EM6,RETURN=NO,FILE=#IN1,LEVEL=E ;- 10$: MOV R0,LIM ;SAVE PROGRAM LIMIT .FETCH LIM,#IN2 ;GET DEVICE HANDLER BCC 20$ ;IF NO ERROR, BRANCH ;+ ;ERROR .ERR #ERAR,#EM6,RETURN=NO,FILE=#IN2,LEVEL=E ;- 20$: MOV R0,LIM ;SAVE PROGRAM LIMIT CLR IN1+2 ;CLEAR WORD 1 .LOOKUP #AREA,#INF1,#IN1,#0 ;NFS LOOKUP ON DEV 1 BCC 40$ ;+ ;ERROR 30$: .ERR #ERAR,#EM1,LEVEL=E,RETURN=NO,FILE=#IN1 ;- 40$: CLR IN2+2 ;CLEAR WORD 1 .LOOKUP #AREA,#INF2,#IN2,#0 ;NFS LOOKUP ON DEV 2 BCC 50$ ;IF NO ERROR, BR ;+ ;ERROR .ERR #ERAR,#EM1,LEVEL=E,RETURN=NO,FILE=#IN2 ;- 50$: .DSTATU #STOST,#IN1 BIT #400,STOST ;Is first device a variable size volume? BEQ 55$ ;beq if not .DSTATU #STOST,#IN2 BIT #400,STOST ;Is second device a variable size volume? BEQ 55$ ;beq if not .SPFUN #DUMPIT,#INF1,#373,#110$,CNT,BLK BCS 55$ .SPFUN #DUMPIT,#INF2,#373,#120$,CNT,BLK BCS 55$ CMP 110$,120$ ;compare the two volume sizes BEQ 55$ ;if they are the same, do nothing BHI 53$ BIS #FN.FL1,MOD ;first device is shorter BR 55$ 53$: BIS #FN.FL2,MOD ;second device is shorter 55$: TST OUTSP ;OUTPUT FILE SPECIFIED? BEQ 100$ ;NO, RETURN .FETCH LIM,#OUTSP ;YES, GET HANDLER BCC 60$ ;IF NO ERROR, BRANCH ;+ ;ERROR .ERR #ERAR,#EM6,RETURN=NO,FILE=#OUTSP,LEVEL=E ;- 60$: MOV R0,LIM ;SAVE LIMIT .ENTER #AREA,#OUTF,#OUTSP,#-1 ;OPEN OUTPUT FILE BCC 100$ ;+ ;ERROR .ERR #ERAR,#EM1,LEVEL=E,RETURN=NO,FILE=#OUTSP ;- 100$: RETURN ;RETURN 110$: .WORD 0 ;Length of first device 120$: .WORD 0 ;Length of secodn device ; THE ONLY VALID FILESPEC FOR /D IS NOTHING OR *.* ; THIS ROUTINE TESTS AREAS IN1 AND IN2 THAT WERE RETURNED BY ; THE .CSIGEN TO BE SURE THAT THEY CONTAIN EITHER DEV1: AND DEV2: ; ,DEV1:* AND DEV2:*, OR DEV1:*.* AND DEV2:*.* SPCTST:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$18 MOV (SP)+,R0 .ENDC ;NE MSS$DB 10$: TST (R0)+ ;WORD 0 MUST BE NON-BLANK BNE 20$ ;IF NON-BLANK, BRANCH 15$: JMP INVCMD ; .ERR #ERAR,#EM5,RETURN=NO,LEVEL=E 20$: TST @R0 ;IS WORD 1 ZERO? BNE 50$ ;BRANCH IF NOT MOV #DSPC1,R1 ;FIRST VALID SPEC (ZEROES) MOV #3,R3 ;INIT WORD COUNT 30$: CMP (R0)+,(R1)+ ;REST OF FILESPEC 0? BNE 15$ ;IF NOT BRANCH SOB R3,30$ ;CONTINUE UNTIL END 40$: BR 100$ ;RETURN 50$: MOV #CHARS,R1 ;BUFFER START FOR RTOA CALL RTOA ;CONVERT FILESPEC TO ASCII MOV #CHARS,R1 ;POINT TO START OF ASCII FILESPEC MOV #DSPC2,R2 ;SECOND VALID SPEC (*) MOV #FILLEN,R3 ;BYTE COUNT 60$: CMPB (R1)+,(R2)+ ;IS FILESPEC *? BNE 70$ ;IF NOT, TRY SPEC 3 SOB R3,60$ ;YES, CONTINUE TEST BR 100$ ;RETURN 70$: MOV #CHARS,R1 ;POINT TO START OF ASCII FILESPEC MOV #DSPC3,R2 ;THIRD VALID SPEC (*.*) MOV #FILLEN,R3 ;BYTE COUNT 80$: CMPB (R1)+,(R2)+ ;IS FILESPEC *.*? BNE 15$ ;IF NOT, ERROR, BRANCH SOB R3,80$ ;YES, CONTINUE TEST 100$: RETURN ;RETURN .SBTTL KPCHECK - Check for valid access of KP: device ;+ ; ; KPCHECK checks to see if either one of the devices is of type ; KPTYPE, if so it returns invalid command. This routine ; is called if there is wildcarding or we are doing a ; device comparison. ;- KPCHECK: .DSTATU #AREA,#IN1 ;get type of first device CALL 10$ ;check it .DSTATU #AREA,#IN2 ;if first ok, then get 2nd device type CALL 10$ ;check it RETURN ;here if everything is valid 10$: MOV AREA,-(SP) BIC #^c,@SP CMP (SP)+,#KPTYPE BEQ 20$ RETURN ;+ ;ERROR 20$: .ERR #ERAR,#ER90,LEVEL=E,RETURN=NO ;invalid operation on KP: ;- .SBTTL WILDCARD PROCESSING ;+ ; ; WILDCARDING IS SET UP SO THAT THE REST OF BINCOM THINKS ; THAT THE USER TYPED IN A CSI COMMAND LINE FOR EACH ; TWO FILES BEING COMPARED. ; ; ALL THE FOLLOWING ROUTINES ARE USED BY WILDCARDING ONLY. ; ; MOST OF THEM ARE REQUIRED ONLY ONCE. ; ; THE PROCESSING SEQUENCE IS: ; ; 1. DETERMINE IF THERE IS WILDCARDING (WILCRD AND WCDCHR) ; AND PARSE THE INPUT SPECS, IF NECESSARY (WCDPAR) ; 2. IF THERE IS, DO THE I/O FOR IT (WCDIO) ; A. DETERMINE IF THERE ARE ANY OUTPUT FILES (WCDOUT) ; B. FIND THE DEVICE TYPES (WCDDEV) ; C. FETCH THE HANDLERS (WCDFET) ; D. ALLOCATE THE BUFFERS WHICH WILL CONTAIN THE ; ASCII FILESPECS MATCHING THE WILDCARDING ; (WCDBUF). IF THERE IS WILDCARDING ON ONE INPUT ; SPEC ONLY, BUFFER WCSAV1 WILL BE USED. ; E. DO NON-FILE-STRUCTURED (NFS) LOOKUPS ON THE ; INPUT DEVICES (WCDFIL) ; F. DO DIRECTORIES ON THE INPUT DEVICES (WCDISP, WCDIR, ; MATCH, AND MATCH1). THESE DIRECTORIES FIND ALL ; FILES MATCHING THE WILDCARDING IN THE SPECS. ; VALID DEVICES ARE DISKS (DKDIR), AND MAGTAPES (MTDIR). ; CHCKSB, READMT, SPFUN, AND SPFUN1 ARE SUPPORT ; ROUTINES FOR MAGTAPES. ; G. DETERMINE WHICH FILENAMES FOUND BY THE DIRECTORY ; ROUTINES MATCH THE BINCOM WILDCARDING (WCDMAT) ; H. LOOKUP THE OUTPUT FILE (WCDLKO), IF ONE WAS ; SPECIFIED ; 3. LOOKUP THE NEXT SET OF INPUT FILES (WCDLKI) ; ; ALL THE SUBROUTINES IN 1 AND 2 ARE PERFORMED ONLY ONCE. ; IF MORE THAT ONE MATCH IS FOUND, WCDINT (WILDCARD INITIALIZATION) ; REINITIALIZES BINCOM, AND WCDLKI SELECTS THE NEXT MATCHING ; FILES(S) AND PERFORMS THE .LOOKUP(S) FOR THEM. WCDINT AND ; WCDLKI ARE CALLED FROM WCDSTR (WILDCARD START). ; ; NOTES: ; 1. RTOA, GETNAM, GETNUM, .SAVRG, CONR50, MOVR50, ; AND MOVASC ARE SUPPORT ROUTINES FOR WILDCARDING. ; RTOA IS ALSO USED BY SPCTST FOR /D PROCESSING. ; 2. BOTSPC IS A MACRO USED TO TEST IF THERE IS WILDCARDING ; ON BOTH INPUT SPECS ; ;- .SBTTL BOTSPC AND .SAVRG ;+ ; BOTSPC WILL DETERMINE IF THERE IS WILDCARDING ON BOTH SPECS ; IF THERE IS, THE PROGRAM WILL TAKE AN EQ BRANCH ;- .MACRO BOTSPC MOV WC.FLG,-(SP) ;PUT WILDCARD FLAG ON STACK BIC #^C,@SP ;CLEAR ALL EXCEPT BITS 2,3 CMP #WC.BOT,(SP)+ ;ARE BOTH SET? .ENDM BOTSPC ;+ ; .SAVRG SETS UP TO USE ULBLIB ROUTINE $SAVRG ; IT IS USED BY MATCH2 AND MATCH ;- .MACRO .SAVRG .DSABL CRF .GLOBL $SAVRG .ENABL CRF JSR R5,$SAVRG .ENDM .SAVRG .SBTTL WILCRD - DETERMINE IF THERE IS WILDCARDING ;+ ; WILCRD ; ; INPUTS: ; IN1 = RAD50 INPUT FILE 1 ; IN2 = RAD50 INPUT FILE 2 ; OUTPUTS: ; WC.FLG <> 0 WHEN THERE IS WILDCARDING ; F2.WCD IN MOD2 IS USED FOR THE LAST LOOP THROUGH ; NON-WC BINCOM SO THAT IT ENDS CORRECTLY ;- .ENABL LSB WILCRD:: .IF NE MSS$DB .PRINT #MSS$19 .ENDC ;NE MSS$DB MOV #IN1,R0 ;POINT TO FIRST INPUT SPEC CALL WCDCHR ;FIND IF THERE ARE WILDCARDS TST R2 ;WILDCARDS? BEQ 10$ ;NO, BRANCH BIS #WC.1FL,WC.FLG ;YES, WC ON INPUT SPEC 1 10$: MOV #IN1ASC,R3 ;SAVE AREA FOR ASCII FILENAME CALL MOVASC ;SAVE INPUT FILENAME 1 MOV #IN2,R0 ;POINT TO SECOND INPUT SPEC CALL WCDCHR ;TEST FOR WILDCARDING TST R2 ;WILDCARDING ON SPEC 2? BEQ 20$ ;NO, BRANCH BIS #WC.2FL,WC.FLG ;YES, WC ON SPEC 2 20$: MOV #IN2ASC,R3 ;SAVE AREA FOR ASCII FILENAME CALL MOVASC ;SAVE ASCII FILENAME OF SPEC 2 TST WC.FLG ;ANY WILDCARDING? BEQ 100$ ;IF NO, BRANCH ; MOV #IN2ASC,R3 ;SAVE AREA FOR ASCII FILENAME ; CALL MOVASC ;SAVE ASCII FILENAME OF SPEC 2 BIS #WC.ENB,WC.FLG ;TURN WC ON BIS #F2.WCD,MOD2 ;TURN LAST TIME THRU WC ON CALL WCDPAR ;IS FILESPEC DEV1:*,DEV2:*? BCC 30$ ;IF NOT, CONTINUE WILDCARDING CLR WC.FLG ;NO WILDCARDING BR 100$ ; If wildcards were specified on both input files, require that ; they be of the same pattern. 30$: BOTSPC ;Wildcards on both specs? BNE 100$ ;Return if not. MOV #IN1ASC,R0 ;Get 1st spec MOV #IN2ASC,R1 ;Get 2nd spec CALL CHKWCC ;Check for similar wildcard positions MOV #IN2ASC,R0 ;Get 2nd spec MOV #IN1ASC,R1 ;Get 1st spec .BR CHKWCC ;Check the other way around CHKWCC: MOV #FILLEN,R3 40$: CMPB @R0,#ASTERK ;1st spec has '*'? BEQ 50$ CMPB @R0,#PRCENT ;1st spec has '%'? BNE 60$ 50$: CMPB @R0,@R1 ;force it in second spec BEQ 60$ ;branch if it's there too. JMP INVCMD ; -F-Invalid command 60$: BITB (R0)+,(R1)+ DEC R3 BGT 40$ 100$: RETURN .DSABL LSB .SBTTL WCDCHR ; ; WCDCHR WILL TEST IF THE INPUT FILE SPECS ; CONTAIN THE WILDCARDING CHARACTERS '*' OR '%' ; ; INPUTS: R0 -> START OF RAD50 INPUT FILE SPEC ; OUTPUTS: R2 <> 0 WHEN A WILDCARDING CHAR IS FOUND ; WCDCHR: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$20 MOV (SP)+,R0 .ENDC ;NE MSS$DB CLR R2 ;ASSUME FAILURE ADD #2.,R0 ;POINT TO INPUT FILENAME MOV #CHARS,R1 ;STORAGE AREA FOR ASCII OF FILENAME CALL RTOA ;CONVERT RAD50 TO ASCII MOV #FILLEN,R4 ;# OF CHARS IN RETURN SPEC MOV #CHARS,R1 ;GET START OF ASCII 10$: MOVB (R1)+,R3 ;GET ASCII CHAR IN R3 CMPB #ASTERK,R3 ;IS IT AN '*'? BEQ 20$ ;IF YES, BRANCH CMPB #PRCENT,R3 ;IS IT A '%'? BEQ 20$ ;IF YES, BRANCH SOB R4,10$ ;CONTINUE UNTIL END OF FILENAME BR 100$ 20$: INC R2 ;TURN WILDCARDING ON 100$: RETURN ;RETURN .SBTTL WCDPAR - PARSE THE FILESPEC, IF NECESSARY ;+ ; WCDPAR ; ; WCDPAR WILL DETERMINE IF AN INPUT FILESPEC IS IN ; THE FORM DEV:* (THIS FORM IS RETURNED BY THE KMON ; DIFFERENCES COMMAND). THE POSSIBILITIES ARE: ; ; 1) DEV1:*,DEV2:* ; THIS MUST WORK THE SAME AS V4. THIS IS NOT WILDCARDING. ; 2) DEV1:*,FIL.TYP OR FIL.TYP,DEV2:* ; THIS ALSO MUST WORK AS V4. THIS IS NOT WILDCARDING ; ; INPUTS: IN1ASC - ASCII INPUT SPEC 1 ; IN2ASC - ASCII INPUT SPEC 2 ; OUTPUTS: C = 0 IF THERE IS WILDCARDING ; C = 1 IF THERE IS NO WILDCARDING ;- WCDPAR:: .IF NE MSS$DB .PRINT #MSS$21 .ENDC ;NE MSS$DB BOTSPC ;WILDCARDING ON BOTH SPECS? BEQ 50$ ;IF YES, BRANCH BIT #WC.1FL,WC.FLG ;WILDCARDING ON SPEC 1? BEQ 10$ ;IF NOT, BRANCH MOV #IN1ASC,R1 ;POINT TO START OF FILESPEC 1 CALL SPCCMP ;SEE IF IN THE FORM DEV1:* BCC 100$ ;IF NOT, RETURN WITH C CLEAR BR 90$ ;IF YES, RETURN WITH C SET 10$: MOV #IN2ASC,R1 ;POINT TO START OF FILESPEC 2 CALL SPCCMP ;SEE IF IN THE FORM DEV2:* BCC 100$ ;IF NOT, RETURN WITH C CLEAR BR 90$ ;IF YES, RETURN WITH C SET 50$: CLR R4 ;FLAG FOR DEV1:* FORM MOV #IN1ASC,R1 ;POINT TO START OF FILESPEC 1 CALL SPCCMP ;SEE IF IN THE FORM DEV1:* BCC 60$ ;IF NOT, BRANCH INC R4 ;YES IT IS 60$: MOV #IN2ASC,R1 ;POINT TO START OF FILESPEC 2 CALL SPCCMP ;SEE IF IN THE FORM DEV2:* BCC 70$ ;IF NOT, BRANCH TST R4 ;DEV1:*,DEV2:* ? BNE 90$ ;IF NOT, BRANCH MOV #IN2ASC,R1 ;GET FILESPEC 2 MOVB DSPC2,7(R1) ;PUT * INTO EXTENSION BR 100$ ;THIS IS WC (FIL.*,DEV2:*) 70$: TST R4 ;NO DEV2:*, IS THERE DEV1:* ? BEQ 100$ ;IF NOT, BRANCH MOV #IN1ASC,R1 ;GET FILESPEC 1 MOVB DSPC2,7(R1) ;PUT * INTO EXTENSION BR 100$ ;THIS IS WC (DEV1:*,FIL.*) 90$: CALL SPCFIX ;FIX INPUT SPEC FOR .CSIGEN SEC ;SET C FOR NO WILCARDING 100$: RETURN ;+ ; SPCCMP DETERMINES IF THE INPUT SPEC IS IN THE FORM ; DEV:* ; ; INPUTS: R1 = ADDRESS OF THE ASCII SPEC TO TEST ; OUTPUTS: C = 0 IF NOT DEV:* ; C = 1 IF DEV:* ;- SPCCMP: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$22 MOV (SP)+,R0 .ENDC ;NE MSS$DB MOV #DSPC2,R2 ;KMON VALID SPEC (*) MOV #FILLEN,R3 ;BYTE COUNT 10$: CMPB (R1)+,(R2)+ ;IS FILESPEC *? BNE 90$ ;IF NOT, GO OUT SOB R3,10$ ;YES, CONTINUE TEST SEC ;MATCH FOUND BR 100$ 90$: CLC ;NO MATCH 100$: RETURN ;+ ; FOR THE TWO CASES ABOVE, REMOVE THE * TO MAKE THE ; LINE ACCEPTABLE TO CSIGEN ;- SPCFIX: .IF NE MSS$DB .PRINT #MSS$23 .ENDC ;NE MSS$DB MOV #CMLB,R1 ;GET COMMAND LINE 10$: CMPB #ASTERK,(R1)+ ;FIND THE * BNE 10$ ;KEEP LOOKING MOV R1,R0 ;R1 POINTS TO CHAR AFTER THE * DEC R0 ;R0 POINTS TO * 20$: TSTB @R0 ;END OF THE LINE? BEQ 100$ ;IF YES, BRANCH MOVB (R1)+,(R0)+ ;PUSH UP 1 CHAR CMPB #ASTERK,(R1) ;FIND THE NEXT *, IF ONE BNE 20$ ; CLRB (R0)+ BR 20$ 100$: RETURN .SBTTL WCDINT - WILDCARD INITIALIZATION ;+ ; WCDINT ; ; WILDCARDING USES THIS INITIALIZATION ROUTINE FOR THE ; SECOND AND SUBSEQUENT WILDCARDING COMPARES ;- WCDINT:: .IF NE MSS$DB .PRINT #MSS$24 .ENDC ;NE MSS$DB MOV #STBL,R0 ;FILL IN FIRST ADDRESS BIT #F2.STB,MOD2 ;/S USED? BEQ 10$ ;IF NOT, BRANCH MOV STBSAV,(R0)+ ;REINIT START BLOCK (STBL) BR 20$ 10$: CLR (R0)+ ;NO /S SPECIFIED 20$: BIT #F2.ENB,MOD2 ;/E USED? BEQ 30$ ;IF NOT, BRANCH MOV ENBSAV,(R0)+ ;REINIT END BLOCK (ENBL) BR 40$ 30$: MOV #177776,(R0)+ ;NO /E SPECIFIED ;034 40$: BIC #FN.FL1+FN.FL2+FN.DIF+FN.DFT,(R0)+ ;MOD CLR (R0)+ ;CLEAR IND CLR (R0)+ ;CLEAR NMBL CLR (R0)+ ;CLEAR SAV1 MOV #-1,(R0)+ ;INIT SAV2 MOV #PBLK,R0 TST (R0)+ ;BYPASS PBLK TST (R0)+ ;BYPASS WBLK CLR (R0)+ ;CLEAR BLK MOV #-1,(R0)+ ;INIT SBLK RETURN .SBTTL WCDIO - WILDCARD I/O ;+ ; WCDIO ; ; THIS ROUTINE WILL CALL THE OTHER WILDCARDING ROUTINES ; NECESSARY TO SET UP FOR BINCOM ; ; OUTPUTS: ; BINCOM IS READY TO COMPARE THE FIRST TWO ; MATCHING FILES ; ; NOTE: THESE SUBROUTINES MUST BE PERFORMED IN THIS ORDER ;- WCDIO:: .IF NE MSS$DB .PRINT #MSS$25 .ENDC ;NE MSS$DB CALL WCDOUT ;TEST IF THERE ARE ANY OUTPUT FILES MOV #IN1,R1 ;GET DEVICE TYPE CALL WCDDEV ;FOR INPUT DEV 1 MOV DEVIN,WDEV1 ;SAVE DEV 1 STRUCTURE MOV #IN2,R1 ;GET DEVICE TYPE CALL WCDDEV ;FOR INPUT DEV 2 MOV DEVIN,WDEV2 ;SAVE DEV 2 STRUCTURE CALL WCDFET ;FETCH HANDLERS FOR THE DEVICES CALL WCDBUF ;ALLOCATE BUFFERS CALL WCDFIL ;LOOKUP THE INPUT DEVICES CALL WCDISP ;DO DIRECTORIES ON THE DEVICES ;AND SAVE MATCHING FILESPECS CALL WCDMAT ;FIND FILES FOR COMPARISON CALL WCDLKO ;GET OUTPUT FILES, IF NEEDED CALL WCDLKI ;LOOKUP FIRST INPUT FILES TST LSTFIL ;LIST FILE WANTED? BEQ 100$ ;IF NOT, BRANCH CALL WCDPRT ;PRINT COMPARING MESSAGE 100$: RETURN ;END OF WILDCARD I/O .SBTTL WCDOUT - LOOK FOR OUTPUT FILE ;+ ; WCDOUT ; ; THIS ROUTINE DETERMINES IF AN OUTPUT FILE WAS SPECIFIED ; IN THE COMMAND LINE. THERE CAN ONLY BE A LIST FILE, NO ; PATCH FILE. ; ; OUTPUTS: ; LSTFIL <> 0 WHEN A PRINT FILE WAS SPECIFIED ;- .ENABL LSB WCDOUT:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$26 MOV (SP)+,R0 .ENDC ;NE MSS$DB CLR LSTFIL ;CLEAR OUTPUT FILE FLAG MOV #OUTSP,R0 ;GET START OF OUTPUT SPECS TST @R0 ;IS THERE A LIST FILE? BEQ 10$ ;BRANCH IF NOT CMP @R0,TTNAM ;TT: SPECIFIED? BEQ 10$ ;IF YES, BRANCH INC LSTFIL ;SAY LIST FILE WANTED 10$: ADD #10.,R0 ;POINT TO PATCH FILE BLOCK TST @R0 ;PATCH FILE WANTED? BEQ 100$ ;IF NOT, BRANCH ;+ ;ERROR INVCMD: .ERR #ERAR,#EM5,RETURN=NO,LEVEL=E ;- 100$: RETURN .DSABL LSB .SBTTL WCDDEV - WILDCARDING DEVICES ;+ ; WCDDEV ; ; THIS ROUTINE DETERMINES WHAT KIND OF DEVICE EACH INPUT ; FILE RESIDES ON. ; ; IT WILL BE CALLED TWICE, ONCE FOR EACH OF THE TWO INPUT FILES ; ; INPUTS: ; R1 = ADDRESS OF THE RAD50 DEVICE NAME ; OUTPUTS: ; DEVIN = 0 FOR A RANDOM ACCESS DEVICE ; DEVIN <> 0 FOR A MAGTAPE ;- WCDDEV:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$27 MOV (SP)+,R0 .ENDC ;NE MSS$DB .DSTATU #IOAREA,R1 ;Find out what it is BCC 20$ ;Branch if no error ;+ ;ERROR 10$: .ERR #ERAR,#EM5,LEVEL=E,RETURN=NO ;- 20$: CLR DEVIN ;Clear device type flag MOV IOAREA,R3 ;Get the status and device id number BMI 100$ ;Branch if it's random access. BIT #NRTDIR,R3 ;Is it directory structured? BEQ 10$ ;Branch if not. Illegal device. 30$: CMPB #MTIDEN,R3 ;Magtape? BEQ 40$ ;Branch if so. CMPB #MMIDEN,R3 ;Magtape? BEQ 40$ ;Branch if so CMPB #MSIDEN,R3 ;Magtape? BEQ 40$ ;Branch if so CMPB #MUIDEN,R3 ;Magtape? BNE 100$ ;Branch if not 40$: BIS #DEVMT,DEVIN ;Remember it 100$: RETURN .SBTTL WCDFET - FETCH HANDLERS ;+ ; WCDFET ; ; ALLOCATE THE HANDLERS ABOVE THE PROGRAM HIGH LIMIT ; ; INPUTS: ; LMT+2 CONTAINS THE FIRST FREE WORD ; ABOVE THE PROGRAM ; OUTPUTS: ; LIM CONTAINS THE NEW HIGH LIMIT ; R0 IS DESTROYED ;- WCDFET:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$28 MOV (SP)+,R0 .ENDC ;NE MSS$DB MOV ,LIM ;GET LIMIT .FETCH LIM,#IN1 ;FETCH HANDLER FOR INPUT DEV 1 BCS 20$ ;IF CS, BRANCH MOV R0,LIM ;SAVE PROGRAM LIMIT .FETCH LIM,#IN2 ;FETCH SECOND DEVICE HANDLER BCS 20$ ;IF CS, BRANCH MOV R0,LIM ;SAVE PROGRAM LIMIT TST LSTFIL ;AN OUTPUT FILE WANTED? BEQ 10$ ;IF NO, BRANCH .FETCH LIM,#OUTSP ;YES, GET HANDLER BCS 20$ ;IF CS, ERROR MOV R0,LIM ;SAVE LIMIT BR 100$ ;GO OUT 10$: .FETCH LIM,#TTNAM ;MAKE TT OUTPUT DEVICE BCC 30$ ;IF CC, BRANCH ;+ ;ERROR 20$: .ERR #ERAR,#ER10,LEVEL=E,RETURN=NO ;- 30$: MOV R0,LIM ;SAVE LIMIT 100$: .SETTOP #-2 ;get as much memory as possible for the TST (R0)+ ;dynamic buffers MOV R0,USRLIM ;set USRLIM RETURN .SBTTL WCDBUF - ALLOCATE WILDCARDING BUFFER 1 ;+ ; WCDBUF ; ; THIS ROUTINE PLACES WCSAV1, THE FIRST WILDCARDING BUFFER, ; ABOVE THE HANDLERS. ; WCSAV2, IF NEEDED, WILL START AFTER WCSAV1. ; WCSAV2 IS ALLOCATED IN WCDISP. ; ; INPUTS: ; LIM ; OUTPUTS: ; WCSAV1, WC1PTR POINT TO THE FIRST BYTE IN ; WILDCARDING BUFFER AREA 1 ;- WCDBUF:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$29 MOV (SP)+,R0 .ENDC ;NE MSS$DB MOV #LIM,R3 ;R3 -> WORD CONTAINING PROG LIMIT MOV (R3)+,R1 ;R1 -> FIRST BUFFER AREA WORD MOV R1,WCSAV1 ;SET WCD BUFFER 1 TO START OF FREE MEM MOV R1,WC1PTR ;SET BUF 1 PTR TO THE SAME PLACE RETURN ;RETURN .SBTTL WCDFIL - Do .LOOKUP's on the input devices ;+ ; WCDFIL ; This routine ; 1) .LOOKUP's the input devices ; 2) If an input device is MT, positions the tape ;- WCDFIL:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$30 MOV (SP)+,R0 .ENDC ;NE MSS$DB MOV #IBUF,MBUF ;Buffer address for magtapes CLR MVAL ;Clear tape 2 flag MOV IN1,LKBLK ;Move spec 1 to LOOKUP block CLR LKBLK+2 ;for non-file structured LOOKUP MOV #INF1,ICHAN ;Channel 3 for input file 1 MOV WDEV1,DEVIN CALL LOOK ;Do LOOKUP MOV IN2,LKBLK ;Move spec 2 to LOOKUP block CLR LKBLK+2 ;for non-file structured LOOKUP MOV #INF2,ICHAN ;Channel 4 for input file 2 MOV WDEV2,DEVIN TST DEVIN ;A magtape? BEQ 10$ ;if not, branch CMP WDEV1,WDEV2 ;Two magtapes? BNE 10$ ;If no, branch MOV #DBUF,MBUF ;Yes, use disk buf for 2nd tape 10$: CALL LOOK ;Do LOOKUP RETURN LOOK: .LOOKUP #IOAREA,ICHAN,#LKBLK,#0 ;NFS LOOKUP BCC 20$ ;Branch if no error CMPB @#$ERRBY,#1 ;Device inactive? BNE 10$ ;If yes, branch ;+ ;ERROR .ERR #ERAR,#EM3,LEVEL=E,RETURN=NO,FILE=#LKBLK 10$: .ERR #ERAR,#ER70,LEVEL=E,RETURN=NO,FILE=#LKBLK ;- 20$: TST DEVIN ;Is the input device directory structured? BEQ 90$ ;Branch if yes 30$: ;Input a magtape JSR R5,SPFUN ;Rewind the magtape .BYTE 377,SF.MRE MOV MBUF,R1 ;Get read buffer address CALL READMT ;Read a record BCC 40$ ;Branch if no error CALL CHCKSB ;Check for a short record BEQ 40$ ;Branch if it was. We'll use it ;+ ;ERROR .ERR #ERAR,#ER50,LEVEL=E,RETURN=NO,FILE=#LKBLK ;- 40$: CMP #MT.VOL,@R1 ;VOL1 label? BEQ 50$ ;Branch if so ;+ ;ERROR .ERR #ERAR,#ER60,LEVEL=E,RETURN=NO,FILE=#LKBLK ;- 50$: MOV MBUF,R3 ;Get buffer start ADD #MT.OWN,R3 ;Point to the owner name CMPB #MT.VP1,(R3)+ ;Is it a DEC written magtape? BNE 60$ ;Branch if not. CMP #MT.VP2,(R3)+ ;Written on an 11? BEQ 70$ ;Branch if so 60$: MOV SP,MABBAD ;Flag that it may be bad 70$: CALL READMT ;Position to the first HDR label BCC 80$ ;Branch if no error CALL CHCKSB ;Check for a short block read error BEQ 80$ ;No error, branch ;+ ;ERROR .ERR #ERAR,#ER60,LEVEL=E,RETURN=NO,FILE=#LKBLK ;- 80$: CMP #MT.HDR,@R1 ;HDR1 label? BNE 70$ ;Branch if not. Try again BR 100$ 90$: .READW #IOAREA,ICHAN,#DBUF,#400,#HOMBLK ;Read the home block BCC 100$ ;Branch on no error ;+ ;ERROR .ERR #ERAR,#ER50,LEVEL=E,RETURN=NO,FILE=#LKBLK ;- 100$: RETURN .SBTTL WCDISP - DISPATCH TO THE DIRECTORY ROUTINES ;+ ; WCDISP ; ; THIS ROUTINE WILL SET UP AND DISPATCH TO THE ; DIRECTORY ROUTINES. ; ; IT WILL FILL UP WCSAV1 AND WCSAV2 WITH THE ASCII FILENAMES ; MATCHING THE WILDCARDING. A ZERO BYTE FLAGS THE END OF ; WCSAV1 AND WCSAV2. WCSAV2 IS USED ONLY WHEN THERE IS ; WILDCARDING ON BOTH SPECS. ; ; ON RETURN FROM WCDIR, R5 POINTS TO A DIRECTORY ENTRY ;- WCDISP:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$31 MOV (SP)+,R0 .ENDC ;NE MSS$DB MOV #IBUF,MBUF ;GET MAGTAPE BUFFER 1 MOV #1,NXTDSG ;INIT FOR DIR ROUTINES MOV #INF1,ICHAN ;POINT TO FIRST INPUT FILE MOV WDEV1,DEVIN ;GET DEVICE TYPE MOV IN1,LKBLK ;GET ERROR MSG, IF NEEDED BIT #WC.1FL,WC.FLG ;WILDCARDING ON INPUT FILE 1? BNE 10$ ;IF YES, BRANCH MOV #INF2,ICHAN ;NO, WILDCARDING ON SPEC 2 ONLY MOV WDEV2,DEVIN ;GET DEVICE TYPE MOV IN2,LKBLK ;GET ERROR MSG, IF NEEDED 10$: CALL WCDIR ;GET A DIRECTORY ENTRY BCS 30$ ;IF C SET, NO MORE ENTRIES MOV #IN1ASC,R3 ;POINT TO ASCII INPUT SPEC BIT #WC.1FL,WC.FLG ;WILDCARDING ON SPEC 1? BNE 20$ ;IF YES, BRANCH MOV #IN2ASC,R3 ;POINT TO ASCII OF SPEC 2 20$: CALL MATCH1 ;FIND MATCH, IF ANY TST R0 ;ANY MATCHES? BEQ 10$ ;BRANCH IF NONE MOV WC1PTR,R3 ;POINT TO START OF BUF 1 CALL 120$ ;Is there enough room? CALL MOVASC ;SAVE ASCII FILENAME IN WCSAV1 MOV R3,WC1PTR ;SAVE BUFFER POINTER BR 10$ ;GET ANOTHER DIRECTORY ENTRY 30$: CMP WCSAV1,WC1PTR ;IF NO MATCHES, THESE TWO ARE BNE 60$ ;EQUAL 40$: BIT #WC.1FL,WC.FLG ;WILDCARDING ON INPUT FILE 1? BEQ 50$ ;IF NOT, BRANCH ;+ ;ERROR .ERR #ERAR,#EM6,RETURN=NO,FILE=#IN1,LEVEL=E 50$: .ERR #ERAR,#EM6,RETURN=NO,FILE=#IN2,LEVEL=E ;- 60$: MOV WC1PTR,R3 ;FLAG END OF WCSAV1 CLRB (R3)+ ;WITH A ZERO BYTE MOV R3,WCEND ;SAVE WCSAV1 END 70$: BOTSPC ;WILDCARDING ON BOTH SPECS? BNE 100$ ;IF NOT, BRANCH MOV R3,WCSAV2 ;START WCSAV2 AT END OF WCSAV1 MOV R3,WC2PTR ;INIT BUFFER POINTER MOV #1,NXTDSG ;INIT FOR DIR ROUTINES CLR EOSFLG INC MVAL ;SET TAPE 2 FLAG, IF NEEDED MOV #INF2,ICHAN ;GET CHANNEL NUMBER MOV WDEV2,DEVIN ;GET DEVICE TYPE MOV IN2,LKBLK ;GET ERROR MSG, IF NEEDED 80$: CALL WCDIR ;GET DIRECTORY ENTRY BCS 90$ ;IF C SET, END OF DIRECTORY MOV #IN2ASC,R3 ;POINT TO ASCII OF SPEC 2 CALL MATCH1 ;FIND MATCH, IF ANY TST R0 ;ANY MATCHES? BEQ 80$ ;BRANCH IF NONE MOV WC2PTR,R3 ;POINT TO START OF BUF 2 CALL 120$ ;Is there enough room? CALL MOVASC ;SAVE ASCII FILENAME IN WCSAV2 MOV R3,WC2PTR ;SAVE BUFFER POINTER BR 80$ ;GET ANOTHER DIRECTORY ENTRY 90$: CMP WCSAV2,WC2PTR ;IF NO MATCHES, THESE TWO ARE BEQ 50$ ;EQUAL MOV WC2PTR,R3 ;FLAG END OF WCSAV2 CLRB (R3)+ ;WITH A ZERO BYTE MOV R3,WCEND ;SAVE WCSAV2 END 100$: RETURN ;Come Here to see if there is room to hold another file name in ;memory without overwriting the USR - Return if so. ;R3 = same as on call to MOVASC 120$: MOV R3,-(SP) ADD #FILLEN,@SP CMP (SP)+,USRLIM BLO 130$ ;+ ;ERROR .ERR #ERAR,#ER10,LEVEL=E,RETURN=NO ;- 130$: RETURN .SBTTL WCDIR Get a directory entry ;+ ; WCDIR ; This routine determines which of the directory entry routines ; should be used (DKDIR or MTDIR). It then JMP's to ; the appropriate routine, which returns to WCDISP. ;- WCDIR:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$32 MOV (SP)+,R0 .ENDC ;NE MSS$DB TST DEVIN ;Input device a disk? BEQ DKDIR ;Branch if yes TST MVAL ;Are we reading a 2nd tape? BEQ 10$ ;If no, branch MOV #DBUF,MBUF ;Get 2nd magtape buffer 10$: JMP MTDIR ;Read a tape .SBTTL DKDIR - Get a disk directory entry ;+ ; DKDIR ; This routine points R5 at the next directory entry of a disk directory. ; R5 cannot be modified once DKDIR has been called. ; OUTPUTS: ; R5 -> next directory entry, if one exists ; C-bit = 1 if no more directory entries ;- DKDIR:: TST EOSFLG ;Have we got a segment? BNE 7$ ;Branch if yes 1$: MOV NXTDSG,RBLK ;Get the next directory segment BNE 2$ ;If NE then we're not at end SEC ;Flag no more entries BR 9$ ; and return to caller 2$: MOV SP,EOSFLG ;Fix the end-of-segment flag ASL RBLK ;Each directory segment is 2 blocks ADD #4,RBLK ;Offset to block 6 for 1st one MOV #DBUF,R5 ;Point R5 at the input buffer MOV R5,NXTFIL ;Set the pointer to the next file ADD #DH.SIZ,NXTFIL ;Skip the header words .READW #IOAREA,ICHAN,R5,#INBFSZ/2,RBLK ;Read a directory segment BCC 3$ ;Branch if no error ;+ ;ERROR .ERR #ERAR,#ER50,RETURN=NO,LEVEL=E,FILE=#LKBLK ;- 3$: MOV DH.EXB(R5),XTRABY ;Set the number of extra bytes BIT #1,XTRABY ;Odd number of extra bytes? BNE 4$ ;Branch if so. Illegal directory. MOV DH.NXT(R5),NXTDSG ;Set the next directory segment MOV DH.STB(R5),SBLOCK ;Get starting block number for segment BNE 5$ ;If EQ, then illegal directory ;+ ;ERROR 4$: .ERR #ERAR,#ER60,RETURN=NO,LEVEL=E,FILE=#LKBLK ;- 5$: TST HISEG ;Is this the first segment? BNE 6$ ;Branch if not MOV DH.HI(R5),HISEG ;Else get the highest segment open MOV DH.AVL(R5),AVAIL ; and the highest available BLE 4$ ;If <= 0, illegal directory CMP #37,AVAIL ;Too many directory segments? BLO 4$ ;Branch if so 6$: TST EOSFLG ;Was the last entry end of a segment? BEQ 1$ ;Branch if so 7$: MOV NXTFIL,R5 ;Point R5 at the next entry BIT #DS.EOS,@R5 ;Are we pointing to end of the segment? BEQ 8$ ;Branch if not CLR EOSFLG ;Set the flag 8$: ADD #DE.SIZ,NXTFIL ;Point to next file entry for next loop ADD XTRABY,NXTFIL ;Don't forget extra bytes CLC ;Clear the carry bit 9$: RETURN .SBTTL MTDIR - Get next magtape filename ;+ ; MTDIR ; This is the main magtape directory routine. It is JMP'ed to ; from WCDIR ; INPUTS: ; An HDR label starting at the address in MBUF. ; OUTPUTS: ; R5 -> a pseudo-directory entry at the address in MBUF+1000 ; CHARS contains the filename ; SBLOCK contains the file sequence number ; All registers modified. ; ;The C bit is set when there are no more files ;- MTDIR:: TST EOSFLG ;Have we encountered EOT or LEOT? BEQ 1$ ;Branch if not JSR R5,SPFUN ;Start a rewind .BYTE 377,SF.MRE SEC ; say we're done BR 17$ ; and return with done. 1$: MOV MBUF,R4 ;Point to input buffer MOV R4,R5 ;003 ADD #1000,R5 ;Put fake directory entry here. ;003 MOV R4,R0 ;Point to filename ADD #MT.FID,R0 ; MOV #CHARS,R1 ;Store the filename here MOV R1,R3 ;Save it. TSTB @R0 ;Delete file? ;preV3 BEQ 2$ ;Yes... ;preV3 CMPB @R0,#377 ;Deleted file? ;preV3 BNE 3$ ;Branch if not 2$: CLR DE.LEN(R5) ;Length is zero MOV #DS.EMP,@R5 ;Empty file BR 9$ ;Go get positioned for next file 3$: MOV #DS.PRM,@R5 ;Make it a permanent entry MOV #13,R2 ;Blank fill the filename area 4$: MOVB #C.SPAC,(R1)+ ; DEC R2 ; BNE 4$ ;Branch if not MOV #6,R2 ;Filenames are 6 characters long 5$: CMPB @R0,#DOT ; or until the '.' is found BEQ 6$ ;Branch if found MOVB (R0)+,(R3)+ ;Move in the character DEC R2 ;Done? BNE 5$ ;Branch if not 6$: CMPB @R0,#DOT ;Was the last character a '.'? BNE 7$ ;Branch if not TSTB (R0)+ ;Else get rid of it SUB #4,R1 ;Point R1 at the filetype area 7$: MOV #3,R2 ;Move 3 characters 75$: CMPB @R0,#DOT ;Is it a dot? BEQ 8$ ;Branch if so. Done. MOVB (R0)+,(R1)+ ;Move in the character DEC R2 ;Done? BNE 75$ ;Branch if not 8$: MOV R4,R1 ;Point to the file sequence number ADD #MT.SEQ,R1 ; CLRB 4(R1) ;Mark the end CALL GETNUM ;Convert it to binary MOV R3,SBLOCK ;Save it BEQ 2$ ;If it's equal, it's an empty file. CALL GETNAM ;Convert the name to RAD50 9$: JSR R5,SPFUN1 ;Space forward to tapemark .BYTE 377,SF.MFS 10$: JSR R5,SPFUN1 ;Again... .BYTE 377,SF.MFS 11$: CALL READMT ;Read a label (we hope) BCC 12$ ;Branch if no error CALL CHCKSB ;Check for a 'short block read' BEQ 12$ ;Branch if so... may be a good label CMP LKBLK,#EM.EOT ;End-of-tape? BEQ 115$ ;Yep... CMP LKBLK,#EM.EFT ;Maybe, is it w/EOF? BNE 11$ ;Nope... 115$: CLR DE.LEN(R5) ;We hit EOT without a label. Zero length BR 15$ ;Finish up 12$: MOV MBUF,R4 ;Get buffer address CMP @R4,#MT.HDR ;Did we get a header label? BNE 13$ ;Branch if not JSR R5,SPFUN1 ;Else do 2 backspaces to tapemark .BYTE 377,SF.MBS ; followed by a space forward JSR R5,SPFUN1 ; and a read .BYTE 377,SF.MBS ; to get to the EOF label BR 10$ ; 13$: CMP @R4,#MT.EOF ;Did we get the EOF label? BNE 11$ ;Branch if not. Try reading another block BIT #DS.PRM,@R5 ;Is this file there? BEQ 14$ ;Branch if not MOV R4,R1 ;Point to record count ADD #MT.FSZ,R1 ; CLRB 6(R1) ;Mark the end of the field CALL GETNUM ;Go make it binary MOV R3,DE.LEN(R5) ;Save it 14$: JSR R5,SPFUN1 ;Space forward tapemark .BYTE 377,SF.MFS CALL READMT ;Read the next label (we hope) BCC 17$ ;Branch if no error CALL CHCKSB ;Short block check. CLC ;Clear carry, just in case BEQ 17$ ;Branch if it was... Ignore error 15$: MOV SP,EOSFLG ;Else assume EOT or LEOT 17$: RETURN .SBTTL CHCKSB- Check for a 'short block' read ;+ ; CHCKSB ; This routine checks to see if a magtape read error was caused ; by the record containing less data than requested. If so, ; the Z bit is returned = 1. ;- CHCKSB:: TSTB @#$ERRBY ;Was it a hard error? BNE 10$ ;Yes... CLZ ;Nope... BR 20$ 10$: CMP LKBLK,#EM.SML ;Was it a 'short block'? 20$: RETURN .SBTTL READMT- Read a magtape record ;+ ; READMT ; This routine is called to read magtape records. A .SPFUN is used ; so that the extra information can be obtained. ;- READMT:: .SPFUN #IOAREA,ICHAN,#SF.MRD,MBUF,#LABSIZ,#LKBLK RETURN .SBTTL SPFUN and SPFUN1- Issue .SPFUN request ;+ ; SPFUN, SPFUN1 ; SPFUN is used to do single block spacing on magtapes. ; SPFUN1 is used to space to tapemarks on magtapes. ; Both assume that a magtape is open on channel ICHAN. ; CALL: ; JSR R5,SPFUN(1) ; .BYTE 377,code ;code is the .SPFUN code to execute ; OUTPUTS: ; R0 is modified. ;- .ENABL LSB SPFUN1:: MOV #-1,-(SP) ;Space to tapemark entry BR 1$ ; SPFUN:: CLR -(SP) ;Single MT block spacing entry 1$: MOV #IOAREA,R0 ;Point to the EMT area block MOV ICHAN,@R0 ;Move in channel ADD #32*400,@R0 ;Add in function MOV #LKBLK,2(R0) ;Error reporting block for magtapes MOV (SP)+,6(R0) ;Word count MOV (R5)+,10(R0) ;.SPFUN code EMT 375 ;Execute it RTS R5 ;And return to caller. .DSABL LSB .SBTTL MATCH1- Filename match driver ;+ ; MATCH1 ; This is the driver for matching input filenames against the directory ; entries. ; INPUTS: ; R5 -> directory entry ; R3 -> ASCII input string ; OUTPUTS: ; R0 <> 0 if any of the input files matched the current file ; R0-R4 modified ; CHARS contains the ASCII of the current filename ;- MATCH1:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$33 MOV (SP)+,R0 .ENDC ;NE MSS$DB MOV R5,R0 ;Point to the directory entry ADD #DE.FN1,R0 ;Point to the 1st word of the filename MOV #CHARS,R1 ;Point to storage area for ASCII of the name CALL RTOA ;Convert the filename to ASCII BIT #DS.PRM,@R5 ;Is it a permanent file? BNE 2$ ;Branch if so 1$: CLR R0 ;Signal no match BR 9$ ; and return 2$: MOV R3,R1 ;Point to the input string MOV #CHARS,R2 ;Point to the filename (from directory) CALL MATCH2 ;Go see if the filenames match TST R0 ;Did they match? BEQ 9$ ;Branch if not. We're done MOV R3,R1 ;Point to the test string again ADD #7,R1 ;Point to the extension MOV #CHARS,R2 ;Point to the filename (from directory) ADD #7,R2 ;Point to the extension CALL MATCH2 ;Go see if the filetypes match TST R0 ;Did they match? BNE 9$ ;Branch if so 9$: RETURN .SBTTL MATCH2 - Pattern match routine ;+ ; MATCH2 ; This routine does a wildcard pattern match against an ASCII pattern string ; pointed to by R1 and a test string pointed to by R2. The matchable ; wildcards are: ; "%" => match any non-null, non-blank character ; "*" => match any string ; Both strings must end in an ASCII blank. ; If there is a match, R0 returns as <> 0. ; R1 is modified. ; ; INPUTS: R1 -> input filespec (pattern string) ; OUTPUTS: R2 -> directory entry (test string) ;- MATCH2:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$34 MOV (SP)+,R0 .ENDC ;NE MSS$DB .SAVRG CLR R0 ;Assume failure MOV #C.SPAC,R4 ;An ASCII blank is often used 1$: MOVB (R1)+,R3 ;Get the next pattern character CMPB #ASTERK,R3 ;Is it a "*"? BNE 2$ ;Branch if not CMPB @R1,R4 ;Are we at the end of the string? BEQ 3$ ;Branch if so. We have a match 2$: CMPB @R2,R4 ;Is this the end of the test string? BNE 4$ ;Branch if not CMPB R3,R4 ;At the end of the pattern string? BNE 6$ ;Branch if not. Return a level 3$: INC R0 ;Else it matched!!! BR 6$ ;Return a level 4$: CMPB R3,R4 ;Is this the end of the pattern string? BEQ 6$ ;Branch if so CMPB #ASTERK,R3 ;Is the pattern character a "*"? BEQ 5$ ;Branch if so CMPB (R2)+,R3 ;Does test char match pattern char? BEQ 1$ ;Branch if yes CMPB #PRCENT,R3 ;Is the pattern char a "%"? BEQ 1$ ;Branch if so. It matches. BR 6$ ;Else return to caller 5$: MOV R1,-(SP) ;Save R1 MOV R2,-(SP) ; and R2 CALL 1$ ;And call self!!!! MOV (SP)+,R2 ;Restore R2 MOV (SP)+,R1 ; and R1 TST R0 ;Did the strings match? BNE 6$ ;Branch if so CMPB (R2)+,R4 ;At the end of the test string yet? BNE 5$ ;Branch if not 6$: RETURN ;Return a level .SBTTL WCDMAT - FIND FILES FOR WILDCARD COMPARISON ;+ ; WCDMAT ; ; WCDMAT WILL DETERMINE WHICH FILES IN THE TWO SAVE AREAS ; WILL ACTUALLY BE COMPARED ; ; ONEFIL PROCESSES WILDCARDING ON ONE SPEC ; ; TWOFIL PROCESSES WILDCARDING ON BOTH SPECS ; ; IF A FILENAME IN THE SAVE AREA MATCHES, IT WILL BE RETAINED. ;- WCDMAT:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$35 MOV (SP)+,R0 .ENDC ;NE MSS$DB BOTSPC ;WILDCARDING ON BOTH SPECS? BEQ TWOFIL ;IF YES, BRANCH .SBTTL ONEFIL - WILDCARDING ON ONE INPUT SPEC ;+ ; ONEFIL ; ; BINCOM WILL COMPARE ALL FILES THAT MATCH THE ; WILDCARDING TO THE FIXED SPEC (SPEC WITH NO WILDCARDING). ; ;- ONEFIL:: MOV WCSAV1,WC1PTR ;POINT TO START OF SAVE AREA RETURN .SBTTL TWOFIL - WILDCARDING ON BOTH INPUT SPECS ;+ ; TWOFIL ; ; A FILENAME IS SELECTED FROM WCSAV1. IT IS COMPARED ; TO EVERY AVAILABLE FILENAME IN WCSAV2. ; ; THE FILES MUST MATCH EXACTLY WHERE WILDCARDING EXISTS. ; ; IF THERE IS NO MATCH, THE FILENAME IN WCSAV1 IS ; BLANKED OUT ; ; IF THERE IS A MATCH, THE FILENAME IN WCSAV2 IS MOVED TO ; THE SLOT AFTER THE LAST MATCH IN WCSAV2 ; ; A FILENAME IN WCSAV1 CAN MATCH ONLY ONE FILENAME IN ; WCSAV2. ONCE A FILE IN WCSAV2 HAS BEEN MATCHED, IT ; CANNOT BE A MATCH FOR ANY OTHER FILES IN WCSAV1. ;- TWOFIL:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$43 MOV (SP)+,R0 .ENDC ;NE MSS$DB CLR MATFND ;CLEAR MATCH FOUND FLAG MOV WCSAV1,WC1PTR ;POINT TO START OF SAVE AREA 1 MOV WCSAV2,SAVPT2 ;POINT TO START OF SAVE AREA 2 10$: MOV WC1PTR,FIXSPC ;SAVE THE FIXED SPEC MOV #STR1A,R4 ;GET SAVE AREA FOR FILNAM MOV #IN1ASC,R1 ;GET INPUT SPEC MOV WC1PTR,R5 ;GET FILENAME 1 CALL MAT2 ;FIND WHICH CHARS MATCH THE WILDCARDING MOV #STR1B,R4 ;GET SAVE AREA FOR FILTYP MOV #IN1ASC,R1 ;GET INPUT SPEC ADD #7,R1 ;POINT TO FILTYP MOV WC1PTR,R5 ;GET FILENAME 1 ADD #7,R5 ;POINT TO FILTYP CALL MAT2 ;FIND WHICH CHARS MATCH THE WILDCARDING MOV SAVPT2,WC2PTR ;POINT TO START OF VARIABLE SPECS MOV WC2PTR,R5 ;SAVE IT BIC #MATPAS,MATFND ;CLEAR THE MATCH FOUND FLAG 20$: MOV #STR2A,R4 ;GET SAVE AREA FOR FILNAM MOV #IN2ASC,R1 ;GET INPUT SPEC CALL MAT2 ;FIND WHICH CHARS MATCH THE WILDCARDING MOV #STR2B,R4 ;GET SAVE AREA FOR FILTYP MOV #IN2ASC,R1 ;GET INPUT SPEC ADD #7,R1 ;POINT TO FILTYP MOV WC2PTR,R5 ;GET FILENAME 2 ADD #7,R5 ;POINT TO FILTYP CALL MAT2 ;FIND WHICH CHARS MATCH THE WILDCARDING MOV #STR1A,R1 ;GET FILE 1 STRING MOV #STR2A,R2 ;GET FILE 2 STRING CALL MATCH ;SEE IF THE TWO MATCH TST R0 ;DO THEY MATCH? BEQ 80$ ;IF NOT, BRANCH 30$: MOV #STR1B,R1 ;GET FILE 1 TYP MOV #STR2B,R2 ;GET FILE 2 TYP CALL MATCH ;SEE IF THE TWO MATCH TST R0 ;DO THEY MATCH? BEQ 80$ ;IF NOT, BRANCH 40$: BIS #MAT,MATFND ;MATCH FOUND CLRB MATTMP ;CLEAR TEMP SAVE AREA MOV SAVPT2,R4 ;GET CURRENT START OF BUFFER 2 CMP R4,WC2PTR ;ALREADY IN CORRECT SLOT? BEQ 75$ ;IF YES, BRANCH MOV #FILLEN,R3 ;MOVE OCCUPANT OF SLOT MOV #MATTMP,R5 ;TO TEMP SAVE AREA 50$: MOVB (R4)+,(R5)+ ;MOVE CHARS INTO MATTMP SOB R3,50$ 60$: MOV #FILLEN,R3 MOV WC2PTR,R4 ;GET MATCH IN WCSAV2 MOV SAVPT2,R5 ;GET DESTINATION SLOT 65$: MOVB (R4)+,(R5)+ ;MOVE MATCH TO DESTINATION SOB R3,65$ MOV #FILLEN,R3 ;IF YES, MOVE CONTENTS MOV #MATTMP,R4 ;TO WHERE THE MATCH MOV WC2PTR,R5 ;CAME FROM IN WCSAV2 70$: MOVB (R4)+,(R5)+ DEC R3 BGT 70$ ;CONTINUE UNTIL END 75$: ADD #FILLEN,SAVPT2 ;GET NEW START OF WCSAV2 MOV SAVPT2,R2 TSTB @R2 ;AT END OF WCSAV2? BNE 110$ ;IF NOT, CONTINUE BR 120$ ;YES, GO OUT 80$: ADD #FILLEN,WC2PTR ;POINT TO THE NEXT VARIABLE SPEC MOV WC2PTR,R5 TSTB @R5 ;AT END OF BUFFER? BNE 20$ ;IF NOT, BRANCH BIT #MATPAS,MATFND ;ANY MATCHES ON THIS PASS? BNE 110$ ;IF YES, BRANCH MOV FIXSPC,R2 ;NO, BLANK OUT MOV #FILLEN,R3 ;FILENAME IN 90$: MOVB #C.SPAC,(R2)+ ;WCSAV1 SOB R3,90$ 110$: ADD #FILLEN,WC1PTR ;GET NEXT FIXED SPEC MOV WC1PTR,R2 TSTB @R2 ;AT END OF FIXED SPECS? BEQ 120$ ;IF YES, GO OUT JMP 10$ ;IF NO, GET ANOTHER FILENAME 120$: BIT #ONEMAT,MATFND ;AT LEAST ONE MATCH FOUND? BNE 100$ ;IF YES, BRANCH ;+ ;ERROR .ERR #ERAR,#EM6,RETURN=NO,FILE=#IN2,LEVEL=E ;- 100$: MOV SAVPT2,R5 ;GET END OF WCSAV2 CLRB @R5 ;FLAG IT WITH A ZERO MOV WCSAV1,WC1PTR ;GET START OF SAVE AREA 1 MOV WCSAV2,WC2PTR ;GET START OF SAVE AREA 2 RETURN .SBTTL MATCH ROUTINES FOR WILDCARDING ON BOTH SPECS ;+ ; WILDCARDING ON BOTH SPECS USES TWO ROUTINES TO ; DETERMINE IF THERE IS A MATCH ; ; 1. MAT2 WILL PRODUCE A STRING CONTAINING THE CHARACTERS ; THAT MATCH THE WILDCARDING FOR EACH PAIR OF FILENAMES. ; ; 2. MATCH WILL DETERMINE IF THE TWO STRINGS PRODUCED ; BY MAT2 ARE THE SAME. ; ; This algorithm allows for special interpretation when two ; filespecs contain similar wildcards. In a sense, it must ; invert the sense of the wildcard string, allowing a match ; wherever fixed characters exist, and demanding equivalence ; for any wildcard. ; ; For example, ; ; DIFFERENCES A*.TXT B*.TXT ; ; means "let A match B and find files where the '*' represents ; the same character(s) in both specs. In other words, the ; traditional wildcard comparison would never match A* and B* ; because A and B are different. But MAT2 tries to isolate those ; characters that are represented by '*'s and '%'s, and places ; those characters in a 'save' area for later comparison. ; ; MAT2 is called four times for each potential comparison; ; once for each filename, and once for each filetype. Then MATCH ; is used to see if the respective save areas match. ; ; Consider the example above, and the following list of directory ; files: ; ; ALPHA.TXT BETA.TXT ; A1.TXT B1.TXT ; A2.TXT B3.TXT ; A4.TXT B2.TXT ; ALL.TXT BLL.TXT ; ; Characters that aren't to be checked are the initial 'A's and 'B's. ; MAT2 will place 'LPHA' and 'ETA' in the save area for comparison. ; Because they don't compare, it will be called again on the second ; filename with '1', '3', '2', and 'LL'. No match will occur. ; Then, looking at the second spec in the first column, MAT2 will be ; called upon to isolate '1' from 'A1', and 'ETA' from 'BETA', then ; '1' from 'B1', and MATCH will detect a match. ;- .SBTTL MAT2 - Find characters that correspond to wildcards ;+ ; MAT2 ; ; MAT2 finds those characters in the input files that ; correspond to the wildcard characters in the supplied pattern ; string. Those characters will be placed in a special save area. ; A blank flags the end of the matching characters. If there are ; no matches, the save area will contain one blank. ; ; INPUTS: ; R1 = ADDRESS OF WILDCARDING SPEC (PATTERN STRING) ; R4 = ADDRESS OF SAVE AREA FOR MATCHING CHARS ; R5 = ADDRESS OF FILENAME TO BE TESTED (TEST STRING) ; OUTPUTS: ; SAVE AREA CONTAINS THE MATCHING CHARACTERS ;- .ENABL LSB MAT2:: MOV R5,SAVPTR ;SAVE FILENAME START 10$: MOVB (R1)+,R2 ;GET PATTERN CHARACTER CMPB R2,#ASTERK ;IS IT AN *? BEQ 20$ ;IF YES, BRANCH CMPB R2,#PRCENT ;IS IT A %? BEQ 20$ ;IF YES, BRANCH CMPB R2,#C.SPAC ;AT THE END? BEQ 50$ ;IF YES, BRANCH ; Character is a "FIXED" character. Convert it to '%' in the save ; area to preserve its position, but also compares. INC R5 ;POINT TO NEXT CHAR IN TEST STRING CMPB #ASTERK,-2(R4) ; '*' already in string ? BEQ 10$ ; Yes, don't add redundant '*'s MOVB #ASTERK,(R4)+ ; translate to match any string BR 10$ ;GET NEXT PATTERN CHAR ; Character is '%' or '*'. 20$: CMPB @R5,#C.SPAC ;end of TEST string? BEQ 50$ ;if YES, done. MOVB (R5)+,(R4)+ ;put TEST character into save area. CMPB R2,#PRCENT ;was PATTERN char a '%'? BEQ 10$ ;if YES, get next PATTERN character ; Finish processing '*' in pattern. One test character is already ; stored for it. 30$: CMPB @R1,#ASTERK ;redundant stars? BNE 40$ INC R1 BR 30$ ; eat them up. 40$: CALL MAT2A ;Test for fixed substring equality BCC 10$ ; if equal, continue scanning. BR 20$ ; if not, keep getting TEST chars. ; Finished 50$: MOVB ASCB,@R4 ;PUT IN TERMINATOR 60$: RETURN .DSABL LSB .SBTTL MAT2A - TEST FOR FIXED SUB-STRING EQUALITY ;+ ; Test for fixed sub-string equality ; ; Compare strings, accepting BLANK, ASTERK or PRCENT as legitimate ; terminators on the PATTERN string, and BLANK as a legitimate ; terminator on the TEST string. This can be used to check whether ; the next fixed portion of a wildcard substring is equivalent to ; the corresponding portion of a test string. ; ; R1 -> PATTERN sub-string ; R5 -> TEST sub-string ; ; Examples: ; ; 1) in "a*bc" let R1 -> a*bc ; in "a123bc" let R5 -> a123bc (match) ; ; 2) in "a*bc" let R1 -> bc ; in "a123bc" let R5 -> 23bc (no match) ; ; 3) in "a*bc" let R1 -> bc ; in "a123bc" let R5 -> 3bc (no match) ; ; 4) in "a*bc" let R1 -> bc ; in "a123bc" let R5 -> bc (match) ; ; NO registers are altered ; ; Upon return, the C-bit ON indicates NOT_EQUAL; use BCC or BCS ; immediately after call. ;- .ENABL LSB MAT2A: MOV R1,-(SP) ; Save working registers MOV R5,-(SP) 10$: CMPB @R1,@R5 ; Are the characters equal? BNE 20$ ; find out why not. CMPB @R1,#C.SPAC ; End of BOTH strings? BEQ 30$ ; That's Equality. BITB (R1)+,(R5)+ ; Yes. bump the pointers, BR 10$ ; and check again. 20$: CMPB @R1,#C.SPAC ; End of just PATTERN string? BEQ 40$ ; That's not equality. CMPB @R1,#PRCENT ; allow '%' for terminating PATTERN BEQ 30$ ; also CMPB @R1,#ASTERK ; allow '*' to terminate BNE 40$ 30$: TST (PC)+ ; EQUAL 40$: SEC ; NOT_EQUAL MOV (SP)+,R5 ;*C* Restore registers MOV (SP)+,R1 ;*C* RETURN .DSABL LSB .SBTTL MATCH - GENERAL MATCH ROUTINE ;+ ; MATCH ; ; MATCH DETERMINES IF TWO INPUT STRINGS ARE EXACTLY ALIKE. ; ; TWOFIL USES MATCH TO DETERMINE IF THE TWO STRINGS ; CONTAINING THE CHARACTERS MATCHING THE WILDCARDING ARE ; THE SAME. IF THEY ARE, THERE IS A MATCH. ; ; INPUTS: ; R1 = ADDRESS OF STRING 1 ; R2 = ADDRESS OF STRING 2 ; OUTPUTS: ; R0 <> 0 IF THERE IS A MATCH ;- MATCH:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$36 MOV (SP)+,R0 .ENDC ;NE MSS$DB .SAVRG CLR R0 ;ASSUME FAILURE MOVB #C.SPAC,R4 ;END OF SPEC = BLANK 10$: MOVB (R1)+,R3 ;GET FIXED SPEC CHAR CMPB @R2,R4 ;END OF VARIABLE SPEC? BNE 20$ ;IF NOT, BRANCH CMPB R3,R4 ;END OF FIXED SPEC? BNE 100$ ;IF NOT, BRANCH INC R0 ;THEY MATCHED BR 100$ ;RETURN 20$: CMPB R3,R4 ;END OF FIXED SPEC? BEQ 100$ ;BRANCH IF SO CMPB (R2)+,R3 ;TEST CHAR MATCH FIXED SPEC? BEQ 10$ ;IF YES, BRANCH 100$: RETURN .SBTTL WCDLKO - LOOKUP OUTPUT FILE ;+ ; WCDLKO ; ; WCDLKO OPENS THE LIST FILE, IF ONE ; WAS SPECIFIED. IT WILL OPEN THE TT: AS OUTPUT FILE ; IF NO LIST FILE WAS SPECIFIED. ; ; THIS ROUTINE IS DONE ONLY ONCE. ALL LISTINGS GO TO ; ONE LIST FILE. ;- WCDLKO:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$37 MOV (SP)+,R0 .ENDC ;NE MSS$DB TST LSTFIL ;A LIST FILE? BEQ 20$ ;IF NOT, BRANCH .ENTER #AREA,#OUTF,#OUTSP,#0 ;NO FILE, SO CREATE ONE BCC 100$ ;+ ;ERROR 10$: .ERR #ERAR,#EM1,LEVEL=E,RETURN=NO ;- 20$: .LOOKUP #AREA,#OUTF,#TTNAM ;SET TT TO OUTPUT BCS 10$ 100$: RETURN .SBTTL WCDLKI - LOOKUP INPUT FILES ;+ ; WCDLKI ; ; WCDLKI DOES THE LOOKUPS ON THE INPUT FILES. ; EACH TIME THROUGH IT SELECTS THE NEXT FILENAME(S) ; FROM WCSAV1 (AND WCSAV2) AND OPENS THE FILES ; ; WHEN THE END OF WCSAV1 IS FOUND, THE WILDCARDING FLAG ; WC.FLG IS SET TO ZERO. ;- WCDLKI:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$38 MOV (SP)+,R0 .ENDC ;NE MSS$DB MOV WC1PTR,R1 ;POINT TO NEXT INPUT FILENAME 10$: CMPB @R1,#C.SPAC ;GET RID OF LEADING BNE 20$ ;BLANKS TSTB (R1)+ BR 10$ 20$: .CLOSE #INF1 ;CLOSE CHANNELS AFTER .CLOSE #INF2 ;PREVIOUS LOOKUPS TSTB @R1 ;AT END OF BUFFER? BNE 25$ ;IF NO, BRANCH BIC #F2.WCD,MOD2 ;WCD ENDED BR 70$ 25$: MOV R1,WC1PTR ;PUSH PAST ANY BLANKS CALL CONR50 ;CONVERT NEXT SPEC TO RAD50 BOTSPC ;WILDCARDING ON BOTH SPECS? BEQ 50$ ;IF YES, BRANCH BIT #WC.1FL,WC.FLG ;WILDCARDING ON FIRST INPUT SPEC? BEQ 30$ ;NO, BRANCH MOV #IN1,R0 ;MOV RAD50 SPEC TO CALL MOVR50 ;IN1 FOR LOOKUP 30$: CALL LOOK1 ;LOOKUP INPUT FILE 1 BIT #WC.2FL,WC.FLG ;WILDCARDING ON INPUT FILE 2? BEQ 40$ ;IF NOT, BRANCH MOV #IN2,R0 ;YES, MOV RAD50 SPEC TO CALL MOVR50 ;IN2 FOR LOOKUP 40$: CALL LOOK2 ;LOOKUP INPUT FILE 2 BR 60$ ;GO BUMP FILE POINTER 50$: MOV WC2PTR,R0 ;GET NEXT FILE2 TSTB @R0 ;AT THE END? BNE 55$ ;IF NOT, BRANCH BIC #F2.WCD,MOD2 ;WCD ENDED BR 70$ 55$: MOV #IN1,R0 ;MOV RAD50 SPEC TO CALL MOVR50 ;IN1 FOR LOOKUP CALL LOOK1 ;LOOKUP INPUT FILE 1 MOV WC2PTR,R1 ;GET INPUT FILE 2 NAME CALL CONR50 ;CONVERT NAME TO RAD50 MOV #IN2,R0 ;MOV RAD50 SPEC TO CALL MOVR50 ;IN2 FOR LOOKUP CALL LOOK2 ;LOOKUP INPUT FILE 2 ADD #FILLEN,WC2PTR ;POINT TO NEXT FILE 2 60$: ADD #FILLEN,WC1PTR ;POINT TO NEXT FILESPEC MOV WC1PTR,R0 TSTB @R0 ;AT END? BNE 100$ ;IF NOT, BRANCH 70$: CLR WC.FLG ;YES, END WILDCARDING 100$: RETURN .SBTTL LOOK1 ;+ ; LOOK1 ; ; LOOK1 DOES THE LOOKUP FOR THE FIRST INPUT SPEC ; THE TYPE OF LOOKUP DEPENDS ON WHETHER THE ; FILE IS ON A MAGTAPE OR A DISK ;- LOOK1:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$40 MOV (SP)+,R0 .ENDC ;NE MSS$DB BIT #DEVMT,WDEV1 ;DEV 1 A MAGTAPE? BNE 20$ ;IF YES, BRANCH .LOOKUP #AREA,#INF1,#IN1 ;LOOKUP INPUT FILE 1 (DISK) BCC 100$ ;+ ;ERROR 10$: .ERR #ERAR,#EM6,RETURN=NO,LEVEL=E,FILE=#IN1 ;- 20$: .LOOKUP #AREA,#INF1,#IN1,#0 ;LOOKUP INPUT FILE 1 (TAPE) BCS 10$ 100$: RETURN .SBTTL LOOK2 ;+ ; LOOK2 ; ; LOOK2 DOES THE LOOKUP FOR THE SECOND INPUT SPEC ; ; THE TYPE OF LOOKUP DEPENDS ON WHETHER THE ; FILE IS ON A MAGTAPE OR A DISK ;- LOOK2:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$39 MOV (SP)+,R0 .ENDC ;NE MSS$DB BIT #DEVMT,WDEV2 ;DEV 2 A MAGTAPE? BNE 20$ ;IF YES, BRANCH .LOOKUP #AREA,#INF2,#IN2 ;LOOKUP INPUT FILE 2 (DISK) BCC 100$ ;+ ;ERROR 10$: .ERR #ERAR,#EM6,RETURN=NO,LEVEL=E,FILE=#IN2 ;- 20$: .LOOKUP #AREA,#INF2,#IN2,#0 ;LOOKUP INPUT FILE 2 (TAPE) BCS 10$ 100$: RETURN .SBTTL CONR50 ;+ ; CONR50 CONVERTS AN ASCII FILENAME TO RAD50 FOR LOOKUP ; ; INPUTS: ; R1 = START OF ASCII FILENAME ; OUTPUTS: ; SAVR50 = RAD50 FILENAME ; ; THE ASCII FILENAME IS IN THE FORM ; XXXXXXbXXXb WHERE b IS AN ASCII BLANK ;- CONR50:: MOV #SAVR50,R2 ;SAVE AREA FOR RAD50 CALL $ASCR50 ;CALL ULBLIB TO CONVERT 1 WORD MOV R0,(R2)+ ;SAVE IT CALL $ASCR50 ;CALL ULBLIB TO CONVERT 1 WORD MOV R0,(R2)+ ;SAVE IT TSTB (R1)+ ;SKIP THE BLANK CALL $ASCR50 ;CALL ULBLIB TO CONVERT 1 WORD MOV R0,(R2)+ ;SAVE IT RETURN .SBTTL MOVR50 ;+ ; MOVR50 MOVES A RAD50 FILESPEC PLACED IN AREA SAVR50 BY ; CONR50 TO EITHER IN1 OR IN2 FOR THE .ENTER IN WCDLKI ; ; INPUTS: ; R0 = START OF RAD50 FILESPEC AREA (IN1 OR IN2) ;- MOVR50:: MOV #SAVR50,R1 ;RAD50 WAS STORED IN SAVR50 ADD #2,R0 ;POINT TO START OF FILENAME MOV (R1)+,(R0)+ ;MOVE IN THE MOV (R1)+,(R0)+ ;THREE RAD50 MOV (R1)+,(R0)+ ;WORDS RETURN .SBTTL WCDPRT - PRINT COMPARING MESSAGE ;+ ; WCDPRT SENDS THE COMPARING MESSAGE TO THE TT WHEN ; THE USER HAS SPECIFIED A PRINT FILE OR USED /Q TO ; SUPPRESS OUTPUT ;- .ENABL LSB WCDPRT:: .IF NE MSS$DB MOV R0,-(SP) .PRINT #MSS$41 MOV (SP)+,R0 .ENDC ;NE MSS$DB BIT #FN.SUP,MOD BEQ 20$ ;not /QUIET TST (PC)+ LOGFLG: .WORD 0 BNE 20$ MOV SP,LOGFLG ;only once per run ;+ ;ERROR .PRINT #LOGHED ;- 20$: MOV #CMLB,R1 ;GET BUFFER START CALL $HEAD ;PUT COMPARING MESSAGE INTO BUFFER .PRINT #CMLB ;PRINT COMPARING MESSAGE RETURN .DSABL LSB .SBTTL RTOA- Convert 3 RAD50 words to ASCII ;+ ; RTOA ; This routine converts 3 RAD50 words to ASCII. It assumes that the 3 ; words to convert is a filename block, and inserts blanks accordingly. ; INPUTS: ; R0 -> 3 word block ; R1 -> 11 byte block to store the ASCII ; OUTPUTS: ; R1 updated past the end of the ASCII ; ; For a filespec AAAA.XXX in RAD50, RTOA returns ; AAAAbbbXXXb in ASCII, where b = ASCII blank ; ; RTOA always returns 11. bytes (FILLEN) ;- RTOA:: MOV R0,-(SP) ;Save R0 MOV R2,-(SP) ; and R2 MOV R0,R2 ;Point to the RAD50 to convert MOV (R2)+,R0 ;Get the first word CALL $R50ASC ;Convert it MOV (R2)+,R0 ;Get next word CALL $R50ASC ; and convert it MOVB #C.SPAC,(R1)+ ;Move in a blank MOV @R2,R0 ;Get the next word CALL $R50ASC ;Convert it MOVB #C.SPAC,(R1)+ ;Store the final blank MOV (SP)+,R2 ;Restore the registers MOV (SP)+,R0 ; RETURN .SBTTL GETNAM- Convert filename to RAD50 ;+ ; GETNAM ; This routine converts the ASCII stored at CHARS to 3 words of RAD50. ; Called from the magtape routine to produce pseudo-directory entries. ; ; INPUTS: ; R5 -> to a pseudo-directory entry ; OUTPUTS: ; R0 is modified ; RAD50 is stored in the filename/filetype locations of the ; pseudo-entry. ;- GETNAM:: MOV R1,-(SP) ;Save R1 MOV #CHARS,R1 ;R1 -> ASCII CALL $ASCR50 ;Convert it to RAD50 MOV R0,DE.FN1(R5) ;Store it CALL $ASCR50 ;Convert the next 3 characters MOV R0,DE.FN2(R5) ; and store the RAD50 TSTB (R1)+ ;Skip the blank CALL $ASCR50 ;Convert the filetype MOV R0,DE.TYP(R5) ;Save it MOV (SP)+,R1 ;Restore R1 RETURN .SBTTL GETNUM - Convert ASCII to binary, decimal ;+ ; GETNUM ; ; INPUTS: ; R1 -> buffer holding an ASCII character string ; OUTPUTS: ; R3 contains the binary number ;- GETNUM:: CLR R3 ;R3 will hold the binary result 10$: MOVB (R1)+,R0 ;Move char to R0 SUB #'0,R0 ;Subtract ASCII zero BMI 100$ ;If MI, char is not a number CMP #9.,R0 ;Is it a 9? BLO 100$ ;If not, branch ASL R3 ;Multiply previous result by 2 MOV R3,-(SP) ;Save it ASL R3 ;R3 * 4 ASL R3 ;R3 * 8 ADD (SP)+,R3 ;(R3 * 2) + (R3 * 8) = R3 * 10 ADD R0,R3 ;Add new digit to previous result BR 10$ ;Keep going until end 100$: RETURN .SBTTL MOVASC ;+ ; ; THIS SUBROUTINE SAVES THE ASCII OF THE INPUT FILENAME ; ; INPUTS: ; R3 = ADDRESS OF THE BUFFER IN WHICH TO PLACE ; THE SPEC ; ;- MOVASC: MOV #FILLEN,R0 ;NUMBER OF BYTES TO MOVE MOV #CHARS,R1 ;START OF ASCII SPEC 10$: MOVB (R1)+,(R3)+ ;MOVE A BYTE INTO THE BUFFER DEC R0 ;DEC COUNTER BGT 10$ ;IF NOT FINISHED, BRANCH RETURN ;RETURN .SBTTL DECIMA - Binary to Decimal conversion routine ;+ ; This routine converts a binary number stored in R2 to a decimal ; ASCII representation and prints it. ; ; R1 -> output buffer ; R2 = Binary number to be printed ; CALL DECIMB ; ; on return, ; ; R4 = Number of characters printed ;- .ENABL LSB ; Decimal-to-ASCII, R2=num, R1->buf DECIMB::CLR R4 ; Clear register four 10$: MOV R2,-(SP) ; Store the value CLR R2 ; Serve as counter 20$: INC R2 ; Count one SUB #10.,@SP ; Divide by repetive subtract BHIS 20$ ; Branch if not minus ADD #10.+'0,@SP ; Restore the remaining number INC R4 ; Count character DEC R2 ; Decrement counter BEQ 30$ ; If = 0 finish CALL 10$ ; Repeat if not 30$: MOV (SP)+,R0 MOVB R0,(R1)+ ; store the character RETURN ; Keep printing till return address .DSABL LSB .SBTTL PATCH SPACE .PSECT $PAT ;PATCH SPACE .BLKW 32. .IF NE MSS$DB .SBTTL - Debug Messages ;+ ; these are messages printed at the entry of routines to help ; future developers ;- MSS$1: .ASCIZ /Entering WCDSTR - Start A New Pair/ MSS$2: .ASCIZ /Entering DONE - Finish Up The Current Comparison/ MSS$3: .ASCIZ /Entering INIT/ MSS$4: .ASCIZ /Entering READ - Read A Block From Each File And Call Compare/ MSS$5: .ASCIZ /Entering WRF - Do A Compare And Call DIFF and Maybe $SIPP/ MSS$6: .ASCIZ /Entering DIFF - Set Up An Output Line/ MSS$7: .ASCIZ /Entering LAB/ MSS$8: .ASCIZ /Entering OCTOUT/ MSS$9: .ASCIZ /Entering WRITBF - Physical Write of Buffer To Output Device/ MSS$10: .ASCIZ /Entering HEAD - Initialize Output Buffer/ MSS$11: .ASCIZ /Entering $SIPP - Create A Sipp Command Line/ MSS$12: .ASCIZ /Entering PRESP - Output Buffer of Sipp Commands/ MSS$13: .ASCIZ /Entering SPPIN - Create Initial Sipp Commands/ MSS$14: .ASCIZ /Entering SLZERO- Suppress Leading Zero/ MSS$15: .ASCIZ /Entering PROUT - Flush The Output Buffer/ MSS$16: .ASCIZ /Entering SETUP - Set Up Compare Loop/ MSS$17: .ASCIZ /Entering DEVDEV - Load Handlers/ MSS$18: .ASCIZ /Entering SPCTST/ MSS$19: .ASCIZ /Entering WILCRD - Determine If There Is Wild Carding/ MSS$20: .ASCIZ /Entering WCDCHR - See If Input Specs Contain "*" or "%"/ MSS$21: .ASCIZ /Entering WCDPAR - Parse The File Spec As Neccessary/ MSS$22: .ASCIZ /Entering SPCCMP/ MSS$23: .ASCIZ /Entering SPCFIX/ MSS$24: .ASCIZ /Entering WCDINT - Wild Card Initialization/ MSS$25: .ASCIZ /Entering WCDIO - Set Up WildCarding/ MSS$26: .ASCIZ /Entering WCDOUT - Set Up Output File/ MSS$27: .ASCIZ /Entering WCDDEV - See What Kind Of Device A File Is On/ MSS$28: .ASCIZ /Entering WCDFET - Fetch The Two Handlers/ MSS$29: .ASCIZ /Entering WCDBUF - Allocate The First WildCarding Buffer/ MSS$30: .ASCIZ /Entering WCDFIL - Do .Lookup On The Input Device/ MSS$31: .ASCIZ /Entering WCDISP - Get Matching File Names, allocate 2nd Buffer/ MSS$32: .ASCIZ /Entering WCDIR - Get A Directory Entry/ MSS$33: .ASCIZ /Entering MATCH1/ MSS$34: .ASCIZ /Entering MATCH2 - Subroutine of Match1/ MSS$35: .ASCIZ /Entering WCDMAT - See Which File Names In Buffers To Compare/ MSS$36: .ASCIZ /Entering MATCH - Are Two Input Strings Exactly Alike/ MSS$37: .ASCIZ /Entering WCDLKO - .Lookup Or .Enter The Output Device/ MSS$38: .ASCIZ /Entering WCDLKI - .Lookup The Input Files/ MSS$39: .ASCIZ /Entering LOOK2/ MSS$40: .ASCIZ /Entering LOOK1/ MSS$41: .ASCIZ /Entering WCDPRT - Display The Comparing Message/ MSS$42: .ASCIZ /Entering MAT2 - Subroutine Of Twofil/ MSS$43: .ASCIZ /Entering TWOFIL/ MSS$45: .ASCIZ /About To Do 373 for Input File 1/ MSS$46: .ASCIZ /About To Do 373 for Input File 2/ .EVEN .ENDC ;NE MSS$DB .END START