Google
 

Trailing-Edge - PDP-10 Archives - BB-M081K-SM - exec/exec2.mac
There are 47 other files named exec2.mac in the archive. Click here to see a list.
; UPD ID= 218, SNARK:<6.1.EXEC>EXEC2.MAC.12,  10-Jun-85 08:42:29 by DMCDANIEL
; UPD ID= 197, SNARK:<6.1.EXEC>EXEC2.MAC.11,  14-May-85 10:32:32 by MCCOLLUM
;TCO 6.1.1386 - Remove SUPERSEDE subcommand from APPEND
; UPD ID= 162, SNARK:<6.1.EXEC>EXEC2.MAC.10,   3-May-85 08:29:27 by DMCDANIEL
;Update copyrights for 6.1.
; UPD ID= 128, SNARK:<6.1.EXEC>EXEC2.MAC.9,   7-Feb-85 09:38:27 by PRATT
;TCO 6.1.1179 - Remove ASCII PARITY/NOPARITY, they've never been coded. 
; UPD ID= 90, SNARK:<6.1.EXEC>EXEC2.MAC.8,  14-Nov-84 11:15:59 by MCCOLLUM
;Still more of TCO 6.1.1025 - Fix up call to MFSET
; UPD ID= 86, SNARK:<6.1.EXEC>EXEC2.MAC.6,  12-Nov-84 16:22:32 by MCCOLLUM
;TCO 6.1.1044 - Add NEWER option to COPY SUPERSEDE
; UPD ID= 53, SNARK:<6.1.EXEC>EXEC2.MAC.5,   5-Nov-84 15:18:44 by MCCOLLUM
;MORE OF TCO 6.1.1025 - FIX BUG
; UPD ID= 47, SNARK:<6.1.EXEC>EXEC2.MAC.4,  30-Oct-84 13:54:43 by MCCOLLUM
;TCO 6.1.1025 - Add SUPERSEDE subcommand to COPY command.
; UPD ID= 2, SNARK:<6.1.EXEC>EXEC2.MAC.2,  28-Sep-84 12:52:00 by PRATT
;TCO 6.1.1012 - Add UNFORMATTED subcommand to TYPE
; UPD ID= 361, SNARK:<6.EXEC>EXEC2.MAC.17,  16-Dec-83 11:50:26 by TSANG
;MORE FOR TCO 6.1731
; UPD ID= 300, SNARK:<6.EXEC>EXEC2.MAC.16,  18-Jul-83 16:15:33 by JCAMPBELL
;TCO 6.1730 - Copy and mask FB%FOR in .FBCTL in FDB on COPY.
; UPD ID= 235, SNARK:<6.EXEC>EXEC2.MAC.15,  15-Jan-83 19:23:49 by CHALL
;TCO 6.1464 - UPDATE COPYRIGHT NOTICE
; UPD ID= 216, SNARK:<6.EXEC>EXEC2.MAC.14,  10-Jan-83 14:10:44 by LOMARTIRE
;TCO 6.1449 - Get system-wide logical SYSTEM: for writing SYSJOB.COMMANDS
; UPD ID= 199, SNARK:<6.EXEC>EXEC2.MAC.13,  24-Nov-82 16:28:11 by TSANG
;TCO 6.1214 - CREATE WRN MSG INSTEAD OF ERR MSG WHEN COPY A FILE OF TYPE
; .DIRECTORY.
; UPD ID= 188, SNARK:<6.EXEC>EXEC2.MAC.12,  27-Oct-82 10:14:32 by CHALL
;MORE TCO 6.1200 - MAKE SURE BYTE ADJUSTMENT STAYS WITHIN ONE PAGE
; UPD ID= 182, SNARK:<6.EXEC>EXEC2.MAC.11,  13-Oct-82 15:35:05 by TSANG
; UPD ID= 174, SNARK:<6.EXEC>EXEC2.MAC.9,   8-Oct-82 17:25:41 by TSANG
;TCO 6.1302 - MAKE AC1 GET A CORRECT JFN.
; UPD ID= 157, SNARK:<6.EXEC>EXEC2.MAC.8,  10-Sep-82 14:59:58 by TSANG
;TCO 6.1200 OUTPUT A CR/LF AT END OF A FILE WHEN USING TYPE COMMAND.
; UPD ID= 112, SNARK:<6.EXEC>EXEC2.MAC.7,   9-Apr-82 10:13:12 by CHALL
;TCO 6.1067 ..DTCH- .DETAC- ^E DIDN'T ECHO AFTER DETACH/ATTACH
; UPD ID= 131, SNARK:<5.EXEC>EXEC2.MAC.8,  13-Jan-82 16:15:37 by TILLSON
;TCO 5.1671 Copy user settable word
; UPD ID= 120, SNARK:<5.EXEC>EXECIN.MAC.21,  28-Dec-81 11:14:01 by CHALL
;TCO 6.1052 - UPDATE COPYRIGHT NOTICE AND DELETE PRE-V4.1 EDIT HISTORY
; UPD ID= 33, SNARK:<5.EXEC>EXEC2.MAC.5,  14-Aug-81 19:12:18 by CHALL
;TCO 5.1454 CHANGE NAME FROM XDEF TO EXECDE
; UPD ID= 1816, SNARK:<5.EXEC>EXEC2.MAC.4,  16-Apr-81 18:20:36 by TILLSON
;TCO 5.1286 - Pass LBLSKP a JFN, not a device type
; UPD ID= 1808, SNARK:<5.EXEC>EXEC2.MAC.3,  15-Apr-81 11:12:56 by TILLSON
;TCO 5.1282 - Stop 512-page COPY from going long
; UPD ID= 1725, SNARK:<5.EXEC>EXEC2.MAC.2,  17-Mar-81 13:14:38 by SCHMITT
;TCO 5.1274 - Fix COPY from labelled EBCDIC tapes to use bytesize 7
;REMOVE MFRK CONDITIONALS
; UPD ID= 1190, SNARK:<5.EXEC>EXEC2.MAC.6,  23-Oct-80 14:08:40 by TILLSON
;tco 5.1178 - Fix COPY from labelled ANSI-ASCII tapes to use bytesize 7
; UPD ID= 803, SNARK:<5.EXEC>EXEC2.MAC.5,  28-Jul-80 09:53:36 by OSMAN
;tco 5.1113 - Don't type [OK] until after CLOSF
; UPD ID= 532, SNARK:<5.EXEC>EXEC2.MAC.4,  20-May-80 14:55:27 by MURPHY
;CHANGE SOME XTND TO NEWF OR MFRK
; UPD ID= 490, SNARK:<4.1.EXEC>EXEC2.MAC.6,  29-Apr-80 16:20:51 by TOMCZAK
;TCO 4.1.1152 - Add ERJMP after XCT in COPNCR, change SKIPE to JUMPE
;more 4.1.1099 - Handle files with page 777777
; UPD ID= 303, SNARK:<4.1.EXEC>EXEC2.MAC.2,   5-Mar-80 11:24:23 by OSMAN
;tco 4.1.1099 - Fix COPY to not go forever on files exactly one section long
;TOPS20 'EXECUTIVE' COMMAND LANGUAGE

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. 1980,1985
;ALL RIGHTS RESERVED.

	SEARCH EXECDE
	TTITLE EXEC2

;THIS FILE CONTAINS CODE TO EXECUTE SOME OF THE LONGER COMMANDS:
; COPY/APPEND
; TYPE
; REDIRECT/DETACH

;TYPE.  CAUSE SOURCE FILE(S) TO BE COPIED TO TTY.
;SET UP ARGS AND JOIN COPY.

.TYPE::	MOVEI Q1,CP%TYP		;IDENTIFY
TYPE1::	MOVE A,COJFN		;USE COMMAND OUTPUT JFN
	MOVEM A,OUTDSG
	TLO Z,F1		;SIGNAL THAT THIS IS A COPY COMMAND
	CAIE Q1,CP%HEL		;NO NOISE IF ENTERING FROM HELP COMMAND
	NOISE (FILE)
	SETZ Q2,
	TLZ Z,F2		;NOT APPEND
	CAIN Q1,CP%HEL		;COMING FROM "HELP" COMMAND ?
	 JRST TPNFIL		;YES - NO FILE SPEC NEEDED NOW
	DMOVE A,[EXP 0,<(GJ%OLD!GJ%IFG!1B15!1B16)>] ;NO SPECIAL, OLD FILE, STARS ALLOWED, LIST O.K., LIST IS LAST ON LINE
	CALL SPECFN		;GATHER SPECS TO TYPE
	 SUBCOM $TYPE		;READ SUBCOMMANDS
TPNFIL:	SETZM TYPGRP		;DON'T PRINT NAME UNLESS GROUPF ON
	SETZM MCOJFN		;SAY NOT MULTI FILE OUTPUT
	SETOM TYPING		; SAY TYPING ON TERMINAL
	CALL COP1A		;GO JOIN COPY
TYPFIN::SKIPN TPCCOC
	 RET			;DON'T RESTORE SETTINGS IF NOT SAVED
	MOVEI Q1,ETTYMD		;RESET TERM CHARACTERISTICS 
	CALL LTTYMD		;RESTORE STATE OF LINE
	MOVEI A,.CTTRM
	MOVEI B,.MOSLW		;SPECIFY SETTING LINE WIDTH
	HRRZ C,TPTTYP		;PICK UP PREVIOUS WIDTH
	MTOPR			;DO IT
	 ERCAL CJERRE		;GO SAY WHY IT FAILED
	MOVEI A,.CTTRM
	MOVEI B,.MOSLL		;SPECIFY SETTING LINE LENGTH
	HLRZ C,TPTTYP		;PICK UP PREVIOUS WIDTH
	MTOPR			;DO IT
	 ERCAL CJERRE		;GO SAY WHY IT FAILED
	SETZM TPCCOC		;UNFLAG THE "CCOC CHANGED" FLAG
	RET

$TYPE:	TABLE			;TYPE SUBCOMMAND TABLE
	T UNFORMATTED,,.TRTYP
	TEND

.TRTYP:	NOISE (OUTPUT)		;UNFORMATTED 
	CONFIRM			
	SETOM TPCCOC		;FLAG THE UNFORMATTED TYPE 
	MOVEI A,.CTTRM
	MOVEI B,.MORLW		;SPECIFY READING LINE WIDTH
	MTOPR			;DO IT
	 ERCAL CJERRE		;GO SAY WHY IT FAILED
	MOVEM C,TPTTYP		;SAVE PREVIOUS WIDTH
	MOVEI A,.CTTRM
	MOVEI B,.MORLL		;SPECIFY SETTING READ LENGTH
	MTOPR			;DO IT
	 ERCAL CJERRE		;GO SAY WHY IT FAILED
	HRLM C,TPTTYP		;SAVE PREVIOUS WIDTH
	MOVEI A,.CTTRM		;CONTROLLING TERMINAL
	RFMOD
	 ERJMP CJERRE
	TXZ B,TT%LEN!TT%WID	;0 THE WIDTH AND THE LENGTH
	STPAR
	 ERJMP CJERRE
	MOVE B,[525252,,525252]
	MOVE C,B
	SFCOC			;SET CCOC WORDS. NO TRANSLATION OF ANY CHAR
	 ERJMP CJERRE
	RET
;COPY COMMAND:  COPY <FILE GROUP> (TO) <FILE>
;AND
;APPEND COMMAND:  APPEND <FILE GROUP> TO <FILE>

