Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_SRC_3_19910112 - stanford/5-swskit/mtcopy.mac
There are 10 other files named mtcopy.mac in the archive. Click here to see a list.
	TITLE	MTCOPY	PROGRAM TO COPY AND VERIFY MAGTAPES
	SUBTTL	J. G. ZIMA/JGZ  SEPTEMBER 1981

	SEARCH	MACSYM,MONSYM	;GET SYMBOLS
	SEARCH	ZSUBS		;GET COMND/LUUOS PACKAGE SYMBOLS
	SALL			;NICE LOOKING MACROS
	.DIRECT	FLBLST		;AND NICE LISTING


;VERSION INFORMATION:


	VMAJOR==1		;MAJOR VERSION LEVEL
	VMINOR==0		;MINOR VERSION LEVEL
	VEDIT==12		;EDIT LEVEL
	VWHO==0			;WHO LAST EDITED



;MTCOPY IS A PRODUCT OF THE MONITOR SUPPORT GROUP OF SOFTWARE SERVICES,
;PRIMARILY FOR INCLUSION ON THE TOPS-20 MONITOR SWSKIT.  THE PURPOSE OF
;THE PROGRAM IS TO COPY AND VERIFY NINE-TRACK MAGNETIC TAPES.
;
;RELATED FILES:
;	MTCOPY.MAC	THIS FILE
;	MTCOPY.CTL	CONTROL FILE TO BUILD MTCOPY
;	ZSUBS.UNV	COMND/LUUO PACKAGE UNIVERSAL
;	ZSUBS.REL	COMND/LUUO PACKAGE CODE
;
;ROUGH PERFORMANCE ESTIMATE:  ABOUT 133 IPS OBSERVED COPYING INSTALLATION
;TAPE WITH A LOAD AVERAGE OF 2.5 ON TU73 DRIVES AT 1600 BPI.
	SUBTTL	TABLE OF CONTENTS


;	TABLE OF CONTENTS					  PAGE
;	-----------------					  ----
;
;  1. J. G. ZIMA/JGZ  SEPTEMBER 1981 . . . . . . . . . . . . . . .   1
;  2. TABLE OF CONTENTS. . . . . . . . . . . . . . . . . . . . . .   2
;  3. REVISION HISTORY . . . . . . . . . . . . . . . . . . . . . .   3
;  4. DEFINITIONS. . . . . . . . . . . . . . . . . . . . . . . . .   4
;  5. ENTRY VECTOR AND INITIALIZATION. . . . . . . . . . . . . . .   5
;  6. THE SIMPLE COMMANDS - HELP . . . . . . . . . . . . . . . . .   7
;  7. SET COMMAND HANDLER. . . . . . . . . . . . . . . . . . . . .   8
;  8. SET REWIND-AT-COMPLETION COMMAND . . . . . . . . . . . . . .   9
;  9. SET MAXIMUM-RECORD-SIZE COMMAND. . . . . . . . . . . . . . .  10
; 10. SET DENSITY COMMAND TO SET TAPE DENSITIES. . . . . . . . . .  11
; 11. DISMOUNT COMMAND TO UNLOAD OR DISMOUNT TAPE. . . . . . . . .  12
; 12. REWIND COMMAND TO POSITION TAPE. . . . . . . . . . . . . . .  13
; 13. BACKSPACE COMMAND TO POSITION TAPE . . . . . . . . . . . . .  14
; 14. SKIP COMMAND TO POSITION TAPE. . . . . . . . . . . . . . . .  15
; 15. COPY COMMAND TO MAKE THE COPY. . . . . . . . . . . . . . . .  16
; 16. SNIFF ROUTINE TO CHECK AVAILABLE TAPE DENSITIES. . . . . . .  19
; 17. VERIFY COMMAND TO CHECK TAPES. . . . . . . . . . . . . . . .  20
; 18. TAPE JFN SUPPORT ROUTINES - TILOSE/TOLOSE/TVLOSE . . . . . .  24
; 19. TAPE JFN SUPPORT ROUTINES - GTIJFN/GTOJFN/GTVJFN . . . . . .  25
; 20. THE DATA AREA. . . . . . . . . . . . . . . . . . . . . . . .  26
	SUBTTL	REVISION HISTORY

;REVISION HISTORY:
;
;   1	JGZ	23-JAN-82
;		START KEEPING REVISION HISTORY, PARSE DESIGNATOR INSTEAD
;		OF JFN FOR TAPE TO MAKE COMMANDS "NICER".
;
;   2	JGZ	23-JAN-82
;		USE A BIG NUMBER TO STAND FOR "ALL" FILES.
;
;   3	JGZ	24-JAN-82
;		ADD (WITH) REWIND-AT-COMPLETION OPTIONS TO COPY AND VERIFY.
;
;   4	JGZ	24-JAN-82
;		REMOVE (WITH) CONSTRUCT, CREATE SET COMMANDS AND USE THEM
;		INSTEAD FOR DENSITY, REWIND AT COMPLETION...
;
;   5	JGZ	24-JAN-82
;		ADD DISMOUNT COMMAND, SET MAXIMUM-RECORD-SIZE COMMAND.
;
;   6	JGZ	24-JAN-82
;		RANGE CHECK MAX RECORD SIZE VALUE.
;
;   7	JGZ	24-JAN-82
;		USE NEW ZSUBS LERROR MACRO IN A FEW PLACES INSTEAD OF ERROR.
;		PRINT NUMBER OF FILES AT END OF COPY, VERIFY.
;
;  10	JGZ	24-JAN-82
;		ADD SNIFF ROUTINE TO BE SURE TAPES CAN HANDLE THE SPECIFIED
;		DENSITIES IN TIDEN AND TODEN.
;
;  11	JGZ	24-JAN-82
;		HANDLE VERIFY CASE OF LAST WORD NOT BEING COMPLETELY FULL
;		OF VALID DATA BYTES (FINALLY).
;
;  12	JGZ	25-JAN-82
;		DEPOSIT NULL AFTER COLON IN DEVICE NAME BEFORE GTJFN.
;
	SUBTTL	DEFINITIONS


