Google
 

Trailing-Edge - PDP-10 Archives - bb-r775d-bm_tops20_ks_upd_4 - sources/lnkfio.mac
There are 48 other files named lnkfio.mac in the archive. Click here to see a list.
TITLE	LNKFIO - SUBROUTINES TO DO ALL FILE I/O FOR LINK
SUBTTL	D.M.NIXON/DMN/JLd/JBC/JNG/PAH/DZN/PY/JBS	17-Dec-84



;COPYRIGHT (C) 1974, 1984 BY
;DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND 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.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
;TRANSFERRED.
;
;
;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
;AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.
;
;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.


SEARCH	LNKPAR,LNKLOW,MACTEN,UUOSYM,SCNMAC
IFN TOPS20,< SEARCH MONSYM >
SALL

ENTRY	LNKFIO
EXTERN	.TYOCH,LNKCOR,LNKLOG


CUSTVR==0		;CUSTOMER VERSION
DECVER==6		;DEC VERSION
DECMVR==0		;DEC MINOR VERSION
DECEVR==2351		;DEC EDIT VERSION


SEGMENT


LNKFIO:
SUBTTL	REVISION HISTORY


;START OF VERSION 1A
;65	TENEX SPEEDUPS

;START OF VERSION 2
;135	ADD OVERLAY FACILITY
;136	FIX I.ALC BUG ON DELETE
;170	CHANGE IODATA MACRO FOR PLOT SWITCH
;221	DELETE DVREN. USE DVRNF. INSTEAD
;222	(12773) DO UPDATE MODE ENTER RIGHT FOR DEFAULT PATH

;START OF VERSION 2B
;240	FIX I/O TO UNASSIGNED CHAN IF /SAVE AND HIGH FILE ALREADY EXISTS
;245	REWORK DVLKP. & LKPERR ROUTINES TO BE MORE GENERAL
;	ADD DVCEM. & DVSUP. (ROUTINE TO CHECK FOR SUPERSEDE)
;356	LABEL EDIT 240
;370	FIX LNKINS ERROR DETECT
;400	Support SFD's on output files.

;START OF VERSION 2C
;501	Support SFD's on symbol input and overlay files.
;537	Don't destroy I.PPN in DVRNF. for /SAVE
;557	Clean up listing for release.

;START OF VERSION 3A
;560	Release on both TOPS-10 and TOPS-20 as LINK version 3A(560)

;START OF VERSION 4
;604	Handle device NUL: correctly
;610	Handle output defaulting of ersatz devices correctly.
;610	Don't let libraries confuse DVSUP.
;731	SEARCH MACTEN,UUOSYM
;740	Add code to get F.VER SCAN block field into I/O blocks
;	and ( if input file ) to set version number of all output files.
;765	Release on both TOPS-10 and TOPS-20 as LINK version 4(765)

;START OF VERSION 4A
;1105	Fix edit 740 to not destroy the path to the file if it includes SFDs.
;1122	Remove edit 740.
;1123	Use HRLI instead of HRL to load ENTER error flag.
;1174	Label and clean up all error messages.
;1202	Make LNKNED message be potentially editable after 1174.
;1217	Clean up the listings for release.
;1220	Release on both TOPS-10 and TOPS-20 as version 4A(1220).
;1230	Remember the path after fake ENTER in DVSUP..
;1250	Clear DATE/TIME fields in DVUPD. if TOPS-20, to preserve seconds.

;START OF VERSION 5
; 1221-1477	Maintanence edits
;1401	Handle overflow and EXE file in native mode on TOPS-20.
;1402	Handle REL files in native mode on TOPS-20.
;1406	Get the creation date and time into I.PRV for /MAP.
;1407	Make overlay files work again ( broken in 1401 ).
;1416	Put an ERJMP after each GTFDB in DVLKP..
;1461	Don't do an OPENF JSYS for an .EXE file if xaddr program is loaded.

;START OF VERSION 5A
;1500-1677 Maintenance edits
;
;1500	Compute word size of file correctly if bytesize not 36 bits.
;1507	Correct typo in DVCLS.
;1511	Correct another typo in DVCLS.
;1513	Correct typo at DVDLF.
;1527	Save IO.CHN at DVVRG2 during DY.GET to avoid ?I-O to Unassigned Channel
;1530	Create temp string in DVLKP./DVUPD. on stack, DY area may be exhausted.
;1541	Close file when deleting it.
;1547	Fix all cases where .REL bytesize not 36 bits.
;2014	Fix NUL: so it can be used.
;2017	Use LN.FL as max size of ASCIZ filespecs.
;2026	Update copyrights and clean up listing.
;2034	Use .IODPR instead of .IODMP in DVOPN. on TOPS-20.
;2067	Fix 2014 for NUL:.  Was POPJing to data.
;2101	Fix off-by-one loop in "DVDPB.".

;Start of version 6
;2202	Remove FTFRK2 conditional.
;2247	Get a second JFN for EXE file.
;2301	Fix up errors for TOPS-20 native files.
SUBTTL	HERE TO SETUP POINTER TO I/O DATA BLOCK


;CALLED BY
;	PUSHJ	P,DVCHN.
;RETURN
;	T1 = POINTER
;EXPECTS I/O CHAN# IN IO.CHN

DVCHN.::MOVE	T1,IO.CHN	;GET CHAN#
	SKIPE	T1,IO.PTR(T1)	;GET I/O BLOCK
	POPJ	P,
E$$INS::.ERR.	(MS,0,V%L,L%F,S%F,INS,<I/O data block not set up>) ;[1174]


;HERE TO DO DEVCHR FOR DEVICE
;CALLED BY
;	PUSHJ	P,DVCHK.##
;USES T1-T2
;EXPECTS I/O CHAN# IN IO.CHN
;SETS IO.CHR WITH DEVCHR OF I/O DEVICE

DVCHK.::PUSHJ	P,DVCHN.	;GET ADDRESS IN T1
	MOVE	T2,I.DEV(T1)	;GET DEVICE
	DEVCHR	T2,		;SEE WHAT IT IS
	MOVEM	T2,IO.CHR	;SAVE FOR POSTERITY
	JUMPE	T2,E01NED	;[1174] NO SUCH DEVICE
	MOVEI	T2,DV.M0	;MODE BIT
	SKIPGE	I.MOD(T1)	;TEST FOR SPECIAL CASE
	POPJ	P,		;WILL SET READ MODE LATER
	LSH	T2,@I.MOD(T1)	;MODE WE WANT
	AND	T2,IO.CHR	;SEE IF WE CAN USE IT
	JUMPN	T2,CPOPJ	;OK RETURN
E$$IDM::PUSH	P,IO.CHN	;[1174] SAVE CHAN
	.ERR.	(I,0,V%L,L%F,S%F,IDM,<Illegal data mode for device >)
SUBTTL	HERE TO DO OPEN FOR NEW DEVICE


;CALLED BY
;	PUSHJ	P,DVOPN.##
;USES T1-T2
;EXPECTS CHAN # IN IO.CHN
;OPENS DEVICE AND SETS UP BUFFERS IF REQUIRED
DVOPN.::PUSHJ	P,DVCHN.	;GET I/O BLOCK
IFN TOPS20,<
	MOVE	T2,IO.CHN	;PEEK AT THE CHAN #
	CAIE	T2,DC		;REL OR EXE FILE?
	JRST	DVOP1		;NO, LET PA1050 PRESIDE
	MOVE	T2,I.MOD(T1)	;DUMP MODE? ( EXE PROCESSING )
	CAIN	T2,.IODPR	;[2034]
	JRST	DVRET1		;RETURN BUFFER FOR THIS CHANNEL
	SKIPE	I.DVZ(T1)	;ALREADY HAVE THE BUFFERS NEEDED?
	JRST	DVBUF1		; YES
	JRST	DVVRG1		; NO
DVOP1: >  ;[1402] IFN TOPS20
	MOVEI	T2,I.MOD(T1)	;ADDRESS OF OPEN BLOCK
	HRLI	T2,(OPEN)	;FORM INST
	IOR	T2,I.CHN(T1)	;PUT IN CHAN
	XCT	T2		;DO OPEN
	  JRST	E01OFD		;[1174] FAILED
;HERE TO ALLOCATE SPACE FOR BUFFERS
	HRRZI	T2,I.MOD(T1)	;POINT TO DATA BLOCK FOR OPEN
	DEVSIZ	T2,		;GET BUFFER SIZE
IFE TOPS20,<HALT		;CAN NOT HAPPEN!!!>
IFN TOPS20,<MOVE T2,[2,,203]	;FAKE IT FOR TOPS20>
	JUMPE	T2,DVRET1	;DUMP MODE HAS NO BUFFERS
				;HERE TO FAKE IT IF NUMBER OF BUFFERS IS TOO SMALL
	MOVE	T3,IO.CHN	;GET CHAN NUMBER