;TAKE SUBCOMMANDS.

;MODE SUBCOMMAND --   LEGAL FOR--	MODE-BYTESIZE USED--
;ASCII		ANY DEVICES		1-7 WHERE LEGAL, ELSE 0-7
;IMAGE		ONE DEVICE MUST ACCEPT	10-8 WHERE LEGAL, ELSE 0-8
;		MODE 10, OTHER MUST
;		NOT BE LPT:.
;IMAGE BINARY	NEITHER DEVICE CAN	13-36 WHERE LEGAL, ELSE 0-36
;		BE TTY: OR LPT:
;BINARY		NEITHER DEVICE CAN	14-36 WHERE LEGAL, ELSE 0-36
;		BE TTY: OR LPT:.
;ASCII PARITY	PAPER TAPE SOURCE	SEE ASCII	NOT IMPLEMENTED
;DUMP		NON-DIRECTORY DTA OR MTA		NOT IMPLEMENTED

;FLAGS IN LH Z
;F1 ON FOR PAGES COPY, OTHERWISE OFF
;F2 ON FOR APPEND, OFF FOR COPY
;F3 ON IF OUTFILE WAS ALREADY OPEN (GROUP SOURCE CASE)
;F4 ON IF NOT DISK TO DISK XFER

;FLAGS IN RH Z
;BITS FOR MODES SPECIFIED BY SUBCOMMANDS
; B35-N ON FOR MODE N, AS IN DVCHR WORD. THAT IS:
NRMF==1			;1	NORMAL - SET IF BYTE SIZE SPECIFIED
ASCF==2			;2	ASCII
			;400	IMAGE
			;4000	IMAGE BINARY
			;10000	BINARY
			;100000 DUMP

;AC USE
;P1  -1 OR BYTE SIZE AND MODE OF PREVIOUS COPY IN GROUP TO SAME DEST
;P2  - # BYTES PER PAGE WHEN COPYING BY BYTES
;P3  BYTE # OF EOF OF DISK SOURCE, # BYTES COPIED TO DSK DEST
;Q1, Q2   SEE 2 PAGES HENCE
;A, B, AND Q3 ALSO USED LOCALLY
;SPEAK COMMAND = COPY (FILE) TTY: (TO) SYSTEM:SYSJOB.COMMANDS

.SPEAK::NOISE <TO SYSJOB>
	CONFIRM
	SETZM MCOJFN		;SET UP SOME THINGS FOR COPY CODE
	SETZM TYPGRP
	HRROI B,[ASCIZ /SYSTEM:SYSJOB.COMMANDS/]
	CALL TRYGTS		;GET OUTPUT JFN
	 ERROR < Can't get JFN on SYSTEM:SYSJOB.COMMANDS>
	MOVEM A,OUTDSG
	HRROI B,[ASCIZ /TTY:/]
	CALL TRYGTJ		;INPUT FROM TTY
	 ERROR <Can't get JFN on TTY:>
	HRRZ A,JBUFP		;GET POINTER TO JFN JUST STACKED
	MOVEM A,INIFH1		;MAKE SINGLE JFN IN LIST
	MOVEM A,INIFH2
	TYPE < [Please type SYSJOB commands - end with ^Z]
>
	MOVEI Q1,CP%SPE		;IDENTIFY COMMAND
	CALL COP1A		;GO PERFORM COPY
	MOVEI A,0		;SET TO WAKE JOB 0
	TWAKE			;...
	  ERJMP CJERRE		;JSYS LOSAGE
	RET			;RETURN
;COPY/APPEND

.COPY::	SETOM TYPGRP		;TYPE ALL FILES
	SETOM SPRSED		;SUPERSEDE ALWAYS IS THE DEFAULT
	NOISE <FROM>
	TLZ	Z,F2!F1		;NOT APPEND, AND NOT TYPE
	CALL .INFG		;GET INPUT FILE GROUP DESCRIPTOR
				;ALLOWS *'S, AND COMMAS IF THEY ARE
				;IMMEDIATE FILE NAME TERMINATOR.
	NOISE <TO>
	CALL MFOUT		;MULTI FILE OUTPUT TERM
	SETOM TYPING		; MAYBE TYPING
	MOVEI Q1,CP%COP		;IDENTIFY FLAVOR
	JRST COP1A

.APPEN::SETOM TYPGRP		;TYPE ALL FILES
	NOISE <SOURCE FILE>
	TLO	Z,F2		;SAY APPEND, NOT COPY
	CALL .INFG		;GET INPUT FILE GROUP DESCRIPTOR
				;ALLOWS *'S, AND COMMAS IF THEY ARE
				;IMMEDIATE FILE NAME TERMINATOR.
	NOISE <TO>
	MOVSI A,-1		;NO DEFAULTS FOR OUTPUT
	MOVEI B,(GJ%MSG)	;PRINT NEW FILE, ETC.
	CALL SPECFN
	 JRST CERR
	MOVEM A,OUTDSG
	HRRZ A,OUTDSG
	DVCHR
	LDB D,[POINT 9,B,17]
				;NO OTHER DEVICES WORK 12/3/70
	CAIE D,.DVNUL		;DEVICE NULL IS OK
	JUMPN D,[ERROR <Destination file must be on disk>]
	SETZM MCOJFN		;SAY NOT MULTI FILE OUTPUT
	MOVEI Q1,CP%APP		;SAY IT'S AN APPEND COMMAND
COP1A:	TRVAR <CERRF,<CFBUF,EXTSIZ>,POJFLG,<TADBLK,TADLEN>,<TTBLK,10>,SAVPN,SRCTYP,DESTYP,PREPAG,SCRF,COPFLG>
	SETZM COPFLG		;ASSUME NOT A COPY COMMAND
	CAIN Q1,CP%COP		;IS THIS TRUE?
	 SETOM COPFLG		;NO
	CAIE Q1,CP%APP		;APPEND?
	CAIN Q1,CP%COP		;OR COPY?
	CAIA			;YES
	JRST COPFL		;NO, CONFIRMATION DONE
	CALL SPRTR		;ANALYZE TERMINATOR, READING MORE IF NEC.
	IFSKP.
	 JRST COPFL		;NO SUBCOMMANDS NEEDED
	ENDIF.
	CAIE Q1,CP%APP		;APPEND COMMAND?
	IFSKP.
	 SUBCOM $APPEN		;YES. GET SUBCOMMANDS
	 JRST COPFL		;DONE.
	ENDIF.	 
	SUBCOM $COPY		;READ SUBCOMMANDS
COPFL:	SETO P1,		;SAY NO PREVIOUS COPY IN GROUP
	MOVE A,JBUFP
	MOVEM A,.JBUFP		;SAVE ALL JFNS SO FAR

;TOP OF LOOP OVER INPUT FILE NAMES

COPFLN:	CALL RLJFNS		;RELEASE ANY TEMPORARY JFNS
	IORM A,CERRF		;ACCUMULATE ERRORS DURING THIS FILE
	CALL CTPOK		;TYPE OK IF APPROPRIATE
	SETZM CERRF		;NO ERROR YET
	TLZ Z,F4		;OK SO FAR
	CALL NXFILE		;CHECK FOR NON-EX FILE TERM
	 JRST [	SKIPE INIFH1	;ALL TERMS DONE?
		JRST COPFLN	;NO, NEXT
		JRST COPFLE]	;YES, DONE
	CALL TYPIF		;TYPE INPUT FILE NAME IF PROCESSING GROUP

;WHEN OUTPUT FILE GROUP DESCRIPTORS IMPLEMENTED, DETERMINE HERE
;THE DESTINATION, AND SETO P1, UNLESS THE SAME AS BEFORE.

	MOVE A,COPFLG		;GET STATUS OF COPY FLAG FOR MFSET
	CALL MFSET		;SET UP JFN FOR MULTI FILE COPY
	 JRST MCOERR		;ERROR DETECTED, MESSAGE ALREADY PRINTED
	SETZM POJFLG		;ASSUME NOT OUTPUTTING TO PRIMARY JFN
	MOVE A,OUTDSG
	CAMN A,COJFN		;QUICK CHECK HERE
	JRST ISPOJ		;WIN
	DVCHR
	LDB D,[POINT 9,B,17]
	HLL D,C
	MOVE A,COJFN
	DVCHR
	LDB B,[POINT 9,B,17]
	HLL B,C
	CAMN B,D		;SAME DEVICE?
ISPOJ:	SETOM POJFLG		;YES, OUTPUTTING TO PRIMARY JFN
;COPY/APPEND...
;CHOOSE MODE AND BYTE SIZE FOR COPY/APPEND AS A FUNCTION OF
;DEVICES AND SUBCOMMANDS GIVEN.

;AC USE
; RH Q1: BYTE(6) READ MODE,WRITE MODE,BYTE SIZE
; Q2: DISC SOURCE BYTE SIZE

;SET UP Q1 PER SUBCOMMAND, IGNORING FOR THE MOMENT WHETHER MODE
; IS LEGAL FOR DEVICES.

	SETZ Q1,		;FOR NO SUBCOMMAND, BYTE SIZE IS DEFAULTED LATER
	TRNE Z,1		;BYTE SIZE SPECIFIED?
	MOVE Q1,BYTSIZ		;LOAD THE BYTE SIZE, MODE ZERO
	TXNE Z,ASCF
	MOVEI Q1,010107
	TRNE Z,400
	MOVEI Q1,101044
	TRNE Z,4000
	MOVEI Q1,131344
	TRNE Z,10000
	MOVEI Q1,141444
;COPY/APPEND...
;DETERMINING MODE-BYTESIZE...
;FOR EACH FILE, DO A "DVCHR" TO GET TYPE NUMBER AND TO SEE IF MODE
; IS LEGAL FOR DEVICE.  CHANGE MODE TO 0 IF NOT LEGAL.
;DESTINATION

	HRRZ A,OUTDSG
	DVCHR
	TXNN B,DV%OUT
	ERROR <%1H: Can't do output>
	LDB D,[POINTR B,DV%TYP]
	MOVEM D,DESTYP		;REMEMBER DEVICE TYPE
	CAIE D,.DVDSK		;IS IT A DISK?
	TLO Z,F4		;NO - SET FLAG
	TRZ B,.DVDES
	TRNN Z,(B)		;SKIP IF MODE SUBCOM GIVEN & OK FOR THIS DEVICE
	JRST [	TRZ Q1,007700	;WRITE IN MODE 0
		TRNN B,DV%M0	;CAN DEVICE USE MODE 0 ?
		ERROR <%1H: Can't do normal mode output>
		JRST .+1]

;SOURCE

	HRRZ A,@INIFH1
	DVCHR
	TXNN B,DV%IN
	ERROR <%1H: Can't do input>
	LDB C,[POINTR B,DV%TYP]
	MOVEM C,SRCTYP		;REMEMBER DEVICE TYPE
	CAIE C,.DVDSK		;OUTPUT A DISK?
	TLO Z,F4		;NO - SET FLAG
	CAIN C,.DVTTY		;INPUT A TERMINAL?
	SETOM POJFLG		;YES - SET FLAG
	TRZ B,.DVDES
	TRNN Z,(B)		;SUBCOMMAND GIVEN & OK ?
	JRST [	TRZ Q1,770000	;READ IN MODE 0
		TRNN B,DV%M0	;CAN DEVICE USE MODE 0?
		ERROR <%1H: Can't do normal mode input>
		JRST .+1]
				;ALSO FOR DISK SOURCE GET BYTE SIZE IN Q2
	JUMPN C,COP2A
	HRRZ A,@INIFH1
	MOVE B,[XWD 1,.FBBYV]	;BYTE SIZE IN B6-11
	MOVEI C,Q2
	CALL $GTFDB		;DO GTFDB, NO SKIP ON NO ACCESS
	ERROR <Access to source not allowed>
	LDB Q2,[POINTR Q2,FB%BSZ]