;DEFAULT PARAMETERS:

	TBFSIZ==^D10*1000	;TAPE BUFFER SIZE - 10 PAGES




;FLAGS:

	FL%ITM==1B0		;INPUT TAPE MARK SEEN FLAG
	FL%VTM==1B1		;VERIFY TAPE MARK SEEN FLAG
	FL%RAC==1B2		;REWIND-AT-COMPLETION FLAG


;CONSTANTS:

	DEN.I==1B35		;INPUT DENSITY SPECIFIED
	DEN.O==1B34		;OUTPUT DENSITY SPECIFIED
	SUBTTL	ENTRY VECTOR AND INITIALIZATION


EVEC:	JRST	MTCOPY		;START
	JRST	REEN		;REENTER
	BYTE	(3)VWHO(9)VMAJOR(6)VMINOR(18)VEDIT	;VERSION



MTCOPY:	SETZ	F,		;CLEAR ALL FLAGS
	$INIT			;INIT THE ZSUBS PACKAGE
	TYPE	<MTCOPY %>	;TYPE BANNER AND VERSION
	VERSIO	EVEC+2		;OUTPUT THE VERSION NUMBER
	TYPE	<

>				;AND A CRLF
	SETOM	TIDEN		;DEFAULT INPUT
	SETOM	TODEN		; AND OUTPUT DENSITY SETTINGS
	MOVX	T1,TBFSIZ*4	;GET AND SET DEFAULT FOR
	MOVEM	T1,MAXREC	; AND MAX RECORD SIZE

REEN:	RESET			;CLEAR EVERYTHING
	MOVE	P,[IOWD PDLSIZ,PDL] ;SET UP A STACK (AGAIN)
	SETZM	OJFN		;CLEAR OUTPUT JFN


NEWCMD:	HRROI	T1,[ASCIZ/MTCOPY>/] ;SET PROMPT
	MOVEM	T1,CMDBLK+.CMRTY ;IN COMND BLOCK
	MOVEI	T1,NEWPAR	;AND SET THE
	HRRM	T1,CMDBLK+.CMFLG ;REPARSE ADDRESS ALSO
	PARSE	[FLDDB. .CMINI]	;INITIALIZATION FUNCTION
	MOVEM	P,SAVEP		;SAVE STACK FOR REPARSING
	JRST	NEWPAR		;AND PARSE A NEW COMMAND

	;...

PARERR:	JRST	REEN		;REPARSE ADR-1=WHERE TO GO ON ERROR
NEWPAR:	MOVE	P,SAVEP		;RESTORE THE STACK
	SKIPE	T1,JFNTMP	;UNLOAD ANY LEFTOVER JFNS
	RLJFN			; FROM REPARSING,...
	 ERJMP	.+1		;DON'T WORRY ABOUT ERRORS
	SETZM	JFNTMP		;AND MARK THE "JFN STACK" EMPTY
	SKIPE	T1,JFNTM2	;UNLOAD ANY LEFTOVER JFNS (SECONDARY)
	RLJFN			; FROM REPARSING,...
	 ERJMP	.+1		;DON'T WORRY ABOUT ERRORS
	SETZM	JFNTM2		;AND MARK THE "JFN STACK" EMPTY (SECONDARY)
	MOVEI	T1,CMDBLK	;POINT TO THE COMMAND BLOCK
	PARSE	[FLDDB. (.CMKEY,,CMDTAB)]	;POINT TO COMMAND TABLE
	HRRZ	T2,0(T2)	;GET ADDRESS OF ROUTINE
	CALL	0(T2)		;CALL IT
	JRST	NEWCMD		;AND GET A NEW COMMAND



;TABLE OF COMMANDS:


CMDTAB:	CMDLEN,,CMDLEN			;HEADER
	AA	BACKSPACE,.BACKSPACE	;BACKSPACE COMMAND
	AA	COPY,.COPY		;COPY COMMAND
	AA	DISMOUNT,.DISMOUNT	;DISMOUNT OR UNLOAD COMMAND
	AA	EXIT,.EXIT		;EXIT COMMAND (ZSUBS)
	AA	HELP,.HELP		;TYPE HELP MESSAGE
	AA	PUSH,.PUSH		;PUSH TO A NEW EXEC (ZSUBS)
	AA	REWIND,.REWIND		;REWIND COMMAND
	AA	SET,.SET		;SET COMMANDS
	AA	SKIP,.SKIP		;SKIP COMMAND
	AA	TAKE,.TAKE		;TAKE COMMANDS FROM FILE (ZSUBS)
	AA	VERIFY,.VERIFY		;VERIFY COMMAND

	CMDLEN==.-CMDTAB-1		;NUMBER OF COMMANDS
	SUBTTL	THE SIMPLE COMMANDS - HELP

;THE "HELP" COMMAND.


.HELP:	NOISE	(WITH COMMANDS)	;DO GUIDEWORDS
	CONFRM			;CONFIRM THE LINE
	TYPE.	HLPTXT		;TYPE THE HELP TEXT
	RET			;AND DONE

HLPTXT:	TEXT	<

MTCOPY is a program to copy and verify unlabeled magnetic tapes.
The commands are:

BACKSPACE	Backspace the given tape a specified number of files.
COPY		Copy from the specified input tape to the specified
		output tape for a specified number of files or to LEOT.
DISMOUNT	Unload or dismount specified tape.  Assigned drives are
		not released.
EXIT		Exit from MTCOPY.
HELP		Type this text.
PUSH		Push to an EXEC in an inferior fork.
REWIND		Rewind the specified magtape.
SET		Set parameters:
   SET DENSITY	Specify the density to use for the input or output tape.
		Output will follow input if not specified.
   SET MAXIMUM-RECORD-SIZE	Specify maximum number of frames per record
		in industry compatible mode to allow some performance gains
		due to savings in buffersize requested.
   SET REWIND-AT-COMPLETION	Rewind both tapes at completion of COPY
		or VERIFY operation.  SET NO REWIND-AT-COMPLETION is the
		default condition.
SKIP		Skip forward the specified number of files or to LEOT.
TAKE		Take commands from the specified file.
VERIFY		Compare and verify the specified tapes for the specified
		number of files.

[End of MTCOPY.HLP]

