.MCALL .MODULE .MODULE PIPEXE,VERSION=36,COMMENT=,IDENT=NO ; 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. ; Edit History ; ; 19-AUG-85 George Thissell ; fix COPY/MULTIVOLUME to a tape ; ; 3-OCT-85 George Thissell ; fix COPY TT: LS: bug ; ; 11-JUL-86 Jacqueline Proulx ; allow lowercase in COPY from TT: ; ; 9-APR-86 Deb Sengupta ; Fix logic so that COPY/DEL of a protected file would go thru ; the copying part before aborting (Action Item #5892). ; ; 9-APR-86 Deb Sengupta ; Fix bug in displaying "Device Full" error message when trying ; to copy to a full magtape (Action Item #6165) ; ; 14-APR-86 Deb Sengupta ; Fix bug in FSM/PIP handling of "position lost" error during write ; to magtape (Action Item #6169) ; ; (027) 09-Jun-89 Code change to cause deletion of input files ; MBG when doing COPY/CONCATENATE/DELETE ; ; (029) 16-Jun-89 Another change for COPY/DELETE/... so that protected ; MBG files are reported during the input volume scan ala ; the DELETE command and so that protected files ; cause a warning message (as before) but then really ; do get copied. ; ; (031) 16-Aug-89 Change to prevent double copying of a file when ; MBG the input and output device names are different ; logicals, but physically the same. ; ; (033) 26-Sep-89 Yet another code change for COPY/CONCATENATE so ; MBG that if an input file is not found, the copy is ; terminated with an 'F' error and the output file ; is discarded. ; ; (034) 05-Apr-90 Per action #7076, fix to code to prevent copy ; MBG of specific file from magtape if file is not ; in position specified by /POS:n. ; ; (035) 02-Nov-1990 bracket error messages with ;+/;ERROR/.../;- ; JFW ; ; (036) 21-oct-1996 Protection bit can no longer reside in high ; Tim Shoppa bit of date word because that's now used for ; epoch bits. Instead, create a bitmap (PROBIT) ; which stores the protection status. .ENABL LC,GBL .MCALL ...CMZ ...CMY .SBTTL PSECT definitions .IIF NDF IND, IND = 0 ;Default to no IND .IIF NDF ATP, ATP = 0 ;ATP can be used in place of IND .IIF NE ATP, IND = 1 .IIF NDF VOL, VOL = 0 ;Default no volume id check ;+ ; The PSECT's are defined here to give them the desired ordering. ; Consider the ordering critical. Several of the PSECT's contain ; stoppers for lists in the previous PSECT. ;- PSECT IMPURE ;Impure data psect PSECT PURE ;Pure data psect PSECT PUREB ;[byte] Pure data psect PSECT PIPEXE ;Main code psect PSECT COPY ;CODE!!!! See comment at DOCOPY PSECT PATCH ;Patch psect .BLKW 32. ;Root patch space .SBTTL Impure data PSECT IMPURE CPYCNT: .WORD 0 ;Counter for number of copies left to do FILDAT: .WORD 0 ;Date to put on files for RENAME and COPY IBLK: .WORD 0 ;Input block number IBSIZ: .WORD 0 ;Input buffer size save area ISIZ: .WORD 0 ;Length of file MATFLG::.WORD 0 ;File matched flag for magtape copies OBSIZ: .WORD 0 ;Output buffer size save area REBOOT: .WORD 0 ;Reboot message needed flag SPCPTR::.WORD 0 ;-> current input file spec OVRLOD::.WORD 0 SYSACT: .WORD 0 ;Flag that .SYS file was found with no /SYSTEM INPDEV: .WORD 0 ;Input device for EXCLUDE DFLAG: .WORD 0 ;Flag word for /BEFORE and /SINCE MVSEQ:: .WORD 0 ;Temp storage for user's requested ;seq number MVFLAG::.WORD 0 ;Flag word for /MULTIVOL and other stuff NOFIT = 1 ;A file didn't fit. OUTFUL = 2 ;Output file full SKIPIT = 4 ;An error occured during ENTER and the ; file should not be copied. MVCOP = 10 ;A file was copied onto the current vol INEQOU = 20 ;Input filespec = output filespec DIRFUL = 40 ;The directory was full on output dev BIGSIZ::.WORD 0 ;Size of the smallest file so far which ;didn't fit. Don't try any bigger. PROBIT: .BLKW 5 ;5 words have room for 80. protection ;036 ;bits, only need 77. ;036 DELBUF: .BLKW 4 ;Buffer for protected filename PSECT PUREB .NLIST BEX FILHED: .ASCII \ Files \<200> COPHED: .ASCIZ \copied:\ CDHED: .ASCIZ \copied/deleted:\ DELHED: .ASCIZ \deleted:\ RENHED: .ASCIZ \renamed:\ PROHED: .ASCIZ \protected:\ UNPHED: .ASCIZ \unprotected:\ .IF NE IND .EVEN APTMP:: .RAD50 \DK AP \ .RAD50 \TMP\ .ENDC ;NE IND PSECT IMPURE FILE1: .ASCII \dev:filnam.typ \ TO: .ASCII \to \ FILE2: .ASCII \dev:filnam.typ \ QMARK: .ASCII \? \<200> .EVEN .LIST BEX .SBTTL EXPAND PSECT IMPURE FOUND: .WORD 0 ;File found flag ORIGIN PIPEXE EXPAND:: .IF NE IND CALL APPRMT ;Insert prompts for /WAIT .ENDC ;NE IND ...CMZ MOV #INFILE,SPCPTR ;Set up pointer to first input file spec MOV #1,ICHAN ;Set up initial input channel number MOV IBFSIZ,IBSIZ ;Save size of input buffer MOV OBFSIZ,OBSIZ ;Save size of output buffer MOV #DEVSTS+2,SAVSTS ;Save -> 1st file's device/file flag word MOV #PNAME,R3 ;R3 -> physical device name TST (R3)+ ;Skip output device name MOV #MATCH2,MATRTN ;Assume normal matching ;CG01+ BIT #PO.COP,FLGWRD ;Physical order copy? BNE 10$ ;Yes; do /EXCLUDE matching BIT #FL.EXC,$MFLAG ;Are we doing /EXCLUDE? BEQ 20$ ;Branch if not 10$: MOV #MATCH3,MATRTN ;Use the exclude "matcher" 20$: MOV IBSIZ,IBFSIZ ;Restore input buffer size MOV OBSIZ,OBFSIZ ; and the output buffer size MOV SPCPTR,R4 ;R4 -> current input file spec TST @R4 ;Any spec given? BNE 30$ ;Branch if so JMP 180$ ;Else check out next one 30$: BIT #DEV.DK,@SAVSTS ;Disk input device? BEQ 40$ ;Branch if not MOV #NEXTDK,R0 ;R0 = address of disk directory scan BR 110$ ; 40$: BIT #DEV.MT,@SAVSTS ;Magtape input device? BEQ 50$ ;Branch if not MOV #NEXTMT,R0 ;R0 = address of magtape directory scan BR 100$ ; 50$: BIT #DEV.CT,@SAVSTS ;Cassette input device? BEQ 60$ ;Branch if not MOV #NEXTCT,R0 ;R0 = address of cassette directory scan BR 100$ ; 60$: BIT #DEV.SD,@SAVSTS ;Is it a strange device? BEQ 80$ ;Branch if not .LOOKUP #IOAREA,ICHAN,R4 ;Lookup the file BCC 70$ ;Branch if no error CLR FOUND ;Say we didn't find the file JMP 150$ ; 70$: MOV BEGLST,R5 ;R5 -> expansion list MOV R5,R0 ;Copy it MOV R4,-(SP) ;Save R4 MOV (R4)+,(R0)+ ;Put in device name MOV (R4)+,(R0)+ ;Copy 1st word of filename MOV (R4)+,(R0)+ ; and 2nd word MOV (R4)+,(R0)+ ; and filetype MOV (SP)+,R4 ;Restore R4 BR 90$ ; 80$: MOV BEGLST,R5 ;Must be TT:, CR:, etc. ;R5 -> expansion MOV R5,R0 ;Copy it MOV @R4,(R0)+ ;Copy device name CLR (R0)+ ;Clear filename CLR (R0)+ ; both words CLR (R0)+ ;Clear filetype 90$: MOV #-1,(R0)+ ;Large amount of input CLR (R0)+ ;Clear start block MOV DATE,(R0)+ ;Use today's date MOV R0,ENDLST ;Save pointer to end of expansion list 100$: MOV #1,R1 ;Use one block buffers MOV R1,IBFSIZ ;Set up input buffer size MOV R1,OBFSIZ ;and output buffer size SWAB R1 ;R1 = number of words in buffer ASL R1 ;R1 = number of bytes in buffer MOV IBUFF,IBUFE ;Set up pointer to end of input buffer ADD R1,IBUFE ;Make it point there MOV OBUFF,OBUFE ;Set up pointer to end of output buffer ADD R1,OBUFE ;Make it point there BIT #,@SAVSTS ;Input CT or MT? BEQ 140$ ;Branch if not 110$: INC OVRLOD ;Don't init overlay unless it's not in. CMP R0,GETNXT ;Is that scan routine in core? BEQ 120$ ;Branch if so MOV R0,GETNXT ;Save the address MOV #SYSDEV,R0 ;R0 -> system physical device name CALL MNTSYS ;*** Mount system volume if needed CLR OVRLOD ;Initialize the overlay if it's already in. CALL @GETNXT ;Load the overlay 120$: CLR $NXTFL ;No next file for directory scanner MOV #1,$NXTSG ;Start at segment 1 130$: MOV R3,R0 ;R0 -> physical device name CALL MNTINP ;*** Mount the input device if necessary ;+ ;ERROR CALL MATDVR ;Try to find a matching file BCC 140$ ;Branch if no error MOV R0,R1 ;R1 = error code CLR 2(R4) ;Print only device name .ERR #ERAREA,R1,LEVEL=FATAL,RETURN=NO,FILE=R4 ; <-F-Directory input error DEV:> ; <-F-Invalid directory DEV:> ;- 140$: CMP R5,ENDLST ;Did we find anything? BEQ 150$ ;Branch if not INC FOUND ;Say that we did CALL @ACTION ;Execute the command BIT #,@SAVSTS ;Normal device? BNE 130$ ;Yes 150$: BIT #PO.COP,FLGWRD ;Doing physical order copying? BNE 180$ ;FNF's will be printed later TST FOUND ;Did we find anything? BNE 180$ ;Branch if so BIT #FL.EXC,$MFLAG ;Doing /EXCLUDE BNE 180$ ;Branch if so - No FNF's BIT #FL.CON,$AFLAG ;Doing /CONC? BEQ 161$ ;Branch if not .PURGE #OCHAN ;+ ;ERROR .ERR #ERAREA,#FE.FNF,LEVEL=FATAL,RETURN=NO,FILE=R4 ;<-F-File not found DEV:FILENAME> ;- 161$: BIT #FL.NOE,$MFLAG ;Doing /NOERR? BEQ 170$ ;Branch if not TST INFOX ;Should the message be printed? BGE 162$ ;Branch if so BISB #10,@#S$UERB ;Set the error byte BR 180$ ;Continue ;+ ;ERROR 162$: .ERR #ERAREA,#FE.FNF,LEVEL=I,RETURN=YES,FILE=R4 ;<-I-File not found DEV:FILENAME> BR 180$ ;Continue 170$: .ERR #ERAREA,#FE.FNF,LEVEL=FATAL,RETURN=YES,FILE=R4 ;<-F-File not found DEV:FILENAME> ;- 180$: .CLOSE ICHAN ;CLOSE THE INPUT CHANNEL ADD #INSPSZ,SPCPTR ;Point to next input spec TST (R3)+ ;Go to next physical device name INC ICHAN ;Bump the channel number ADD #2,SAVSTS ;Bump device/file flag word -> CLR FOUND ;Clear the found file flag CMP SPCPTR,#ENDSPC ;Past the end? BHIS 190$ ;Branch if so JMP 20$ ;Else try the next one 190$: BIT #PO.COP,FLGWRD ;Doing /PHYSICAL? BEQ 230$ ;No MOV #FNAME,R2 ;R2 -> device names MOV #DEVSTS,R1 ;R1 -> dev status words MOV #INFILE,R4 ;R4 -> first input filespec 200$: TST (R1)+ ;Next status word. Skip output BIT #FLG.CO,(R1) ;Was a matching file found? BNE 220$ ;Yes MOV (R2),(R4) ;Move in the device name BIT #FL.CON,$AFLAG ;Doing /CONC? BEQ 201$ ;Branch if not ;+ ;ERROR .ERR #ERAREA,#FE.FNF,LEVEL=FATAL,RETURN=NO,FILE=R4 ;<-F-File not found DEV:FILENAME 201$: BIT #FL.NOE,$MFLAG ;Doing /NOERR? BEQ 210$ ;Branch if not .ERR #ERAREA,#FE.FNF,LEVEL=I,RETURN=YES,FILE=R4 ;<-I-File not found DEV:FILENAME BR 220$ ;Continue 210$: .ERR #ERAREA,#FE.FNF,LEVEL=FATAL,RETURN=YES,FILE=R4 ;<-F-File not found DEV:FILENAME> ;- 220$: ADD #INSPSZ,R4 ;R4 -> Next filespec TST (R2)+ ;Next device name TST (R2) ;IS THERE ANOTHER SPEC? BNE 200$ ;YES 230$: BIT #FL.CON,$AFLAG ;Doing /CONCATENATE? BEQ 260$ ;Branch if not MOV #OCHAN,R1 ;R1 = output channel number CALL LPCHEK ;If output = LP: then force out BCS 240$ ;Branch on error CALL FILBUF ;If /ASCII or /BINARY, force out last buffer BCC 250$ ;Branch if no error 240$: CALL CHKERR ;Do output error recovery BR 260$ ; 250$: MOV #PNAME,R0 ;R0 -> physical device name of output volume CALL MNTOUT ;*** Mount it .CLOSE R1 ;Close the output channel BCC 260$ ;Branch if no error ;+ ;ERROR .ERR #ERAREA,#FE.FCP,LEVEL=WARNING,RETURN=YES,FILE=#OLDNAM ; <-W-File created:protected file already exists DEV:FILENAME> ;- 260$: TST REBOOT ;Do we need to print the reboot message? BEQ 270$ ;Branch if not BIT #FL.NOE,$MFLAG ;Doing /NOERR? BEQ 263$ ;Branch if not TST INFOX ;Should the message be printed? BGE 263$ ;Branch if so BISB #2,@#S$UERB ;Set the error byte BR 270$ ;Continue ;+ ;ERROR 263$: .ERR #ERAREA,#RBT,LEVEL=WARNING,RETURN=YES ; <-W-Reboot> ;- CLR REBOOT ;Reset flag 270$: ...CMY RETURN .SBTTL Insert /WAIT prompts for IND ;+ ; This routine inserts 3 user specified prompts into the strings ; which are used for prompts when /WAIT is specified. The strings ; consist of 3 lines in a file AP.TMP. These are the text strings ; for the input, output and system device (in that order). The ; strings will be inserted into the prompts in this format: ; Mount in DX1:; Continue? ; TEXT is a string such as 'Autopatch volume 1'. ; If an asterisk is specified in place of one of the strings, ; the prompt for that volume will not be issued. In that case it ; is assumed that the volume is already mounted. ;- .IF NE IND APPRMT::MOV #$AFLAG,R5 ;Options flag BIT #FL.WAT,@R5 ;Doing /WAIT? BEQ 30$ ;Branch if not .LOOKUP #IOAREA,ACHAN,#APTMP ;Lookup AP.TMP BCC 10$ ;Branch if no error ;+ ;ERROR ;only if IND conditional selected .ERR #ERAREA,#FE.FNF,LEVEL=FATAL,RETURN=NO,FILE=#APTMP ; <-F-File not found: AP.TMP> 10$: .READW #IOAREA,ACHAN,#APIN,APSZ,APBLK ;Read the text BCC 20$ ;Branch if no error .ERR #ERAREA,#FE.INE,LEVEL=FATAL,RETURN=NO,FILE=#APTMP ; <-F-Input error: AP.TMP> ;- 20$: .CLOSE ACHAN ;Close AP channel MOV #WAITIN,R1 ;R1 -> Input volume prompt MOV #APIN,R2 ;R2 -> Text from AP.TMP CALL GETSTR ;Save the input volume prompt MOVB #200,(R1) ;Insert a <200> .IF NE VOL MOV #WTINVL,R1 ;R1 -> Input volid string CALL GETSTR ;Save the input volid string .ENDC ;NE VOL MOV #WAITOUT,R1 ;R1 -> Output volume prompt CALL GETSTR ;Save the output volume prompt MOVB #200,(R1) ;Insert a <200> .IF NE VOL MOV #WTOUVL,R1 ;R1 -> Output volid string CALL GETSTR ;Save the output volid string .ENDC ;NE VOL MOV #WAITSY,R1 ;R1 -> System volume prompt CALL GETSTR ;Save the system volume prompt MOVB #200,(R1) ;Insert a <200> .IF NE VOL MOV #WTSYVL,R1 ;R1 -> System volid string CALL GETSTR ;Save the system volid string .ENDC ;NE VOL 30$: RETURN .SBTTL - GETSTR - Get a string for the IND prompts ;+ ; GETSTR ; This procedure moves one string (up to a CR) into a buffer. ; ; INPUT: ; R2 -> source ; R1 -> destination ;- GETSTR: 10$: CMPB (R2),#15 ;Is it a CR? BEQ 20$ ;Branch if it is MOVB (R2)+,(R1)+ ;Move a byte to prompt BR 10$ ;Get next byte 20$: TSTB (R2)+ ;Skip the CR TSTB (R2)+ ; and the LF RETURN .ENDC ;.IF NE IND .SBTTL Copy routines ;+ ; The following routines do the actual PIP funtions. They are in ; a separate DATA psect to prevent overlay vectors from being generated ; by references to them in the initialization overlay. ;- ORIGIN COPY .SBTTL DOCOPY - Copy driver ;+ ; DOCOPY ; This is the copy driver. It uses routines COPIMA, COPASC, and COPBIN ; to process the actual copy operations. ; ; R3 -> physical device name ; R4 -> CSI filespec ; R5 -> Input list ; ; CALL COPY ;- .ENABL LSB DOCOPY:: JSR R5,$SAVRG ;Save R3 - R5 MOV OFILNO,MVSEQ ;Save the sequence number the user wants MOV #COPHED,R1 ;Set up default header ("copied") BIT #FL.DEL,$AFLAG ;Doing /DELETE? BEQ 10$ ;Branch if not MOV #CDHED,R1 ;Use correct header ("copied/deleted") 10$: CALL HEADER ;Print header, if needed 20$: MOV KOPIES,CPYCNT ;Set up number of copies 30$: .WAIT #OCHAN ;Is the output file open? BCC 40$ ;Branch if so. Skip checking, .ENTER MOV OBUFF,OBFPTR ;Set up output buffer pointer CLR OBLK ;Clear the output block number 40$: MOV IBFSIZ,R0 ;R0 = size of input buffer in blocks SWAB R0 ;R0 = size of input buffer in words ASL R0 ;R0 = size of input buffer in bytes ADD IBUFF,R0 ;R0 -> end of input buffer MOV R0,IBUFE ;Save it MOV EB.STB(R5),IBLK ;Set up the input block number MOV EB.LEN(R5),ISIZ ;Set up length of file CALL GETOUT ;Get the output filename BCS 120$ ;Branch if .SYS with no /SYSTEM BIT #FL.NRP,$AFLAG ;No replace? BEQ 60$ ;Branch if not MOV #PNAME,R0 ;R0 -> physical device name for output CALL MNTOUT ;Mount the output volume if necessary .LOOKUP #IOAREA,#NCHAN,R4 ;Look for it BCC 50$ ;Branch if we found it ;**-1 TSTB @#S$EERB ;Channel in use? BNE 60$ ;Branch if not. File not found. That's right ;+ ;ERROR CHIU: .ERR #ERAREA,#FE.CIU,LEVEL=FATAL,RETURN=NO ; <-F-Channel in use> 50$: .ERR #ERAREA,#NRP,LEVEL=W,RETURN=YES,FILE=R4 ; <-W-Output file found, no action performed DEV:FILENAME> ;- .CLOSE #NCHAN ;Close the channel BR 120$ ;Go get next file ;**-1 60$: CALL QUERY ;Do query if necessary BNE 120$ ;Branch if we shouldn't copy it BIT #DEV.TT,DEVSTS ;Is output to TT:? BEQ 70$ ;Branch if not CALL CRLOG ;Else log it now. ; ; If PREDELETE specified and the input and output file specifications ; match, don't delete the file. ; ; If DELETE specified and the input and output file specifications ; match, set INEQOU so that the file won't be deleted after the copy. ; 70$: BIC #INEQOU,MVFLAG ;Inputfile not equal to outfile yet MOV R5,R2 ;R2 -> input filespec MOV R4,R0 ;R0 -> output filespec MOV (R2)+,-(SP) ;Get the input device name CALL LTRANP ; translate it to physical MOV (R0)+,-(SP) ;Get the output device name CALL LTRANP ; translate it to physical CMP (SP)+,(SP)+ ;Are input and output devices the same? ;;; CMP (R2)+,(R0)+ ;Are devices the same? BNE 80$ ;No -> delete the file CMP (R2)+,(R0)+ ;1st word of filenames the same? BNE 80$ ;No -> delete the file CMP (R2)+,(R0)+ ;2nd word of filenames the same? BNE 80$ ;No -> delete the file CMP @R2,@R0 ;Extensions the same? BNE 80$ ;No -> delete the file BIS #INEQOU,MVFLAG ;Don't delete the file after copying BR 130$ ;Just continue 80$: BIT #FL.OPD,$AFLAG ;Doing /PREDELETE? BEQ 130$ ;Branch if not (Doing only /DELETE) 90$: MOV #PNAME,R0 ;R0 -> physical device name for output CALL MNTOUT ;Mount output volume if necessary .DELETE #IOAREA,#OCHAN,R4 ;Delete the file BCC 100$ ;Branch if no error CMPB #3,@#S$EERB ;Output file protected? BEQ 110$ ;Branch if so 100$: CMP R4,R5 ;COPY/DELETE, PRINT/DELETE in progress? BNE 130$ ;Branch if not BR 120$ ;Else go to the next file ;+ ;ERROR 110$: .ERR #ERAREA,#PFL,LEVEL=FATAL,RETURN=YES,FILE=R4 ; <-F-Protected file DEV:FILENAME> ;- 120$: JMP 340$ 130$: BIT #,$AFLAG ;/CONCATENATE or /WAIT mode? BNE 140$ ;Branch if so. ; ; If the input dev:filename.type matches the output dev:filename.type ; we rename the file instead of copying it, to prevent our finding ; it in some later directory segment. ; ; There are two conditions under which the file specifications match and ; we do the copy rather than the rename: either ASCII or BINARY convers ; is requested, or a non-filestructured device is specified. ; ; NOTE: This code is not executed if either the /WAIT or the /CONCATENAT ; option was specified ; BIT #INEQOU,MVFLAG ;Does input spec=output spec? BEQ 140$ ;Branch if not to do copy BIT #,$AFLAG ;ASCII or BINARY conversion? BNE 140$ ;Branch if so to do copy BIT #,DEVSTS ; OUTPUT TO TT,NL,LP,LS,MT,CT ? BEQ 140$ ; NO, GO DO COPY CMP @R3,PNAME ;Physical devices the same? BNE 140$ ;Branch if not to do copy JMP 290$ ;Physical input & output devices are the ; same so do rename instead 140$: .WAIT #OCHAN ;Is the output file open? BCC 190$ ;Branch if so. Skip .ENTER CALL ENTER ;Enter the output file BIT #FL.MUL,$AFLAG ;Doing /MULTIVOL? BEQ 180$ ;No BCC 190$ ;It fits; copy it BIT #SKIPIT,MVFLAG ;Should the file be copied? BNE 120$ ;No - skip it. BIT #DEV.DR,DEVSTS ;Is output NON directory structured? BEQ 150$ ;Branch if it is dir structured BIS #NOFIT,MVFLAG ;Set nofit flag JMP 350$ ;Yes - it's MT or CT 150$: CMP OVSIZE,EB.LEN(R5) ;Is file bigger than output device? BGE 160$ ;No - try next file ;+ ;ERROR .ERR #ERAREA,#FLO,LEVEL=WARNING,RETURN=YES,FILE=R5 ; <-W-File larger than output device FILESPEC> ;- JMP 340$ ;Say it's been copied 160$: BIS #NOFIT,MVFLAG ;It didn't fit; indicate so BIT #DIRFUL,MVFLAG ;Is the directory full? BEQ 170$ ;Branch if not JMP 380$ ;Try another volume 170$: MOV EB.LEN(R5),BIGSIZ ;Save the size which didn't fit JMP 350$ ;Try next file 180$: BCC 190$ ;Branch if error 185$: JMP 340$ ;Jump if error (BR chain to 340$) 190$: BIC #OUTFUL,MVFLAG ;No output file full yet CLR OERR ;No output errors yet CLR IERR ;No input errors yet BIT #DEV.TT,DEVSTS+2 ;Is input from TT:? BEQ 200$ ;No, go do copy BIS #JS.TTLC,@#S$JSW ;Set lowercase in JSW .RCTRLO 200$: CALL @COPRTN ;Do the copy BIS #MVCOP,MVFLAG ;A file was copied BIT #DEV.TT,DEVSTS+2 ;Is input from TT:? BEQ 210$ ;No, go do copy BIC #JS.TTLC,@#S$JSW ;Set lowercase in JSW .RCTRLO 210$: MOV #OCHAN,R1 ;R1 = output channel number TST OERR ;Was there an output error? BNE 220$ ;Branch if so TST IERR ;Was there an input error? BEQ 250$ ;Branch if not. 220$: CALL CHKERR ;Handle output error recovery BCS 240$ ;Branch if error on error recovery! BIT #FL.MUL,$AFLAG ;Doing /MULTIVOL? BEQ 230$ ;No BIT #OUTFUL,MVFLAG ;was the error output file full? BEQ 240$ ;No, it's not recoverable BIS #NOFIT,MVFLAG ;A file didn't fit; (it's MT) MOV EB.LEN(R5),BIGSIZ ;Save the size which didn't fit .CLOSE #OCHAN ;Close output for /MULTIVOL JMP 350$ ;Try next file 230$: TST OERR ;Was there an output error BNE 240$ ;Branch if so. Never continuable TST IERR ;Is the input error continuable? BMI 185$ ;Branch if so (chained to 340$) 240$: JMP ABORT ;Else abort! 250$: CALL LPCHEK ;Force if output = LP: BCS 220$ ;Branch on error BIT #FL.CON,$AFLAG ;Doing a /CONCATENATE? BNE 300$ ;Branch if so. Don't close output CALL FILBUF ;Dump last buffer if /ASCII or /BINARY BCS 220$ ;Branch on error MOV #PNAME,R0 ;R0 -> physical device name for output CALL MNTOUT ;*** Mount it if need be .CLOSE R1 ;Close the output channel BCC 260$ ;Branch if no error ;+ ;ERROR .ERR #ERAREA,#FE.FCP,LEVEL=WARNING,RETURN=YES,FILE=#OLDNAM ; <-W-File created:protected file already exists DEV:FILENAME> ;- BR 300$ ; 260$: BIT #DEV.DK,DEVSTS ;Is output a disk? BEQ 300$ ;If not, don't protect or set date BIT #FL.PRO,$AFLAG ;Doing /Protect? BNE 270$ ;Yes - go protect the output file BIT #FL.UNP,$AFLAG ;Doing /Unprotect? BNE 280$ ;Yes - don't protect output file CALL PROBLU ;look up the protection bits ;036 BIT R0,PROBIT(R1) ;check the protection bit ;036 BEQ 280$ ;branch if we don't want it protected ;036 270$: MOV R3,-(SP) ;Save the physical device name MOV #1,R3 ;R3 = Set the protection MOV R4,R2 ;R2 -> File to be protected CALL PROTFL ;Protect the file MOV (SP)+,R3 ;Restore the physical device name 280$: MOV R4,R2 ;R2 -> File to set date for CALL SDATFL ;Set the date of the file BR 300$ ; 290$: MOV ENDLST,-(SP) ;Save the endpoint of the input list MOV R5,ENDLST ; and make it point at the current ADD #EB.SIZ,ENDLST ; position plus one entry MOV $MFLAG,-(SP) ;Save the options word BIC #,$MFLAG ; and clear the query and log mo CALL DOREN1 ;Rename the file. MOV (SP)+,$MFLAG ;Restore the options word MOV (SP)+,ENDLST ; and the end of the input list SUB #EB.SIZ,R5 ;RESTORE R5 BCS 340$ ;Branch if there was an error 300$: DEC CPYCNT ;Decrement the copy counter BLE 310$ ;Branch if done JMP 30$ ;Else go do another one 310$: BIT #DEV.TT,DEVSTS ;Output to TT:? BNE 320$ ;Branch if so. Logging already done CALL CRLOG ;Do logging if necessary 320$: BIT #FL.DEL,$AFLAG ;/DELETE specified? BEQ 340$ ;Branch if not BIT #INEQOU,MVFLAG ;Does inputspec eq output spec? BNE 340$ ;Yes -> ignore the /DELETE MOV #PNAME+2,R0 ;R0 -> input device CALL MNTINP ;Mount the input volume if needed MOV R5,R4 ;Point to the input file BIT #FL.WAT,$AFLAG ;Doing /WAIT? BEQ 330$ ;Branch if not .PVAL #IOAREA,#S.BLKY,#0 ;Force directory read 330$: .DELETE #IOAREA,#NCHAN,R4 ;Delete the input file ; Protected file errors are not reported at this point since they should ; be reported during the input volume scan performed by the MATCH1 routine. ; The only reason a file would not be displayed at that time yet fail ; deletion now is if a foreground or system job protected it in the ; intervening time. The following code is not included because it would ; cause a second message to be printed if the file had been protected ; at the time of the input volume scan. ;;; BCC 340$ ;Success... ;;; CMPB @#S$EERB,#3 ;Failure due to protected file? ;;; BNE 340$ ;Nope... ;;; .ERR #ERAREA,#PFL,LEVEL=WARNING,RETURN=YES,FILE=R4 ;;;; <-W-Protected file DEV:FILENAME> 340$: CLR EB.DEV(R5) ;Indicate it was copied 350$: ADD #EB.SIZ,R5 ;R5 -> next file in input list CMP R5,ENDLST ;Are there any more files to copy? BHIS 380$ ;Branch if not 360$: TST EB.DEV(R5) ;Was it already copied? BEQ 350$ ;Yes; Get next one BIT #NOFIT,MVFLAG ;Was there a file that didn't fit? BEQ 370$ ;No there wasn't CMP EB.LEN(R5),BIGSIZ ;Is this any smaller than the one ; that didn't fit? BGE 350$ ;Try the next one 370$: JMP 20$ ;Go do next file 380$: BIT #FL.MUL,$AFLAG ;Doing /MULTIVOL BEQ 400$ ;No BIT #NOFIT,MVFLAG ;Do we still have a file to copy? BEQ 400$ ;No MOV BEGLST,R5 ;Start at top of list BIC #NOFIT,MVFLAG ;And say all have fit so far BIT #MVCOP,MVFLAG ;Were any files copied? BNE 390$ ;Branch if so ;+ ;ERROR .ERR #ERAREA,#FE.DVF,LEVEL=I,RETURN=YES,FILE=R4 ;- 390$: WAIT #WAITMV,#PNAME ;Wait for a new volume BIC #MVCOP,MVFLAG ;Say no files were copied .CLOSE #OCHAN ;Close the output channel CALL GTOVSZ ;Get the size of this volume CLR OFILNO ;Force a rewind for first file on tape ;(It's the only way it will work) BR 360$ ;GO THRU LIST 400$: RETURN .DSABL LSB .SBTTL COPIMA - Do image mode copy ;+ ; COPIMA ; This routine does the /IMAGE (block for block) copy. ; ; R3 -> physical device name of input device ; R5 -> expansion block ; IBUFF -> input buffer ; IBLK = input block number (next) ; ISIZ = number of blocks left to transfer ; IBFSIZ = size of input buffer in blocks ; ; CALL COPIMA ; ; R0 modified ; ; C-bit = 1 => EOF or error on input file ;- COPIMA:: CALL GETBUF ;Get a buffer load BCS 10$ ;Branch on error or EOF MOV IBUFE,R0 ;R0 -> past end of input buffer SUB IBUFF,R0 ;R0 = size of buffer in bytes MOV OBUFF,OBUFE ;OBUFE -> output buffer ADD R0,OBUFE ;OBUFE -> past output buffer CALL PUTBUF ;Output a buffer load BCC COPIMA ;Branch if no error 10$: RETURN .SBTTL COPASC - Do /ASCII copy ;+ ; COPASC ; This routine does the /ASCII copy. It strips all characters to 7-bit, ; ignores null and rubouts, and quits on eof or ^Z. ; ; R3 -> physical device name of input device ; R5 -> expansion block ; IBUFE -> past end of input buffer ; IBUFF -> input buffer ; IBLK = input block number (next) ; ISIZ = number of blocks left to transfer ; IBFSIZ = size of input buffer in blocks ; ; CALL COPASC ; ; R0 modified ; ; C-bit = 1 => EOF or error on input ;- COPASC:: MOV IBUFE,IBFPTR ;Force a read 10$: CALL GETC ;Get a character BCS 20$ ;Branch if eof or error BIC #^C<177>,R0 ;Leave only 7-bit ASCII BEQ 10$ ;Ignore nulls CMP R0,#177 ;? BEQ 10$ ;Branch if so. Ignore it CMPB R0,#'Z-100 ;^Z? BEQ 20$ ;Branch if so. EOF CALL PUTC ;Output the character BCC 10$ ;Branch if no error 20$: RETURN .SBTTL COPBIN - Do /BINARY copy ;+ ; COPBIN ; This routine does the /BINARY copy. Anything before the first 001 byte ; is ignored. Library files generate an error message and exit. ; ; R3 -> physical device name of input device ; R5 -> expansion block ; IBUFE -> past end of input buffer ; IBUFF -> input buffer ; IBLK = input block number (next) ; ISIZ = number of blocks left to transfer ; IBFSIZ = size of input buffer in blocks ; ; CALL COPBIN ; ; R0 modified ; ; C-bit = 1 => EOF or error on input file ;- PSECT PURE THREAD: .WORD BYTE1 ;Find the 001 byte .WORD MBYTEA ;Output following null .WORD SIZE1 ;Get first byte of byte count .WORD SIZE2 ;Get second byte of byte count .WORD MBYTE ;Get rest of data w/out advancing thread PSECT IMPURE BCNTMP: .WORD 0 ;Byte count accumulator BYCNT: .WORD 0 ;Byte count for binary block CKSUM: .WORD 0 ;Checksum accumulator CSERR: .WORD 0 ;Flag for having given a checksum error LIBFLG: .WORD 0 ;Flag to check for library files PSECT * .ENABL LSB COPBIN:: JSR R5,$SAVRG ;Save R3 - R5 MOV IBUFE,IBFPTR ;Force a read CLR LIBFLG ;Set flag to check for .OBJ libraries CLR CSERR ;Haven't given a checksum error 10$: MOV #THREAD,R4 ;R4 -> jump list for code thread 20$: CALL GETC ;Get a byte BCS 70$ ;Branch if eof BIC #^C<377>,R0 ;Leave only low byte TST LIBFLG ;Have we checked for .OBJ library yet? BNE 30$ ;Branch if so MOV IBUFF,R2 ;R2 -> input buffer CMP 4(R2),#7 ;Is it a library file? BEQ 50$ ;Branch if so. Can't binary copy INC LIBFLG ;Flag that we don't need to check again 30$: MOV @R4,PC ;*** JMP in disguise BYTE1: CMP R0,#1 ;Found first data byte? BNE 20$ ;Branch if not. Ignore CLR CKSUM ;Clear the checksum word CLR BYCNT ;Clear the byte count. BR MBYTEA ;Output data and advance code thread SIZE1: MOVB R0,BCNTMP ;Save the first byte of the byte count BR MBYTEA ;Output data and advance code thread SIZE2: MOVB R0,BCNTMP+1 ;Save the second byte of the byte count ADD BCNTMP,BYCNT ;Compute the byte count INC BYCNT ;Adjust for checksum byte .BR MBYTEA ;Output data and advance code thread MBYTEA: TST (R4)+ ;Advance the code thread MBYTE: MOV R0,R1 ;Copy data byte CALL PUTC ;Output it BCS 70$ ;Branch on error ADD R1,CKSUM ;Compute checksum DEC BYCNT ;Done with this block? BNE 20$ ;Branch if not. Get next byte. TSTB CKSUM ;Checksum 0? BEQ 10$ ;Branch if so. Do next block MOV #CSE,R1 ;Get the error code BIT #FL.IGN,$MFLAG ;Ignoring errors? BNE 40$ ;Branch if so ;+ ;ERROR .ERR #ERAREA,R1,LEVEL=FATAL,RETURN=YES,FILE=R5 ; <-F-Checksum error DEV:FILENAME> ;- BR 60$ ; 40$: TST CSERR ;Have we given the error for this file? BNE 10$ ;Branch if so. Don't give it again .ERR #ERAREA,R1,LEVEL=WARNING,RETURN=YES,FILE=R5 ; <-W-Checksum error DEV:FILENAME> INC CSERR ;Flag that we've given the error once BR 10$ ; 50$: .ERR #ERAREA,#LNC,LEVEL=WARNING,RETURN=YES,FILE=R5 ; <-W-Library file not copied DEV:FILENAME> ;- 60$: BIS #100000,IERR ;Flag error as continuable SEC ;Indicate the error to caller 70$: RETURN .DSABL LSB .SBTTL DODEL - Delete processor ;+ ; DODEL ; Delete files. ; ; R3 -> physical device name of the input device ; R4 -> CSI filespec ; R5 -> input list ; ; CALL DODEL ;- DODEL:: JSR R5,$SAVRG ;Save R3 - R5 MOV #DELHED,R1 ;R1 -> header ("deleted") CALL HEADER ;Print it if needed 10$: CALL QUERY ;Do query if necessary BNE 80$ ;Branch if we shouldn't copy it .DELETE #IOAREA,#OCHAN,R5 ;Delete the output file BCC 70$ ;Branch if no error MOVB @#S$EERB,R0 ;Get the EMT error byte BNE 20$ ;Branch if not 0 JMP CHIU ;Give channel in use error ; <-F-Channel in use> 20$: DEC R0 ;Check for file not found BNE 30$ ;Branch if not ;+ ;ERROR MOV #FE.FNF,R1 ;Set the error code ; <-F-File not found DEV:FILENAME> BR 50$ ;Set up filename and give error 30$: DEC R0 ;See if Invalid operation BNE 40$ ;Branch if not MOV #IDL,R1 ;Set the error code ; <-F-Invalid delete DEV:FILENAME> BR 50$ ;Give the error 40$: MOV #PFL,R1 ;Set up the error code ; <-F-Protected file DEV:FILENAME> 50$: MOV R5,R3 ;R3 -> input filename 60$: .ERR #ERAREA,R1,LEVEL=FATAL,RETURN=YES,FILE=R3 ;- BR 80$ ; 70$: CALL DLOG ;Do it MOV 6(R4),R0 ;R0 = filetype of output file CMP R0,#<^RSYS> ;Is the output filetype /SYS? BNE 80$ ;Branch if not CMP @R3,SYSDEV ;Is the output to the system dev? BNE 80$ ;Branch if not INC REBOOT ;Yes - print the reboot message 80$: ADD #EB.SIZ,R5 ;Point to the next file CMP R5,ENDLST ;Are there any more files? BLO 10$ ;Branch if so RETURN .SBTTL DOPROT - PROTECT/NOPROTECT processor ;+ ; DOPROT ; Protect or Unprotect files. ; ; R4 -> CSI filespec ; R5 -> input list ; ; CALL DOPROT ;- DOPROT:: JSR R5,$SAVRG ;Save R3 - R5 MOV #UNPHED,R1 ;R1 -> header ("unprotected") CLR R3 ;R3 = reset protection (noprotect) BIT #FL.PRO,$AFLAG ;Doing Protect? BEQ 10$ ;No MOV #PROHED,R1 ;R1 -> header ("protected") INC R3 ;R3 = set protection (protect) 10$: CALL HEADER ;Print it if needed 20$: CALL QUERY ;Do query if necessary BNE 40$ ;Branch if we shouldn't copy it MOV R5,R2 ;R2 -> file to be protected CALL PROTFL ;Protect the file BIT #FL.DAT,$MFLAG ;Doing /SETDATE? BEQ 30$ ;Branch if not MOV OUTDAT,FILDAT ;Use the current or given date CALL SDATFL ;Go set the date 30$: CALL DLOG ;Do it 40$: ADD #EB.SIZ,R5 ;Point to the next file CMP R5,ENDLST ;Are there any more files? BLO 20$ ;Branch if so RETURN .SBTTL DOREN - Rename processor ;+ ; DOREN ; Rename files. ; ; R3 -> physical device name of the input device ; R4 -> CSI filespec ; R5 -> input list ; ; CALL RENAME ;- .ENABL LSB DOREN:: JSR R5,$SAVRG ;Save R3 - R5 CMP @R3,PNAME ;Input device same as output device? BNE 40$ ;Branch if not. Go give error MOV #RENHED,R1 ;Set up pointer to header ("renamed") CALL HEADER ;Print the header if needed 10$: CALL GETOUT ;Get the output filename BCS 120$ ;Branch if .SYS with no /SYSTEM CALL QUERY ;Check for query mode BNE 120$ ;Branch if user said no. BIT #FL.NRP,$AFLAG ;IS THIS /NOREPLACE? BEQ DOREN1 ;IF NOT, DO RENAME .LOOKUP #IOAREA,#OCHAN,#NEWNAM ;LOOK FOR NEW NAME BCS DOREN1 ;IF ERROR, ASSUME NOT FOUND .CLOSE #OCHAN ;CLOSE the channel ;+ ;ERROR MOV #NRP,R1 ;NO ERROR-> FILE WAS FOUND ; <-W-OUTPUT FILE FOUND, NO ACTION PERFORMED> ;- BR 60$ ;GIVE THE ERROR DOREN1: ;MOV #FIXDAT,IOAREA+10 ;Set up date fixing routine ; MOV EB.DAT(R5),FILDAT ;Set up the file's date ; BIC #DS.PRO,FILDAT ;Clear protection if there ;036 .RENAME #IOAREA,#OCHAN,#OLDNAM ;Rename the file BCC 80$ ;Branch if no error MOVB @#S$EERB,R0 ;Get the EMT error byte BNE 20$ ;Branch if not 0 JMP CHIU ;Give channel in use error ; <-F-Channel in use> 20$: DEC R0 ;Check for file not found BNE 30$ ;Branch if not ;+ ;ERROR MOV #FE.FNF,R1 ;Set the error code ; <-F-File not found DEV:FILENAME> BR 60$ ;Set up filename and give error ;- 30$: DEC R0 ;See if Invalid operation BNE 50$ ;Branch if not 40$: MOV R5,R2 ;R2 -> old (input) filename ;+ ;ERROR MOV #ILR,R1 ;Set the error code ; <-F-Invalid rename DEV:FILENAME> BR 70$ ;Give the error 50$: MOV #FE.OFP,R1 ;Set up the error code ; <-F-Protected file already exists DEV:FILENAME> MOV R4,R2 ;R2 -> new (output) filename BR 70$ ;Give error message 60$: MOV R5,R2 ;R2 -> old (input) filename 70$: .ERR #ERAREA,R1,LEVEL=FATAL,RETURN=YES,FILE=R2 ;- CMP R1,#ILR ;Invalid rename? BNE 120$ ;Branch if not. Don't log it JMP ABORT ;Quit. Can't possibly do anything else! 80$: BIT #,$AFLAG ;Doing /PROTECT or /UNPROTECT BEQ 100$ ;Branch if not MOV R3,-(SP) ; SAVE FILE DESCRIPTOR POINTER CLR R3 ;R3 = unprotect BIT #FL.PRO,$AFLAG ;Doing /PROTECT? BEQ 90$ ;Branch if doing /UNPROTECT INC R3 ;R3 = protect 90$: MOV R4,R2 ;R2 -> File to be protected CALL PROTFL ;Protect or unprotect the file MOV (SP)+,R3 ; RESTORE FILE DESCRIPTOR POINTER 100$: BIT #FL.DAT,$MFLAG ;Doing /SETDATE? BEQ 110$ ;Branch if not MOV OUTDAT,FILDAT ;Use the current or given date MOV R4,R2 ;R2 -> File to set date of CALL SDATFL ;Set the file date 110$: CALL CRLOG ;Do the logging MOV 6(R4),R0 ;R0 = filetype of output file CMP R0,#<^RSYS> ;Is the output filetype /SYS? BNE 120$ ;Branch if not CMP PNAME,SYSDEV ;Is the output to the system dev? BNE 120$ ;Branch if not INC REBOOT ;Yes - print the reboot message 120$: ADD #EB.SIZ,R5 ;Point to the next filename CMP R5,ENDLST ;Do we have any more files? BLO 10$ ;Branch if so. 130$: RETURN .DSABL LSB .SBTTL PROTFL - Protect a file ;+ ; PROTFL ; This routine is used to protect or unprotect a file ; ; R2 -> File to be protected or unprotected (RAD50) ; R3 = 0 to unprotect, 1 to protect ; ; CALL PROTFL ; PROTFL:: .FPROT #IOAREA,#OCHAN,R2,R3 BCC 40$ ;Branch if no error MOVB @#S$EERB,R0 ;Get the EMT error byte BNE 10$ ;Branch if not 0 JMP CHIU ;Give channel in use error ; <-F-Channel in use> 10$: DEC R0 ;Check for file not found BNE 20$ ;Branch if not ;+ ;ERROR MOV #FE.FNF,R1 ;Set the error code ; <-F-File not found DEV:FILENAME> BR 30$ ;Set up filename and give error 20$: MOV #IPR,R1 ;Set the error code ; <-F-Invalid protect DEV:FILENAME> 30$: MOV R2,R3 ;R3 -> input filename .ERR #ERAREA,R1,LEVEL=FATAL,RETURN=NO,FILE=R3 ;- 40$: RETURN ;Return .SBTTL SDATFL - Set the date of a file ;+ ;SDATFL ; This routine sets the date of a file ; ; R2 -> File whose date is to be changed (RAD50) ; FILDAT = The date to be used ; ; CALL SDATFL ;- SDATFL:: .SFDAT #IOAREA,#OCHAN,R2,FILDAT BCC 40$ ;Branch if no error MOVB @#S$EERB,R0 ;Get the EMT error byte BNE 10$ ;Branch if not 0 JMP CHIU ;Give channel in use error ; <-F-Channel in use> 10$: DEC R0 ;Check for file not found BNE 20$ ;Branch if not ;+ ;ERROR MOV #FE.FNF,R1 ;Set the error code ; <-F-File not found DEV:FILENAME> BR 30$ ;Set up filename and give error 20$: MOV #ISD,R1 ;Set the error code ; <-F-Invalid set date DEV:FILENAME> 30$: MOV R2,R3 ;R3 -> input filename .ERR #ERAREA,R1,LEVEL=FATAL,RETURN=NO,FILE=R3 ;- 40$: RETURN ;Return .SBTTL FIXDAT - Put the correct date and protection on a file ;+ ; FIXDAT ; This routine is used to place the correct date and protection on a fil ; It is called by the USR if there is an extra argument to .RENAME or ; .ENTER and the device/filename argument is odd. ; ; * NOTE * NOTE * NOTE * NOTE * NOTE * NOTE * NOTE * NOTE * NOTE * NOTE ; It must not be swapped over by the USR ; ALL registers MUST be preserved ; * NOTE * NOTE * NOTE * NOTE * NOTE * NOTE * NOTE * NOTE * NOTE * NOTE ; ; R1 -> date word of the directory entry ; FILDAT = date to place on the file ; FL.PRO set in $AFLAG => set no-delete bit in status word ; FL.UNP set in $AFLAG => clear no-delete bit in status word ; ; JSR PC,FIXDAT ;- ORIGIN PIPEXE .IF NE 0 FIXDAT:: BIT #FL.DAT,$MFLAG ;/SETDATE? BEQ 10$ ;Branch if not MOV DATE,@R1 ;Use today's date BNE 20$ ; if it's not 0 10$: MOV FILDAT,@R1 ;Put correct date on file 20$: BIT #FL.PRO,$AFLAG ;Set protection bit? BEQ 30$ ;Branch if not BIS #DS.PRO,DE.ST-DE.DAT(R1) ;Else set the bit BR 40$ ; 30$: BIT #FL.UNP,$AFLAG ;Clear protection bit? BEQ 40$ ;Branch if not BIC #DS.PRO,DE.ST-DE.DAT(R1) ;Else clear the bit 40$: RETURN .ENDC ;IF 0 NE .SBTTL GETOUT - Create an output filename ;+ ; GETOUT ; This routine sets up the output filename for COPY and the rename area ; for RENAME. Checks are also made here for .SYS as the output filetype ; ; R3 -> physical device name of the input device ; R5 -> expansion block ; ; CALL GETOUT ; ; R4 -> NEWNAM (output filename) ;- GETOUT:: JSR R2,$SAVVR ;Save R0 - R2 MOV #OLDNAM,R4 ;R4 -> input filename area MOV R5,R0 ;R0 -> expansion list MOV (R0)+,(R4)+ ;Copy the device name MOV (R0)+,(R4)+ ; and the first word of the filename MOV (R0)+,(R4)+ ; and the second word MOV (R0)+,(R4)+ ; and the filetype MOV R4,R2 ;R2 -> output filename area MOV R5,R0 ;R0 -> input filename MOV #OUTFIL,R1 ;R1 -> CSI output filespec MOV (R1)+,(R2)+ ;Move in device name TST (R0)+ ;Skip it in the input name CMP @R1,#R50AST ;"*"? BNE 20$ ;Branch if not MOV (R0)+,(R2)+ ;Use input filename as output filename BNE 10$ ;Branch if filename there BIT #DSH.RA,DEVSTS ;SEQUENTIAL DEVICE ? BNE 30$ ; NO, BRANCH BIT #DEV.WO,DEVSTS ; DEVICE A PRINTER ? BEQ 30$ ; NO, BRANCH. CAN'T HAVE THAT. 10$: MOV (R0)+,(R2)+ ;Both words CMP (R1)+,(R1)+ ;Skip output spec filename BR 50$ ; 20$: MOV (R1)+,(R2)+ ;Use output spec as filename BNE 40$ ;Branch if one there BIT #,DEVSTS ;Output device directory structu BEQ 40$ ;Branch if not. That's ok. ;+ ;ERROR 30$: .ERR #ERAREA,#IOF,LEVEL=FATAL,RETURN=NO ; <-F-Invalid output file> ;- 40$: MOV (R1)+,(R2)+ ;Both words CMP (R0)+,(R0)+ ;R0 -> input filetype 50$: CMP @R1,#R50AST ;Filetype wildcarded? BNE 60$ ;Branch if not MOV (R0)+,@R2 ;Store the filetype BR 70$ ; 60$: MOV (R1)+,@R2 ;Store the filetype 70$: TST (PC)+ ;Flag no error 80$: SEC ;Flag error RETURN .SBTTL ENTER - Enter an output file ;+ ; ENTER ; This routine enters a file in the output directory. ; ; R5 -> expansion block ; NEWNAM = expanded output filename ; OUTFIL = output filespec (from CSI) ; ; CALL ENTER ; ; If /MULTIVOL: ; Carry bit set -> The file didn't fit ; Carry bit clear->The file fit ; #SKIPIT set in MVFLAG -> An error occured and the file ; shouldn't be copied. (C bit is set, too) ; #DIRFUL set in MVFLAG -> The file didn't fit because the ; directory was full on the output device ; If not /MULTIVOL: ; Carry bit set -> Protected file exists or output file found ; (with /NOREPLACE) ; Carry bit clear->Success ;- .ENABL LSB ENTER:: JSR PC,$SAVAL ;Save all registers .SERR ;Trap directory fill errors BIC #SKIPIT,MVFLAG ;Clear error bit BIC #DIRFUL,MVFLAG ;Clear directory full bit MOV #PNAME,R0 ;R0 -> output volume physical device name CALL MNTOUT ;*** Mount it, if it isn't MOV #OUTFIL,R1 ;R1 -> output file spec MOV #NEWNAM,R2 ;R2 -> expanded output filename MOV #IOAREA,R0 ;R0 -> EMT area block CLR 10(R0) ;Assume magtape or cassette output BIT #DEV.DK,DEVSTS ;Output a disk? BEQ 10$ ;Branch if not 10$: MOV 10(R1),4(R0) ;Get size specified thru CSI BNE 15$ ;Branch if specified BIT #FL.CON,$AFLAG ;/CONCATENATE? BNE 20$ ;Branch if so. Use 0. MOV EB.LEN(R5),4(R0) ;Else use size of input file BIT #FL.DAT,$MFLAG ;Doing /SETDATE? BNE 20$ ;Yes - use current date 15$: MOV EB.DAT(R5),FILDAT ;Use the date currently on the file ; BIC #DS.PRO,FILDAT ;clear the protection status if there ;036 BR 30$ ; 20$: MOV OUTDAT,FILDAT ;Use today's date for /CONCATENATE 30$: MOV R0,R4 ;Copy -> area block for later .ENTER ,#OCHAN,R2,,OFILNO,CODE=SET ;Enter the output file BIC #1,R2 ;Get rid of low bit BCS 70$ ;Branch if error .HERR ;Turn off .SERR BIT #DEV.MT,DEVSTS ;Magtape output? BNE 40$ ;Branch if so JMP 240$ ;Jump if not 40$: BIT #FL.MUL,$AFLAG ;Doing /MULTIVOL? BEQ 50$ ;No MOV MVSEQ,OFILNO ;Put back the seq number for /MULTIVOL 50$: TST OFILNO ;Should we modify the file sequence numb BLE 60$ ;Branch if not MOV #-1,OFILNO ;Enter all other files at EOT 60$: JMP 240$ ; 70$: CLR R3 ;Clean out high byte MOVB @#S$EERB,R3 ;Get the EMT error code .HERR ;Turn of .SERR MOV R3,R0 ;Save error byte from .enter TST R0 ;Channel in use? BMI 110$ ;Branch if hard error BNE 80$ ;Branch if not JMP CHIU ;Else give the error ; <-F-Channel in use> 80$: BIT #DEV.MT,DEVSTS ;Was it a magtape? BNE 180$ ;Branch if so CMP R0,#3 ;Protected file? BNE 90$ ;Branch if not ; MOV #FE.OFP,R1 ;Set error code ;+ ;ERROR .ERR #ERAREA,#FE.OFP,LEVEL=ERROR,RETURN=YES,FILE=R2 ; <-E-Protected file alread exists DEV:FILENAME> ;- ; BR 230$ ; and give error BIS #SKIPIT,MVFLAG ;File shouldn't be copied. BR 260$ ;return with error 90$: BIT #FL.MUL,$AFLAG ;Doing /MULTIVOL? BEQ 100$ ;No BR 260$ ;Return with carry ;+ ;ERROR 100$: MOV #FE.DVF,R1 ;Assume device full ; <-F-Device full DEV:FILENAME> ;- TST 4(R4) BEQ 230$ ;Branch if so CMP 4(R4),#-1 ;-1 enter? BNE 230$ ;Branch if not. Device full. 110$: CMP #-3,R0 ;Is it Directory I/O error? BEQ 120$ ;Branch if so CMP #-14,R0 ;Is it Invalid directory? BNE 130$ ;Branch if not ;+ ;ERROR 120$: MOV #FE.DIO,R1 ;Indicate directory I/O error ; <-F-Directory I/O error> BR 230$ ;Go give it ;- 130$: CMP #-4,R0 ;Is it a FETCH error? BNE 140$ ;Branch if not ;+ ;ERROR MOV #FE.FER,R1 ;Indicate Fetch error ; <-F-Fetch error> BR 230$ ;Go give it ;- 140$: CMP #-5,R0 ;Is it overlay read error? BNE 150$ ;Branch if not ;+ ;ERROR MOV #FE.INE,R1 ;Indicate input error ; <-F-Input error> CLR R2 ;No file BR 230$ ;Go give it ;- 150$: CMP #-6,R0 ;Is it directory full? BNE 170$ ;Branch if not BIT #FL.MUL,$AFLAG ;Doing /MULTIVOL? BEQ 160$ ;No BIS #DIRFUL,MVFLAG ;Indicate directory full BR 260$ ;Return with carry ;+ ;ERROR 160$: MOV #FE.DFL,R1 ;Set error code ; <-F-Directory full DEV:FILENAME> BR 230$ ; 170$: MOV #FE.SYS,R1 ;Indicate system error ; <-F-System error> CLR R2 ;No file BR 230$ ;Go give it. ;- 180$: CLR 4(R4) ;Indicate device full if that's the error CMP R0,#6 ;largest error code recognized from .ENTER BHI 170$ ; if higher, don't jump indirect. ASL R0 ;Make the error code a word index MOV MTERRS(R0),PC ;***JMP in disguise!! ;++DSG ;+ ;ERROR 185$: MOV #FE.DVF,R1 ;Assume device full ; <-F-Device full DEV:FILENAME> BR 230$ ; ;- ;--DSG ;+ ;ERROR 190$: MOV #DIU,R1 ;Set error code ; <-F-Device in use DEV:FILENAME> BR 230$ ; 200$: .ERR #ERAREA,#NRP,LEVEL=WARNING,RETURN=YES,FILE=R2 ; <-W-Output file found, no operation performed DEV:FILENAME> BIS #SKIPIT,MVFLAG ;File shouldn't be copied BR 260$ ; 210$: MOV #FSN,R1 ;Set error code ; <-F-File sequence number not found DEV:FILENAME> BR 230$ 215$: MOV #DIE,R1 ;Set error code ; <-F-Directory input error DEV:FILENAME> BR 230$ 220$: MOV #ILO,R1 ;Set error code ; <-F-Invalid option value> 225$: CLR R2 ;No filename 230$: .PURGE #OCHAN ;Purge the output channel .ERR #ERAREA,R1,LEVEL=FATAL,RETURN=NO,FILE=R2 ;- 240$: MOV 6(R2),R0 ;R0 = filetype of output file CMP R0,#<^RSYS> ;Is the output filetype /SYS? BNE 250$ ;Branch if not CMP PNAME,SYSDEV ;Is the output to the system dev? BNE 250$ ;Branch if not INC REBOOT ;Yes - print the reboot message 250$: TST (PC)+ ;Indicate success 260$: SEC ;Indicate error RETURN ;+ ;ERROR MTERRS: .WORD CHIU ;Code 0 <-F-Channel in use> .WORD 185$ ; Changed from 80$ (DSG) ;Code 1 <-F-Device full DEV:FILENAME> .WORD 190$ ;Code 2 <-F-Device in use DEV:FILENAME> .WORD 200$ ;Code 3 <-W-Output file found, no operation performed DEV:FILENAME> .WORD 210$ ;Code 4 <-F-File sequence number not found DEV:FILENAME> .WORD 220$ ;Code 5 <-F-Invalid option value> .WORD 215$ ;Code 6 <-F-Directory input error> (invalid unit) .DSABL LSB ;- .SBTTL GETC - Get a byte from the input buffer ;+ ; GETC ; Remove a byte from the input buffer. ; ; R3 -> physical device name of input device ; R5 -> expansion block ; IBFPTR -> into input buffer ; IBUFE -> past end of input buffer ; IBUFF -> input buffer ; IBLK = input block number (next) ; ISIZ = number of blocks left to transfer ; IBFSIZ = size of input buffer in blocks ; ; CALL GETC ; ; C-bit = 0 => no error if /IGNORE not specified ; R0 = byte from input buffer ; ; C-bit = 1 => error ; IERR = 0 => EOF detected ; IERR <> 0 => IERR = error code ;- GETC:: CMP IBFPTR,IBUFE ;Past the end of the buffer? BLO 10$ ;Branch if not CALL GETBUF ;Get a buffer load BCS 20$ ;Branch on error or eof MOV IBUFF,IBFPTR ;Reset the buffer pointer 10$: CLR R0 ;Set up for MOVB BISB @IBFPTR,R0 ;Get the character INC IBFPTR ;Bump the buffer pointer CLC ;Indicate no error 20$: RETURN .SBTTL PUTC - Put a byte into the output buffer ;+ ; PUTC ; Move a byte into the output buffer. ; ; R0 = byte to move to buffer ; R5 -> expansion block ; OBUFF -> output buffer ; OBFPTR -> into output buffer ; OBUFE -> past end of buffer ; OBLK = output block number ; NEWNAM = expanded output filename ; ; CALL PUTC ; ; C-bit = 0 => success ; ; C-bit = 1 => output file full or output error ;- PUTC:: CMP OBFPTR,OBUFE ;Past the end of the buffer? BLO 10$ ;Branch if not CALL PUTBUF ;Output the buffer BCS 20$ ;Branch on error MOV OBUFF,OBFPTR ;Reset the buffer pointer 10$: MOVB R0,@OBFPTR ;Store the character INC OBFPTR ;Bump the buffer pointer CLC ;Indicate no error 20$: RETURN .SBTTL GETBUF - Fill an input buffer ;+ ; GETBUF ; This routine fills an input buffer. ; ; R3 -> physical device name of input device ; R5 -> expansion block ; IBUFF -> input buffer ; IBLK = input block number (next) ; ISIZ = number of blocks left to transfer ; IBFSIZ = size of input buffer in blocks ; ; CALL GETBUF ; ; C-bit = 0 => no error if /IGNORE not specified ; IBUFE -> past end of buffer ; ISIZ updated (number of blocks left to transfer) ; IBLK updated (next input block number) ; ; C-bit = 1 => error ; IERR = 0 => EOF detected ; IERR <> 0 => IERR = error code ;- GETBUF:: JSR PC,$SAVAL ;Save all registers MOV R3,R0 ;R0 -> physical device name of input device CALL MNTINP ;*** Get the input volume mounted MOV ISIZ,R4 ;R4 = number of blocks left MOV IBFSIZ,R3 ;R3 = number of blocks in buffer CMP R3,R4 ;More in buffer than left to transfer? BLOS 10$ ;Branch if not MOV R4,R3 ;Else use what's left as buffer size 10$: SWAB R3 ;R3 = number of words in buffer TST R3 ;Any room? BEQ 50$ ;Branch if none. Done .READW #IOAREA,ICHAN,IBUFF,R3,IBLK ;Read a buffer load ROR R3 ;Save C-bit SWAB R0 ;Get number of blocks transferred. BNE 20$ ;Branch if non-zero. INC R0 ;Make it 1 20$: ADD R0,IBLK ;Bump the input block number SUB R0,ISIZ ;Subtract from length SWAB R0 ;Get number of words ASL R0 ;Make it bytes ADD IBUFF,R0 ;R0 -> end of input buffer MOV R0,IBUFE ;Save it. ROL R3 ;Get C-bit back from read BCC 60$ ;Branch if no error MOVB @#S$EERB,R0 ;Get the error byte BEQ 50$ ;Branch if EOF DEC R0 ;Channel not open? BEQ 30$ ;Branch if not the error ;+ ;ERROR .ERR #ERAREA,#FE.CNO,LEVEL=FATAL,RETURN=NO,FILE=R5 ; <-F-Channel not open DEV:FILENAME> ;- ;+ ;ERROR 30$: MOV #FE.INE,R1 ;Set up the error code BIT #FL.IGN,$MFLAG ;Ignore the error? BNE 40$ ;Branch if so .ERR #ERAREA,R1,LEVEL=FATAL,RETURN=YES,FILE=R5 ; <-F-Input error DEV:FILENAME> ;- INC IERR ;Indicate an error BR 50$ ;Return to caller with C-bit set ;+ ;ERROR 40$: .ERR #ERAREA,R1,LEVEL=WARNING,RETURN=YES,FILE=R5 ; <-W-Input error DEV:FILENAME> ;- TST (PC)+ ;Clear C-bit 50$: SEC ;Set C-bit 60$: RETURN .SBTTL PUTBUF - Output a buffer load ;+ ; PUTBUF ; This routine empties an output buffer. ; ; R5 -> expansion block ; OBUFF -> output buffer ; OBUFE -> past end of buffer ; OBLK = output block number ; NEWNAM = expanded output filename ; ; CALL PUTBUF ; ; C-bit = 0 => success ; ; C-bit = 1 => output file full or output error ;- PUTBUF:: JSR PC,$SAVAL ;Save all registers MOV #PNAME,R0 ;R0 -> physical device of output device CALL MNTOUT ;*** Get output volume mounted MOV OBUFE,R3 ;R3 -> past end of buffer SUB OBUFF,R3 ;R3 = number of bytes in buffer ROR R3 ;R3 = number of words in buffer .WRITW #IOAREA,#OCHAN,OBUFF,R3,OBLK ;Write the buffer BCS 50$ ;Branch on error BIT #FL.VER,$AFLAG ;Doing /VERIFY? BEQ 40$ ;Branch if not .READW #IOAREA,#OCHAN,VBUFF,R3,OBLK ;Read it back in BCC 10$ ;Branch on no error ;+ ;ERROR .ERR #ERAREA,#FE.INE,LEVEL=FATAL,RETURN=NO,FILE=#NEWNAM ; <-F-Input error dev:filename> ;- 10$: MOV VBUFF,R2 ;Address of verification buffer MOV IBUFF,R1 ;Address of input buffer 20$: CMP (R1)+,(R2)+ ;Verify a word BEQ 30$ ;Branch if they match ;+ ;ERROR .ERR #ERAREA,#VER,LEVEL=FATAL,RETURN=NO,FILE=#NEWNAM ; <-F-Verification error dev:filename> ;- 30$: SOB R3,20$ 40$: SWAB R0 ;R0 = number of blocks transferred ADD R0,OBLK ;Bump the output block number MOV OBUFF,OBFPTR ;Reset the output buffer pointer CLC ;Indicate no error BR 100$ ; 50$: MOVB @#S$EERB,R0 ;Get the error byte BNE 80$ ;Branch if not write past eof ;+ ;ERROR MOV #FE.OFF,R1 ;Set error code BIT #FL.MUL,$AFLAG ;Doing /MULTVOL BEQ 60$ ;No BIS #OUTFUL,MVFLAG ;Output file full BR 70$ ;Skip message ; <-F-Output file full DEV:FILENAME> 60$: .ERR #ERAREA,R1,LEVEL=FATAL,RETURN=YES,FILE=#NEWNAM ;- 70$: INC OERR ;Say we got an error SEC ;Indicate it BR 100$ ; 80$: DEC R0 ;Output error? BNE 90$ ;Branch if not ;+ ;ERROR MOV #FE.OPE,R1 ; <-F-Output error DEV:FILENAME> BR 60$ 90$: .ERR #ERAREA,#FE.CNO,LEVEL=FATAL,RETURN=NO,FILE=#NEWNAM ; <-F-Channel not open DEV:FILENAME> ;- 100$: RETURN .SBTTL LPCHK - Append to LP:, TT: output LPCHEK:: BIT #,DEVSTS ;Output file LP: or TT:? BEQ 20$ ;Branch if not BIT #,$AFLAG ;/ASCII or /BINARY? BEQ 10$ ;Branch if so MOV #CR,R0 ;Output a CALL PUTC ;Send it BCS 20$ ;Branch on error MOV #LF,R0 ;Output a CALL PUTC ;Send it BR 20$ ;Return to caller 10$: MOV #,@OBUFF ;Store a pair MOV OBUFF,OBUFE ;Set the end buffer pointer ADD #2,OBUFE ;to 1 word CALL PUTBUF ;Write it 20$: RETURN .SBTTL FILBUF - Fill buffer with nulls FILBUF:: MOV R1,-(SP) ;Save R1 BIT #,$AFLAG ;/ASCII or /BINARY? BEQ 20$ ;Branch if not ;;; MOV #511.,R1 ;Set character count MOV OBUFE,R1 ;R1 -> End of buffer SUB OBFPTR,R1 ;R1 = Count of bytes left in buffer INC R1 ; + 1 in order to force a buffer write 10$: CLR R0 ;Send a null CALL PUTC ;Send it BCS 20$ ;Branch on error SOB R1,10$ ; CLC ;Indicate no error 20$: MOV (SP)+,R1 ;Restore R1 RETURN .SBTTL CHKERR - Handle error recovery CHKERR:: ;***************************************************************************** ;;;; BIT #,DEVSTS ;Output a magtape or cassette? ;++DSG BIT #DEV.MT,DEVSTS ;Output a magtape? BEQ 15$ ; Yes... ;-------------------------------------------------------------------------- ; The contents of the magtape now are... ; * EOF1 * HDR1 * Data Data Data... * * * ; ^ ; where "*" -> tape mark and "^" -> current tape position. ; In order to write the EOF correctly (when the ".CLOSE" is done at 10$), ; the current tape position has to be... ; * EOF1 * HDR1 * Data Data Data... * * * ; ^ ; so that, after the .CLOSE at 10$, the tape contents can be... ; * EOF1 * HDR1 * Data Data Data... * EOF1 * * * ; ^ ;------------------------------------------------------------------------ CALL BSTM2 ; THEREFORE, backspace 2 tape marks. ;------------------------------------------------------------------------ ; After the .CLOSE, the tape is back-spaced 4 tape-marks and then, 3 tape- ; marks are written. Hence, after this has been done, the contents of the ; tape becomes... ; * EOF1 * * * ; and the partial file written on the tape effectively "disappears". ;------------------------------------------------------------------------ BR 10$ 15$: BIT #,DEVSTS ;Output a magtape or cassette? ;--DSG ;***************************************************************************** BNE 10$ ;Branch if so .PURGE R1 ;Just purge the channel BR 20$ ; 10$: .CLOSE R1 ;Close the output channel BIT #DEV.MT,DEVSTS ;Output file a magtape? BEQ 20$ ;Branch if not JSR R5,MTNFS ;Do non-file-structured lookup .WORD NEWNAM ; -> dblk for .LOOKUP BCS 20$ ;Ooops! CALL BSTM4 ;Backspace to tapemark 4 times BCS 20$ ; CALL WRT3TM ;Write 3 tape marks 20$: RETURN .SBTTL LTRANP - Logical to physical device translation ;+ ; ; LTRANP ; Performs the translation of a logical device name to a ; physical one. Handler for device must have been already ; LOADed or .FETCHed. Makes use of the SYSLIB routine, ; $DEVTR, to complete the translation. Works with 64-unit ; support. ; ; Call: ; (SP) contains RAD50 logical device name (placed on stack ; prior to CALL ; ; eg: ; MOV #device_name,-(SP) ; CALL LTRANP ; ; Return: ; (SP) contains RAD50 physical device name ; ;- .GLOBL $DEVTR LTRANP: MOV R0,-(SP) ;Save a few registers MOV R1,-(SP) MOV R2,-(SP) MOV 10(SP),NFSLBK ;Place device name in lookup block .LOOKU #IOAREA,#NCHAN,#NFSLBK,#-1 ;Open it non-file-structured BCS 10$ .CSTAT #IOAREA,#NCHAN,#CSTABK ;Get info on the channel BCS 10$ .CLOSE #NCHAN ;Close the channel MOV CSTABK+12,R0 ;R0 = Device name MOV CSTABK+10,R1 ;R1 = Unit number CALL $DEVTR ;Complete the translation MOV R0,10(SP) ;Return physical device name 10$: MOV (SP)+,R2 ;Restore previously saved registers MOV (SP)+,R1 ;Restore previously saved registers MOV (SP)+,R0 RETURN NFSLBK: .WORD 0,0,0,0 CSTABK: .BLKW 6 .SBTTL QUERY - Handle query mode ;+ ; QUERY ; This routine does the query for copy, rename, and delete if /LOG (/W) was ; specified on the command line. ; ; OLDNAM contains input filename ; NEWNAM contains output filename ; ; CALL QUERY ; ; R0 modified ; Z-bit = 1 if FL.QRY not set in $MFLAG ; Z-bit = 1 if user types "Y*" on console ; Z-bit = 0 in all other cases ;- QUERY:: BIT #FL.QRY,$MFLAG ;Doing query? BEQ 40$ ;Branch if not ;SEZ ;Done by test MOV #YESCHK,-(SP) ;Return from here JSR R2,$SAVVR ;Save volatile registers CMP #DODEL,ACTION ;Doing a delete? BEQ 10$ ;Branch if so. Print just 1 filename CMP #DOPROT,ACTION ;Doing protect? BNE 20$ ;Branch if not. Print 2 filenames 10$: MOV #FILE2,R1 ;R1 -> area to store name MOV R1,R2 ;R2 -> area for prompt MOV R5,R0 ;R0 -> filename to convert CALL $FNASC ;Convert filename to ASCII BR 30$ ;Go do query 20$: CALL SETUPL ;Set up "dev:filnam.typ to " 30$: MOVB #BLANK,(R1)+ ;Put in a " " CMP R1,#QMARK ;Done yet? BLO 30$ ;Branch if not .RCTRLO .PRINT R2 ;Print the prompt 40$: RETURN ;Return thru $SAVVR to YESCHK to caller .SBTTL DLOG - Handle logging for delete and protect/noprotect .ENABL LSB DLOG:: .RCTRL BIT #FL.LOG,$MFLAG ;Doing logging? BEQ 20$ ;Branch if not MOV #FILE1,R2 ;R2 -> area for filename MOV R2,R1 ;R1 -> area for filename MOV R5,R0 ;R0 -> filename CALL $FNASC ;Convert filename to ASCII BR 10$ ;Go print it .SBTTL CRLOG - Handle logging for copy and rename CRLOG:: .RCTRL BIT #FL.LOG,$MFLAG ;Doing logging? BEQ 20$ ;Branch if not CALL SETUPL ;Set up for .PRINT 10$: CLRB (R1)+ ; after .PRINT R2 ;Print the log 20$: RETURN .DSABL LSB .SBTTL SETUPL - Set up for logging and query prompts SETUPL:: MOV #FILE1,R2 ;R2 -> area for ASCII filename MOV R2,R1 ;R1 -> area for ASCII filename MOV #OLDNAM,R0 ;R0 -> filname CALL $FNASC ;Convert to ASCII 10$: MOVB #BLANK,(R1)+ ;Blank out to "to" CMP R1,#TO ;There yet? BLO 10$ ;Branch if not. Put in another blank MOV #NEWNAM,R0 ;R0 -> output filename MOV #FILE2,R1 ;R1 -> area for ASCII filename CALL $FNASC ;Convert to ASCII RETURN .SBTTL MNTINP - Request the input volume be mounted ;+ ; MNTINP ; This routine makes sure that the input volume is mounted on the input ; device. ; ; R0 -> Input device name ; ; CALL MNTINP ;- MNTINP:: JSR PC,$SAVAL ;Save all registers MOV #VOL.IN,R1 ;R1 offset to input word in PDEV MOV #WAITIN,R3 ;R3 -> text for prompt BR MOUNT ; .SBTTL MNTOUT - Request the output volume be mounted ;+ ; MNTOUT ; This routine makes sure that the output volume is mounted on the system ; device. ; ; R0 -> Output device name ; ; CALL MNTOUT ;- MNTOUT:: JSR PC,$SAVAL ;Save all registers MOV #VOL.OU,R1 ;R1 offset to output word in PDEV MOV #WAITOU,R3 ;R3 -> text for prompt BR MOUNT ; .SBTTL MNTSYS - Request the system device be mounted ;+ ; MNTSYS ; This routine makes sure that the system volume is mounted on the system ; device. ; ; R0 -> System device name ; ; CALL MNTSYS ;- MNTSYS:: JSR PC,$SAVAL ;Save all registers MOV #VOL.SY,R1 ;R1 offset to system word in PDEV MOV #WAITSY,R3 ;R3 -> text for prompt BR MOUNT ; ;+ ; MOUNT ; ; R0 -> device name (physical) ; R1 = offset into PDEV for the device ; R3 -> text for prompt ; ; CALL MOUNT ;- MOUNT:: MOV R0,R2 ;R2 -> physical device name CMP @R2,PDEV(R1) ;Is it already mounted? BEQ 30$ ;Branch if so MOV #PDEV,R5 ;R5 -> mounted device table MOV #3,R4 ;R4 = number of devices 10$: CMP @R2,@R5 ;Is this one the same as one we're mounting? BNE 20$ ;Branch if not CLR @R5 ;Not any more, it's not 20$: TST (R5)+ ;Go to the next one SOB R4,10$ ;Do them all WAIT R3 ;Wait for the proper one to be mounted MOV @R2,PDEV(R1) ;Say that this one is now mounted 30$: RETURN .SBTTL HEADER - Print the logging header ;+ ; HEADER ; This routine prints the logging header, if needed (PRNTHD <>0). ; ; R1 -> header to print ; ; CALL HEADER ; ; R0 modified ;+ HEADER:: TST PRNTHD ;Print the header? BEQ 10$ ;Branch if not .PRINT #FILHED ;Print " Files " .PRINT R1 ;Print the rest CLR PRNTHD ;Don't do it again 10$: RETURN .SBTTL MATDVR - Match routine driver ;+ ; MATDVR ; This routine sets up the input filename for the actual match routine and ; calls the directory scanner to get an entry from the directory of the input ; device. It also tests for nonentity files. ; ; R3 -> physical device name of the input device ; R4 -> CSI input filespec ; GETNXT -> appropriate directory scan routine for the input device ; ; CALL MATDVR ; ; R0 - R2 modified ; R5 -> expanded input list (if R5 = ENDLST, nothing matched) ; ; C-bit = 0 => no error ; ; C-bit = 1 => error ; R0 = error code ; ; Errors: ; DIE ; ILD ;- MATDVR:: MOV BEGLST,R5 ;R5 -> start of expansion list JSR R5,$SAVRG ;Now save R3 - R5 MOV R4,R0 ;R0 -> input file spec TST (R0)+ ;Point to filename MOV #CMDBUF,R1 ;R1 -> area for ASCII expansion CALL RTOA ;Convert it to ASCII for match routines 10$: BIT #PO.COP,FLGWRD ;Doing /PHYSICAL? BEQ 20$ ;No CALL POCHK ;Any more to copy BCS 60$ ;No more to copy 20$: CALL @GETNXT ;Call the directory scanner BCS 70$ ;Branch on error TST R0 ;Did we get an entry? BEQ 60$ ;Branch if none left BIT #DS.EOS,@R0 ;Is this an end-of-segment? BNE 50$ ;Branch if so. May be done BIT #DS.PRM,@R0 ;New test for nonentity file copy BEQ 10$ ;Branch if so. Try for another one CALL MATCH1 ;See if it matches TST R0 ;Well? BNE 25$ ;It matched... BIT #DEV.MT,DEVSTS+2 ;No match, is input from magtape? BEQ 10$ ;Nope, then we can continue scan... TST IFILNO ;Yes, positive sequence number? BLOS 10$ ;Nope, continue scan... BR 60$ ;Yes, but file not found here... 25$: MOV @R4,(R5)+ ;Store the device name ; TST (R0)+ ;Skip directory status word MOV (R0)+,-(SP) ;Save the status word MOV (R0)+,(R5)+ ;Store the filename MOV (R0)+,(R5)+ ;Both words MOV (R0)+,(R5)+ ;Store the filetype MOV (R0)+,(R5)+ ;Store the file length MOV $STBLK,(R5)+ ;And the starting block number TST (R0)+ ;Skip channel/job number MOV (R0)+,(R5)+ ;Store the creation date BNE 30$ ;Branch if it's not 0 MOV DATE,-2(R5) ;Else use today's date 30$: ;Store the protection status as bit in PROBIT ;036 MOV (SP)+,R2 ;R2 = Status word ;036 SUB #EB.SIZ,R5 ;PROBLU wants R5 at start of entry ;036 CALL PROBLU ;Look up the protection bit ;036 BIS R0,PROBIT(R1) ;set the protection bit ;036 ASL R2 ;check protection bit in status word ;036 BCS 40$ ;good, we wanted to set it all along ;036 BIC R0,PROBIT(R1) ;oops, we really wanted to clear it ;036 40$: ADD #EB.SIZ,R5 ;and put R5 back to end of entry ;036 BIT #DEV.MT,@SAVSTS ;MAGTAPE INPUT? ;036 BEQ 10$ ;NO; GET ALL FILES IN SEGMENT 50$: CMP R5,BEGLST ;Have we got any files? BEQ 10$ ;Branch if not 60$: MOV R5,ENDLST ;Store pointer past end of list CLC ;CLEAR ERROR FROM POCHK 70$: RETURN .SBTTL POCHK - Check for more files to copy ;+ ;POCHK ;CHECK FOR MORE FILES TO COPY ;This procedure checks to see if there are any more files to be copied o ;the input device pointed to by R3. There are more files to copy if: ;The bit FLG.CO has not been set in the device status word ;or ;There is a wildcard specification for this device. ; ; R3 -> The current input device ; ; CALL POCHK ; ; C bit clear -> more to copy ; C bit set -> no more to copy ; ;- POCHK:: JSR PC,$SAVAL ;Save all regs MOV #FNAME,R5 ;R5 -> device specs MOV #DEVSTS,R4 ;R4 -> device status words 10$: TST (R4)+ ;Next status word, (skip output) TST @R5 ;Any more specs? BEQ 30$ ;No CMP (R3),(R5)+ ;Is this the device? BNE 10$ ;No BIT #FLG.WD,@R4 ;Any wildcard given? BNE 20$ ;Yes BIT #FLG.CO,@R4 ;Was a file copied for this spec BNE 10$ ;YES 20$: CLC ;More to copy BR 40$ 30$: SEC ;No more to copy 40$: RETURN ;Return .SBTTL MATCH1 - Filename match driver ;+ ; MATCH1 ; This is the driver for matching input filenames against the directory ; entries. ; ; R0 -> permanent directory entry ; R3 -> physical device name of the input device ; SAVSTS -> device/file flag word ; ; CALL MATCH1 ; ; R0 = 0 => no match ; R0 <> 0 => R0 -> matching directory entry ; R1, R2 modified ; ; Note: ; Apparently, this routine also checks the directory entry for ; a file for the protection status and ignores files which are. ; Other portions of PIP assume this and if the action of this ; routine is changed, it will have affects elsewhere. ; ;- MATCH1:: JSR R5,$SAVRG ;Save R3 - R5 MOV R0,R4 ;R4 -> directory entry 10$: ADD #DE.FN1,R0 ;R0 -> 1st word of the filename MOV #CMDBF1,R1 ;R1 -> storage area for ASCII of the nam CALL RTOA ;Convert the filename to ASCII MOV #CMDBUF,R1 ;R1 -> ASCII input filename from CSI MOV #CMDBF1,R2 ;R2 -> ASCII test filename from director CLR MATFLG ;Say we haven't found a file, yet CALL @MATRTN ;Go see if the filenames match MOV R0,MATFLG ;Did they match? Set match flag. BNE 20$ ;Branch if so JMP 160$ ;We're done 20$: BIT #FL.EXC,$MFLAG ;Doing /EXCLUDE? BNE 25$ ;Branch if so BIT #FLG.WE,@SAVSTS ;Wildcarded input? BEQ 30$ ;Branch if not 25$: CMP DE.TYP(R4),#<^RBAD> ;Filetype "BAD" BEQ 90$ ;Branch if so. That's not a match 30$: CLR DFLAG ;Clear date option flag BIT #FL.CUR,$MFLAG ;Doing /DATE? BEQ 40$ ;Branch if not CALL CHKDAT ;Check for a valid date for /DATE TST R0 ;Did dates match? BEQ 90$ ;Branch if not 40$: BIT #FL.BEF,$MFLAG ;Doing /BEFORE? BEQ 50$ ;Branch if not BIS #FL.BEF,DFLAG ;Set flag for CHKDAT CALL CHKDAT ;Check for a valid date for /BEFORE TST R0 ;Did dates match? BEQ 90$ ;Branch if not 50$: CLR DFLAG ;Clear date option flag BIT #FL.SIN,$MFLAG ;Doing /SINCE BEQ 60$ ;Branch if not BIS #FL.SIN,DFLAG ;Set flag for CHKDAT CALL CHKDAT ;Check for a valid date for /SINCE TST R0 ;Did dates match? BEQ 90$ ;Branch if not 60$: MOV DE.TYP(R4),R0 ;R0 = filetype of input file CMP R0,#<^RSYS> ;Filetype .SYS? BNE 100$ ;Branch if not. No further checks needed BIT #FL.YES,$MFLAG ;/SYSTEM given? BNE 100$ ;Branch if so. The file can be used BIT #FL.EXC,$MFLAG ;Doing /EXCLUDE? BNE 70$ ;Branch if so BIT #FLG.WE,@SAVSTS ;Any wildcards on extension? BEQ 100$ ;No - The file can be used 70$: TST SYSACT ;Already printed the message? BNE 80$ ;Branch if so. Done .ERR #ERAREA,#NSY,LEVEL=WARNING,RETURN=YES ;CG01 ; <-W-No .SYS action> INC SYSACT ;Don't print the message again 80$: INC FOUND ;We found one, but can't use it 90$: CLR R0 ;Signal no match BR 160$ ; and return 100$: CMP #DOPROT,ACTION ;Doing PROTECT or UNPROTECT? BNE 120$ ;Branch if not MOV DE.ST(R4),R1 ;R1=status and protection status BIT #FL.PRO,$AFLAG ;Doing PROTECT? BEQ 110$ ;Branch if not ASL R1 ;Set carry if protected BCC 150$ ;It's unprotected - OK to use BR 140$ ;No match 110$: ASL R1 ;Set carry if protected BCS 150$ ;It's protected - OK to use BR 140$ ;No match 120$: BIT #FL.DEL,$AFLAG ;Doing DELETE? BEQ 150$ ;Branch if not MOV DE.ST(R4),R1 ;R1=status & protection status ASL R1 ;Set carry if protected BCC 150$ ;Branch if not protected 130$: MOV #DELBUF,R1 ;R1 -> protected file buffer MOV @R3,(R1)+ ;Move in physical device name MOV DE.FN1(R4),(R1)+;Move in filename MOV DE.FN2(R4),(R1)+;all of it MOV DE.TYP(R4),(R1) ;and the type ;+ ;ERROR .ERR #ERAREA,#PFL,LEVEL=WARNING,RETURN=YES,FILE=#DELBUF ; <-W-Protected file FILENAME> ;- CMP ACTION,#DOCOPY ;Is file being copied? BEQ 150$ ;Yes, so don't worry about ; protected status, will be caught ; after the file is copied 140$: INC FOUND ;We found one, but can't use it CLR R0 ;Signal no match BR 160$ ;And return 150$: MOV R4,R0 ;R0 -> directory entry 160$: RETURN .SBTTL MATCH2 - Check for a matching filename ;+ ; MATCH2 ; This routine checks to see if the next file in the directory matches t ; current CSI filespec. It is used if /EXCLUDE is NOT specified. ; ; R1 -> ASCII input filename from CSI ; R2 -> ASCII test filename from directory ; ; CALL MATCH2 ; ; R0 = 0 => no match ; R0 <> 0 => match ; R1 and R2 modified ;- MATCH2:: CALL MATCH ;See if the filenames match TST R0 ;Did they? BEQ 10$ ;Branch if not MOV #CMDBUF+7,R1 ;R1 -> extension of input filename MOV #CMDBF1+7,R2 ;R2 -> extension of test filename CALL MATCH ;Go see if the filetypes match 10$: RETURN .SBTTL MATCH3 - Handle /EXCLUDE "matching" ;+ ; MATCH3 ; This routine is called to "match" filenames if /EXCLUDE was specified. ; It compares the current directory entry with all the filespec on the c ; line. If it matches any spec, the routine returns failure. ; ; This routine is also used if any of the input devices are magtape. If ; all files from the input devices will be copied in the physical order ; which they reside on the device, rather than the order in which they a ; on the command line. The PO.COP bit will be set in FLGWRD if this is ; case. Also, if we end up in this routine, but /EXCLUDE processing is ; being done, then we're doing COPY/PHYSICAL. ; ; R2 -> ASCII test filename from directory ; TESTNM contains the ASCII of all input file specs with a tra ; 0 byte. ; R3 Physical device name of the input device ; ; CALL MATCH3 ; ; If /EXCLUDE: ; R0 = 0 => no match (file matched input specs) ; R0 <> 0 => match ; ; If not /EXCLUDE: ; R0 <> 0 => no match (file matched input specs) ; R0 = 0 => match ; ; R1 and R2 modified ;- MATCH3:: JSR R5,$SAVRG ;Save R3 - R5 MOV #FNAME,FPTR ;FPTR -> Physical device list MOV #DEVSTS+2,STAT ;STST -> Device status words for input MOV #TESTNM,R4 ;R4 -> ASCII input file specs MOV R2,R5 ;Save -> ASCII filename from directory 10$: MOV R4,R1 ;R1 -> ASCII CSI filespec MOV R5,R2 ;R2 -> ASCII directory filespec TSTB @R1 ;Anything left to check? BEQ 40$ ;Branch if not. We want the file CMP @R3,@FPTR ;Does input spec match input device? BNE 20$ ;No, don't match it CALL MATCH ;See if the names match. TST R0 ;Well? BEQ 20$ ;Branch if it didn't match. Check the ne MOV R4,R1 ;R1 -> CSI filespec again. ADD #7,R1 ;R1 -> filetype MOV R5,R2 ;R2 -> directory filespec again ADD #7,R2 ;R2 -> filetype CALL MATCH ;Check the filetypes for a match TST R0 ;Did it match? BNE 30$ ;Branch if so. We don't want the file 20$: ADD #11.,R4 ;R4 -> next spec ADD #2,FPTR ;Update FNAME pointer ADD #2,STAT ;Update DEVSTS pointer BR 10$ ;Check it out 30$: BIS #FLG.CO,@STAT ;Match found for this spec CLR R0 ;Say that we don't want the file BR 50$ ;Return to caller 40$: MOV #1,R0 ;Say that we want this one 50$: BIT #FL.EXC,$MFLAG ;Doing /EXCLUDE? BNE 60$ ;Yes. DEC R0 ;Not doing /EXCLUDE- doing /PHYSICAL 60$: RETURN .SBTTL MATCH - Pattern match routine ;+ ; MATCH ; This routine does a wildcard pattern match against an ASCII pattern st ; ; R1 -> ASCII input filename from CSI ; R2 -> ASCII test filename from directory ; ASCII filename is set up as: xxxxxxbxxxb ; ; CALL MATCH ; ; R0 = 0 => no match ; R0 <> 0 => match ; R1 and R2 modified ;- MATCH:: JSR R5,$SAVRG ;Save R3 - R5 CLR R0 ;Assume failure MOV #BLANK,R4 ;An ASCII blank is often used 10$: MOVB (R1)+,R3 ;Get the next pattern character CMPB R3,#'* ;Is it a "*"? BNE 20$ ;Branch if not CMPB @R1,R4 ;Are we at the end of the string? BEQ 30$ ;Branch if so. We have a match 20$: CMPB @R2,R4 ;Is this the end of the test string? BNE 40$ ;Branch if not CMPB R3,R4 ;At the end of the pattern string? BNE 60$ ;Branch if not. Return a level 30$: INC R0 ;Else it matched!!! BR 60$ ;Return a level 40$: CMPB R3,R4 ;Is this the end of the pattern string? BEQ 60$ ;Branch if so CMPB R3,#'* ;Is the pattern character a "*"? BEQ 50$ ;Branch if so CMPB (R2)+,R3 ;Does test char match pattern char? BEQ 10$ ;Branch if yes CMPB R3,#'% ;Is the pattern char a "%"? BEQ 10$ ;Branch if so. It matches. BR 60$ ;Else return to caller 50$: MOV R1,-(SP) ;Save R1 MOV R2,-(SP) ; and R2 JSR PC,10$ ;And call self!!!! MOV (SP)+,R2 ;Restore R2 MOV (SP)+,R1 ; and R1 TST R0 ;Did the strings match? BNE 60$ ;Branch if so CMPB (R2)+,R4 ;At the end of the test string yet? BNE 50$ ;Branch if not 60$: RETURN ;Return a level .SBTTL CHKDAT- Check two dates for a 'match' ;+ ; CHKDAT ; This routine is used to determine if the current file qualifies ; as a match in regards to its creation date. It is only called ; if /I or /C or /J was specified on the command line. ; INPUTS: ; DFLAG - If FL.BEF or FL.SIN is set in it, CHKDAT will check ; for a /BEFORE or /SINCE match. If neither are set, CHKDAT ; will assume /DATE. ; R4 -> a directory entry ; OUTPUTS: ; R0 <> 0 If the dates match ; All registers are saved ;- CHKDAT:: MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV R5,-(SP) MOV #UDATE,R2 ;R2 -> /DATE storage area BIT #FL.BEF,DFLAG ;Doing /BEFORE this time? BEQ 10$ ;Branch if not MOV #BDATE,R2 ;R2 -> /BEFORE storage area 10$: BIT #FL.SIN,DFLAG ;Doing /SINCE this time? BEQ 20$ ;Branch if not MOV #IDATE,R2 ;R2 -> /SINCE storage area 20$: MOV DE.DAT(R4),R0 ;Get the file's creation date CALL CONDAT ;Make it useful CLR R0 ;Clear the match flag MOV #TYEAR+2,R1 ;Point to the converted year MOV #3,R3 ;Initialize a counter 30$: MOV -(R1),R5 ;Get the file's creation date SUB (R2)+,R5 ;Subtract the given date BEQ 60$ ;Branch if they are the same BLT 50$ ;Branch if created before given date BIT #FL.SIN,DFLAG ;'since' switch? 40$: BEQ 80$ ;Branch if not BR 70$ ;Good date 50$: BIT #FL.BEF,DFLAG ;Doing /BEFORE? BEQ 80$ ;Branch if not BR 70$ ;Good date 60$: DEC R3 ;Down the counter BNE 30$ ;Try again BIT #FL.BEF,DFLAG ;Doing /BEFORE? BNE 80$ ;Branch if so 70$: INC R0 ;Good date. 80$: MOV (SP)+,R5 MOV (SP)+,R3 MOV (SP)+,R2 MOV (SP)+,R1 RETURN ;Bad date. .SBTTL PROBLU- Look up protection bit ;036 ;036 ;+ ;036 ; PROBLU ;036 ; This routine looks up the protection bit in PROBIT for a entry. ;036 ; ;036 ; INPUTS: ;036 ; R5 - points to entry in BEGLST region ;036 ; OUTPUTS: ;036 ; R1 - offset into PROBIT ;036 ; R0 - bit flag ;036 ; no other registers modified ;036 ;- ;036 ;036 PROBLU::CLR R1 ;R1 will accumulate /14. ;036 MOV R5,R0 ;We want to preserve R5 ;036 SUB BEGLST,R0 ;Subtract BEGLST offset ;036 10$: SUB #EB.SIZ,R0 ;Subtract 14.'s until underflow ;036 BLO 20$ ;If underflow, we're done here ;036 INC R1 ;Bump R1 ;036 BR 10$ ;And continue subtracting ;036 20$: MOV R1,R0 ;Split R1 up now ;036 BIC #^c17,R0 ;R0 gets the low 4 bits ;036 ASR R1 ;And R1 gets the upper bits ;036 ASR R1 ; shift over until it becomes ;036 ASR R1 ; the word pointer into PROBIT ;036 BIC #1,R1 ;Word align it ;036 INC R0 ;Bump R0, we need at least one shift ;036 CLR -(SP) ;Ready the bitmask ;036 SEC ; and set bit that will live in it ;036 30$: ROL (SP) ;Shift that bit over ;036 SOB R0,30$ ;until it points out the guy we want ;036 MOV (SP)+,R0 ;On exit, R0 has bitmask ;036 RETURN ; and R1 has the word pointer. ;036 .END