COP2A:
;COPY/APPEND...
;DETERMINING MODE-BYTESIZE...

;IF MODE SUBCOMMAND IS ACCEPTABLE TO ONE DEVICE,
;IT IS ACCEPTED AND MODE 0 USED FOR OTHER DEVICE, PROVIDED OTHER
; DEVICE WILL ACCEPT THE BYTE SIZE (ONLY TTY AND LPT ARE RESTRICTED).
;IF MODE IS ACCEPTABLE TO NEITHER, ACTION DEPENDS ON SUBCOMMAND;
; IF UNACCEPTABLE A WARNING MESSAGE IS TYPED AND DEFAULT EXECUTION
; PROCEEDS, SO THAT A WHOLE GROUP COPY DOESN'T GET ABORTED.

	TRNN Z,177777		;ANY MODE SUBCOMMANDS GIVEN?
	JRST COPDEF		;NO, GO DEFAULT MODE AND BYTE SIZE
	TXNN Z,NRMF		;MODE 0 REQUESTED, OR
	TRNE Q1,777700		;EITHER MODE NON-0?
	JRST COP3		;YES, SUBCOMMAND ACCEPTABLE TO ONE DEVICE

;SUBCOMMAND-DEPENDENT ACTION FOR SBCMD WHOSE MODE IS LEGAL FOR
;NEITHER SOURCE NOR DESTINATION DEVICE

	TXNE Z,ASCF
	JRST [	MOVEI Q1,7	;ASCII ALWAYS LEGAL, USE 0-7.
		JRST COP3]
	TRNN Z,4000		;TREAT "IMAGE BINARY" AS "BINARY"
	TRNE Z,10000
	JRST [	MOVEI Q1,44	;"BINARY", USE 0-36, LEGAL EXCEPT FOR
		JRST COP3]	;TTY OR LPT, DETECTED AT COP3.
				;ONLY IMAGE GETS THRU TO HERE
	JRST COPDF1		;GO TYPE MESSAGE AND DEFAULT
				;IMAGE IS NOT INTERPRETED FOR DEVICES OTHER THAN PAPER
				;TAPE BECAUSE ITS BYTE SIZE WILL PRESUMABLY BE
				;DIFFERENT WHEN IT IS DEFINED FOR OTHER DEVICES.

;IF HERE, ALL SET EXCEPT SUBCOMMAND MAY HAVE SPECIFIED A BYTE SIZE
;ILLEGAL FOR DEVICE. CHECK FOR THAT.

COP3:	LDB B,[POINT 6,Q1,35]	;CHOSEN BYTE SIZE
	MOVE C,SRCTYP
	CAIE C,12
	MOVEM D,DESTYP		;GET DEVICE TYPE OF DESTINATION
	CAIN D,12
	JRST [	CAIE B,7	;TTY TAKES 7 OR 8 ONLY
		CAIN B,10
		JRST .+1
		JRST COPDF1]	;TYPE MESSAGE AND DEFAULT
	CAIN D,7		;LPT TAKES 7 ONLY
	CAIN B,7
	JRST COP4		;ALL IS OK
				;JRST COPDF1
;COPY/APPEND...
;DETERMINING MODE-BYTESIZE...   DEFAULT CASE...
;NO ACCEPTABLE SUBCOMMAND GIVEN.
;DEFAULT MODE AND BYTE SIZE AS A FUNCTION OF DEVICES USED.
;MODE ALWAYS 0 AT PRESENT.

COPDF1:	TYPE < [Illegal mode subcommand being ignored]
>
COPDEF:	JUMPN D,.+3
	SKIPN SRCTYP
				;DISK TO DISK USES SOURCE BYTE SIZE
	SKIPA Q1,Q2		;DISK SOURCE BYTE SIZE IS IN Q2
				;MOST OTHER CASES USE 0-36
	MOVEI Q1,^D36
				;IF TTY: OR LPT: INVOLVED, USE 0-7
	MOVE C,SRCTYP
	CAIN C,.DVCDR		;READING FROM CARD READER?
	MOVEI Q1,7		;YES, USE BYTE SIZE OF 7
	CAIE C,12
	CAIN D,12
	JRST .+2
	CAIN D,7
	JRST [	MOVEI Q1,7
		JRST COP4]
;COPY/APPEND...
;DETERMINING MODE-BYTESIZE...   DEFAULT CASE...
;SPECIAL CASES FOR PAPER TAPE

	CAIE C,4		;PTR
	JRST [	CAIE C,.DVMTA	;MAGTAPE?
		JRST COPDF3
		HRRZ A,@INIFH1
		CALL LBLSKP	;LABELED?
		JRST COPDF3
		CAIE A,.LTANS	;ANSI-ASCII?
		CAIN A,.LTEBC	;EBCDIC?
		SKIPA		;YES, ASCII OR EBCDIC
		JRST COPDF3
		MOVEI Q1,7	;YES, SAY BYTESIZE 7
		JRST COPDF3]
	CAIN D,5		;PTP
	JRST [	MOVEI Q1,^D8	;USES 0-8 TO DUPLICATE PAPER TAPE
		JRST COP4]
	HRRZ B,OUTDSG		;PTR TO OTHER DEVICES DEPENDS ON DEST EXT
	JRST COPDF4
COPDF3:	CAIE D,5		;PTP
	JRST COPDF6
	JUMPE C,[MOVE Q1,Q2	;DSK TO PTP
		CAIN Q2,7	;IF SC BYTE SIZE 7, USE IT, NO MESSAGE.
		JRST COP4
		CAIE Q2,10	;IF 8, USE IT, TYPE MESSAGE
		MOVEI Q1,^D36	;OTHERWISE ASSUME 36 AND TYPE MESSAGE
		JRST COPDF5]	;NOTE THAT CAN'T TRUST SIZE OF 36 IN
				;FILE BECAUSE OTHER SIZES CAN BECOME
				;36 IF FILE IS COPIED TO DTA AND BACK.
	HRRZ B,@INIFH1		;OTHER DEVICES TO PTP, DEPENDS ON SC EXT
COPDF4:				;ONE IS PAPER TAPE, OTHER ISN'T. USE 0-36 FOR FILES
				;WITH EXTENSION OF .REL OR .SAV, 0-7 FOR OTHERS.
				;TYPE MESSAGE.  JFN OF NON-PAPERTAPE DEVICE NOW IN B.
	HRROI A,CFBUF		;SOME STRING SPACE
	SETZM CFBUF		;MAKE SURE NULLS AFTER EXTENSION
	MOVX C,FLD(.JSAOF,JS%TYP)	;GET FILE TYPE
	JFNS
	 ERCAL JERRE
	MOVE A,CFBUF
	CAME A,[ASCIZ /REL/]
	CAMN A,[GETSAVE()]
	JRST .+2		;REL OR SAV, USE 36 (ALREADY IN Q1)
	MOVEI Q1,7		;OTHER EXT OR NON-DIR DEVICE, USE 0-7
				;A MARGINAL ASSUMPTION HAS BEEN MADE ABOUT PAPER TAPE,
				;TYPE EXPLANATORY MESSAGE.
COPDF5:	TYPE < [>
	CAIN Q1,7
	TYPE <ASCII>
	CAIN Q1,10
	TYPE <IMAGE>
	CAIN Q1,44
	TYPE <BINARY>
	TYPE < mode assumed.]
>
				;JRST COP4
COPDF6:				;ADD CASES TO THE DEFAULTING STUFF HEHE
COP4:				;NOW HAVE MODES AND BYTE SIZE IN Q1
;COPY/APPEND...
;HAVE FINISHED CHOOSING MODE-BYTESIZE.
;OPEN FILES NOW, SO FFUFP WILL WORK.

				;SOURCE
	LDF B,OF%RD		;OPEN FOR READ
	LDB A,[POINT 6,Q1,23]	;GET READ MODE FROM Q1
	DPB A,[POINT 4,B,9]
	MOVE C,SRCTYP
	CAIN C,.DVPTR		;PAPER TAPE READER?
	CAIE A,10		;YES, MODE 10?
	CAIA			;NO, USE SPECIFIED BYTE SIZE
	SKIPA A,[8]		;YES, USE 8 BIT BYTES FOR IMAGE MODE
	LDB A,[POINT 6,Q1,35]	;BYTE SIZE
	DPB A,[POINT 6,B,5]
	HRRZ A,@INIFH1		;JFN
	TXO B,OF%PLN		;PASS LINE SEQUENCE NUMBERS
	CAIN C,.DVTTY		;OPEN TERMINAL FOR WRITE ALSO, SO TEXTI WILL WORK
	TXO	B,OF%WR
	CALL OPENX		;OPENF WITH CHECK FOR PRI IO FILES
				;AND FANCY ERROR MESSAGES
				;DESTINATION
	 JRST MCOERR		;FAILED, ERROR PRINTED, GO TO NEXT FILE
	HRRZ A,OUTDSG
	GTSTS
	JUMPGE B,COP5A
				;DEST ALREADY OPEN, ITS ANOTHER COPY IN GROUP, SEE IF
				;MODE-BYTESIZE CONSISTENT, CHANGE WHERE POSSIBLE
	TLO Z,F3		;SAY IT WAS ALREADY OPEN
	MOVE B,Q1		;MODES-BYTESIZE CHOSEN FOR THIS COPY
	XOR B,P1		;COMPARE TO THOSE USED FOR LAST COPY
	CAME P1,[EXP -1]	;First time, always OK.
	TRNN B,7777		;OUTPUT MODE & SIZE THE SAME?
	JRST COP5B		;YES, ALL IS OK
	MOVE D,DESTYP
	JUMPN D,.+2		;IF DEST NOT DSK, CHANGE ILLEGAL
	TRNE B,7700		;FOR DSK SIZE CAN CHANGE BUT MODE CAN'T
	ERROR <Illegal mode or byte size change,
 multiple source copy cannot procede>
	LDB B,[POINT 6,Q1,35]
	JUMPE B,[TYPE < [Byte size = 0, will use 36]>
		MOVEI B,^D36
		JRST .+1]
	SFBSZ
	 CALL JERR
	JRST COP5B