>
	SUBTTL	SET COMMAND HANDLER

;HERE TO PARSE SET COMMAND AND TRANSFER

.SET:
	PARSE	[FLDDB.	(.CMKEY,,SETTAB)] ;PARSE SET OPTION
	HRRZ	T2,0(T2)	;FETCH THE TRANSFER ADDRESS
	JRST	0(T2)		;AND GO THERE


;TABLE OF SET COMMANDS

SETTAB:	SETLEN,,SETLEN
	AA	DENSITY,.DENSITY	;SET TAPE DENSITY
	AA	MAXIMUM-RECORD-SIZE,.MAXIMUM
	AA	NO,.NOSET		;NO OPTION
	AA	REWIND-AT-COMPLETION,.REWAC
	SETLEN==.-SETTAB-1
	SUBTTL	SET REWIND-AT-COMPLETION COMMAND

;HERE TO PARSE SET REWIND AND SET NO REWIND COMMANDS

.NOSET:
	PARSE	[FLDDB.	(.CMKEY,,NOTAB,,<REWIND-AT-COMPLETION>)] ;PARSE OPTION
	CONFRM			;CONFIRM IT
	TXZ	F,FL%RAC	;CLEAR THE FLAG
	RET			;AND DONE


;KEYWORD TABLE FOR "NO"

NOTAB:	NOLEN,,NOLEN
	AA	REWIND-AT-COMPLETION,0
	NOLEN==.-NOTAB-1


;HERE FOR SET REWIND

.REWAC:
	CONFRM			;CONFIRM THE COMMAND LINE
	TXO	F,FL%RAC	; AND SET THE FLAG
	RET			; AND WE ARE DONE
	SUBTTL	SET MAXIMUM-RECORD-SIZE COMMAND

;HERE TO PARSE SET MAXIMUM-RECORD-SIZE COMMAND TO GET MAX RECORD SIZE
;TO REQUEST FROM MONITOR

.MAXIMUM:
	NOISE	(TO REQUEST FROM MONITOR) ;GUIDEWORDS
	PARSE	[FLDDB.	(.CMNUM,CM%SDH,^D10,<decimal max frame count>,<20480>)]
	MOVE	P1,T2		;COPY THE NUMBER
	CONFRM			;CONFIRM THE COMMAND LINE
	SKIPL	P1		;IS THE GIVEN VALUE
	CAILE	P1,TBFSIZ*4	; IN RANGE?
	 ERROR	Value out of range for internal buffers
	MOVEM	P1,MAXREC	;STORE THE VALUE
	RET			; AND WE ARE DONE
	SUBTTL	SET DENSITY COMMAND TO SET TAPE DENSITIES

;HERE TO SPECIFY TAPE DENSITIES
;FORMAT OF COMMAND IS:  DENSITY (OF) 1600-BPI (FOR) INPUT

.DENSITY:
	NOISE	(OF)		;GUIDEWORDS
	PARSE	[FLDDB. (.CMKEY,,DENTAB,,<1600-BPI>)]
	HRRZ	P1,0(T2)	;FETCH THE VALUE AND SAVE IT
	NOISE	(FOR)		;MORE GUIDEWORDS
	PARSE	[FLDDB. (.CMKEY,,INOTAB,,,[
		FLDDB. (.CMCFM)])]
	TSC	T3,T3		;SEE IF INPUT OR OUTPUT
	JUMPN	T3,[		;IF CONFIRMED, WANTS BOTH
		MOVX	P2,DEN.I!DEN.O ;REMEMBER HERE BOTH
		JRST	DENSI1]	; AND CONTINUE LATER ON
	MOVE	P2,0(T2)	;GET INPUT/OUTPUT VALUE
	CONFRM			;CONFIRM THE COMMAND
DENSI1:	TXNE	P2,DEN.I	;INPUT?
	 MOVEM	P1,TIDEN	; YES, REMEMBER VALUE
	TXNE	P2,DEN.O	;OUTPUT?
	 MOVEM	P1,TODEN	; YES, REMEMBER VALUE
	RET			;AND DONE



DENTAB:	DENLEN,,DENLEN
	AA	1600-BPI,.SJD16
	AA	6250-BPI,.SJD62
	AA	800-BPI,.SJDN8
	DENLEN==.-DENTAB-1

INOTAB:	INOLEN,,INOLEN
	AA	INPUT,DEN.I
	AA	OUTPUT,DEN.O
	INOLEN==.-INOTAB-1
	SUBTTL	DISMOUNT COMMAND TO UNLOAD OR DISMOUNT TAPE

;HERE TO PARSE THE DISMOUNT COMMAND TO UNLOAD TAPE

.DISMOUNT:
	NOISE	(OR UNLOAD)	;GUIDEWORDS
	PARSE	[FLDDB.	(.CMDEV,CM%SDH,,<tape designator>)] ;PARSE TAPE
	MOVEM	T2,JFNTMP	;SAVE JFN
	CONFRM			;CONFIRM THE COMMAND LINE

;NOW SEE IF WE DO UNLOAD OR DISMOUNT

	MOVE	T1,JFNTMP	;GET DESIGNATOR BACK
	LOAD	T2,DV%TYP,T1	;GET DEVICE TYPE
	CAIE	T2,.DVMTA	;TAPE?
	 ERROR	Device is not a magtape
	TRNN	T1,400000	;MT OR MTA?
	 JRST	UNLMTA		; MTA

;HERE WE HAVE AN MT: DEVICE, WE JUST RELD IT TO GET RID OF IT

UNLMT:	RELD			;RELEASE THE DEVICE
	 ERJMP [LERROR	<DISMOUNT failed:>]
	RET			;DONE

;HERE WE HAVE AN MTA: DEVICE, ISSUE THE MTOPR TO UNLOAD

UNLMTA:	CALL	GTIJFN		;GET A JFN TO USE ON THE TAPE
	MOVX	T2,.MORUL	;UNLOAD FUNCTION CODE
	MTOPR			;DO IT
	 ERJMP [LERROR	<UNLOAD failed:>]
	CLOSF			;AND GET RID OF THE JFN
	 ERJMP	.+1		;IGNORE THIS PARTICULAR ERROR
	RET			;DONE
	SUBTTL	REWIND COMMAND TO POSITION TAPE