IFE TOPS20,<
	CAIE	T3,DC		;INPUT ONLY
	JRST	DVNDC		;NO
	HLRZ	T3,T2		;GET NUMBER OF BUFFERS
	CAIGE	T3,.IBR		;ENOUGH ALREADY
	HRLI	T2,.IBR		;[1174] NO, USE TOPS-10 LINK DEFAULT
DVNDC:>;END IFE TOPS20
	CAMN	T2,I.DVZ(T1)	;SEE IF SAME
	JRST	DVBUF1		;SET UP BUFFERS
	EXCH	T2,I.DVZ(T1)	;SWAP NEW FOR OLD
	JUMPE	T2,DVVRG1	;NOTHING TO GIVE BACK
	PUSHJ	P,DVRET2	;RETURN OLD BUFFER SPACE
	JRST	DVVRG.		;AND GET NEW
;HERE TO RETURN ALL SPACE USED BY CHAN I/O DATA BLOCK
;CALLED BY
;	PUSHJ	P,DVZAP.
;USES T1, T2, T3
;EXPECTS CHAN# IN IO.CHN

DVZAP.::PUSHJ	P,DVRET.	;REMOVE BUFFERS
	MOVE	T3,IO.CHN	;GET CHAN#
	HRRZ	T1,IO.PTR(T3)	;GET PTR
	SETZM	IO.PTR(T3)	;CLEAR IT
	MOVEI	T2,LN.IO	;LENGTH
	PJRST	DY.RET##	;RETURN

;HERE TO RETURN OLD BUFFER SPACE
;CALLED BY
;	PUSHJ	P,DVRET.
;USES T1, T2, T3
;EXPECTS CHAN# IN IO.CHN

DVRET.::PUSHJ	P,DVCHN.	;GET POINTER TO I/O BLOCK
DVRET1:	MOVE	T2,I.DVZ(T1)	;GET BUFSIZ WORD
DVRET2:	JUMPLE	T2,CPOPJ	;DUMP OR UNKNOWN
IFN TOPS20,<
	MOVE	T3,IO.CHN	;PEEK AT CHAN #
	CAIN	T3,DC		;REL OR EXE CHANNEL?
	JRST	DVRET3		;YES, HANDLE IT DIFFERENTLY
> ;[1402] IFN TOPS20
	HLRZ	T3,T2
	HRRZ	T2,T2
	IMULI	T2,(T3)		;CALCULATE HOW MUCH
	MOVE	T1,I.RNG(T1)	;FROM WHERE
	PJRST	DY.RET##	;GIVE IT ALL BACK
IFN TOPS20,<
DVRET3:	MOVE	T1,I.RNG(T1)	;PICK UP BUFFER PAGE #
	LSH	T1,9		;MAKE IT AN ADDRESS
	PJRST	DY.RET		;GIVE IT BACK
> ;[1402] IFN TOPS20
;HERE TO GET VIRGIN SPACE
;CALLED BY
;	PUSHJ	P,DVVRG.
;USES T1, T2
;EXPECTS CHAN# IN I/O CHAN