COP5A:				;DEST WASN'T OPEN (NORMAL CASE), OPEN IT
	TLZ Z,F3		;SAY JUST OPENED (HENCE PAGE COPY OK)
	LDF B,OF%WR		;"WRITE" BIT FOR OPENF
	TLNE Z,F2		;SKIP IF "COPY" NOT "APPEND"
	LDF B,OF%APP		;"APPEND" BIT FOR OPENF
	LDB A,[POINT 6,Q1,29]	;GET WRITE MODE FROM Q1
	DPB A,[POINT 4,B,9]
	MOVE C,DESTYP
	CAIN C,.DVPTP		;PAPER TAPE PUNCH?
	CAIE A,10		;YES, MODE 10?
	CAIA			;NO, USE SPECIFIED BYTE SIZE
	SKIPA A,[8]		;YES, USE 8 BIT BYTES FOR IMAGE MODE
	LDB A,[POINT 6,Q1,35]	;BYTE SIZE
	DPB A,[POINT 6,B,5]
	HRRZ A,OUTDSG		;JFN
	CALL OPENX		;OPEN THE OUTPUT FILE
	 JRST MCOERR		;FAILED, DON'T BOMB ENTIRE COPY JUST FOR THIS ONE FILE!
	SETZM SCRF		;NOT STRIPPING CARRIAGE RETURNS
	MOVE D,DESTYP		;GET DEVICE TYPE
	CAIN D,.DVMTA		;MAGTAPE?
	JRST [	MOVE A,OUTDSG	;YES, SEE IF LABELED
		CALL LBLSKP
		 JRST .+1	;NOT
		TXNN Z,ASCF	;WRITING IN ASCII?
		JRST .+1	;NO
		MOVE A,OUTDSG	;PREPARE TO SET MODE OF TAPE
		MOVEI B,.MOSMV	;SAY WE'RE SETTING MODE
		MOVEI C,.TPFNC	;SAY THERE ARE NO FORMATTERS (ONE LINE OF TEXT
				;ASSUMED PER TAPE RECORD)
		MTOPR
		SETOM SCRF	;REMEMBER TO STRIP CRLF'S AND USE SOUTR
		JRST .+1]
COP5B:	MOVE P1,Q1		;SAVE MODE AND BYTE SIZE (NEEDED IF ANOTHER
				;COPY TO SAME FILE OCCURS IN GROUP)
;COPY/APPEND...
;HAVE ESTABLISHED MODE-BYTESIZE AND OPENED FILES.
;NOW DECIDE WHETHER A COPY WITH DISK SOURCE IS TO BE DONE BY BYTES
;OR PAGES (SET F1 FOR PAGES), BECAUSE BYTES CASE REQUIRES SPECIAL
;CHECKS BELOW.

	TLZ Z,F1		;SAY BYTES FOR NOW
	SKIPE SRCTYP
	JRST COP6Z		;NON-DISC SOURCE, NO SPECIAL CHECK
	MOVE D,DESTYP
	TLNN Z,F2+F3		;"APPEND" COMMAND AND OUTFILE ALREADY OPEN
				;(GROUP CASE) CAUSE BYTE COPYING
	JUMPE D,[		;NON-DISK DEST ALWAYS REQUIRES BYTE COPY.
				;BUT IF HERE, DEST IS ALSO DISK, CAN COPY BY
				;PAGES.
		TRNN Z,177777	;DON'T CPY BY PAGES IF MODES SPECIFIED
		TLO Z,F1	;SAY COPY BY PAGES
		JRST COP6Z]	;SKIP SPECIAL CHECK
;COPY/APPEND...
;SPECIAL WARNING CHECKS FOR COPYING/APPENDING FROM DSK BY BYTES.
;(OTHER CASES BRANCHED AROUND THIS CODE ABOVE.)
;CHECK FOR HOLES NOT BEYOND EOF AND ANY PAGES BEYOND EOF IN SOURCE FILE
; AND TYPE WARNING MESSAGES IF FOUND.

				;GET PAGE # OF LAST DATA BYTE INTO B
	HRRZ A,@INIFH1
	SIZEF			;BYTE # OF EOF INTO B
	 CALL JERR
	SUBI B,1		;CONVERT BYTE # OF EOF TO BYTE # LAST DATA BYTE
	JUMPL B,COP6C		;IF IT WAS 0, ITS NOW -1, WHICH IS PAGE #.
	MOVEI C,^D36
	IDIV C,Q2		;36 / BYTESIZE = # BYTES PER WORD
	IDIV B,C		;BYTE # / THAT   MAKES IT WORD #
	IDIVI B,1000		;MAKE IT PAGE # OF LAST DATA BYTE

;TEST FOR FIRST FREE PAGE NOT BEING AFTER LAST DATA BYTE'S PAGE

COP6C:	HRRZ A,@INIFH1
	FFFFP			;FIND FIRST FREE FILE PAGE
	CAMN A,[-1]
	JRST .+3		;NO FREE PAGES IN FILE
	CAIL B,(A)
	TYPE < [Holes in file]
>
				;CHECK FOR USED PAGES AFTER LAST DATA BYTE PAGE
	HRL A,@INIFH1
	HRR A,B			;LAST DATA BYTE'S PAGE
	CALL $FNUFP		;INCREMENT A AND FIND NEXT USED PAGE
	JUMPE A,.+2		;0 RETURNED MEANS NO USED PAGE
	TYPE < [Pages after EOF will not be copied]
>
COP6Z:
;COPY/APPEND...
;IF WE WISH TO CONFIRM EACH COPY IN GROUP, HERE IS WHERE TO DO IT.

;HERE WE TYPE <CRLF> IF OUTPUTTING TO PRIMARY JFN
;THIS IS TO END FILE NAME PREVIOUSLY TYPED OUT

	SKIPN POJFLG
	JRST COP6Y		;SKIP IF TTY NOT INVOLVED
	SKIPN TYPGRP		;PRINT IF FORCED
	TLNE Z,GROUPF		;BUT ONLY IF NAME TYPED BEFORE
	TYPE <

>
COP6Y:

;NOW, AT LAST, WE ARE READY TO COPY. WELL, ALMOST.
;THERE ARE SEVERAL CASES:
; DISK TO DISK,
;	DONE BY PAGES, REPRODUCING "HOLES" AND PAGES AFTER BYTE EOF
; TTY TO ANYTHING, TERMINATED BY ^Z
; DISK TO OTHER DEVICE OR DISK-DISK FOR APPEND OR OUTFILE ALREADY OPEN,
;	PAGE READ AND BYTE WRITE.
; OTHER DEVICE TO DISK, USUALLY BYTE READ AND PAGE WRITE.
; ANY OTHER COMBINATION, DONE ENTIRELY BY BYTES.

				;COMPUTE NEGATIVE NUMBER OF BYTES PER PAGE INTO P2
				;(DONE NOW CAUSE CAN CLOBBER P3)
	MOVEI P2,^D36		;# BITS PER WORD
	LDB P3,[POINT 6,Q1,35]	;# BITS PER BYTE
	IDIV P2,P3		;FORM # BYTES PER WORD
	IMUL P2,[-1000]		;FORM - # BYTES PER PAGE
				;GET DISK SOURCE BYTE EOF IN P3
	HRRZ A,@INIFH1
	MOVE C,SRCTYP
	JUMPN C,COP7A
	SIZEF			;GETS BYTE # OF EOF IN FILE'S BYTESIZE INTO B
	 CALL JERR

;TRANSLATE FROM BYTE SIZE OF FILE TO BYTE SIZE OF COPY.
;NEW PTR = (OLD PTR*(36/NEW BYTE SIZE))/(36/OLD BYTE SIZE)
; WITH ALL DIVISIONS INTEGER AND OUTERMOST ONE ROUNDED UP

	MOVEI C,^D36
	IDIV C,Q2		;Q2: SOURCE FILE (OLD) BYTE SIZE
	MOVE P3,C
	MOVEI C,^D36
	LDB D,[POINT 6,Q1,35]	;COPY (NEW) BYTE SIZE
	IDIV C,D
	MUL B,C
	DIV B,P3
	JUMPE C,.+2		;REMAINDER 0 ?
	ADDI B,1		;NO, ROUND UP.
	MOVE P3,B		;BYTE # OF EOF IN COPY BYTE SIZE
COP7A:
	TLNE Z,F1		;COPY BY PAGES FLAG ON?
	JRST PAGES		;YES, GO COPY BY PAGES
;COPY/APPEND...  DISPATCHING TO VARIOUS EXECUTION CASES...
;COPY BY BYTES OR A COMBINATION OF BYTES AND PAGES.

				;HRRZ A,@INIFH1	;ONE JFN IN A
	HRRZ Q2,OUTDSG		;OTHER ALWAYS IN Q2
				;GENERATE POINTER TO BUFFER W PROPER BYTE SIZE IN Q3
	MOVE Q3,[XWD 440000,BUF1] ;P FIELD AND ADDRESS
	DPB Q1,[POINT 6,Q3,11]	;BYTE SIZE = S FIELD
				;NOW DISPATCH TO THE VARIOUS CASES
	MOVE C,SRCTYP
	MOVE D,DESTYP
	CAIN C,.DVTTY		;SOURCE TTY: ?
	JRST COPTTY		;YES, SPECIAL CODE TO END ON ^Z.
	SKIPE SCRF		;STRIPPING CRLF'S?
	JRST COPBY		;YES, SO DO BY BYTES
	JUMPE C,CPGBYT		;JUMP IF SOURCE DISK
	JUMPN D,COPBY		;JUMP IF DEST NOT DISK
	TLNE Z,F2+F3		;PG OUTPUT OK IF NOT "APPEND" AND
	JRST COPBY		;OUTFILE WASN'T ALREADY OPEN (GROUP)
	JRST CBYTPG		;USE PAGES TO WRITE ON DISK

;COPY BY BYTES WITH TELETYPE SOURCE
;DO BYTE BY BYTE, WATCHING FOR ^Z TERMINATOR