;HERE TO REWIND A GIVEN TAPE

.REWIND:
	NOISE	(MAGTAPE)	;NOISE
	PARSE	[FLDDB.	(.CMDEV,CM%SDH,,<tape designator>)] ;PARSE TAPE
	MOVEM	T2,JFNTMP	;SAVE JFN
	CONFRM			;CONFIRM THE COMMAND LINE
	CALL	GTIJFN		;SETUP A GOOD TAPE JFN IN T1
	MOVX	T2,.MOREW	;REWIND CODE
	MTOPR			;DO IT
	 ERJMP	TILOSE		;OOPS
	CLOSF			;CLOSE THE JFN
	 ERJMP	LOSE
	RET			;DONE
	SUBTTL	BACKSPACE COMMAND TO POSITION TAPE

;BACKSPACE COMMAND COMES HERE TO BACKSPACE N FILES

.BACKSPACE:
	NOISE	(DEVICE)	;GUIDEWORDS
	PARSE	[FLDDB. (.CMDEV,CM%SDH,,<tape designator>)] ;GET TAPE
	MOVEM	T2,JFNTMP	;SAVE FOR NOW
	NOISE	(NUMBER OF FILES) ;MORE GUIDEWORDS
	PARSE	[FLDDB. (.CMNUM,CM%SDH,^D10,<number of files>,<1>)]
	MOVEM	T2,P1		;SAVE THE VALUE
	CONFRM			;CONFIRM THE COMMAND LINE
	SKIPG	P1		;MUST HAVE POSITIVE NUMBER
	 ERROR	Number of files must be greater than zero
	CALL	GTIJFN		;GET A GOOD TAPE JFN TO USE
	MOVX	T2,.MOBKF	;BACKSPACE?
BACKL:	MTOPR			;DO THE WORK
	 ERJMP	TILOSE		;FAILED SOMEHOW
	SOJG	P1,BACKL	;LOOP FOR ALL
	CLOSF			;GET RID OF THE JFN
	 ERJMP	LOSE
	RET			;DONE
	SUBTTL	SKIP COMMAND TO POSITION TAPE

;SKIP COMMAND COMES HERE TO SKIP N FILES OR TO LOGICAL END OF TAPE

.SKIP:	NOISE	(DEVICE)	;GUIDEWORDS
	PARSE	[FLDDB. (.CMDEV,CM%SDH,,<tape designator>)] ;GET TAPE
	MOVEM	T2,JFNTMP	;SAVE FOR NOW
	NOISE	(NUMBER OF FILES) ;MORE GUIDEWORDS
	PARSE	[FLDDB. (.CMNUM,CM%SDH,^D10,<number of files>,<1>,[
		 FLDDB. (.CMKEY,,EOTTAB)])]
	TSC	T3,T3		;SEE WHICH WAS PARSED
	MOVEM	T3,P2		;REMEMBER IN P2
	MOVEM	T2,P1		;SAVE THE VALUE IN P1
	CONFRM			;CONFIRM THE COMMAND LINE
	SKIPE	P1		;LEOT?
	 JRST	SKPEOT		;YES
	SKIPG	P1		;MUST BE POSITIVE VALUE
	 ERROR	Number of files must be greater than zero
	CALL	GTIJFN		;GET A GOOD TAPE JFN TO USE
	MOVX	T2,.MOFWF	;SKIP FORWARD FUNCTION
SKIPLP:	MTOPR			;DO THE WORK
	 ERJMP	TILOSE		;FAILED SOMEHOW
	SOJG	P1,SKIPLP	;LOOP FOR ALL
	CLOSF			;GET RID OF THE JFN
	 ERJMP	LOSE
	RET			;DONE

;HERE FOR SKIPPING TO LEOT

SKPEOT:	CALL	GTIJFN		;GET A GOOD TAPE JFN TO USE
	MOVX	T2,.MOEOT	;GET FUNCTION CODE
	MTOPR			;DO THE WORK
	 ERJMP	TILOSE		;FAILED SOMEHOW
	CLOSF			;GET RID OF THE JFN
	 ERJMP	LOSE
	RET			;ALL DONE


EOTTAB:	EOTLEN,,EOTLEN
	AA	LEOT,0		;SINGLE KEYWORD
	EOTLEN==.-EOTTAB-1
	SUBTTL	COPY COMMAND TO MAKE THE COPY

;COPY COMMAND COMES HERE

.COPY:	NOISE	(FROM)		;GUIDEWORDS
	PARSE	[FLDDB. (.CMDEV,CM%SDH,,<input tape designator>,<IN:>)]
	MOVEM	T2,JFNTMP	;STACK THE INPUT JFN
	NOISE	(TO)		;MORE GUIDEWORDS
	PARSE	[FLDDB. (.CMDEV,CM%SDH,,<output tape designator>,<OUT:>)]
	MOVEM	T2,JFNTM2	;STACK THE OUTPUT JFN
	NOISE	(FOR)		;MORE GUIDEWORDS
	PARSE	[FLDDB. (.CMNUM,CM%SDH,^D10,<number of files>,<ALL>,[
		 FLDDB. (.CMKEY,,ALLTAB)])]
	TSC	T3,T3		;SEE WHICH WAS PARSED
	SKIPE	T3		;FIRST?
	 JRST	COPY1		;NO - GO ON
	SKIPG	T2		;YES.  VALUE MUST BE .GT. ZERO
	 ERROR	Number of files must be greater than zero
	SKIPA			;OK, CONTINUE