DVVRG.::PUSHJ	P,DVCHN.	;GET I/O BLOCK
DVVRG1:	MOVE	T2,IO.CHR	;GET DEVCHR BITS
	TXC	T2,DV.TTA!DV.TTY;[1174] MUST BE CONTROLLING TTY: (NUL: ISN'T)
	TXCN	T2,DV.TTA!DV.TTY;[1174]   ..
	  JRST	DVTTY		;[1174] YES
IFN TOPS20,<
	MOVE	T2,IO.CHN	;PEEK AT CHANNEL #
	CAIN	T2,DC		;REL OR EXE FILE?
	JRST	DVVRG2		;YES, HANDLE DIFFERENTLY
> ;[1402] IFN TOPS20
	MOVE	T2,I.DVZ(T1)	;GET BACK DEVSIZ INFO
	HLRZ	T1,T2		;NUMBER OF BUFFERS
	HRRZ	T2,T2		;SIZE OF EACH
	IMULI	T2,(T1)		;TOTAL SIZE REQUIRED
	PUSHJ	P,DY.GET##	;FIND THE SPACE
	MOVE	T2,T1		;TEMP STORE
	MOVE	T1,IO.CHN	;GET CHAN
	MOVE	T1,IO.PTR(T1)	;GET DATA BLOCK
	MOVEM	T2,I.RNG(T1)	;STORE START OF BUFFER
	JRST	DVBUF1		;ALLOCATE THE BUFFERS
IFN TOPS20,<
DVVRG2:	MOVEI	T2,LN.BF	;FIXED BUFFERSIZE
	MOVEM	T2,I.DVZ(T1)	;SET IN I/O BLOCK
	ADDI	T2,.IPS*2	;ASK FOR A LITTLE MORE
	PUSH	P,IO.CHN	;[1527] SAVE IN CASE PAGING STARTS
	PUSHJ	P,DY.GET	;SO WE'RE SURE TO GET IT ALL
	POP	P,IO.CHN	;[1527] RESTORE CHANNEL NUMBER
	MOVE	T2,T1		;TEMP STORE
	MOVE	T1,IO.CHN	;GET CHAN
	MOVE	T1,IO.PTR(T1)	;GET DATA BLOCK
	ADDI	T2,.IPS		;SET TO NEXT PAGE IN BUFFER
	LSH	T2,-9		;MAKE IT A PAGE #
	MOVEM	T2,I.RNG(T1)	; AND STORE IT.
	JRST	DVBUF1		; FAKE UP BUFFER HEADERS
> ;[1402] END IFN TOPS20

;HERE TO  SET UP  BUFFERS
;CALLED BY
;	PUSHJ	P,DVBUF.
;USES T1, T2
;EXPECTS CHAN# IN IO.CHN

DVBUF.::PUSHJ	P,DVCHN.	;GET I/O DATA BLOCK
DVBUF1:
IFN TOPS20,<
	MOVE	T2,IO.CHN	;PEEK AT CHAN #
	CAIN	T2,DC		;REL OR EXE FILE?
	JRST	DVBUF2		;YES, DO IT DIFFERENTLY
> ;[1402] IFN TOPS20
	MOVE	T2,I.RNG(T1)	;GET START OF AREA
	MOVEM	T2,.JBFF	;SET FREE SPACE POINTER TO POINT TO IT
	HLRZ	T2,I.DVZ(T1)	;GET NUMBER OF BUFFERS
	HLL	T2,I.BUF(T1)	;GET OUTPUT BUFFER HEADER
	TLZE	T2,-1		;OUTPUT DEVICE?
	TLOA	T2,(OUTBUF)	;YES, FORM OUTBUF UUO
	HRLI	T2,(INBUF)	;FORM INBUF UUO
	IOR	T2,I.CHN(T1)	;PUT IN CHAN#
	XCT	T2		;SETUP BUFFERS
	MOVE	T2,.JBREL	;INCASE /HELP
	MOVEM	T2,.JBFF
	POPJ	P,
IFN TOPS20,<
DVBUF2:	MOVE	T2,I.RNG(T1)	;PICK UP PAGE#
	LSH	T2,9		;MAKE IT AN ADDRESS
	HRL	T2,[POINT 36,0]	;MAKE IT A BYTE POINTER
	MOVE	T3,I.BUF(T1)	;PICK UP BUFFER HEADER POINTER
	HRRM	T2,0(T3)	;PUT START-OF-BUFFER IN HEADER
	MOVEM	T2,1(T3)	;SET START OF BUFFER
	SETZM	2(T3)		;CURRENT BUFFER LENGTH
	POPJ	P,		;RETURN
> ;[1402] IFN TOPS20

DVTTY:	SETZM	I.RNG(T1)	;CLEAR BITS JUST INCASE
	SETZM	I.DVZ(T1)
	POPJ	P,		;WILL USE TTCALLS
;HERE TO READ FILE SPEC AND BUILD LOOKUP BLOCK
;CALLED BY
;	PUSHJ	P,DVINP.##
;USES T1-T3

DVINP.::MOVE	P1,F.INZR	;MAKE SURE P1 IS SETUP
	MOVEI	T2,LN.RIB-1	;LENGTH OF LOOKUP BLOCK DATA
	MOVEM	T2,RIBLEN	;INCASE NOT SET UP
	MOVE	T2,F.MOD(P1)	;PRESERVE SCAN MODE BITS
	MOVEM	T2,MDSCN
	MOVE	T2,F.NAME(P1)	;NAME
	MOVEM	T2,FNAM
	MOVE	T2,F.EXT(P1)	;EXTENSION
	HLLZM	T2,FEXT
	MOVE	T2,F.DIR(P1)	;DIRECTORY
	MOVEM	T2,UFDPPN
IFN LN.DRB,<			;IF ALLOWED FOR SFD'S
	SKIPN	F.DIR+2(P1)	;DO WE HAVE ANY?
	POPJ	P,		;NO
	MOVEM	T2,SFDDIR	;STORE PPN
	MOVEI	T1,SFDARG	;GET PNTR
	MOVEM	T1,UFDPPN	;AS PPN
	MOVE	T1,[-LN.DRB,,SFDDIR+1]
	MOVEI	T2,F.DIR+2(P1)	;ADDRESS OF DIRECTORY
DVSFD:	MOVE	T3,(T2)		;GET NEXT SFD
	MOVEM	T3,(T1)		;STORE EVEN IF ZERO
	JUMPE	T3,CPOPJ	;EXIT WHEN ZERO FOUND
	ADDI	T2,2		;SCAN COUNTS IN 2'S
	AOBJN	T1,DVSFD	;KEEP GOING
>
	POPJ	P,
;ROUTINE TO A LOOKUP
;CALLED BY
;	PUSHJ	P,DVLKP.
;	  ERROR	RETURN
;	NORMAL	RETURN
;
;EXPECTS
;	IO.CHN TO CONTAIN I/O CHANNEL (AND CHANNEL IS OPEN)
;	IO.CHR TO CONTAIN THE DEVCHR UUO WORD
;
;RETURNS WITH THE LOOKUP DONE ACCORDING TO DEVICE TYPE

DVLKP.::PUSHJ	P,DVCHN.	;SET POINTER TO I/O BLOCK
IFE TOPS20,<
	MOVE	T2,I.CHN(T1)	;GCHAN # JUSTIFIED TO AC
	TLO	T2,(LOOKUP)	;MAKE AN I/O INSTRUCTION
	MOVE	T3,IO.CHR	;SEE WHAT IT WAS
	TXNN	T3,DV.DSK	;SEE IF A F/S
	JRST	NFSLKP		;NO
	HRRI	T2,I.RIB(T1)	;GET ADDR OF LOOKUP BLOCK
	XCT	T2		;EXTENDED LOOKUP
	  POPJ	P,		;FAILURE, ERROR RETURN
	MOVE	T2,IO.CHN	;NOW FIND WHERE FILE IS USING
	MOVEM	T2,I.ARG(T1)	;PATH. UUO, SINCE MONITOR LIES
	MOVEI	T2,I.PTH(T1)	;IF FILE IS IN AN SFD...
	MOVEM	T2,I.PPN(T1)	;ALWAYS MAKE I.PPN POINT TO PATH
	HRLI	T2,.PTMAX	;LENGTH OF PATH BLOCK
	PATH.	T2,		;FIND IT
	  SETZM	I.PPN(T1)	;CAN'T, ASSUME DEFAULT PATH
	PJRST	CPOPJ1		;SUCCESS, NORMAL RETURN

;HERE FOR NON-FILE STRUCTURE LOOKUP
NFSLKP:	HRRI	T2,I.NAM(T1)	;ADDR OF SHORT BLOCK
	XCT	T2		;SHORT LOOKUP
	  POPJ	P,		;ERROR RETURN
	PJRST	CPOPJ1		;NORMAL RETURN
> ;[1402] IFE TOPS20
IFN TOPS20,<
	MOVEI	T1,1(P)			;[1530] NOTE START OF FREE STACK
	ADJSP	P,LN.FL			;[2017] GET SOME SPACE THERE
	PUSHJ	P,DVTXT1		;[1530] CREATE THE STRING
	MOVE	T2,T1			; AND NOTE BYTEPOINTER THERETO
	MOVE	T1,[GJ%SHT!GJ%OLD]	; FILE MUST EXIST
	GTJFN%				; GET JFN
	  JRST	[ ADJSP P,-LN.FL	;[2017]
		  JRST DVERR. ]		;[2301] FAILURE
	ADJSP	P,-LN.FL		;[2017] THROW AWAY STRING
	MOVE	T2,[BYTE (6)0(4).GSNRM]	; FILE BYTESIZE AND MODE
	IOR	T2,[OF%RD]
	OPENF%				; OPEN THE FILE
	  JRST	DVERR.			;[2301] FAILURE
	MOVE	T2,IO.CHN		; PICK UP CHANNEL AGAIN
	MOVEM	T1,CHAN.JF(T2)		; STASH JFN AWAY ...
	CAIE	T2,DC			; WAS IT OPEN OF REL FILE?
	PJRST	CPOPJ1			; NO, JUST RETURN
	PUSH	P,T3			;[2014] SET ASIDE T3
	PUSH	P,T1			;[2014] SAVE THE JFN
	DVCHR%				;[2014] GET THE DEVICE CHARISTERICS
	 ERJMP	[POP P,T1		;[2301] FAILED, RESTORE THE JFN
		 POP P,T3		;[2301] CLEAN UP THE STACK
		 JRST DVERR.]		;[2301] PRETTY STRANGE DEVICE...
	POP	P,T1			;[2014] RESTORE THE JFN
	LDB	T2,[POINTR T2,DV%TYP]	;[2014] GET THE DEVICE TYPE
	CAIN	T2,.DVNUL		;[2014] IS IT THE NUL DEVICE?
	 JRST	[SETZB T2,RFLEN		;[2014] HAS NO LENGTH OR CREATION TIME
		 JRST DVLKP3]		;[2067] REJOIN MAIN ROUTINE
	CAIE	T2,.DVDSK		;[2301] IS IT A DISK?
	 JRST	[MOVEI T2,DESX8		;[2301] NO, GET "NOT DISK" ERROR
		 POP P,T3		;[2301] CLEAN UP THE STACK
		 JRST DVERR1]		;[2301] TAKE ERROR RETURN		
	MOVE	T2,[6,,.FBCRE]		;[1547] LOOK AT WRDS 5-12 OF FDB
	MOVEI	T3,.FBCRE(P)		;[1547] PTR TO VERY TEMPORARY STORAGE
	ADJSP	P,6			;[1547] SET IT ASIDE
	GTFDB%				;[1547] GET FILE DATA BLOCK
	  ERJMP	[ ADJSP P,-6		;[1547] RELEASE TEMP STORAGE
		  POP	P,T3		;[1547] AND T3
		  JRST	DVERR.]		;[2301] GET THE ERROR CODE
	MOVE	T2,<.FBCRE-.FBCRE>(T3)	;[1547] PICK UP CREATION DATE
	MOVE	T1,IO.CHN		;[1547]
	MOVE	T1,IO.PTR(T1)		;[1547] SAVE THIS INFO
	MOVEM	T2,I.PRV(T1)		;[1547] FOR THE MAP FILE

;[1547] Now compute RFLEN, length of .REL file

	MOVE	T1,<.FBSIZ-.FBCRE>(T3)	;[1547]
	LDB	T3,[POINT 6,<.FBBYV-.FBCRE>(T3),11]
					;[1547] GET BYTESIZE DATA
	JUMPE	T3,DVLKP2		;[1547] BYTESIZE=WORD SIZE
	CAILE	T3,^D18			;[1547] IF GREATER THAN 18
	JRST	DVLKP2			;[1547] BYTESIZE=WORD SIZE
	MOVEI	T2,^D36			;[1547] DIVIDE 36
	IDIV	T2,T3			;[1547] BY THE BYTESIZE
	IDIV	T1,T2			;[1547] FILE SIZE IN WORDS
	SKIPE	T2			;[1547] EXTRA BYTES?
	AOS	T1			;[1547] YES, ONE MORE WORD
DVLKP2:	MOVEM	T1,RFLEN		;[1547] STORE WORD COUNT
	ADJSP	P,-6			;[1547] RELEASE TEMP STORAGE
DVLKP3:	POP	P,T3			;[2067] AND AC
	PJRST	CPOPJ1			; AND RETURN
>  ;[1402] IFN TOPS20
;HERE TO HANDLE OUTPUT FILE SPECS
;CALLED BY 
;PUSHJ	P,DVOUT.##
;XWD	CHAN#, MODE

;DVOUT. CHECKS FOR DEVICE ALREADY OPEN ON THIS CHAN
;SETS UP DATA BLOCK AND RETURNS
;OPEN AND ENTER WILL BE DONE LATER

DVOUT.::HLRZ	T1,@(P)		;PICKUP CHAN NUMBER 
	MOVEM	T1,IO.CHN	;SAVE FOR DEFERED SWITCHES
	MOVEI	T2,LN.IO	;LENGTH REQUIRED
	SKIPN	T1,IO.PTR(T1)	;ALREADY SETUP?
	PUSHJ	P,DY.GET##	;NO, GET SPACE
	MOVE	T2,IO.CHN	;GET CHAN AGAIN
	HRROM	T1,IO.PTR(T2)	;POINT TO DATA AREA
				;-1 IN LEFT SIGNALS OPEN NOT YET DONE
	MOVE	T3,T1		;SAFER PLACE FOR POINTER
	HRRE	T1,@(P)		;GET MODE
	MOVEM	T1,I.MOD(T3)	;STORE MODE IN OPEN BLOCK
	AOS	(P)		;PASS OVER IT
	MOVE	T1,OBFTBL(T2)	;GET BUFFER HEADER
	HRLZM	T1,I.BUF(T3)	;INTO OPEN BLOCK
	HLLZM	T1,I.CHN(T3)	;CHAN# IN AC FIELD
	MOVE	T1,F.MOD(P1)	;PRESERVE SCAN MOD WORD
	MOVEM	T1,I.SCN(T3)
	MOVEI	T1,LN.RIB-1	;LENGTH OF EXTENDED ENTER
	MOVEM	T1,I.RIB(T3)
	SKIPN	T1,F.NAME(P1)	;FILE NAME
	MOVE	T1,O.NAM
	MOVEM	T1,I.NAM(T3)
	SKIPN	T1,F.EXT(P1)	;EXTENSION
	MOVE	T1,O.EXT	;DEFAULT MUST BE SETUP PRIOR TO THIS
	HLLZM	T1,I.EXT(T3)
	SKIPN	T1,F.PROT(P1)	;PROTECTION CODE
	MOVE	T1,O.PROT
	DPB	T1,[POINT 9,I.PRV(T3),8]	;STORE LOWER 9 BITS

;CONTINUED ON NEXT PAGE
;FALL IN FROM ABOVE TO DEFAULT OUTPUT PATH AND OUTPUT DEVICE.
;MUST REMEMBER THAT AN EXPLICIT ERSATZ DEVICE IS EXPLICITLY
;SPECIFYING BOTH A DEVICE AND A PATH, SO THE DEFAULT PATH
;(FROM [PATH]/DEFAULT:OUTPUT) SHOULD NOT BE APPLIED EVEN IF NO
;EXPLICIT PATH WAS GIVEN. SIMILARLY, A DEFAULT ERSATZ DEVICE
;(REL:/DEFAULT:OUTPUT) CAN ONLY BE APPLIED IF NEITHER DEVICE
;NOR PATH WERE EXPLICITLY GIVEN.

	MOVSI	T2,(FX.DIR)	;SET UP FOR TEST
	TDNN	T2,F.MOD(P1)	;WAS DIRECTORY SPECIFIED?
	JRST	DVOUT1		;MAYBE NOT. GO SEE.
	MOVE	T4,F.DIR(P1)	;ONE WAS. GET IT.
	TLNN	T4,-1		;PROJECT SPECIFIED?
	HLL	T4,MYPPN	;NO, ASSUME DEFAULT
	TRNN	T4,-1		;PROGRAMMER GIVEN?
	HRR	T4,MYPPN	;NO, DEFAULT
	MOVEI	T1,F.DIR(P1)	;POINT TO DIRECTORY WE'RE USING
	JRST	DVOUT4		;[610] AND GO CHECK SFD'S

;HERE WHEN FX.DIR IS OFF. EITHER NONE SPECIFIED OR IT'S [-].
DVOUT1:	TDNE	T2,F.MODM(P1)	;[610] WHICH IS IT?
	JRST	DVOUT3		;[610] IT'S [-]. DON'T USE DEFAULT.
	MOVE	T1,[3,,T2]	;[610] NO PATH GIVEN EXPLICITLY, SEE IF
	MOVE	T2,F.MOD(P1)	;[610]   ONE GIVEN VIA AN ERSATZ DEVICE
	TXNN	T2,FX.NDV	;[610] FIRST, SEE IF THERE WAS A DEVICE
	SKIPN	T2,F.DEV(P1)	;[610] SHOULD BE, MAKE SURE
	JRST	DVOUT2		;[610] NO DEVICE!
	PATH.	T1,		;[610] SEE IF EXPLICIT DEVICE IS ERSATZ
	  SETZ	T3,		;[610] PROBABLY NOT
	TXNN	T3,PT.IPP	;[610] DEVICE ERSATZ?
DVOUT2:	SKIPA	T1,[O.DIR]	;[610] NO, COPY PATH FROM DEFAULT
DVOUT3:	MOVEI	T1,F.DIR(P1)	;[610] YES, USE EXPLICIT PATH GIVEN
	MOVE	T4,(T1)		;GET UFD FOR OUTPUT
DVOUT4:	MOVE	T3,IO.CHN	;[610] RESTORE POINTER TO I.XXX
	HRRZ	T3,IO.PTR(T3)	;[610] POSSIBLY DESTROYED BY PATH UUO
	SKIPN	2(T1)		;[610] ANY SFD'S???
	JRST	[MOVEM T4,I.PPN(T3)	;NO, STORE PPN
		JRST DVOUT6]	;[610] AND GO DEFAULT DEVICE
	MOVEM	T4,I.UFD(T3)	;THERE ARE..UFD GOES IN I.UFD
	MOVEI	T2,I.PTH(T3)	;GET POINTER TO PATH BLOCK
	MOVEM	T2,I.PPN(T3)	;AND PUT IT IN ENTER BLOCK
DVOUT5:	ADDI	T1,2		;[610] POINT TO NEXT SFD FROM SCAN
	SKIPN	T2,(T1)		;IS THIS THE END?
	JRST	DVOUT6		;[610] YES, GO DEFAULT DEVICE
				;NOTE THAT THIS IS THE ONLY
				; EXIT FROM THIS LOOP, BECAUSE
				; THERE WILL ALWAYS BE A ZERO
				; AFTER THE LAST SFD.
	MOVEM	T2,I.SFD(T3)	;NOT LAST SFD. STORE IT.
	AOJA	T3,DVOUT5	;[610] CHECK FOR MORE
				;*** NOTE T3 MODIFIED HERE ***


;CONTINUED ON NEXT PAGE
;NOW TO DEFAULT THE DEVICE. IF THE DEFAULT DEVICE IS ERSATZ,
;WE CAN ONLY USE IT IF EXPLICIT SPEC CONTAINED NEITHER DEVICE
;NOR PATH. NOTE THAT DEVICE DEFAULTING MUST TAKE PLACE AFTER PATH
;DEFAULTING TO AVOID CONFUSING THE DEFAULT AND EXPLICIT DEVICES
;IN PATH DEFAULTING CODE.

DVOUT6:	MOVE	T2,F.MOD(P1)	;[610] SEE IF USER GAVE EXPLICIT DEVICE
	TXNN	T2,FX.NDV	;[610] ..
	SKIPN	T2,F.DEV(P1)	;[610] BITS SAY SO, MAKE SURE
	CAIA			;[610] NO DEVICE, DO DEFAULTING
	JRST	DVOUT9		;[610] EXPLICIT DEVICE--GO USE IT
	SKIPN	T2,O.DEV	;[610] IS THERE A DEFAULT DEVICE?
	JRST	DVOUT8		;[610] NO, JUST GO USE DSK:
	MOVE	T1,[3,,T2]	;[610] SEE IF THE DEFAULT DEVICE IS
	PATH.	T1,		;[610]   ERSATZ VIA A PATH UUO
	  SETZ	T3,		;[610] PROBABLY NOT
	TXNN	T3,PT.IPP	;[610] IS IT ERSATZ?
	JRST	DVOUT7		;[610] NO, OK TO USE IT
	MOVE	T2,F.MODM(P1)	;[610] DEFAULT DEVICE IS ERSATZ. WE CAN
	TXNN	T2,FX.DIR	;[610]   ONLY USE IT IF NO EXPLICIT PATH
DVOUT7:	SKIPN	T2,O.DEV	;[610] OK TO USE THE DEFAULT DEVICE
DVOUT8:	MOVSI	T2,'DSK'	;[610] CAN'T USE DEFAULT, JUST USE DSK:
DVOUT9:	MOVE	T3,IO.CHN	;[610] RESTORE POINTER TO I.XXX BLOCK
	HRRZ	T3,IO.PTR(T3)	;[610]   (LOST TO DVOUT5)
	MOVEM	T2,I.DEV(T3)	;[610] STORE FINAL DEVICE
	JRST	DVCHK.		;[610] AND GO CHECK DATA MODE
;HERE TO DO ENTER FOR OUTPUT SPEC
;CALLED BY
;	PUSHJ	P,DVENT.##
;EXPECTS CHAN# IN IO.CHN
;ALSO DOES SWITCHES BEFORE FILE NAME

DVENT.::PUSHJ	P,DVCHK.	;GET DEVCHR, POINT TO I/O DATA BLOCK
	HLRZ	T2,I.SWT(T1)	;ANY SWITCHES TO DO
	JUMPE	T2,DVENTR	;BEFORE WE DO ENTER
	HRRZS	I.SWT(T1)	;CLEAR SWITCHES
DVENT1:	MOVE	T3,1(T2)	;GET UUO
	TLZ	T3,(Z 17,)	;CLEAR CHAN#
	OR	T3,I.CHN(T1)	;USE CORRECT ONE
	MOVE	T1,T2		;PRESERVE ADDRESS OF BLOCK TO DELETE
	MOVE	T2,2(T1)	;GET REPEAT COUNT
	XCT	T3		;DO UUO
	SOJG	T2,.-1		;REPEAT?
	MOVEI	T2,3
	SKIPN	0(T1)		;MORE?
	JRST	DVENT2		;NO
	PUSH	P,0(T1)		;YES
	PUSHJ	P,DY.RET##
	PUSHJ	P,DVCHN.	;RESET T1
	POP	P,T2		;AND POINTER
	JRST	DVENT1		;AND LOOP

;HERE FOR LAST TIME
DVENT2:	PUSHJ	P,DY.RET##
	PUSHJ	P,DVCHN.	;GET DATA BLOCK

DVENTR:	SETZM	I.ALC(T1)	;MAKE SURE ALLOCATION IS CLEAR
	MOVEI	T2,I.RIB(T1)	;POINT TO LOOKUP/ENTER BLOCK
	HRLI	T2,(ENTER)
	IOR	T2,I.CHN(T1)	;BUILT INST
	MOVE	T3,IO.CHR	;GET DEVCHR WORD
	TXNN	T3,DV.DSK	;ONLY DSK CAN DO EXTENDED ENTERS
	ADDI	T2,2		;DO NORMAL 4 WORD ENTER
	PUSH	P,I.PPN(T1)	;SAVE PATH FROM DESTRUCTION
	XCT	T2		;DO ENTER
	  PUSHJ	P,ENTERR	;FAILED
	POP	P,I.PPN(T1)	;RESTORE PATH (MONITOR LIES)
	MOVE	T1,IO.CHN	;GET CHAN#
	HRRZS	IO.PTR(T1)	;SIGNAL DONE
	POPJ	P,
DEFINE	XXX (CH,NUM,MODE)<
 IFN CH-%%,<
  REPEAT CH-%%,<
   0
 >>
 IFGE MODE,<
  IFIDN <MODE><.IODPR>,<
   NUM,0
  >
  IFDIF <MODE><.IODPR>,<
   NUM,CH'BUF
 >>
 IFL MODE,<
  NUM,0
 >
 %%==CH+1
>
SYN	XXX,XXXX
%%==0
	XALL
OBFTBL:	IODATA
	SALL

PURGE	%%,XXX,XXXX
;HERE TO DO SWITCH ACTION JUST PRIOR TO RELEASE
;AND TO DO RELEASE
;EXPECTS CHAN # IN IO.CHN

DVRLS.::PUSHJ	P,DVCLS.	;CLOSE FILE IF OPEN, GET DATA BLOCK
	JUMPE	T1,CPOPJ	;GIVE UP IF NO ACTIVE I/O
	HRRZ	T2,I.SWT(T1)	;ANY SWITCHES TO DO
	JUMPE	T2,DVRLSZ	;NO, JUST RELEASE
	SETZM	I.SWT(T1)	;CLEAR SWITCHES
DVRLS1:	MOVSI	T3,(MTWAT.)	;INCASE TAPE STILL MOVING (DTA?)
	IOR	T3,I.CHN(T1)
	XCT	T3
	MOVE	T3,1(T2)	;GET UUO
	TLZ	T3,(Z 17,)	;CLEAR CHAN#
	OR	T3,I.CHN(T1)	;USE CORRECT ONE
	MOVE	T1,T2		;ADDRESS OF BLOCK TO DELETE
	MOVE	T2,2(T1)	;REPEAT COUNT
	XCT	T3		;DO UUO
	SOJG	T2,.-1		;REPEAT IT?
	MOVEI	T2,3
	SKIPN	0(T1)		;MORE?
	JRST	DVRLS2		;NO
	PUSH	P,0(T1)		;YES
	PUSHJ	P,DY.RET##
	PUSHJ	P,DVCHN.	;RESET T1
	POP	P,T2		;AND POINTER
	JRST	DVRLS1		;AND LOOP

DVRLS2:	PUSHJ	P,DY.RET##	;RETURN SWITCH BLOCK
	PUSHJ	P,DVCHN.	;SETUP T1 AGAIN
DVRLSZ:	MOVSI	T2,(RELEASE)
	IOR	T2,I.CHN(T1)	;BUILD INST
	XCT	T2
	POPJ	P,

;HERE TO DO CLOSE
;CALLED BY
;	PUSHJ	P,DVCLS.
;EXPECTS CHAN# IN IO.CHN

DVCLS.::
IFN TOPS20,<
	MOVE	T1,IO.CHN	;PICK UP CHANNEL
	SKIPN	CHAN.JF(T1)	;[1511] JFN FOR THIS ONE?
	JRST	DVCLS0		;NO, DO UUOS
	MOVE	T1,CHAN.JF(T1)	;[1511]
	CLOSF%			;DO IT
	  JRST [  MOVE T1,IO.CHN;[1507]
		  POPJ P, ]	;HMM, NOT SUCCESSFUL
	MOVE	T1,IO.CHN	;ZERO OUT JFN
	SETZM	CHAN.JF(T1)
	SETZM	T1		;ALSO T1
	POPJ	P,		;OK, RETURN
DVCLS0:
> ;[1401] IFN TOPS20
	PUSHJ	P,DVCHN.	;POINT TO I/O DATA BLOCK
	MOVSI	T2,(CLOSE)
	IOR	T2,I.CHN(T1)	;COMPLETE INST.
	XCT	T2
	POPJ	P,
;HERE TO SET DEFAULT FILE NAME IF ZERO
;CALLED BY
;	PUSHJ	P,DVNAM.
;EXPECTS CHAN# IN IO.CHN

DVNAM.::PUSHJ	P,DVCHN.	;POINT TO I/O DATA BLOCK
	SKIPE	T2,I.NAM(T1)	;GET USER SUPPLIED NAME
	POPJ	P,		;YES, JUST RET
	SKIPE	T2,LODNAM	;NOT SUPPLIED USE MAIN PROG NAME
	JRST	.+3		;HOWEVER IF STILL ZERO
	HLLZ	T2,JOBNUM	;GET SIXBIT JOBNUMBER
	HRRI	T2,'LNK'	;000LNK BY DEFAULT
	MOVEM	T2,I.NAM(T1)
	POPJ	P,
;HERE TO GET INTO UPDATE MODE FOR OVERFLOW FILES
;CALLED BY
;	MOVEI	T1,CHAN#
;	PUSHJ	P,DVUPD.
;RETURNS
;+1	FAILED (LOOKUP OR ENTER)
;+2	SUCCESS
;USES T1, T2, T3

DVUPD.::
IFN TOPS20,<
	CAIE	T1,OC		;[1407] OVERLAY FILE?
	JRST	DVUPDX		;[1407] NO, DO NATIVE UPDATE
> ;[1407]

;IFE TOPS20,<
	HRLZ	T2,T1		;CHAN # IN LEFT
	LSH	T2,5		;THENCE TO AC FIELD
	MOVE	T1,IO.PTR(T1)	;POINT TO DATA CHAN
	MOVEM	T2,I.CHN(T1)	;STORE INCASE NEEDED
	HRRI	T2,I.MOD(T1)	;ADDRESS OF OPEN BLOCK
	TLO	T2,(OPEN)
	XCT	T2
	  JRST	E01OFD		;[1174] SHOULD NEVER HAPPEN FOR DSK
	HRRI	T2,I.RIB(T1)	;POINT TO LOOKUP/ENTER BLOCK
	TLC	T2,027000	;OPEN .XOR. ENTER
	MOVE	T3,I.PPN(T1)	;SAVE PPN INCASE DEFAULT PATH
	XCT	T2		;ENTER FILE
	  POPJ	P,		;FAILED
	MOVEM	T3,I.PPN(T1)	;RESTORE DIRECTORY
	TLZ	T2,007000	;CONVERT TO CLOSE
	HRRI	T2,CL.DLL	;BUT DON'T DEALLOCATE
	XCT	T2
	HRRI	T2,I.RIB(T1)	;PUT LOOKUP ADDRESS BACK
	TLO	T2,006000	;LOOKUP
	XCT	T2
	  POPJ	P,		;FAILED
	MOVEM	T3,I.PPN(T1)	;RESTORE DIRECTORY
IFN	TOPS20,<		;[1250]
	MOVX	T3,RB.PRV+RB.MOD;[1250] SET UP FIELDS TO SAVE
	ANDM	T3,.RBPRV(T2)	;[1250] CLEAR DATE/TIME FIELDS
	HLLZS	.RBEXT(T2)	;[1250] SO PA1050 WON'T USE THEM
	MOVE	T3,I.PPN(T1)	;[1250] GET BACK DIRECTORY
>				;[1250]
	TLO	T2,001000	;ENTER
	XCT	T2
	  POPJ	P,		;FAILED
	JRST	CPOPJ1		;[1407] SUCCESS
;>  ;[1401] IFE TOPS20
IFN TOPS20,<
DVUPDX:	MOVEM	T1,IO.CHN		; CHAN# TO IO.CHN GLOBAL
	HRLZ	T2,T1			;[2301] CHAN # IN LEFT
	LSH	T2,5			;[2301] THENCE TO AC FIELD
	MOVE	T1,IO.PTR(T1)		;[2301] POINT TO DATA CHAN
	MOVEM	T2,I.CHN(T1)		;[2301] STORE INCASE NEEDED
	MOVEI	T1,1(P)			;[1530] NOTE START OF FREE STACK
	ADJSP	P,LN.FL			;[2017] GET SOME SPACE THERE
	PUSHJ	P,DVTXT1		;[1530] CREATE THE STRING
	MOVE	T2,T1			; AND NOTE BYTEPOINTER THERETO
	MOVX	T1,<GJ%FOU!GJ%SHT>	;[2247] CREATE NEW TEMP FILE
	MOVE	T3,IO.CHN		;[2247] GET THE CHANNEL
	CAIE	T3,DC			;[2247] .EXE FILE?
	 JRST	DVUPD1			;[2247] NO
	PUSH	P,T2			;[2247] SAVE THE NAME POINTER	
	GTJFN%				;[2247] NEED A SPARE JFN
	  JRST	[ ADJSP P,-<LN.FL+1>	;[2301] REMOVE AC AND NAME BLOCK
		  JRST	DVERR. ]	;[2301] FAILURE
	MOVE	T3,T1			;[2247] GOT IT, HOLD ON TO IT
	POP	P,T2			;[2247] GET BACK THE FILESPEC
	MOVX	T1,<GJ%FOU!GJ%SHT>	;[2247] GET THE FLAGS BACK
DVUPD1:	GTJFN%				;[2247] GET THE JFN
	  JRST	[ ADJSP P,-LN.FL	;[2017]
		  JRST DVERR. ]		;[2301] FAILURE
	ADJSP	P,-LN.FL		;[2017] THROW AWAY STRING
	MOVE	T2,IO.CHN		;[1461] PICK UP CHANNEL AGAIN
	MOVEM	T1,CHAN.JF(T2)		;[1461] STASH JFN AWAY ...
	CAIN	T2,DC			;[2247] IF .EXE FILE
	JRST	CPOPJ1			;[1461] DON'T BOTHER WITH AN OPENF
	MOVE	T2,[BYTE (6)0(4).GSNRM]	; FILE BYTESIZE AND MODE
	IOR	T2,[OF%RD!OF%WR!OF%THW!OF%DUD]
	OPENF%				; OPEN THE FILE
	 JRST	DVERR.			;[2301] FAILURE
>  ;[1401] IFN TOPS20
CPOPJ1:	AOS	(P)
CPOPJ:	POPJ	P,
;HERE TO DELETE A FILE & RELEASE CHAN#
;CALLED BY
;	MOVEI	T1,CHAN#
;	PUSHJ	P,DVDEL.
;USES T1, T2
;RETURNS
;+1	FAILED
;+2	SUCCESS

DVDEL.::
IFN TOPS20,<
	PUSH	P,T1		;SET ASIDE CHANNEL #
>  ;[1401] IFN TOPS20
	PUSHJ	P,DVDLF.	;DELETE FILE
IFE TOPS20,<
	  POPJ	P,		;NON-SKIP RETURNS (FAILURE)?
> ;[1401] IFE TOPS20
IFN TOPS20,<
	  JRST	[ POP P,T1
		  POPJ P, ]	; RETURN
	POP	P,T1
	SKIPE	CHAN.JF(T1)	;WAS HANDLED BY DELF?
	JRST	[ SETZM CHAN.JF(T1)
		  JRST	CPOPJ1	;YES, GOODBYE!
		]
> ;[1401] IFN TOPS20
	TLC	T2,024000	;RELEASE_RENAME
	HLLZ	T2,T2		;CLEAR RHS INCASE CLOSE BITS EVER WORK
	XCT	T2
	JRST	CPOPJ1		;OK RETURN
;HERE TO JUST DELETE A FILE
;CALLED BY
;	PUSHJ	P,DVDLF.
;ARGS AS ABOVE

DVDLF.::
IFN TOPS20,<
	SKIPN	CHAN.JF(T1)	;[1513] IF A JFN EXISTS USE DELF JSYS
	JRST	DVDLF0		;OTHERWISE USE UUOS
	MOVE	T1,CHAN.JF(T1)	;[1513]
	DELF%			;DELETE FILE
	  SKIPA			;TOO BAD
	CLOSF%			;[1541] CLOSE IT
	 SKIPA			;[1541] TOO BAD
	AOS	0(P)		;CLAIM SUCCESS
	JRST	DVCEM.		;AND GO WIPE IO.ERG
DVDLF0:>  ;[1401] IFN TOPS20
	HRLZ	T2,T1		;CHAN# IN LEFT
	LSH	T2,5		;THENCE TO AC FIELD
	MOVE	T1,IO.PTR(T1)	;GET PTR TO DATA
DVDLFC:				;ENTER HERE WITH T2 =CHAN # IN AC FIELD
				;AND T1 POINTING TO DATA BLOCK
				;NOW COPY FILE SPEC TO SAFE PLACE
				;OTHERWISE STRANGE ERRORS OCCUR ON FUTURE RENAMES
	HRLZ	T3,T1		;FROM
	HRRZ	T1,IO.EMG	;A SAFE PLACE
	HRR	T3,T1		;TO
	BLT	T3,LN.IO-1(T1)	;T1 POINTS TO NEW BLOCK
	TLO	T2,(CLOSE)	;CLOSE FILE INCASE STILL OPEN
	XCT	T2
	HRRI	T2,I.RIB(T1)	;POINT TO LOOKUP BLOCK
	TLO	T2,006000	;CONVERT CLOSE TO LOOKUP
	PUSH	P,I.PPN(T1)	;SAVE PATH OVER LOOKUP
	XCT	T2
	  JRST	DVDLF1		;TOO BAD
	SETZM	I.NAM(T1)	;CLEAR NAME
	TLC	T2,023000	;RENAME _ LOOKUP
	XCT	T2		;DELETE FILE
	  JRST	DVDLF1		;TOO BAD
	AOS	-1(P)		;OK RETURN
DVDLF1:	POP	P,I.PPN(T1)	;RESTORE PATH FROM ENTRY
;	PJRST	DVCEM.		;CLEAR IO.EMG AND RETURN

;ROUTINE TO CLEAR IO.EMG, THE EMERGENCY FREE I/O DATA BLOCK
;CALLED BY
;	PUSHJ	P,DVCEM.
;
;USES T1,T3
;*** WARNING *** MUST LEAVE T2 UNCHANGED

DVCEM.::MOVE	T1,IO.EMG	;GET POINTER TO I/O BLOCK
	HRLZ	T3,T1		;BLT TO CLEAR IO.EMG
	HRRI	T3,1(T1)	;SO ITS FREE FOR NEXT TIME
	SETZM	(T1)
	BLT	T3,LN.IO-1(T1)
	POPJ	P,
;HERE TO RENAME A FILE
;CALLED BY
;	MOVE	T1,IO.CHN+CHAN# OF NEW FILE
;	MOVE	IO.CHN CHAN# OF OLD FILE
;	PUSHJ	P,DVRNF.
;USES T1, T2, T3, T4
;RETURNS
;+1	FAILED
;+2	SUCCESS

DVRNF.::PUSH	P,T1		;SAVE T1
	PUSHJ	P,DVCLS.	;CLOSE OUT OLD FILE
	POP	P,T2		;RECOVER NEW NAME
	MOVEI	T3,I.RIB(T1)	;ADDRESS
	TLO	T3,(LOOKUP)
	IOR	T3,I.CHN(T1)	;PLUS CHAN#
	PUSH	P,I.PPN(T1)	;SAVE PPN IN CASE DEFAULT PATH
	XCT	T3		;LOOKUP
	  JRST	[POP	P,0(P)	;ERROR - RESTORE STACK
		POPJ	P,]	;AND GIVE ERROR RETURN TO CALLER
	POP	P,I.PPN(T1)	;DON'T BELIEVE FALSE MONITOR VALUE
	TLC	T3,023000	;RENAME_LOOKUP
	HRRI	T3,I.RIB(T2)	;POINT TO NEW NAME
	LDB	T4,[POINT 9,I.PRV(T2),8]	;GET USER SPECIFIED PROTECTION
	SKIPE	T4		;UNLESS NOT SPECIFIED
	DPB	T4,[POINT 9,I.PRV(T1),8]	;STORE IN OLD SO WE COPY IT
	MOVE	T4,I.PRV(T1)	;GET DATE TIME ETC
	MOVEM	T4,I.PRV(T2)	;SINCE SAME FILE
	HRRZ	T4,I.EXT(T1)	;GET HIGH ORDER PART
	HRRM	T4,I.EXT(T2)	; ALSO
	PUSH	P,I.PPN(T2)	;SAVE PATH, SINCE MONITOR WIPES IT
	XCT	T3
	  JRST	DVRNFE		;TEST ERROR CONDITION
	POP	P,I.PPN(T2)	;RESTORE TO BEFORE (MONITOR LIES)
	JRST	CPOPJ1		;OK RETURN

DVRNFE:	POP	P,I.PPN(T2)	;RESTORE REAL PPN OF FILE
	HRRZ	T4,I.EXT(T2)	;GET RENAME ERROR CODE
	CAIE	T4,ERAEF%	;ALREADY EXISTS
	POPJ	P,		;NO, JUST IGNORE THIS ERROR?
	PUSH	P,I.NAM(T2)	;SAVE NAME
	PUSH	P,T2		;SAVE P2
	EXCH	T1,T2		;GET POINTER TO 2ND FILE
	MOVE	T2,I.CHN(T2)	;GET CHAN# TO 1ST FILE
	PUSHJ	P,DVDLFC
	  JRST	[SUB P,[2,,2]	;BACKUP STACK
		POPJ	P,]	;AND GIVE UP
	POP	P,T1		;RESTORE POINTER
	POP	P,I.NAM(T1)	;AND NAME
	JRST	DVRNF.		;TRY AGAIN
;DVUPD. TAKES THE CHANNELS FOR AN OUTPUT FILE (SAY, THE OVERLAY FILE) AND ITS
;ASSOCIATED OVERFLOW FILE, AND ATTEMPTS TO PUT THE OVERFLOW FILE EXACTLY WHERE
;THE OUTPUT FILE WILL EVENTUALLY GO. THE ASSUMPTION IS THAT THE FORMAT OF THE
;OVERFLOW FILE IS THE SAME AS THE EVENTUAL OUTPUT FILE, SO A SIMPLE RENAME MAY
;BE DONE AT THE END OF LOADING.
;
;THE METHOD USED IS TO TEMPORARILY OPEN AND ENTER THE OUTPUT FILE TO SEE WHERE
;IT WILL GO, AND THEN PUT THE OVERFLOW FILE IN THAT AREA. THIS HAS THE ADVANTAGE
;THAT ALL LOGICAL NAMES AND SEARCH LISTS ARE AUTOMATICALLY TRACKED DOWN FOR US
;BY THE MONITOR, AND FILES SUPERSEDING EXISTING ONES END UP ON THE CORRECT
;STRUCTURE. THE ARGUMENTS FROM THE EXTENDED ENTER AND PATH. UUOS WILL THEN TELL
;US WHERE THE OVERFLOW FILE SHOULD GO.
;
;THE DECISION TO DO A RENAME IN LNKXIT IS THEN MADE BY COMPARING THE DEVICE OF
;THE OVERFLOW FILE WITH THE DEVICE OF THE OUTPUT FILE. THIS REQUIRES THAT ALL
;LOGICAL NAMES, ERSATZ DEVICES, ETC. MUST BE RESOLVED INTO THE EXACT STRUCTURE
;AND PATH SO THAT THE OUTPUT FILE WILL END UP IN THE RIGHT PLACE.
;
;CALL:
;	T1/	CHANNEL OF THE OUTPUT FILE
;	T2/	CHANNEL OF THE ASSOCIATED OVERFLOW FILE
;
;RETURNS +1 IF THE OVERFLOW FILE COULD NOT BE OPEN, AND +2 IF IT COULD. THE
;OVERFLOW FILE WILL BE IN THE SAME AREA THAT THE OUTPUT FILE WILL GO, UNLESS
;THAT ISN'T A DISK. IN THAT CASE, THE OVERFLOW FILE WILL BE INITIALIZED ON
;DSK:[-]. ALSO, IF THE OVERFLOW FILE WAS PUT WHERE THE OUTPUT FILE WILL
;EVENTUALLY GO, THEN THE OUTPUT FILE'S SPEC WILL HAVE BEEN CHANGED FROM WHAT THE
;USER ACTUALLY TYPED (SAY, SYS:PROG.OVL) TO THE EXACT SPECIFICATION FOR THAT
;FILE (SAY, DSKB:PROG.OVL[1,5] IF /NEW WAS SET).

DVSUP.::SPUSH	<P1,P2>			;[1230] SAVE SOME STABLE ACS
	MOVE	P1,IO.PTR(T1)		;[1230] KEEP REAL CHANNELS AND POINTERS
	HRLI	P1,(T1)			;[1230]   TO I/O DATA BLOCKS AROUND
	MOVE	P2,IO.PTR(T2)		;[1230]   ..
	HRLI	P2,(T2)			;[1230]   ..
	HRROM	P1,IO.PTR(T2)		;[1230] START WORK ON USER'S OUTPUT SPEC
	HLRZM	P2,IO.CHN		;[1230]   BY USING OVERFLOW FILE'S CHAN
	PUSHJ	P,DVCHK.		;[1230] SEE IF USER'S FILE IS ON A DISK
	MOVE	T1,IO.CHR		;[1230]   ..
	TLC	T1,-1-<(DV.TTA)>	;[1230]   AND NOT ON NUL:
	TLCE	T1,-1-<(DV.TTA)>	;[1230]   ..
	TXNN	T1,DV.DSK		;[1230]   ..
	JRST	DVSUP1			;[1230] NOT A DISK--CAN'T OVERFLOW THERE

;  ..
;  ..

	PUSHJ	P,DVOPN.		;[1230] OPEN ...
	PUSHJ	P,DVENT.		;[1230]   ... AND ENTER USER'S FILE
	MOVE	T1,I.RIB+.RBDEV(P1)	;[1230] COPY THE EXACT DEVICE
	MOVEM	T1,I.DEV(P1)		;[1230]   FOR USE BY THE OUTPUT FILE
	MOVEM	T1,I.DEV(P2)		;[1230]   AND THE OVERFLOW FILE
	MOVE	T1,IO.CHN		;[1230] COPY THE EXACT PATH ALSO
	MOVEM	T1,I.PTH+.PTFCN(P1)	;[1230]   BY DOING A PATH. UUO ON THE
	MOVSI	T1,LN.SFD		;[1230]   CHANNEL NOW OPEN AND ENTERED
	HRRI	T1,I.PTH(P1)		;[1230]   ..
	PATH.	T1,			;[1230]   ..
	  SETZM	I.PTH+.PTPPN(P1)	;[1230] NO PATH. UUO?! THEN [-] WORKS
	MOVSI	T1,I.PTH(P1)		;[1230] COPY EXACT PATH FOR USE BY
	HRRI	T1,I.PTH(P2)		;[1230]   THE OVERFLOW FILE TOO
	BLT	T1,I.PTH+LN.SFD-1(P2)	;[1230]   ..
	MOVEI	T1,I.PTH(P1)		;[1230] MAKE EACH ENTER BLOCK POINT
	MOVEM	T1,I.RIB+.RBPPN(P1)	;[1230]   TO ITS OWN PATH. BLOCK
	MOVEI	T1,I.PTH(P2)		;[1230]   ..
	MOVEM	T1,I.RIB+.RBPPN(P2)	;[1230]   ..
	HLLZS	I.RIB+.RBEXT(P1)	;[1230] ZERO ANY ENTER ARGS THAT MAY
	MOVX	T1,<INSVL. 777,RB.PRV>	;[1230]   MAY HAUNT US LATER
	ANDM	T1,I.RIB+.RBPRV(P1)	;[1230]   ..
	SETZM	I.RIB+.RBSIZ(P1)	;[1230]   ..
	SETZM	I.RIB+.RBSPL(P1)	;[1230]   ..
	MOVSI	T1,I.RIB+.RBALC(P1)	;[1230]   ..
	HRRI	T1,I.RIB+.RBALC+1(P1)	;[1230]   ..
	SETZM	T1,I.RIB+.RBALC(P1)	;[1230]   ..
	BLT	T1,I.RIB+LN.RIB-1(P1)	;[1230]   ..
	MOVE	T1,IO.CHN		;[1230] GET RID OF USER'S FILE NOW THAT
	RESDV.	T1,			;[1230]   WE KNOW WHERE IT WILL GO
	  JFCL				;[1230] FORGET ERRORS
	JRST	DVSUP2			;[1230] NOW READY TO OPEN OVERFLOW FILE

DVSUP1:	MOVX	T1,'DSK   '		;[1230] PUT OVERFLOW FILE IN DSK:[,]
	MOVEM	T1,I.DEV(P2)		;[1230]   ..
	SETZM	I.RIB+.RBPPN(P2)	;[1230]   ..
;	JRST	DVSUP2			;[1230] NOW READY TO OPEN OVERFLOW FILE

DVSUP2:	HLRZ	T1,P2			;[1230] SET UP CHANNEL FOR OVERFLOW FILE
	HRRZM	P2,IO.PTR(T1)		;[1230] UNDO USE OF OUTPUT FILE
	PUSHJ	P,DVUPD.		;[1230] OPEN OVERFLOW FILE IN UPDATE MODE
	  SKIPA				;[1230] FAILED--SKIP THE SKIP RETURN
	AOS	-2(P)			;[1230] FILE OPENED SUCCESFULLY--SKIP
	SPOP	<P2,P1>			;[1230] RESTORE SAVED ACS
	POPJ	P,			;[1230] DONE
SUBTTL	TOPS-20 JSYS ROUTINES


IFN TOPS20,<

;HERE TO CONVERT SCAN BLOCK INTO TEXT STRING
;CALLED BY
;	MOVEM	AC,IO.CHN	STORE CHANNEL # AWAY
;	PUSHJ	P,DVTXT.
;DVTXT1 ENTRY POINT IS FOR TIMES WHEN WE KNOW WHERE THE
; STRING OUGHT TO GO.

DVTXT.::MOVEI	T2,F.LEN	;GET SPACE TO STORE STRING
	PUSHJ	P,DY.GET##
DVTXT1::MOVE	T4,T1		;SAFER PLACE
	HRLI	T4,(POINT 7)	;MAKE INTO BYTE PTR
	PUSH	P,T4		;[1402] SET ASIDE INITIAL PTR
	PUSHJ	P,DVCHN.	;GET DATA BLOCK IN T1
	SKIPN	T3,I.DEV(T1)	;GET DEVICE
	JRST	DVTXT2		;NO DEVICE
	PUSHJ	P,DVDPB.	;STORE
	MOVEI	T2,":"
	IDPB	T2,T4
DVTXT2:
	SKIPN	T2,I.PPN(T1)	;[1407] SEE IF DIRECTORY
	JRST	DVTXT3		;NO
; THIS CODE DOESN'T DO ANYTHING USEFUL TODAY, BUT WHEN
; THE COMMAND SCANNER UNDERSTANDS DIRECTORY NAMES IT SHOULD
; BE PUT BACK INLINE.
;	MOVEI	T2,"<"		;OPEN IT
;	IDPB	T2,T4
;	PUSHJ	P,DVDPB.	;STORE NAME
;	MOVEI	T2,">"
;	IDPB	T2,T4		;CLOSE IT
	PUSH	P,T1		;[1407] SAVE AWAY DEV BLOCK PTR
	MOVE	T1,-1(P)	;[1407] RE-USE STRING FOR DESTINATION
	MOVE	T3,T1		;[1407] CURRENTLY THE DEVICE
	PPNST%
	  ERJMP	DVTXT3-1		;[1407] TOO BAD!
	EXCH	T4,T1		;[1407] NEW CURRENT BYTE POINTER
	POP	P,T1		;[1407] AND GET DEV BLOCK PTR BACK

DVTXT3:	MOVE	T3,I.NAM(T1)	;[1402]
	PUSHJ	P,DVDPB.	
	SKIPN	T3,I.EXT(T1)	;[1402]
	JRST	DVTXT4		;NO EXTENSION
	MOVEI	T2,"."
	IDPB	T2,T4
	PUSHJ	P,DVDPB.
DVTXT4:
	SETZM	T2		;[1402]
	IDPB	T2,T4		;[1402] INSERT TRAILING NULL
	POP	P,T1		;[1402] GET BACK INITIAL TEXT PTR
	POPJ	P,
;HERE TO STORE BYTE IN STRING
;CALLED BY
;	T3 = SIXBIT WORD
;	T4 = BYTE PTR
;	PUSHJ	P,DVDPB.
;USES T2

DVDPB.::JUMPE	T3,CPOPJ	;[2101] EXIT IF DONE CONVERTING
	SETZ	T2,
	LSHC	T2,6		;GET NEXT CHAR
	ADDI	T2," "		;TO ASCII
	IDPB	T2,T4
	JRST	DVDPB.		;[2101] LOOP UNTIL DONE

;DVGFO. - ROUTINE TO DO GTJFN FOR OUTPUT FILE
;EXPECTS TEXT STRING IN IO.PTR(IO.CHN)
;STORES JFN THERE ON COMPLETION

DVGFO.::MOVE	T4,IO.CHN	;GET CHAN#
	MOVSI	1,(1B0+1B17)	;OUTPUT SO VERSION# STUFF WORKS RIGHT
	HRRO	2,IO.PTR(T4)	;POINT TO TEXT STRING
	GTJFN%
 	  HALT
	EXCH	T1,IO.PTR(T4)	;STORE JFN
	MOVEI	T2,F.LEN
	PJRST	DY.RET##	;REMOVE TEXT STRING

>;[1401] END OF IFN TOPS20
SUBTTL	ERROR MESSAGES


E01OFD::PUSH	P,IO.CHN	;[1174] PUT CHANNEL ON STACK
	.ERR.	(I,0,V%L,L%F,S%F,OFD) ;[1174]

E01NED::PUSH	P,IO.CHN	;[1174] PUT CHANNEL ON STACK FOR LNKLOG
	.ERR.	(I,0,V%L,L%F,S%E,NED)
	POPJ	P,		;[1174] RETURNS IF CHAN WAS DC; TRY NOW

ENTERR:	MOVE	T1,IO.CHN
	HRLI	T1,(%ENT)	;[1123] SIGNAL ENTER
	MOVE	T2,IO.CHR	;GET DEVCHR WORD
	TXNE	T2,DV.DTA	;DTA MIGHT BE SPECIAL
	JRST	[MOVE	T2,IO.PTR(T1)	;[1174] GET DATA BLOCK POINTER
		HRRZ	T3,I.EXT(T2)	;[1174] IF ERROR WAS ERPRT%
		CAXN	T3,ERPRT%	;[1174] AS IT MEANS DIRECTORY FULL
		HLLOS	I.EXT(T2)	;[1174] SIGNAL BY -1
		JRST	.+1]
E01FEE::PUSH	P,T1		;[1174] SAVE CHANNEL FOR LNKLOG
	.ERR.	(LRE,,V%L,S%D,L%D,FEE) ;[1174]
	POPJ	P,

E01FLE::PUSH	P,IO.CHN	;[1174] REMEMBER WHAT # FAILED
IFE TOPS20,<			;[2301]
	.ERR.	(LRE,,V%L,S%D,L%D,FLE) ;[1174]
> ;[2301] IFE TOPS20
IFN TOPS20,<
E$$COF::.ERR.	(LRE,.EC,V%L,S%D,L%D,COF,<Cannot open file>) ;[2301]
	.ETC.	(NLN,.EC)	 ;[2301] CRLF
	.ETC.	(STR,,,,,ERRJSY) ;[2301] Type error text
>;[2301] IFN TOPS20
	POPJ	P,

IFN TOPS20,<		;[2301]
;[2301] DVERR. - Routine to do store TOPS-20 error
;[2301] Stores error in right half of I.EXT(I)
;[2301] Expects channel in I.CHN

DVERR.::
	MOVEI	T1,.FHSLF	;[2301] Get the fork handle
	GETER%			;[2301] Get the error in T2
DVERR1:	PUSHJ	P,DVCHN.	;[2301] Set pointer to I/O block
	HRRM	T2,I.EXT(T1)	;[2301] Remember the error
	MOVE	T1,IO.CHN	;[2301] Get the channel back
	SKIPN	T1,CHAN.JF(T1)	;[2301] Get the JFN
	 POPJ	P,		;[2301] No JFN, just return
	TXO	T1,CO%NRJ	;[2301] Don't return the JFN
	CLOSF%			;[2301] Close the file
	 JFCL			;[2301] Probably not open
	POPJ	P,		;[2301] Done
>;[2301] IFN TOPS20
SUBTTL	THE END


FIOLIT:	END