COPTTY:	MOVEI B,CTTEOF		;WHERE TO GO ON EOF PSI
	MOVEM B,EOFDSP		;(DON'T THINK IT CAN OCCUR 11/20/70)
	MOVEI B,4		;ONLY 4 WORD TEXTI HERE
	MOVEM B,TTBLK
	MOVE B,[RD%BRK+RD%BEL+RD%JFN]
	MOVEM B,1+TTBLK
	MOVEM A,2+TTBLK
	HRLM A,2+TTBLK
	SETZM 5+TTBLK
	SETZM 6+TTBLK
COPTT0:	MOVE B,[POINT 7,BUF0]	;INPUT TO FREE PAGE
	MOVEM B,3+TTBLK
	MOVEI B,1000*5		;MAX NUMBER OF CHRS
	MOVEM B,4+TTBLK
COPTT1:	MOVEI A,TTBLK
	TEXTI
	 CALL JERR
	LDB B,3+TTBLK		;GET LAST BYTE STORED
	CAIN B,CTRLZ
	JRST COPTT2
	CAIE B,.CHLFD		;END OF LINE?
	JRST COPTT1		;NO, READ MORE BEFORE DUMPING (IN CASE SCRF)
	CALL COPTTS		;DUMP STRING
	JRST COPTT0		;GET MORE

COPTTS:	SKIPN SCRF		;STRIPPING CRLF'S?
	JRST COPNCR		;NO
	MOVNI A,1		;REMOVE LINEFEED
	ADJBP A,.RDDBP+TTBLK
	MOVEM A,.RDDBP+TTBLK
	AOS .RDDBC+TTBLK	;SAY THERE'S ROOM FOR ONE MORE CHAR NOW
	LDB A,.RDDBP+TTBLK	;GET CHARACTER BEFORE LINEFEED
	CAIE A,.CHCRT		;CARRIAGE RETURN BEFORE LINEFEED?
	JRST COPNCR		;NO
	MOVNI A,1		;YES, REMOVE IT.
	ADJBP A,.RDDBP+TTBLK	;FIX BYTE POINTER TO NO LONGER INCLUDE CR.
	MOVEM A,.RDDBP+TTBLK	;STORE NEW BYTE POINTER
	AOS .RDDBC+TTBLK	;SAY THERE'S ROOM FOR ANOTHER CHAR NOW
COPNCR:	MOVE A,Q2
	MOVE B,[POINT 7,BUF0]
	MOVNI C,1000*5
	ADD C,4+TTBLK		;NUMBER OF BYTES TO SEND
	MOVE D,[SOUT]		;FIRST ASSUME STANDARD OUTPUT
	SKIPE SCRF		;STRIPPING CRLF'S?
	MOVE D,[SOUTR]		;YES, OUTPUT TO INDIVIDUAL RECORD
	JUMPE C,R		;JUST IN CASE NO BYTES
	XCT D
	ERJMP CJERRE		;To catch problems
	RET

COPTT2:	AOS 4+TTBLK		;FUDGE CHAR COUNT TO NOT SEND ^Z
	CALL COPNCR		;NO CRLF TO REMOVE IF JUST TYPED ^Z
CTTEOF:	HRRZ A,2+TTBLK
	HRROI B,[ASCIZ /
/]
	SETZ C,
	SOUT			;CRLF AFTER ^Z
	JRST CBYEF1		;GO DELETE EXTRA PAGES IF DEST IS DSK
;COPY/APPEND...
;COPY/APPEND BY BYTES, NON-TTY-SOURCE CASE
;USE FULL PAGE SINS AND SOUTS FOR SPEED.

COPBY:	MOVEI B,CBYEOF
	MOVEM B,EOFDSP		;WHERE TO GO ON EOF PSI
	SKIPE SCRF		;STRIPPING CRLF'S?
	JRST COPSCR		;YES, USE DIFFERENT LOOP
COPB1:	MOVE B,Q3		;BYTE PTR
	MOVE C,P2		;BYTE COUNT, NEG FOR NO SPECIAL TERM CHARACTER
	SIN			;INPUT A STRING (JFN ALL SET IN A)
				;SIN CAUSES EOF PSI AFTER READING WHATEVER CHARACTERS
				;THERE ARE IF NOT A WHOLE "COUNT"'S WORTH LEFT IN FILE
	EXCH A,Q2		;GET DESTINATION JFN, SAVE SOURCE JFN
	MOVE B,Q3		;BYTE PTR AGAIN
	MOVE C,P2		;SAME COUNT
	SOUT			;OUTPUT STRING
	EXCH A,Q2		;BACK TO SOURCE JFN
	JRST COPB1		;LOOP TILL EOF PSI

;EOF PSI WHILE COPYING BY BYTES (NON-TTY CASE)
;OUTPUT PARTIAL STRING INPUT BEFORE EOF OCCURRED
; (NOTE THAT C IS UPDATED TO REFLECT THOSE BYTES WHICH WERE READ)

CBYEOF:	EXCH A,Q2		;GET DEST JFN
	MOVE B,Q3		;THAT GOOD OLD BYTE PTR
	SKIPN SCRF		;COUNT IS POSITIVE IF STRIPPING CRLF'S
	SUBM P2,C		;CREATE COUNT IN C OF CHARS THAT WERE INPUT
	SKIPE SCRF
	ADD C,P2		;C HAS POSITIVE NUMBER IF STRIPPING CRLF'S
	JUMPE C,.+2		;0 COUNT, NO SOUT!
	SOUT			;OUTPUT THE LAST PART

;IF DESTINATION WAS DISK, DELETE ANY ADDITIONAL PAGES
; (CLOSF DOES NOT DO THIS, BUT WILL LATER ZERO REST OF LAST PAGE).
;TTY CASE JOINS HERE.

CBYEF1:	HRRZ A,OUTDSG
	DVCHR
	LDB A,[POINT 9,B,17]	;DEVICE TYPE 0 IS DSK
	JUMPN A,COPEOF		;IF NOT DISK, DONE HERE
	LDB D,[POINT 6,Q1,35]	;GET BYTE SIZE USED IN COPYING
	HRRZ A,OUTDSG
	RFPTR			;GETS BYTE # OF LAST DATA BYTE IN B
	 CALL JERR
	MOVEI C,^D36
	IDIV C,D		;36/BYTESIZE = # BYTES PER WORD
	IDIV B,C		;BYTE # /THAT = WORD # OF LAST DATA BYTE
	IDIVI B,1000		;MAKE IT PAGE #
	HRR A,B
	HRL A,OUTDSG
CBYEF2:	CALL $FNUFP		;FIND A PAGE
	JUMPE A,COPEOF		;NO MORE PAGES IN FILE, DONE
	MOVE B,A
	SETO A,
	HRLZI C,1
	PMAP			;DELETE THE PAGE
	MOVE A,B
	JRST CBYEF2
;COPY INDIVIDUAL LINES OF TEXT TO INDIVIDUAL OUTPUT RECORDS
;A & Q2/ JFNS, P2/ NEGATIVE COUNT OF BUFFER SPACE, Q3/ POINTER TO BUFFER SPACE

COPSCR:	MOVE B,Q3		;READ DATA INTO BUFFER SPACE
	MOVN C,P2		;USE POSITIVE COUNT SO WE CAN FIND END OF LINE
	MOVEI D,.CHLFD		;SEARCH FOR END OF LINE
	SIN			;READ NEXT LINE (TRAP TO CBYEOF IF END OF FILE)
	ADD C,P2		;CALCULATE NEGATIVE NUMBER OF BYTES TO OUTPUT
	MOVEI D,.CHNUL		;PUT NULL ON LINEFEED IN CASE BUFFER NOW NULL
	DPB D,B
	MOVNI D,1
	ADJBP D,B		;FIX POINTER TO POINT AT POSSIBLE CR
	AOJE C,COPSC1		;IF ONLY LINEFEED, THERE'S NO CR BEFORE IT!
	LDB B,D			;NOW GET CHARACTER BEFORE LINEFEED
	CAIE B,.CHCRT		;CARRIAGE RETURN?
	JRST COPSC1		;NO
	MOVEI B,.CHNUL		;YES, NULLIFY IT IN CASE BUFFER NOW NULL
	DPB B,D
	AOJ C,			;SHRINK BUFFER DUE TO CR (MIGHT BE 0 LENGTH NOW!)
COPSC1:	EXCH A,Q2		;GET OUTPUT JFN, SAVE INPUT JFN
	MOVE B,Q3		;POINT AT BUFFER
	SOUTR			;WRITE A RECORD WITHOUT THE END-OF-LINE (MIGHT BE 0 IN C)
	EXCH A,Q2		;GET INPUT JFN AGAIN
	JRST COPSCR		;LOOP FOR REST OF DATA
;COPY/APPEND...
;COPY FROM DISK, READING BY PAGES AND WRITING BY BYTES.
;TRANSFERS ZEROS FOR HOLES OR BEYOND BYTE EOF.
;ADDED TO SPEED UP DISK TO LPT COPY.
;AT ENTRY: A,Q2: JFNS
;	Q3: BYTE PTR TO BUFFER PAGE
;	P2: - # BYTES / PAGE
;	P3: BYTE # OF EOF
;ALSO:	A: SOURCE JFN,,PAGE #

CPGBYT:	SETOM PREPAG		;INITIALIZE PREFAULTED PAGE WORD
	HRLZ A,@INIFH1
CPGBY2:	MOVEM A,SAVPN		;SAVE PAGE NUMBER
	CALL PREFLT		;PERHAPS IT'S TIME FOR PREFAULTING
	MOVE A,SAVPN		;RESTORE PAGE NUMBER
	RPACS
	TLNN 2,(1B5)		;PAGE EXISTS?
	JRST .+4		;NO, DON'T MAP IT
	MOVE B,[XWD .FHSLF,<BUF1>B44]
	LDF C,PM%RD
	PMAP			;MAP IN THE PAGE

;HAVE A PAGE IN SOURCE FILE, DECIDE WHAT TO DO WITH IT BY
;COMPARING PAGE # AND FILE'S BYTE EOF

	HRRZ C,A		;PAGE #
	IMUL C,P2		; - BYTE # OF FIRST BYTE IN PAGE
	ADD C,P3		;P3: BYTE # OF EOF
	MOVN C,C		;FORM - # BYTES IN OR BEYOND THIS PAGE
	JUMPGE C,CPBEOF		;NONE, DONE.

;TRANSFER PARTIAL PAGE IF THIS IS EOF PAGE, ELSE WHOLE PAGE.

	CAMGE C,P2		;- # BYTES/PAGE
	MOVE C,P2		;MAXIMUM TRANSFER
	RPACS
	TLNN 2,(1B5)		;PAGE EXISTS?
	JRST CPGBY4		;NO, USE ZEROS

;OUTPUT # BYTES IN C

	EXCH A,Q2		;GET DEST JFN
	MOVE B,Q3		;STRING PTR TO BUFFER
	SOUT			;STRING OUTPUT
CPGBY3:	EXCH A,Q2
	AOJA A,CPGBY2		;DO NEXT PAGE

CPGBY4:	EXCH A,Q2
	SETZ 2,
	BOUT			;DO PAGE WORTH OF ZEROS
	AOJL C,.-1
	JRST CPGBY3

;COPY BY PAGES-BYTES EOF. CLEAR BUFFER.

CPBEOF: HRRZ A,OUTDSG		;GET OUTPUT JFN
	DVCHR
	LDB D,[POINTR B,DV%TYP] ;GET DEVICE TYPE
	CAIE D,.DVTTY		;IS IT TTY ?
	 JRST NXLF		;NO - SKIP THIS
	MOVN B,P2		;GET THE BYTES # IN A PAGE
	MOVE A,P3		;YES - GET THE NUMBER OF BYTES
	IDIV A,B		; IN THE LAST FILE PAGE IN AC B
	CAIN B,0		;END RIGHT ON A PAGE BOUNDARY?
	MOVN B,P2		;YES - SET TO THE MAXIMUM NUMBER OF BYTES
	IBP B,Q3		;POINT TO THE LAST CHARACTER OF THE FILE
	LDB A,B			;GET THE LAST CHARACTER
	CAIN A,.CHLFD		;IS IT A LINEFEED?
	JRST NXLF		;YES - O.K.
	MOVE A,Q2		;NO - GET DESTINATION JFN
	HRROI B,[15B6+12B13]	;FORCE OUT A CRLF TO ENSURE THAT THE
	SETZ C,			; CURSOR ENDS AT THE LEFT MARGIN
	SOUT
NXLF:	SETO A,
	MOVE B,[XWD .FHSLF,<BUF1>B44]
	SETZ C,
	PMAP
	HRRI B,<BUFPRE>_-9	;GET RID OF PREFAULT PAGES
	MOVE C,[PM%CNT+NPRE]	;COUNT BIT+THE COUNT
	PMAP
	JRST COPEOF
;COPY/APPEND...
;COPY NON-DISK TO DISK IN NON-APPEND, NON MULTIPLE SOURCE CASE.
;USES BYTES FOR INPUT, PAGES FOR OUTPUT.
;ADDL ACS: Q2: DEST JFN,,PAGE #
;	P3: # BYTES TRANSFERRED+1, USED TO SET DEST EOF PTR.

CBYTPG:	HRLZ Q2,OUTDSG
	MOVEI B,CBPGEF
	MOVEM B,EOFDSP		;WHERE TO GO ON EOF
	SETZ P3,
CBYPG2:	SETO A,			;CLEAR BUFFER AT TOP OF LOOP TO MAKE SURE
	MOVE B,[XWD .FHSLF,<BUF1>B44] ;...OF EOF PAGE IS 0
	SETZ C,
	PMAP
	HRRZ A,@INIFH1
	MOVE B,Q3
	MOVE C,P2		;NEG # BYTES/PAGE
	SUB P3,C		;COUNT BYTES TRANSFERRED
	SIN			;READ A PAGE'S WORTH OF BYTES
	MOVE B,Q2
	MOVE A,[XWD .FHSLF,<BUF1>B44]
	LDF C,PM%WT
	PMAP			;MAP OUT THE PAGE
	AOJA Q2,CBYPG2		;NEXT PAGE AND LOOP

;BYTES-PAGES END OF FILE

CBPGEF:	ADD P3,C		;ADJUST FOR UNUSED PART OF BYTE COUNT
	CAMN C,P2		;WHOLE PAGE UNUSED?
	SKIPA A,[-1]		;YES, PUT NO PAGE IN DESTINATION
	MOVE A,[XWD .FHSLF,<BUF1>B44]
	MOVE B,Q2
	LDF C,PM%WT
	PMAP			;MAP OUT LAST PAGE OR DELETE PAGE

;FAKE THINGS UP AND ENTER PAGES-PAGES ROUTINE TO DELETE RESET OF DEST
;AND SET EOF AND BYTE SIZE

	SETZ D,			;SAYS NO MORE SOURCE "PAGES"
	JRST PAGE5A
;COPY/APPEND...
;COPY DISK TO DISK BY PAGES
;NOTE THAT BYTE SIZE IN Q1 MUST BE PRESERVED

NPAGES:	^D25			;MOUTH SIZE (LOOK HOW MUCH I GOT IN ONE BITE, MA!)
PAGES:	MOVE A,@INIFH1		;GET SOURCE JFN
	MOVE B,OUTDSG		;AND DESTINATION JFN
	CALL DSKCPY		;COPY THE DATA
	MOVE C,NPAGES		;GET SIZE OF BUFFER
	LSH C,1			;THERE ARE TWO OF THEM
	IORX C,PM%CNT		;REPEATE COUNT
	HRROI A,-1		;SAY REMOVING PAGES
	MOVE B,[.FHSLF,,BUF0PN]	;START FROM BEGINNING OF BUFFER
	PMAP			;REMOVE (ONLY SO CLOSF WILL SUCCEED)
				;POSSIBLE SPEEDUP WOULD BE TO NOT DO
				;CLOSF UNTIL JFN'S WERE USED UP.  THAT
				;WOULD MEAN ONLY HAVING TO DO THIS
				;PMAP ABOUT ONCE PER 100 FILES (BUT
				;AT LEAST ONCE PER COPY COMMAND)
	JRST PAGES1		;GO PUT ON FINISHING TOUCHES

;DISK TO DISK COPY LOOP.  CALL WITH SOURCE JFN IN A AND DESTINATION
;JFN IN B.
;THIS LOOP DOES NOTHING EXCEPT COPY THE DATA, I.E. DOES NO CLOSF OR
;CHFDB'S.

DSKCPY:	STKVAR <NXTBEG,DESBFR,DESPN,BLTPTR,ENDPTR,SAVBLT,SRCJFN,DESJFN,ENDPT0>
	MOVEM A,SRCJFN
	MOVEM B,DESJFN		;REMEMBER JFN'S
	SETZM NXTBEG		;INITIALIZE NEXT PAGE TO BEGIN BUFFER WITH
	MOVE A,NPAGES		;GET NUMBER OF PAGES
	LSH A,9			;MAKE RELATIVE ADDRESS OF DESTINATION BUFFER
	ADDI A,BUF0		;MAKE ACTUAL ADDRESS
	MOVEM A,DESBFR		;REMEMBER WHERE DESTINATION BUFFER STARTS
	LSH A,-9		;CALCULATE DESTINATION PAGE NUMBER
	MOVEM A,DESPN		;REMEMBER THAT TOO
	ADD A,NPAGES		;CALCULATE FIRST PAGE NUMBER BEYOND DESTINATION BUFFER
	LSH A,9			;MAKE ADDRESS
	SOJ A,			;GET LAST ADDRESS IN DESTINATION
	MOVEM A,ENDPTR		;REMEMBER END OF DESTINATION
	MOVEM A,ENDPT0		;REMEMBER VERSION FOR NORMAL FULL FILE CHUNKS
DSKLUP:	HRL A,SRCJFN		;MAP FROM SOURCE JFN
	HRR A,NXTBEG		;STARTING WITH FIRST PAGE OF NEW GROUP
	MOVE B,[.FHSLF,,BUF0PN]	;MAP INTO OUR BUFFER AREA
	MOVX C,PM%RD!PM%PLD!PM%CNT	;READ, PRELOAD, REPEAT COUNT GIVEN
	HRR C,NPAGES		;DO AS MANY AS OUR BUFFER SIZE
	PMAP			;MAP SOME SOURCE PAGES IN
	 ERJMP [CALL DGETER	;PMAP FAILED, SEE WHY
		CAIE A,LNGFX1	;OFF INTO NONEXISTENT SECTION
		CAIN A,ARGX06	;OR OFF THE END OF ALL POSSIBLE PAGES?
		JRST DSKNEW	;YES, EXPECTED
		CALL JERR]	;NO, UNEXPECTED
DSKLP1:	HRL A,DESJFN		;MAP FROM DESTINATION
	HRR A,NXTBEG		;CORRESPONDING PAGES OF SOURCE
	MOVE B,DESPN		;MAP INTO DESTINATION BUFFER
	HRLI B,.FHSLF		;OURSELF
	MOVX C,PM%WR!PM%CNT	;WRITE, REPEAT COUNT
	HRR C,NPAGES
	MOVE D,ENDPTR		;GET END POINTER
	CAMN D,ENDPT0		;WAS IT CHANGED
	JRST DSKLP2		;NO, PROCEED WITH PMAP
	AOS D			;YES, HOW MUCH DO WE REALLY NEED TO MAP?
	SUB D,DESBFR		;NUMBER OF WORDS
	LSH D,-9		;MAKE IT PAGES
	HRR C,D			;MAP THAT MANY FROM THE DESTINATION FILE
DSKLP2:	PMAP			;SET UP DESTINATION PAGES
	 ERJMP [CALL DGETER	;FAILED, PRESUMABLY BECAUSE TRYING TO GO OFF END OF WORLD
		CAIE A,ARGX06	;MAKE SURE THAT'S THE PROBLEM
		CALL JERR	;NO, SO UNEXPECTED ERROR
		JRST .+1]	;ENDPTR HAS ALREADY ACCOUNTED FOR THIS
	HRLI A,BUF0		;COPY FROM SOURCE
	HRR A,DESBFR		;TO DESTINATION
	MOVEM A,BLTPTR		;REMEMBER BLT POINTER
DSKBLT:	MOVE B,ENDPTR		;GET ADDRESS OF LAST WORD OF DESTINATION BUFFER
	BLT A,(B)		;COPY THE DATA
	 ERJMP DSKDIS		;DISCONTINUITY, PROBABLY END OF FILE, HOLE, OR QUOTA EXCEEDED
	MOVEM A,SAVBLT		;SAVE HOW FAR WE GOT BEFORE ERROR
	MOVE B,ENDPTR		;GET POINTER TO END OF DESTINATION WE JUST SET UP
	CAME B,ENDPT0		;IS IT A FULL BUFFERFUL?
	JRST DSKDS1		;NO, WE'VE HIT HOLE OR END.
	MOVE A,NPAGES		;GET NUMBER OF PAGES PER BUFFER
	ADDM A,NXTBEG		;UPDATE PAGE TO START WITH
	JRST DSKLUP		;LOOP FOR NEXT PAGE GROUP

DSKDIS:	MOVEM A,SAVBLT		;SAVE HOW FAR WE GOT BEFORE ERROR
	MOVEI A,.FHSLF
	GETER			;GET TYPE OF ERROR
	CAMN B,[.FHSLF,,IOX11]	;NO ROOM?
	CALL CJERRE		;YES
	CAME B,[.FHSLF,,ILLX01]	;NOT ROOM PROBLEM, HIT HOLE OR END?
	CALL JERRE		;NO, UNEXPECTED PROBLEM
DSKDS1:	MOVE A,ENDPT0		;RESTORE BLT POINTER FOR FULL CHUNKS
	MOVEM A,ENDPTR
	LDB A,[331100,,SAVBLT]	;GET MEMORY PAGE NUMBER ASSOCIATED WITH NONX SOURCE PAGE
	SUBI A,BUF0PN-1		;GET RELATIVE POSITION IN BUFFER
	ADD A,NXTBEG		;GET ACTUAL FILE PAGE NUMBER
DSKDS2:	TLNE A,-1		;ARE WE OFF THE END OF THE WORLD?
	RET			;YES, SO WE MUST BE DONE
	HRL A,SRCJFN		;SET UP FOR FFUFP
	FFUFP			;FIND NEXT USED PAGE
	 ERJMP DSKMEF		;FAILED, PROBABLY END OF FILE
	HRRZ C,A		;COPY PAGE NUMBER
	SUB C,NXTBEG		;SEE WHERE IN BUFFER PAGE IS
	CAML C,NPAGES		;IN SUBSEQUENT BUFFER?
	JRST DSKNXT		;YES
	LSH C,9			;NO, IN THIS BUFFER.  MAKE MEMORY OFFSET
	MOVE A,BLTPTR		;GET ORIGINAL BLT POINTER
	ADJSP A,(C)		;ADJUST FOR CONTINUATION
	JRST DSKBLT		;CONTINUE THIS BUFFER

DSKNXT:	HRRZM A,NXTBEG		;REMEMBER NEXT PAGE TO START WITH
	JRST DSKLUP		;GO START NEW BUFFER

DSKMEF:	MOVEI A,.FHSLF
	GETER			;GET REASON FOR FFUFP FAILING
	CAME B,[.FHSLF,,FFUFX3]	;NO MORE USED PAGES?
	CALL JERRE		;NO, UNEXPECTED ERROR
	RET			;YES, DONE!

;COME HERE WHEN PMAP FAILS SOMEWHERE IN THE MIDDLE OF A SOURCE CHUNK.
;THIS IS BECAUSE WE HAVE HIT A NONEXISTENT FILE SECTION.
;WE NOW ASSUME THAT SOME PORTION OF THE SOURCE BUFFER HAS BEEN MAPPED, AND THE
;REST OF THE SOURCE BUFFER IS STILL MAPPED TO PART OF THE PREVIOUS CHUNK.
;HENCE WE CAN'T RELY ON THE BLT TO STOP AT THE END OF THE CURRENT CHUNK!

DSKNEW:	LDB A,[001100,,NXTBEG]	;SEE WHERE IN SECTION WE STARTED
	JUMPE A,[MOVE A,NXTBEG	;ABORTED CHUNK HAD NONE, START IN VOID.
		 JRST DSKDS2]	;GO FIND NEXT EXISTING CHUNK
	MOVN A,A		;NEGATE TO PREPARE TO SUBTRACT
	ADDI A,1000		;SEE HOW MANY PAGES WE MAPPED IN IN ABORTED CHUNK
	LSH A,9			;GET NUMBER OF WORDS MAPPED IN
	ADD A,DESBFR		;GET FIRST WORD OUT OF BOUNDS IN DESTINATION BUFFER
	SOJ A,			;GET LAST WORD TO BE USED IN DESTINATION BUFFER
	MOVEM A,ENDPTR		;SET UP SHORTENED BLT POINTER
	JRST DSKLP1		;GO DO SHORTENED VERSION

;COPY BY BYTES-PAGES COMES HERE AFTER EOF WITH D 0 AND P2,P3,Q2 CORRECT
;TO DELETE REST OF DEST FILE AND SET ITS PTR AND BYTE SIZE.

PAGE5A:	MOVE A,Q2
	CALL $FNUFP		;NEXT PAGE IN DEST
	MOVE Q2,A
PAGES6:	MOVE A,D
	CALL $FNUFP		;ALWAYS NEXT PAGE IN SOURCE
	MOVE D,A
	;...

;HAVE A PAGE IN EACH FILE. DECIDE WHAT TO DO WITH THEM.

PAGES3:	JUMPE Q2,[JUMPE D,PAGES9 ;NO MORE PAGES IN DEST. NOR SOURCE - DONE
		  JRST PAGES5]	;GO COPY PAGE
	JUMPE D,PAGES4		;NO MORE PAGES IN SOURCE, DELETE REST OF DEST
	MOVEI A,(D)
	CAIG A,(Q2)		;COMPARE SOURCE PAGE # TO DEST PAGE #
	JRST PAGES5

;DELETE DEST PAGES CORRESPONDING TO "HOLE" IN SOURCE

PAGES4:	SETO A,
	MOVE B,Q2
	HRLZI C,1		;PMAP DISPOSAL INFO
	PMAP
	MOVE A,Q2
	CALL $FNUFP		;NEXT PAGE IN DEST
	MOVE Q2,A
	JRST PAGES3		;GO DECIDE AGAIN
;COPY/APPEND...
;COPY BY PAGES...
;COPY A PAGE

PAGES5:	MOVE A,D		;SOURCE JFN AND PAGE NUMBER
	CALL PREFLT		;PERHAPS IT'S TIME FOR PREFAULTING
	MOVE A,D		;SOURCE JFN AND PAGE NUMBER
	MOVE B,[XWD .FHSLF,<BUF1>B44]
	LDF C,PM%RD
	PMAP			;MAP SOURCE PAGE INTO BUFFER
	HRL A,OUTDSG		;DON'T USE Q2 HERE, MAY BE 0!
	HRRI B,<BUF2>B44
	LDF C,PM%WT
	PMAP			;MAP DESTINATION PAGE INTO ANOTHER BUFFER
	 ERJMP CJERRE		;REPORT FAILURE (PROBABLY OVER QUOTA)
	MOVE A,[XWD BUF1,BUF2]
	BLT A,BUF2+777		;COPY DATA
	MOVEI A,(D)		;MASK PAGE # OF PAGE JUST COPIED
	CAIGE A,(Q2)		;COMPARE TO DEST PAGE #
	JRST PAGES6		;PAGE WAS COPIED INTO A HOLE IN DEST
;COPY/APPEND...
;FINISH UP COPY BY PAGES.
;ALSO USED FOR BYTES-PAGES, SO NOTHING DISK-DEPENDENT CAN BE DONE HERE.

PAGES9:	SETO A,			;CLEAR BUFFERS
	MOVE B,[XWD .FHSLF,<BUF1>B44]
	SETZ C,
	PMAP
	HRRI B,<BUF2>B44
	PMAP
	HRRI B,<BUFPRE>_-9	;CLEAR PREFAULT PAGES
	MOVE C,[PM%CNT+NPRE]	;DESIGNATE HOW MANY PAGES TO CLEAR
	PMAP			;CLEAR 'EM

;SET END POINTER OF DESTINATION FILE

PAGES1:	MOVE B,P3		;BYTE COUNT OF SOURCE EOF
	HRRZ A,OUTDSG		;SET POINTER FOR THIS OPENING OF FILE, IN CASE
	SFPTR			;SEQUENTIAL I/O FOLLOWS (GROUP SOURCE CASE)
	 CALL JERR
	HRLI A,.FBSIZ		;SET EOF PTR IN FILE (CLOSF DOES NOT WHEN
	MOVE C,B		;NO SEQUENTIAL OUTPUT HAS BEEN DONE)
	SETO B,
	CALL $CHFDB		;SET FILE DESCRIPTOR BLOCK
	 CALL JERR

;SET BYTE SIZE OF DESTINATION FILE
;(CLOSF DOES NOT SET IT WHEN NO SEQUENTIAL OUTPUT HAS BEEN DONE)

	HRLI A,.FBBYV
	SETZ C,
	DPB Q1,[POINTR C,FB%BSZ] ;BYTE SIZE STILL IN Q1
	HRLZI B,<77B11>B53
	CALL $CHFDB
	 CALL JERR

;COPY OR APPEND COMPLETE.
;PAGE-COPY FALLS IN, ALL OTHER CASES BRANCH HERE.

COPEOF:	TDNE Z,[F2,,-1]		;APPEND/LIST OR ANY SUBCOMMANDS?
	JRST COPDON		;YES, LEAVE NEW DATES
	TLNE Z,F4		;DISK DEVICE?
	JRST COPEF1		;NO - SKIP THIS
	HRRZ	A,@INIFH1	;INPUT JFN
	MOVE	B,[1,,.FBCTL]	;GET CTL WORD FROM FDB
	MOVEI	C,C		;WHERE TO PUT IT
	CALL	$GTFDB		;GET IT
	  CALL	JERR		;SHOULDN'T
	HRRZ	A,OUTDSG	;OUTPUT JFN
	HRLI	A,.FBCTL	;WORD TO CHANGE
	AND	C,[FB%FCF!FB%FOR] ;BITS TO SET
	LDF	B,FB%FCF!FB%FOR	;MAKE A MASK
	CALL	$CHFDB		;SET IN OUTPUT FILE
	  CALL	JERR		;CHFDB DIED
	HRRZ	A,@INIFH1	;INPUT JFN
	HRLI	B,1
	HRRI	B,.FBUSW	;USER SETTABLE WORD
	MOVEI	C,C		;WHERE TO PUT IT
	CALL	$GTFDB		;GET IT
	  CALL 	JERR		;LOSAGE
	HRRZ 	A,OUTDSG	;OUTPUT JFN
	HRLI	A,.FBUSW	;USER SETTABLE WORD
	SETO	B,
	CALL	$CHFDB		;PUT USER WORD INTO NEW FDB
	  CALL	JERR		;LOSAGE
COPEF1:	HRRZ A,@INIFH1		;INPUT JFN
	MOVEI B,TADBLK		;WHERE TO PUT DATES
	MOVEI C,TADLEN		;HOW MUCH TO GET
	RFTAD			;READ DATES
	 ERJMP [CALL %MESS
		TYPE <Failed to read dates from source file - >
		JRST TDERR]	;MESSAGE AND WRAPUP
	MOVE C,.RSWRT+TADBLK	;GET WRITE DATE
	CAMN C,[-1]		;IF NO WRITE DATE,
	JRST COPDON		;THEN ASSUME NO DATES AVAILABLE
	MOVE D,.RSCRV+TADBLK	;GET CREATION DATE
	CAMN D,[-1]		;IF NO CREATE DATE,
	MOVE D,C		;USE WRITE DATE
	SETOM TADBLK		;CLEAR BLOCK FOR SFTAD
	HRLI A,TADBLK
	HRRI A,1+TADBLK		;MAKE BLT POINTER
	BLT A,TADLEN-1+TADBLK
	MOVEM C,.RSWRT+TADBLK
	MOVEM D,.RSCRV+TADBLK	;STORE DATES TO SET
	MOVE A,OUTDSG
	MOVEI C,TADLEN
	SFTAD
	 ERJMP [CALL %MESS
		TYPE <Failed to set dates for destination file - >
		JRST TDERR]	;MESSAGE AND WRAPUP
COPDON:	SETZM EOFDSP		;(REDUNDANT EXCEPT IN ^Z ON TTY CASE)
	SKIPE HELPSN		;IS IT A HELP COMMAND?
	JRST COPFLE		;YES, DON'T DO ANY MORE.
	CALL GNFIL		;GET NEXT FILE IN INPUT GROUP
	 JRST COPFLE
	SKIPE POJFLG		;IF OUTPUT TO COJFN
	ETYPE<%_>		;THEN SEPARATE FILENAMES
	JRST COPFLN

MCOERR:	SETOM CERRF		;REMEMBER THAT THIS FILE HAD ERROR
	JRST COPDON

COPFLE:	SETZM HELPSN		;RESTORE THE FLAG
	CALLRET CTPOK		;TYPE OK ON LAST FILE IF APPROPRIATE

;CTPOK TYPES [OK] IF APPROPRIATE.

CTPOK:	SKIPE CERRF		;ERRORS?
	RET			;YES, SO NOT OK.
	SKIPN POJFLG		;IF NOT OUTPUTTING TO PRIMARY JFN, TYPE [OK] HERE
	CALL TYPOK
	RET

TDERR:	CALL	%GETER		;GET ERROR CODE
	MOVE	A,ERCOD		;...
	CALL	$ERSTR		;PRINT MSG
	ETYPE<%_>		;CRLF
	JRST	COPDON		;FINISH UP
;COPY/APPEND...
;SUBROUTINE TO GET NEXT USED PAGE # OF DISK FILE.
;TAKES IN A:  JFN,,CURRENT PAGE #.  RETURNS A 0 IF NO MORE PAGES.
;MUST BE NEAR COPY TO MINIMIZE PAGE FAULTS

$FNUFP:	JUMPE A,[RET]		;ALREADY AT END, NOP.
	ADDI A,1		;NEXT PAGE NUMBER
	TRNN A,-1
	JRST [	SETZ A,		;WRAP-AROUND FROM MAX PAGE NUMBER
		RET]

;ENTRY TO GET FIRST USED PAGE NUMBER. DOESN'T INCREMENT FIRST.

$FFUFP:	FFUFP
	 CALL [	CAIE A,FFUFX3	;"NO MORE PAGES" ERROR?
		JRST JERR
		SETZ A,
		RET]
	RET

;ROUTINE TO PREFAULT DISK PAGES IN.  CALL IT WITH PAGE NUMBER IN RIGHT
;HALF OF "A".  IT RETURNS +1 ALWAYS.  THIS ROUTINE LOOKS IN VARIABLE
;"PREPAG" TO DETERMINE WHICH PAGE NUMBER STARTS THE LAST GROUP OF
;PAGES THAT WAS PREFAULTED IN.  IF THE PAGE NUMBER IN R.H. OF A ISN'T
;IN THIS GROUP, THIS ROUTINE PREFAULTS IN THE GROUP OF WHICH R.H. A
;IS A MEMBER.  THE PAGES ARE PREFAULTED IN TO MEMORY STARTING AT
;LOCATION "BUFPRE", ASSUMED TO BE ON A PAGE BOUNDARY.  "NPRE" (DEFINED
;IN XDEF) DEFINES HOW MANY PAGES TO PREFAULT IN.
;ALSO ASSUMES INIFH1 POINTS TO WORD CONTAINING JFN OF
;FILE OPEN AS SOURCE

PREFLT:	HRRZ A,A		;KEEP ONLY PAGE NUMBER
	IDIVI A,NPRE
	IMULI A,NPRE		;CALCULATE FIRST PAGE OF THE GROUP
	CAMN A,PREPAG		;IS THIS GROUP ALREADY IN?
	JRST PREOUT		;YES, WE'RE DONE

;THE FOLLOWING WAS ADDED TO CORRECTLY HANDLE LONG FILES.
;IF AN ATTEMPT IS MADE TO PRELOAD A PAGE FROM A NONEXISTENT
;SECTION, A FILE OPENED FOR READ-ONLY ACCESS (OF%RD IN OPENF)
;PMAP WILL BARF SINCE IT CAN'T CREATE A PAGE TABLE WITHOUT WRITE
;ACCESS TO THE FILE. ALL THIS CODE DOES IS ELIMINATE THE ANNOYING
;ERROR MESSAGE GENERATED BY JWARN WHEN THIS OCCURS.
;					B.TOMCZAK 9/14/79

	HRRZ A,A		;NO - CLEAR OUT ANY OTHER TRASH
	CAIG A,777		;SEC GREATER THAN 0?
	JRST PREMAP		;NO, SEC 0 ALWAYS EXISTS

	PUSH P,A		;SAVE THE PAGE NUMBER DESIRED
	SKIPGE B,PREPAG		;HAVE WE ALREADY DONE A MAPPING?
	JRST CHKSEC		;NO, SO JUST CHECK CURRENT

	ADDI B,NPRE-1		;GET LAST PG# OF LAST GROUP
	XOR B,A			;CHECK SEC#'S
	TRNE B,777000		;CURR IN SAME SEC AS PREVIOUS?
CHKSEC:	 JRST [	ANDI A,777000	;NO, GET 1ST PG IN CURRENT SEC
		MOVEM A,B	;AND SAVE IT
		HRL A,@INIFH1	;A/   JFN,,PG#
		CALL $FFUFP	;FIND NEXT USED PAGE
		JUMPE A,[POP P,A ;ZERO MEANS NOTHING IN USE AFTER THIS
			 RET]
		XOR B,A
		TRNN B,777000	;NEXT USED PAGE IN SAME SEC?
		JRST .+1	;YES, MAPPING WILL BE OKAY
		POP P,A		;NO, NONEXISTENT SEC
		RET]		;MAPPING WILL FAIL
	POP P,A			;RESTORE T1 TO PREVIOUS GLORY

PREMAP:	MOVEM A,PREPAG		;READ IN THIS GROUP
	HRL A,@INIFH1		;GET HANDLE ON FIRST PAGE OF GROUP TO BE READ IN
	MOVE B,[.FHSLF,,<BUFPRE>_-9]	;GET HANDLE ON AREA WE'RE READING INTO
	MOVE C,[PM%CNT+PM%PLD+NPRE]	;COUNT GIVEN, PREFAULT, HOW MANY PAGES]
	PMAP			;START THE PAGES IN
	 JWARN			;GIVE WARNING IF THIS PMAP FAILS