COPY1:	MOVEI	T2,400000	; NO, GET A BUG NUMBER TO FAKE "ALL"
	MOVEM	T2,NFILES	;SAVE NUMBER OF FILES TO DO
	CONFRM			;CONFIRM THE COMMAND LINE
	CALL	GTIJFN		;SETUP THE INPUT JFN
	CALL	GTOJFN		; AND THE OUTPUT JFN
	CALL	SNIFF		;SEE IF TAPES CAN HANDLE THE DENSITIES
	CALL	DOCOPY		;DO THE WORK
	MOVX	T2,.MOREW	;REWIND FUNCTION CODE
	MOVE	T1,TIJFN	;NOW CLOSE UP INPUT
	TXNE	F,FL%RAC	;REWIND AT COMPLETION?
	 JRST [	MTOPR		; YES, DO IT
		 ERJMP	.+1	;IGNORE ERRORS HERE
		JRST .+1]	;AND CONTINUE INLINE
	CLOSF			; SIDE
	 ERJMP	.+1		;IGNORE ERRORS FOR NOW
	MOVE	T1,TOJFN	;AND THEN OUTPUT
	TXNE	F,FL%RAC	;REWIND AT COMPLETION?
	 JRST [	MTOPR		; YES, DO IT
		 ERJMP	.+1	;IGNORE ERRORS HERE
		JRST .+1]	;AND CONTINUE INLINE
	CLOSF			; SIDE
	 ERJMP	.+1
	TYPE	<
[COPY Completed:  >		;START LINE
	HRRZS	P1		;GET NUMBER OF FILES FROM DOCOPY
	TDEC	P1		;TYPE IT
	TYPE	< files]>		;FINISH UP
	RET			;DONE



ALLTAB:	ALLLEN,,ALLLEN
	AA	ALL,0		;SINGLE KEYWORD
	ALLLEN==.-ALLTAB-1

;DOCOPY - ROUTINE TO DO THE ACTUAL COPY.  AOBJN FILE COUNTER KEPT IN P1.

DOCOPY:
	MOVE	T1,TIJFN	;GET THE INPUT JFN
	MOVX	T2,.MOSDM	;SET DATA MODE
	MOVX	T3,.SJDM8	;TO 8 BIT MODE
	MTOPR			;DO IT
	 ERJMP	LOSE		;FAILED
	MOVE	T1,TOJFN	;SAME FOR THE OUTPUT
	MTOPR			;SET 8 BIT MODE
	 ERJMP	LOSE
	MOVX	T2,.MOSRS	;SET RECORD SIZE FUNCTION
	MOVE	T3,MAXREC	;GET MAX RECORD SIZE
	MTOPR			;SET SIZE
	 ERJMP	LOSE		;FAILED
	MOVE	T1,TIJFN	;SAME FOR THE INPUT
	MTOPR			;SET MAX RECORD SIZE
	 ERJMP	LOSE
	MOVX	T2,.MOSDN	;SET DENSITY FUNCTION
	SKIPL	T3,TIDEN	;GET INPUT DENSITY IF SET
	MTOPR			;SET IT
	 ERJMP	LOSE
	MOVE	T1,TOJFN	;OUTPUT JFN BACK AGAIN
	SKIPGE	T3,TODEN	;AND THE OUTPUT SIDE
	 SKIPL	T3,TIDEN	; FOLLOWING INPUT IF NOT SPECIFIED
	MTOPR			;SET IT TOO
	 ERJMP	LOSE
	TXZ	F,FL%ITM	;FLAG NO TAPE MARKS SEEN YET
	MOVN	P1,NFILES	;GET NUMBER OF FILES TO BUILD
	HRLZS	P1		;AOBJN COUNTER ON THEM

DOCOPL:	MOVE	T1,TIJFN	;GET THE INPUT JFN
	MOVE	T2,TIPTR	;POINT TO THE BUFFER
	MOVN	T3,MAXREC	;ASK FOR THE MAX
	SINR			;READ THEM IN
	 ERJMP	IERR		;HANDLE ERRORS, EOF, EOT, ...
	TXZ	F,FL%ITM	;DATA, SO NOT TAPE MARK...
	ADD	T3,MAXREC	;COMPUTE BUFFER SIZE
	MOVEM	T3,BUFSIZ	; SAVE IT

	MOVE	T1,TOJFN	;GET OUTPUT JFN
	MOVE	T2,TIPTR	;POINT TO THE BUFFER
	MOVN	T3,BUFSIZ	;SAME SIZE
	SOUTR			;WRITE THE BUFFER
	 ERJMP	OERR		;HANDLE ERRORS, EOT, ...

	JRST	DOCOPL		;AND LOOP TIL DONE

;HERE FOR ERRORS ON THE INPUT SINR

IERR:	GDSTS			;GET TAPE STATUS
	 ERJMP	LOSE
	TXNN	T2,MT%EOF	;EOF DETECTED?
	 JRST	IERR1		;NO, GO ON

	SETZM	T2		;CLEAR END OF FILE ON TAPE
	SDSTS			;BY RESETTING CONDITION
	 ERJMP	LOSE

	MOVE	T1,TOJFN	;WRITE TAPE MARK
	MOVX	T2,.MOEOF	; ON OUTPUT TAPE
	MTOPR			;DO IT
	 ERJMP	LOSE		;FAILED SOMEHOW
	TXON	F,FL%ITM	;SET TAPE MARK SEEN FLAG, SEE IF ALREADY SET
	AOBJN	P1,DOCOPL	;GO IF STILL SOME LEFT TO DO
	 RET			;DONE - # FILES OR LEOT ENCOUNTERED

IERR1:	TXNE	T2,MT%EOT	;REACHED END OF TAPE?
	 RET			;YES, ALL DONE

	TXNE	T2,MT%DAE!MT%DVE ;DEVICE OR DATA ERROR SET?
	 ERROR	Copy: Input magtape device or data error

	LERROR	Copy: Input magtape unknown error condition




;HERE FOR ERRORS ON THE OUTPUT SOUTR

OERR:	GDSTS			;GET THE DEVICE STATUS
	 ERJMP	LOSE
	TXNE	T2,MT%EOT	;REACH END OF TAPE?
	 ERROR	Copy: Premature end-of-tape reached on output

	TXNE	T2,MT%ILW	;WRITE LOCKED?
	 ERROR	Copy: Output tape is write-locked

	TXNE	T2,MT%DVE!MT%DAE ;DEVICE OR DATA ERROR?
	 ERROR	Copy: Output magtape device or data error

	LERROR	Copy: Unknown error on output magtape
	SUBTTL	SNIFF ROUTINE TO CHECK AVAILABLE TAPE DENSITIES