PREOUT:	RET
;COPY/APPEND SUBCOMMAND TABLE AND ROUTINES

$COPY:	TABLE
	T ASCII
	T BCD,ONEWRD,NIYE,CM%INVIS
	T BINARY,ONEWRD
	T BYTE
	T DUMP,ONEWRD,NIYE,CM%INV
	T IMAGE
	T RECORD,,,CM%INVIS
	T SUPERSEDE
	TEND

$APPEN:	TABLE
	T ASCII
	T BCD,ONEWRD,NIYE,CM%INVIS
	T BINARY,ONEWRD
	T BYTE
	T DUMP,ONEWRD,NIYE,CM%INV
	T IMAGE
	T RECORD,,,CM%INVIS
	TEND

.ASCII::CONFIRM
	MOVX P3,ASCF		;ASCII FLAG
ASCII2:	HRR Z,P3 		;ENTRY FROM OTHER PLACES
	RET


.BINAR::HRRI Z,10000		;"BINARY" MODE BIT (MODE 14)
	RET

.BYTE:	NOISE (SIZE)
	DECX <Byte size in decimal>
	 CMERRX
	CONFIRM
	MOVEM B,BYTSIZ		;BYTE SIZE GOES IN BYTSIZ
	HRRI Z,NRMF		;SAY NORMAL MODE
	RET

.IMAGE::MOVEI B,[FLDDB. .CMCFM,,,,,[FLDDB. .CMKEY,,$IMAGE]]
	CALL FLDSKP		;CONFIRMATION OR KEYWORD
	 CMERRX <"BINARY" or nothing>
	LDB C,[POINT 9,(C),8]	;PICK UP FUNCTION CODE
	CAIN C,.CMCFM		;NO ARG TO "DETACH"?
	MOVEI B,[T ,,400]	;DUMMY ARG FOR NOTHING TYPED
	CAIE C,.CMCFM
	CONFIRM			;IF NO CONFIRMATION YET, DO IT NOW
	MOVE P3,(B)		;GET TABLE ENTRY
	MOVE P3,(P3)		;GET CONTENTS OF WORD POINTED TO BY TABLE ENTRY
	JRST ASCII2		;GO PROCESS MODE

$IMAGE:	TABLE
	T BINARY,,4000
	TEND

.RECOR::NOISE (LENGTH)
	JRST NIYE

$SUPER:	TABLE
	T ALWAYS,,<0,,-1>	;CANNOT HAVE A NEGATIVE VALUE
	T NEVER,,0
	T NEWER,,2
	T OLDER,,1
	TEND

.SUPER:	KEYWD $SUPER		;GET A KEYWORD
	T OLDER,,1		;DEFAULT IS "SUPERSEDE OLDER"
	 JRST CERR
	CONFIRM			;CONFIRM INPUT NOW
	HRREM P3,SPRSED		;SET UP FLAG WORD WITH VALUE
	RET	