;SNIFF - ROUTINE TO SEE IF THE DENSITIES IN TIDEN AND TODEN ARE VALID
;FOR THE RESPECTIVE TAPES.  ERROR OUT IF NOT.

SNIFF:	SKIPGE	T4,TIDEN	;INPUT SET?
	 JRST	SNIFF2		; NO, CHECK OUTPUT

	MOVE	T1,TIJFN	;GET INPUT DENSITY
	MOVX	T2,.MOSTA	;STATUS FUNCTION
	MOVEI	T3,TAPBLK	;POINT TO THE BLOCK
	MTOPR			;GET STATUS
	 ERJMP	R		;CONTINUE ON ERROR AND HOPE FOR THE BEST...
	MOVSI	T1,-DENLEN	;NUMBER TO CHECK
	HRRZ	T2,DENTAB+1(T1)	;GET CODE
	CAME	T2,TIDEN	;MATCH?
	AOBJN	T1,.-2		; NO, LOOP
	MOVE	T2,DENAVL(T1)	;GET THE CORRESPONDING AVAILABLE BIT
	TDNN	T2,TAPBLK+.MODDN ;MAKE THE TEST
	 ERROR	Input magtape drive does not support requested density

SNIFF2:	SKIPGE	T4,TODEN	;OUTPUT SET?
	SKIPL	T4,TIDEN	;NO - FOLLOW INPUT IF SET
	 SKIPA			; YES, CONTINUE
	RET			; NO, NEITHER, DONE

	MOVEM	T4,TODEN	;COPY RIGHT ONE TO TODEN
	MOVE	T1,TOJFN	;GET INPUT DENSITY
	MOVX	T2,.MOSTA	;STATUS FUNCTION
	MOVEI	T3,TAPBLK	;POINT TO THE BLOCK
	MTOPR			;GET STATUS
	 ERJMP	R		;CONTINUE ON ERROR AND HOPE FOR THE BEST...
	MOVSI	T1,-DENLEN	;NUMBER TO CHECK
	HRRZ	T2,DENTAB+1(T1)	;GET CODE
	CAME	T2,TODEN	;MATCH?
	AOBJN	T1,.-2		; NO, LOOP
	MOVE	T2,DENAVL(T1)	;GET THE CORRESPONDING AVAILABLE BIT
	TDNN	T2,TAPBLK+.MODDN ;MAKE THE TEST
	 ERROR	Output magtape drive does not support requested density
	RET			;ALL CHECKS OUT, DONE


;TABLE OF AVAILABLE DENSITIES BITS - *** INDEX ORDER SAME AS DENTAB !!! ***

DENAVL:	SJ%C16			;1600-BPI
	SJ%C62			;6250-BPI
	SJ%CP8			;800-BPI
	SUBTTL	VERIFY COMMAND TO CHECK TAPES

;VERIFY COMMAND COMES HERE

.VERIFY:
	NOISE	(FROM)		;GUIDEWORDS
	PARSE	[FLDDB. (.CMDEV,CM%SDH,,<base tape designator>,<IN:>)]
	MOVEM	T2,JFNTMP	;STACK THE BASE JFN
	NOISE	(AGAINST)	;MORE GUIDEWORDS
	PARSE	[FLDDB. (.CMDEV,CM%SDH,,<tape designator to verify>,<OUT:>)]
	MOVEM	T2,JFNTM2	;STACK THE OTHER JFN
	NOISE	(FOR)		;MORE GUIDEWORDS
	PARSE	[FLDDB. (.CMNUM,CM%SDH,^D10,<number of files>,<ALL>,[
		 FLDDB. (.CMKEY,,ALLTAB)])]
	TSC	T3,T3		;SEE WHICH WAS PARSED
	SKIPE	T3		;FIRST?
	 JRST	VERIF1		;NO - GO ON
	SKIPG	T2		;YES.  VALUE MUST BE .GT. ZERO
	 ERROR	Number of files must be greater than zero
	SKIPA			;OK, CONTINUE
VERIF1:	MOVEI	T2,400000	; NO - USE A LARGE NUMBER FOR "ALL"
	MOVEM	T2,NFILES	;SAVE NUMBER OF FILES TO DO
	CONFRM			;CONFIRM THE COMMAND LINE
	CALL	GTIJFN		;SETUP THE BASE SIDE
	CALL	GTVJFN		; AND THE VERIFY SIDE JFNS
	CALL	SNIFF		;SEE IF TAPES CAN HANDLE THE DENSITIES
	CALL	DOVERIFY	;DO THE WORK
	MOVX	T2,.MOREW	;REWIND FUNCTION CODE
	MOVE	T1,TIJFN	;NOW CLOSE UP INPUT
	TXNE	F,FL%RAC	;REWIND AT COMPLETION?
	 JRST [	MTOPR		; YES, DO IT
		 ERJMP	.+1	;IGNORE ERRORS HERE
		JRST .+1]	;AND CONTINUE INLINE
	CLOSF			; SIDE
	 ERJMP	.+1		;IGNORE ERRORS FOR NOW
	MOVE	T1,TOJFN	;AND THEN "OUTPUT"
	TXNE	F,FL%RAC	;REWIND AT COMPLETION?
	 JRST [	MTOPR		; YES, DO IT
		 ERJMP	.+1	;IGNORE ERRORS HERE
		JRST .+1]	;AND CONTINUE INLINE
	CLOSF			; SIDE
	 ERJMP	.+1
	TYPE	<
[VERIFY Completed:  >		;START LINE
	HRRZS	P1		;GET NUMBER OF FILES FROM DOVERIFY
	TDEC	P1		;TYPE IT
	TYPE	< files]>		;FINISH UP
	RET			;DONE

;DOVERIFY - ROUTINE TO DO THE ACTUAL VERIFY.  AOBJN FILE COUNTER KEPT IN P1.