;OPEN FILE SUBROUTINE
;DOES OPENF, RETURNS ON SUCCESS, GIVES MESSAGE ON FAILURE
;CALL WITH A & B SET UP FOR "OPENF" JSYS.
;CHECKS FOR AND DOES NOT RE-OPEN PRI I/O FILES
; (PRI FILES ARE SOMETIMES DEFAULT ARG VALUES).

$OPEN7::HRLI B,<7B5+0B9>B53	;ENTER HERE FOR 7 BIT BYTES NORMAL MODE
$OPENF::CALL OPENX		;TRY TO OPEN FILE
	 JRST ERRFIN		;GO BACK TO TOP LEVEL IF FAILS
	RET			;SUCCEEDED

;ROUTINE LIKE ABOVE, BUT SKIPS IFF SUCCESS.

OPENX:	STKVAR <OFJFN>
	MOVEM A,OFJFN
	CALL $IOCHK		;SPECIAL CHECK FOR PRIMARIES AND EXEC IO
	RETSKP			;SPECIAL (ALREADY OPEN)
	OPENF			;OPEN FILE
	 CAIA			;FAILED
	RETSKP
	MOVE C,OFJFN		;RETRIEVE JFN FOR %S

;ENTER HERE WITH ERROR CODE IN A AND JFN IN C
;SHOULD BE CALLED WITH "CALL OPNERR" SO JERR PRINTS CORRECT PC

OPNERR::MOVEI D,0		;SO WE'LL KNOW IF WE CATCH A FISH
	CAIN A,OPNX2		;NONX FILE?
	MOVE D,[LERROR <File is empty: %3S>]
	CAIN A,OPNX3
	MOVE D,[LERROR <Read protection violation for: %3S>]
	CAIN A,OPNX4
	MOVE D,[LERROR <Write protection violation for: %3S>]
	CAIN A,OPNX6
	MOVE D,[LERROR <Append protection violation for: %3S>]
	CAIN A,OPNX7
	JRST [	MOVE A,C
		DVCHR
		HLRZ C,C
		MOVE D,[LERROR <%1H: is assigned to job %3Q>]
		JRST OPNE1]
	CAIN A,OPNX8
	MOVE D,[LERROR <%3H: is not on-line>]
	CAIN A,OPNX9
	MOVE D,[LERROR <File is busy: %3S>]
	CAIN A,OPNX9+4
	MOVE D,[ETYPE <%_ %%Invalid access requested: %3S %_>]
	CAIN D,0		;IF OTHER ERROR, USE SYSTEM'S VERSION
	MOVE D,[LERROR <%?: %3S>]
OPNE1:	XCT D			;PRINT ERROR MESSAGE
	RET			;SINGLE SKIP RETURN

;ENTER HERE TO CHECK FOR PRIMARY OR EXEC IO ALREADY OPEN
;IF PRIMARY OR EXEC IO, CHECK MODE AND BYTE SIZE

$IOCHK:	CAIE A,.PRIIN		;DON'T OPEN PRIMARY IO
	CAIN A,.PRIOU
	RET
	CAME A,CIJFN		;DON'T OPEN EXEC IO FILES
	CAMN A,COJFN
	RET
	RETSKP			;TELL CALLER NOT SPECIAL
;"REDIRECT" AND "DETACH" COMMANDS

;REDIRECT (INFILE) <NAME>/* (OUTFILE) <NAME>/* (AND) START/REENTER/CONT

;DETACH IS SAME SYNTAX AND HAS SAME MEANING EXCEPT IT DETACHES
; TERMINAL AFTER REDIRECTING IO.
;ALL ARGUMENTS CAN BE OMITTED AND DEFAULT TO NULL

.DETAC::TLO Z,DTACHF		;SET "DETACH" FLAG

;START/REENTER/CONTINUE ARGUMENT

	NOISE <AND>
	MOVEI B,[FLDDB. .CMCFM,,,,,[FLDDB. .CMKEY,,$REDIR]]
	CALL FLDSKP		;CONFIRMATION OR KEYWORD
	 CMERRX <"START", "REENTER", "CONTINUE", or nothing>
	LDB C,[331100,,(C)]	;PICK UP FUNCTION CODE
	CAIN C,.CMCFM		;NO ARG TO "DETACH"?
	MOVEI B,[T NOTHING,,<[XWD ..DTCH,[RET]]>] ;DUMMY ARG FOR NOTHING TYPED
	CAIE C,.CMCFM
	CONFIRM			;IF NO CONFIRMATION YET, DO IT NOW
	MOVE P3,(B)		;GET TABLE ENTRY
	MOVE P3,(P3)		;GET CONTENTS OF WORD POINTED TO BY TABLE ENTRY

;P3 POINTS TO A WD WHOSE RH POINTS TO A SUBR TO FINISH DECODING
;  AND CHECK THE ARGUMENT.

	MOVE A,FORK		;SET FORK HANDLE OF CURRENT FORK
	MOVE B,(P3)
	CALL (B)		;CALL ARGUMENT-DEPENDENT DECODE & CHECK SUBR
	TLNE Z,DTACHF
	ETYPE < Detaching job # %J
>
	HLRZ A,(P3)
	JRST (A)		;DISPATCH TO
				;FINAL-ARGUMENT-DEPENDENT EXECUTION ROUTINE

;TABLE FOR THIRD ARGUMENT
;VALUE POINTS TO A WORD --
;	RH: DECODE-AND-CHECK SUBR ADDRESS
;	LH: EXECUTION DISPATCH ADDRESS

$REDIR:	TABLE
	T CONTINUE,,<[XWD ..CONT,$CONTI]>
	T REENTER,,<[XWD ..REEN,$REENT]>
	T START,,<[XWD ..STRT,$START]>
	TEND

;EXECUTION ROUTINE FOR NULL THIRD ARGUMENT

..DTCH::TLNE Z,DTACHF
	DTACH
	MOVEI Q1,ETTYMD		;TTY MODES FOR USE WHEN EXEC IS RUNNING
	CALL LTTYMD		;PUT SAME INTO EFFECT NOW.
	JRST CMDIN4

;..CONT, ..REEN, ..STRT ARE WITH THE CORRESPONDING COMMANDS.

END