DOVERIFY:
	MOVE	T1,TIJFN	;GET THE INPUT JFN
	MOVX	T2,.MOSDM	;SET DATA MODE
	MOVX	T3,.SJDM8	;TO 8 BIT MODE
	MTOPR			;DO IT
	 ERJMP	LOSE		;FAILED
	MOVE	T1,TOJFN	;SAME FOR THE OUTPUT
	MTOPR			;SET 8 BIT MODE
	 ERJMP	LOSE
	MOVX	T2,.MOSRS	;SET RECORD SIZE FUNCTION
	MOVE	T3,MAXREC	;MAX BYTES
	MTOPR			;SET SIZE
	 ERJMP	LOSE		;FAILED
	MOVE	T1,TIJFN	;SAME FOR THE INPUT
	MTOPR			;SET MAX RECORD SIZE
	 ERJMP	LOSE
	MOVX	T2,.MOSDN	;SET DENSITY FUNCTION
	SKIPL	T3,TIDEN	;GET INPUT DENSITY IF SET
	MTOPR			;SET IT
	 ERJMP	LOSE
	MOVE	T1,TOJFN	;OUTPUT JFN BACK AGAIN
	SKIPGE	T3,TODEN	;AND THE OUTPUT SIDE
	 SKIPL	T3,TIDEN	; FOLLOWING INPUT IF NOT SPECIFIED
	MTOPR			;SET IT TOO
	 ERJMP	LOSE
	TXZ	F,FL%ITM!FL%VTM	;RESET TAPE MARK SEEN FLAGS
	MOVN	P1,NFILES	;GET NUMBER OF FILES TO DO
	HRLZS	P1		; AND BUILD AOBJN COUNTER
	;...			;FALL THROUGH TO LOOP

;FALL THROUGH FROM ABOVE

DOVERL:	MOVE	T1,TIJFN	;GET BASE JFN
	MOVE	T2,TIPTR	;POINT AT BUFFER
	MOVN	T3,MAXREC	;ASK FOR THE MAX
	SINR			;READ THEM IN
	 ERJMP	IVERRI		;HANDLE ERRORS, EOF, EOT
	TXZ	F,FL%ITM	;DATA, SO NOT TAPE MARK...
	ADD	T3,MAXREC	;CALCULATE BUFFERSIZE
	MOVEM	T3,BUFSIZ	;AND STORE IT

	MOVE	T1,TOJFN	;GET VERIFY JFN
	MOVE	T2,TVPTR	;POINT AT OTHER BUFFER
	MOVN	T3,BUFSIZ	;NUMBER OF BYTES
	SINR			;READ THEM TOO
	 ERJMP	IVERRV		;HANDLE ANY ERRORS HERE...

	SKIPE	T3		;BUFFER SHOULD BE SAME SIZE
	 ERROR	Verify: Verify record is too short
	TXZ	F,FL%VTM	;DATA, SO NOT TAPE MARK...
	MOVE	T2,BUFSIZ	;NUMBER OF BYTES
	IDIVI	T2,4		;AND GET NUMBER OF WORDS (REMAINDER TO T3)
	MOVNS	T2		;NEGATE
	HRLZS	T2		; AND BUILD AOBJN POINTER

VERCMP:	MOVE	T1,TIBUF(T2)	;FETCH A WORD
	CAMN	T1,TVBUF(T2)	; AND SEE IF IT MATCHES
	AOBJN	T2,VERCMP	;LOOP FOR ALL IF SO
	JUMPL	T2,VERERR	;REPORT ERROR IF STOPPED BEFORE END

	MOVE	T1,TIBUF(T2)	;GET LAST WORD (MAYBE ONE BEYOND, BUT...)
	MOVE	T2,TVBUF(T2)	; FROM BOTH BUFFERS
	AND	T1,REMAIN(T3)	;MASK TO VALID BITS
	AND	T2,REMAIN(T3)	; IN BOTH WORDS
	CAMN	T1,T2		;FINAL MATCH?
	 JRST	DOVERL		; YES! CONTINUE READING

;HERE WE HAVE A MISCOMPARE TO REPORT

VERERR:	ERROR	Verify: Miscompare of data in file


;TABLE OF MASKS FOR VALID BITS IN LAST BUFFER WORD

REMAIN:	EXP	0		;NO VALID BITS
	EXP	377B7		;ONE BYTE
	EXP	377B7+377B15	;TWO BYTES
	EXP	377B7+377B15+377B23 ;THREE BYTES

;HERE FOR ERRORS ON THE BASE INPUT SINR

IVERRI:	GDSTS			;GET TAPE STATUS
	 ERJMP	LOSE
	TXNN	T2,MT%EOF	;EOF DETECTED?
	 JRST	IVERR1		;NO, GO ON

	SETZM	T2		;CLEAR END OF FILE ON TAPE
	SDSTS			;BY RESETTING CONDITION
	 ERJMP	LOSE

	MOVE	T1,TOJFN	;GET OTHER JFN
	MOVE	T2,TVPTR	;POINT TO ITS BUFFER
	MOVN	T3,MAXREC	;SET UP A COUNT
	SINR			;EXPECT A TAPE MARK
	 ERJMP	.+2
	ERROR	Verify: Verify file too long

	GDSTS			;GET TAPE STATUS
	 ERJMP	LOSE
	TXNN	T2,MT%EOF	;TAPE MARK HERE TOO?
	 LERROR	Verify: Error on verify tape when tape mark expected
	SETZM	T2		;TAPE MARK.  CLEAR CONDITION
	SDSTS			; AND REST OF DEVICE BITS
	 ERJMP LOSE
	TXON	F,FL%ITM	;SET TAPE MARK SEEN FLAG, SEE IF ALREADY SET
	AOBJN	P1,DOVERL	;COUNT DOWN NUMBER OF FILES AND LOOP
	 RET			;DONE - # FILES OR LEOT ENCOUNTERED

IVERR1:	TXNE	T2,MT%EOT	;REACHED END OF TAPE?
	 RET			;YES, ALL DONE

	TXNE	T2,MT%DAE!MT%DVE ;DEVICE OR DATA ERROR SET?
	 ERROR	Verify: Input magtape device or data error

	LERROR	Verify: Input magtape unknown error condition


;HERE FOR ERRORS ON THE VERIFY INPUT SINR

IVERRV:	GDSTS			;GET TAPE STATUS
	 ERJMP	LOSE
	TXNE	T2,MT%EOF	;EOF DETECTED?
	 ERROR	Verify: Tape mark encountered on verify tape when data expected

	TXNE	T2,MT%EOT	;REACHED END OF TAPE?
	 ERROR	Verify: End of tape encountered early on verify tape

	TXNE	T2,MT%DAE!MT%DVE ;DEVICE OR DATA ERROR SET?
	 ERROR	Verify: Verify magtape device or data error

	LERROR	Verify: Verify magtape unknown error condition
	SUBTTL	TAPE JFN SUPPORT ROUTINES - TILOSE/TOLOSE/TVLOSE


;TVLOSE - ROUTINE TO CLOSE OFF AND RELEASE TOJFN THEN GO TO LOSE
;TOLOSE - ROUTINE TO CLOSE OFF AND RELEASE TOJFN THEN GO TO LOSE
;TILOSE - ROUTINE TO CLOSE OFF AND RELEASE TIJFN THEN GO TO LOSE

TVLOSE:
TOLOSE:	SKIPA	T1,TOJFN	;GET THE JFN
TILOSE:	MOVE	T1,TIJFN	;GET THE JFN
	PUSH	P,T1		;SAVE IN CASE CLOSF FAILS
	CLOSF			;TRY TO CLOSE
	 ERJMP [POP	P,T1	;GET JFN AGAIN
		RLJFN		;CLOSE FAILED, TRY RLJFN
		 ERJMP	LOSE	;OH WELL
		JRST	LOSE]	;GET TO LOSE
	POP	P,T1		;ADJUST STACK
	JRST	LOSE		;WIND UP AT LOSE ONE WAY OR ANOTHER
	SUBTTL	TAPE JFN SUPPORT ROUTINES - GTIJFN/GTOJFN/GTVJFN


;GTIJFN/GTOJFN/GTVJFN - ROUTINES TO SETUP TIJFN/TOJFN WITH AN OPEN TAPE
;JFN FROM THE DESIGNATOR IN JFNTMP OR JFNTM2.
;
;	CALL	GTIJFN	OR CALL	GTOJFN	OR CALL	GTVJFN
;
;RETURNS:  +1:	ALWAYS, UNLESS ERROR EXIT
;		T1/	JFN, OPENED FOR READ OR WRITE APPROPRIATELY
;USES T1-T4.


GTVJFN:	MOVEI	T4,2		;CODE FOR GTVJFN
	JRST	GTXJFN		;DO THE WORK
GTOJFN:	SKIPA	T4,[1]		;CODE FOR GTOJFN
GTIJFN:	MOVEI	T4,0		;CODE FOR GTIJFN
GTXJFN:	MOVE	T2,@[	JFNTMP	;GTIJFN
			JFNTM2	;GTOJFN
			JFNTM2](T4) ;GTVJFN - SELECT PROPER DESIGNATOR
	LOAD	T1,DV%TYP,T2	;GET THE TYPE
	CAIE	T1,.DVMTA	;TAPE?
	 ERROR	Device is not a magtape
	HRROI	T1,JFNSTR	;POINT TO STRING AREA FOR DEVST
	DEVST			;CONVERT DESIGNATOR TO STRING
	 ERJMP	LOSE		;OOPS
	MOVEI	T2,":"		;TERMINATE WITH THE COLON...
	IDPB	T2,T1		; TO BUILD PROPER DEVICE NAME
	SETZ	T2,		;AND A NULL
	IDPB	T2,T1		; TO TIE OFF THE STRING
	MOVX	T1,GJ%SHT	;SETUP AND CONVERT STRING
	HRROI	T2,JFNSTR	; TO A JFN TO USE
	GTJFN			; INSTEAD OF THE DESIGNATOR
	 ERJMP [LERROR	<Cannot get a JFN on tape designator>]
	MOVEM	T1,@[	TIJFN	;GTIJFN
			TOJFN	;GTOJFN
			TOJFN](T4) ;GTVJFN - SET THE JFN
	SETZM	@[	JFNTMP	;GTIJFN
			JFNTM2	;GTOJFN
			JFNTM2](T4) ;GTVJFN - CLEAR TEMP SLOT
	MOVE	T2,[	FLD(^D8,OF%BSZ)!OF%RD ;GTIJFN
			FLD(^D8,OF%BSZ)!OF%WR ;GTIJFN
			FLD(^D8,OF%BSZ)!OF%RD](T4) ;GTVJFN - GET OPEN MODE BITS
	OPENF			;DO IT
	 ERJMP [JRST @[	TILOSE	;GTIJFN
			TOLOSE	;GTOJFN
			TVLOSE](T4)] ;GTVJFN - HANDLE ERROR
	RET			;DONE
	SUBTTL	THE DATA AREA

	XLIST			;DUMP THE LITERALS
DSLITS:	LIT
	LIST


SAVEP:	BLOCK	1		;STORAGE OF STACK
JFNTM2:	BLOCK	1		;SECOND WORD FOR COMND'S JFNS RETURNED DURING PARSE
JFNSTR:	BLOCK	20		;STRING OF DEVICE DESIGNATOR
TAPBLK:	EXP	.MODDN+1	;TAPE STATUS BLOCK
	BLOCK	.MODDN+2	;AND SOME SPACE FOR IT

TIJFN:	BLOCK	1		;INPUT TAPE JFN
TOJFN:	BLOCK	1		;OUTPUT TAPE JFN

TIDEN:	BLOCK	1		;INPUT DENSITY TO USE
TODEN:	BLOCK	1		;OUTPUT DENSITY TO USE

NFILES:	BLOCK	1		;NUMBER OF FILES TO COPY/VERIFY
MAXREC:	BLOCK	1		;USER SPECIFED MAX RECORD SIZE OR DEFAULT
BUFSIZ:	BLOCK	1		;EXPECTED SIZE OF BUFFER IN BYTES

TIPTR:	POINT 8,TIBUF		;POINTER TO INPUT BUFFER
TVPTR:	POINT 8,TVBUF		;POINTER TO VERIFY BUFFER

TIBUF:	BLOCK	TBFSIZ		;INPUT BUFFER
TVBUF:	BLOCK	TBFSIZ		;VERIFY BUFFER

	END	<3,,EVEC>