Google
 

Trailing-Edge - PDP-10 Archives - tops10_tools_bb-fp64a-sb - 10,7/f11/f11.mac
There are 10 other files named f11.mac in the archive. Click here to see a list.
	TITLE	F11
	SALL
	SEARCH	UUOSYM
	.REQUE	REL:WILD, REL:SCAN
	TWOSEG
	RELOC	400000
	RELOC	0
	LOWSEG=.
	RELOC
	.DIRECT	FLBLST

Comment	@
	F11 is a cheap program to create, destroy, and manipulate
	FILES-11 structures and files.
	@
	SUBTTL	Revision History

VER==1	;7-Jan-85
	;	Duplicate some of the functionality of FESET with known compiler
VER==2	;6-Nov-85
	;	Teach NXTFDB to ignore files with a file number of zero if the
	;	file being matched is non-null.  Seems F11ACP does strange and
	;	wonderful things when dealing with files (such as leaving the
	;	directory entry and just zeroing the FHB).  Fix a few bugs in
	;	image mode PUT code so first free byte gets set up correctly.
VER==3  ;1-Jan-86
        ;       Fix "?NO WORD FOR INPUT" - remove instruction at EOFBYT+22L.
        ;       Fix "?Ill UUO at..." - pop T3 off stack before POPJ at FCRLF+4L
        ;       Fix "?Illegal switch" - forbid using "=" for switches @ILLSWT+6L
        ;       RSX20F allows null file names! - make NXTFDB check name AND type
        ;               before declaring directory slot as "null"
        ;       LIBRARY files are not ascii - add .OLB and .SML to IMGTBL.
        ;       Adding 33rd file to a UFD causes problems.  Create EXPDIR
        ;               to expand a UFD (or MFD) by one block and make it work.
        ;       Add ASS FOO:=BLAH/IMAGE to allow reading a file which is a
        ;               "disk image" file - ie: 1:1 correspondence between
        ;               tops10 data blocks and a real disk.
        ;       Do some things to make a F11 maintained "volume" acceptable
        ;               to the RSX "VFY" utility (so it can recover lost blocks
        ;               or simply verify the correctness of the volume)
        ;
        ;               o Create TOPS10.NDL;n files in [0,0] to occupy the space
        ;                 between physical block 0 and the 1st block of FE.SYS.
        ;               o Stop setting the "dirty" bits in the Storage Control
        ;                 Block in BITMAP.SYS.
        ;               o Insert the "max # of retrieval pointers possible"
        ;                 in the proper slot when the FHB is initialized.
        ;               o Insert the "BMAX" word into the Storage Control Block.
        ;                 (it contains a copy of the last valid LBN in volume).

	LOC	<.JBVER=137>
	VER
	RELOC
	SEARCH	$SCNDC,MACTEN
	EXTERN	.TYOCH		;FORCE SCAN TO LOAD WILD SUBROUTINES

;	THESE ACS ARE IN ADDITION TO THOSE DEFINED IN $SCNDC FOR SCAN
DEFINE BIT,<1B<BITNUM==<BITNUM+1>>>
BITNUM==-1
F=0
	X%INTRO==BIT	;INTRO LINE ALREADY TYPED
	X%EOF==BIT	;EOF PENDING
	X%SUPER==BIT	;SUPERCEEDING
	X%REEAT==BIT	;TYI SHOULD RETURN LASTCH AGAIN
	X%ODD==BIT	;ODD # OF BYTES IN ASCII RECORD
	X%UIC==BIT	;TYPFHB SHOULD GIVE UIC
	X%VMS==BIT	;VERTICAL MOTION SEEN ON THIS LINE
	X%PEOF==BIT	;PREMATURE EOF
	X%INT==BIT	;INTERACTIVE OUTPUT DEVICE (DO OUTPUT AFTER CRLF)


N==P3			;COPY SCAN'S N AC

U0=16

FP=13	;FILE POINTER AC
M1=14	;1ST MASK WORD
M2=15	;2ND MASK WORD
;N.B.:	IT SEEMS LIKE SCAN DOES NOT USE ACS 0, 11 THRU 16, INCLUSIVE
;	HERE ARE SOME RANDOM CONSTANTS

;THESE ARE I/O CHANNELS
TTY=10	; TTY I/O
FIO==15	; FILE I/O
VIO=16	; VOLUME I/O
WLD==17	; WILD'S I/O

.RBSLF==177	; WORD IN TOPS-10 FILE RIB THAT POINTS TO ITSELF

M.INFH==^D64	;# OF FILE HEADER BLOCKS (FHBs) IN FIRST CHUNK OF INDEXF.SYS
		;NOT SURE, BUT SUSPECT MUST BE GREATER THAN 5.
		;ALSO, DUE TO LAZINESS ON OUR PART TO CORRECTLY UPDATE
		;THE EQUIVILENT OF THE RETRIEVAL POINTER IN THE FHB FOR
		;INDEXF.SYS, YOU REALLY OUGHT TO MAKE THIS NUMBER LARGE ENOUGH
		;TO ACCOUNT FOR THE NUMBER OF FILES YOU EXPECT TO HAVE IN
		;A NEWLY CREATED FILES-11 VOLUME WHICH IS MANIPULATED BY
		;F11 - OF COURSE 20F ITSELF WILL CORRECTLY ADD MORE THAN
		;M.INFH FILES AND DO CORRECT UPDATES.
; **** N.B. **** DUE TO DESIGN DEFICIENCIES IN "FELOAD", F11ACP.TSK MUST
; ****      **** HAVE AN FHB ALLOCATED IN THE FIRST CHUNK OF INDEXF.SYS
; ****      **** OR IT WILL NOT BE ABLE TO FIND F11ACP DURING THE LOAD

OPDEF	PJRST	[JRST]

VOLMAX=3	;MAX NUMBER OF CONCURRENTLY DEFINED LOGICAL VOLUMES
	SUBTTL	DEFINITIONS -- MACROS

;	DEFINE THE DEFINE'R MACRO
DEFINE DEFPRE(.a),<.prefix=='.a'
		.offset==0>

DEFINE X(.name,.size,.defalt),<
	IFNB <.name>,<	A.'.name'==<.prefix>
			 .XCREF A.'.name', S.'.name'>
	O.'.name'==.offset
	.offset==.offset+^D'.size'
	S.'.name'==^D'.size'
	IFNB <.defalt>,< M.'.name'==.defalt>
	>
	SUBTTL	TOPS-10 HOME BLOCK

DEFPRE	<HOME1>

HOMNAM==0	;PDP10 WORD #0 HAS 36 BITS OF SIXBIT *HOM*
.OFFSET==HOMNAM*4;FORCE PDP11 POINTER AT HOMNAM
X	HSIX,2	; CONTAIN "SIXBIT" 'HOM'
X	HSX0,2	; CONTAIN 0'S

HOMFE0==61	;PDP10 WORD#61 HAS 36 BIT POINTER TO FE.SYS (AND VALID BIT)
.offset==HOMFE0*4;FORCE PDP11 POINTER AT HOMFE0
X	HLBN,4	; ADDRESS OF PDP11 FE.SYS FILE
HOMFE1==62	;PDP10 WORD#62 HAS 36 BIT LENGTH OF FE.SYS
X	HLEN,4,^D2048	;LENGTH OF PDP11 FE.SYS FILE
	SUBTTL	FILES-11 HOME BLOCK

DEFPRE	<H11BUF>	;THESE ALL OFFSET OFF OF H11BUF

X	IBSZ,2		; SIZE OF INDEX-BIT-MAP IN BLOCKS
X	IBLH,2		; DISK LBN ADRRES OF INDEX BIT MAP  HIGH WORD
X	IBLL,2		; DISK LBN ADDRESS OF INDEX BIT MAP  LOW WORD
X	FMAX,2,^O77777	; MAX # OF FILES ALLOWED ON THIS VOLUME
X	SBCL,2,1	; CLUSTER SIZE FOR STORAGE-BIT-MAP
X	DVTY,2		; DISK-DEVICE TYPE
X	VLEV,2		; STRUCTURE LEVEL
X	VNAM,12		; VOLUME NAME
X	,4		; RESERVED AREA
X	VOWN,2,401	; VOLUME OWNER'S DECIMAL UIC IN BINARY (IE: [1,1])
X	VPRO,2,0	; VOLUME PROTECTION CODE
X	VCHA,2,30	; VOLUME CHARACTERISTICS (30=NO ATTACH, NO DEVICE CONTROL FCNS)
X	DFPR,2,164000	; DEFAULT PROTECTION FOR FILES
X	,6		; RESERVED AREA
X	WISZ,1,7	; DEFAULT # OF RETRIEVAL PAIRS IN A WINDOW
X	FIEX,1,5	; DEFAULT # OF BLOCKS TO EXTEND FILES
X	LRUC,1,3	; # ENTRIES IN A DIRECTORY LRU
X	,11		; "AVAILABLE SPACE"
X	CHK1,2		; CHECKSUM OF WORDS 0-28

X	VDAY,2		; 2 DIGIT DAY OF MONTH
X	VMON,3		; 3 BYTE NAME OF MONTH
X	VYER,2		; 2 DIGIT YEAR IN CENTURY
X	,1		; ? BLANK PERHAPS?
X	VHOR,2		; 2 DIGIT HOUR IN DAY
X	VMIN,2		; 2 DIGIT MINUTE IN HOUR
X	VSEC,2		; 2 DIGIT SECOND IN MINUTE

X	,398		;RESERVED FOR RELATIVE VOLUME TABLE
X	INDN,12		;SYSTEM INDEPENDENT VOLUME NAME (12 BLANKS)
X	INDO,12		;SYSTEM INDEPENDENT OWNER NAME ([001,001])
X	INDF,12		;SYSTEM INDEPENDENT FORMAT TYPE ("DECFILE11A")
X	,2		;NOT USED
X	CHK2,2		;CHECKSUM OF WORDS 0-255.
	SUBTTL	FILES-11 FILE HEADER BLOCK

DEFPRE	<FHBBUF>		;THESE ALL OFFSET OFF OF FHBBUF

X	IDOF,1		; ID AREA OFFSET IN WORDS
X	MPOF,1		; MAP AREA OFFSET IN WORDS
X	FNUM,2		; FILE NUMBER
X	FSEQ,2		; FILE SEQUENCE #
X	FLEV,2,401	; STRUCTURE LEVEL AND SYSTEM NUMBER
X	PROG,1		; PROGRAMMER NUMBER (MEMBER NUMBER)
X	PROJ,1		; PROJECT NUMBER (GROUP NUMBER)
X	FPRO,2,164000	; FILE PROTECTION CODE
X	UCHA,1		; USER CONTROLLER FILE CHARACTERISTICS
	UC.CON=200	; THIS FILE IS "LOGICALLY" (IE: DECLARED) CONTIGUOUS
	UC.DLK=100	; FILE IMPROPERLY CLOSED

X	SCHA,1		; SYSTEM CONTROLLED FILE CHARACTERISTICS
	SC.MDL=200	; FILE MARKED FOR DELETETION
	SC.BAD=100	; BAD BLOCK IN FILE

; ** HERE ARE THE USER FILE ATTRIBUTES
X	UFAT,32		; USER FILE ATTRIBUTES
...==.offset		;;SAVE OFFSET TO THING AFTER UFAT
.offset==O.UFAT		;;GO BACK TO UFAT
	X	RTYP,1	; RECORD TYPE BYTE
			R.FIX==1	;TYPE 1 IS FIXED LENGTH
			R.VAR==2	;TYPE 2 IS VARYED LENGTH
			R.SEQ==3	;TYPE 3 IS SEQUENCED RECORDS
	X	RATT,1	; RECORD ATTRIBUTE BYTE
			FD.FTN==1;IF BIT SET, 1ST DATA BYTE IS CARRIAGE CONTROL
			FD.CR==2 ;IF BIT SET, DO "LF" BEFORE LINE DATA,CR AFTER
			FD.BLK==10;IF BIT SET, RECORDS CANNOT CROSS BLK BOUNDRYS
	X	RSIZ,2	; RECORD SIZE (IF VARYED LENGTH, BIGGEST RECORD IN FILE)
;	X	HIBK,4	; HIGH BLOCK; HIGHEST VBN ACTUALLY IN USE
	X	HIBH,2	; HIGH BLOCK HIGH
	X	HIBL,2	; HIGH BLOCK LOW
;	X	EFBK,4	; EOF BLOCK; VBN WHICH IS FIRST NOT IN USE
	X	EFBH,2	; EOF BLOCK HIGH
	X	EFBL,2	; EOF BLOCK LOW
	X	FFBY,2	; FIRST FREE BYTE (IN THE LAST BLOCK)
	X	RACC,1	;RECORD ACCESS BYTE
		FD.RWM==1;READ$/WRITE$ MODE IF1, 0 MEANS GET$/PUT$
		FD.RAN==2;RANDOM ACCESS IF 1, 0 MEANS SEQUENTIAL
		FD.PLC==4;LOCATION MODE IF 1, 0 MEANS MOVE MODE
		FD.INS==10;PUT$ DOES NOT TRUNCATE IF 1, 0 IT DOES

	X	RCTL,1	;DEVICE-CHARACTERISTICS BYTE
		FD.REC==1;1 IF RECORD ORIENTED, 0 IF BLOCK ORIENTED (LIKE DISK)
		FD.CCL==2;1 IF CARRIAGE CONTROL DEVICE, 0 OTHERWISE
		FD.TTY==4;1 IF TELEPRINTER DEVICE
		FD.DIR==10;1 IF DIRECTORY DEVICE
		FD.SDI==20;1 IF SINGLE DIRECTORY ONLY
		FD.SEQ==40;1 IF INHERENTLY SEQUCENTIAL
.offset==...		;;RESUME NORMAL ALLOCATION

;	HERE IS THE ID AREA
M.IDOF==.offset/2	;COMPUTE OFFSET TO ID AREA
X	FNAM,4		; FILE NAME IN RAD50
X	,2		; (LAST 3 CHARACTERS OF 9 CHARACTER RAD50 FILE NAME)
.offset==o.fnam
X	FNM1,2		; 1ST WORD OF 3 CONTAINING FILE NAME IN RAD50
X	FNM2,2		; 2ND WORD OF 3 CONTAINING FILE NAME IN RAD50
X	FNM3,2		; 3RD WORD OF 3 CONTAINING FILE NAME IN RAD50

X	FTYP,2		; FILE TYPE IN RAD50
X	FVER,2		; FILE VERSION IN BINARY

X	RVNO,2		; REVISION # IN BINARY
X	RVDT,7		;REVISION DATE
.OFFSET==O.RVDT
X	RDAY,2		; REVISION DATE DAY
X	RMON,3		; REVISION DATE MONTH
X	RYER,2		; REVISION DATE YEAR

X	RVTI,6		;REVISION TIME
.OFFSET==O.RVTI
X	RHOR,2		; REVISION TIME HOUR
X	RMIN,2		; REVISION TIME MINUTE
X	RSEC,2		; REVISION TIME SECOND

X	CRDT,7		;CREATE DATE
.OFFSET==O.CRDT
X	CDAY,2		; CREATION DATE DAY
X	CMON,3		; CREATION DATE MONTH
X	CYER,2		; CREATEION DATE YEAR

X	CRTI,6		;CREATE TIME
.OFFSET==O.CRTI
X	CHOR,2		; CREATION TIME HOUR
X	CMIN,2		; CREATION TIME MINUTE
X	CSEC,2		; CREATION TIME SECOND

X	EXDT,7		;EXPIRATION DATE
.OFFSET==O.EXDT
X	XDAY,2		; EXPIRATION DATE DAY
X	XMON,3		; EXPIRATION DATE MONTH
X	XYER,2		; EXPIRATION DATE YEAR
X	,1		; USED TO ROUND TO A WORD BOUNDRY

;;	MAP AREA
M.MPOF==.offset/2	;COMPUTE OFFSET TO THE MAP AREA
X	ESQN,1		; EXTENSION SEGMENT NUMBER
X	ERVN,1		; EXTENSION RELATIVE VOLUME NUMBER
X	EFNU,2		; EXTENSION FILE NUMBER
X	EFSQ,2		; EXTENSION FILE SEQUENCE
X	CTSZ,1,1	; SIZE OF THE BLK COUNT FIELD (ALWAYS 1)
X	LBSZ,1,3	; SIZE OF BLOCK NUMBER FIELD (ALWAYS 3)
X       USE,1,0         ; # OF RET PNTRS IN USE
X       MAX,1,314       ; # OF RET PNTRS SLOTS POSSIBLE

;;	RETRIEVAL POINTERS
...==.offset
X	RETP,4		; 4 BYTES OF STUFF FOR EACH RETRIEVAL PAIR

.offset==...
X	HRET,1		; HIGH BYTE OF LBN OF 1ST BLOCK
X	RCNT,1		; # BLKS-1 IN THIS CHUNK
X	RLBN,2		; LOW LBN# OF 1ST BLK IN THIS CHUNK

.offset==776
X	CKSM,2		; CHECKSUM OF WORDS 0 THRU 255.
;	THE ABOVE DATA WAS RECONSTRUCTED FROM A SIMPLISTIC APPENDIX OF
;	A "WELCOME TO RSX-11M" TYPE MANUAL AND IS LIKELY TO BE
;	INCOMPLETE AND INACCURATE TO SOME UNDETERMINED EXTENT.
	SUBTTL	FILES-11 DIRECTORY ENTRY

DEFPRE	<MFDDAT>		;THESE ALL OFFSET OFF OF MFDDAT

X	UFNO,2	; FILE #
X	UFSQ,2	; SEQ #
X	UFX0,2	; ALWAYS (APPARENTLY) 0
X	UFN1,2	; 1ST NAME WORD
X	UFN2,2	; 2ND NAME WORD
X	UFN3,2	; 3RD NAME WORD
...==.offset
.offset==o.ufn1
X	UFNM,4	; FILE NAME
X	,2
X	UFTY,2	; FILE TYPE
X	UVER,2	; OCTAL BINARY GENERATION #

.DIROF==.offset	; REMEMBER LENGTH OF DIRECTORY ENTRY

;	DETERMINED BY INSPECTION
	SUBTTl	FILES-11 BIT MAP BUFFER BLOCK

DEFPRE	<BMBUF>

X	,3	; UNUSED
X	BCNT,1	; # OF BLOCKS IN THE SBM
; THESE 2 FIELDS "FLOAT" AND ALWAYS FOLLOW THE LAST USED SAB COUNT WORD
X       BDMH,2  ; (THE "INI" UTILITY SETS THIS TO SOMETHING)?
X       BDML,2  ; (THE "INI" UTILITY SETS THIS TO SOMETHING)?
 
X       BMXH,2  ; HIGH PART OF LSTLBN COPY
X       BMXL,2  ; LOW PART OF LST LBN COPY

;	DETERMINED BY INSPECTION
	SUBTTL	FILE DESCRIPTOR BLOCK
	SEARCH	SCNMAC

;	THESE VALUES ARE STOLEN FROM SCAN, SO THAT WE CAN USE SCAN/WILD
;	ROUTINES.  NOTE HOWEVER, THAT BECAUSE OF THE "EXTRA" WORDS, WE
;	MUST HAVE OUR OWN VERSION OF "FILIN" TO READ A FILE SPEC.
.FXDEV==.FXDEV		;DEVICE NAME, COPIED FROM SCAN
.FXNAM==.FXNAM		;FILE NAME, COPIED FROM SCAN
.FXNMM==.FXNMM		;FILE NAME MASK
.FXEXT==.FXEXT		;FILE-NAME-EXTENSION,,EXTENSION-MASK (MASK NON0 IF .)
.FXMOD==.FXMOD		;MODIFIED WORD
.FXMOM==.FXMOM		;MODIFIER MASK
.FXDIR==.FXDIR		;DIRECTORY WORD (EACH HALF =0 IF DEFAULT;SFD:0 IF END)
.FXDIM==.FXDIM		;DIRECTORY MASK
	.FXLND==.FXLND	;LENGTH OF "DIRECTORY SPECIFICATION"
.FXBFR==.FXBFR		;/BEFORE VALUE
.FXSNC==.FXSNC		;/SINCE
.FXABF==.FXABF		;/ABEFORE
.FXASN==.FXASN		;/ASINCE
.FXFLI==.FXFLI		;FILE MINIMUM SIZE, IN WORDS
.FXFLM==.FXFLM		;FILE MAXIMUM SIZE, IN WORDS
.FXEST==.FXEST		;/ESTIMATE
.FXVER==.FXVER		;/VERSION

DEFINE FX(.NAME),<'.NAME'==.FXLEN
.FXLEN==.FXLEN+1>

.FXLEN==.FXVER+1	;COMPUTE SIZE OF FILE SPEC BLOCK
FX	.F2NAM		;ADD ANOTHER WORD, 2ND PART OF FILE NAME
FX	.F2NMM		;ADD ANOTHER WORD, 2ND PART OF FILE NAME MASK
FX	.FXNUM		;FILE # OF FILE NXTFDB FOUND
FX	.FXFLG		;FLAGS ASSOCIATED WITH THAT FILE
FX	.FXGEN		;"GENERATION" NUMBER OF FILE
FX	.FXSEQ		;SEQ# OF FILE
FX	.FXSWT		;SWITCHES APPLIED TO THIS FILE SPEC
FX	.FXLNK		;POINTER TO NEXT FILE SPEC IN THIS CHAIN

;HERE ARE BITS, BYTES, AND FIELDS IN THE MODIFIER WORD

FX.NDV==FX.NDV		;SET IF NULL DEVICE
FX.NUL==FX.NUL		;NULL EXTENSION
FX.DIR==FX.DIR		;DIRECTORY SPECIFIED (MOD=0 IF [-])
FX.PHY==FX.PHY		;/PHYSICAL
FX.NOM==FX.NOM		;/OKNONE
FX.DFX==FX.DFX		;DIRECTORY DOES NOT NEED FIX-UP BY WILD
FX.TRM==FX.TRM		;FIELD, CODE FOR FILE SPEC'S TERMINATING CHARACTER
	.FXTRA==.FXTRA	;& (AND)
	.FXTRO==.FXTRO	;! (OR)
	.FXTRN==.FXTRN	;- (NOT)
	.FXTRC==.FXTRC	;+ (CONCATENATE)
FX.STR==FX.STR		;/STRS
FX.PRT==FX.PRT		;/OKPROT
FX.SUP==FX.SUP		;/ERSUPERSEDE

;N.B.: IT LOOKS AS IF BITS 12 THRU 20 ARE FREE, BUT DON'T BET ON IT

FX.DEN==FX.DEN		;/DENSITY, 3 BIT FIELD
FX.PAR==FX.PAR		;/PARITY, 1 BIT FIELD
FX.PRO==FX.PRO		;/PROTECTION OR <NNN>, 9 BIT FIELD

FX.NUN==1B12		;SET IF NO NAME WAS EVER SPECIFIED
FX.EQL==1B13		;SET IF THIS SPEC ENDED WITH =
FX.CMA==1B14		;SET IF THIS SPEC ENDED WITH ,

;	DEFINE THE FILE SWITCHES


DEFINE	SS,<
S	FILENO,FILEIN	;/FILENUMBER:number
S	CHARAC,CHAIN	;/CHARACTERISTICS:{ATCH:DCF}
S	CONTIG
S	IMAGE		;/IMAGE
S	BINARY		;/BINARY
S	ASCII		;/ASCII
S	SIZE,SIZIN	;/SIZE:nnn
S	MAXFIL,MAXFIN	;/MAXFIL:nnn
S	FULL		;/FULL
S	INDEX,IDXIN	;/INDEX:{BEG,MID,END,BLK:nnn}
S	DETAIL		;/DETAILS
S	ALLOCA,ALCIN	;/ALLOCATE:nnnn
S	VPROTE,VPRTIN	;/VPPROTECTION:<RWED,R...>
S	FPROTE,FPRTIN	;/FPROTECTION:<RWED,R...>
S	EXTEND,EXTDIN
S	DOTS		;/DOTS - give got every time ENTER for FE.SYS fails
S	NOVM		;/NOVM - do not copy motion characters CR,LF
			;(BUT they are still implied if record type says so)
>

DEFINE	S(.name,.serve),<FX	V$'.name'>
SS	;BUILD THE SWITCH SECTION OF THE FDB
DEFINE TYPE(.text,adr),<
	PUSHJ	P,[PUSHJ P,TYPE..
		   CAI [ASCIZ ~'.TEXT'~]
		   IFB <ADR>,<POPJ P,0>
		   IFNB <ADR>,<POP P,(P)
				JRST ADR>]
>

DEFINE	ERROR(.text,.adr<.ERR>),<
	JRST	[RELEAS TTY,
		 OUTSTR	[ASCIZ ~? '.text'
~]
		 JRST	'.adr']>

;	DEFINE THE PDP11 RAD50 CHARACTER SET
DEFINE	RDEF(.START,.STRING),<.FOO==.START-1
IRPC .STRING,<$R.'.STRING'==<.FOO==<.FOO+1>>>>

$R.==0	;BLANK MUST BE DONE THIS WAY
RDEF	1,<ABCDEFGHIJKLMNOPQRSTUVWXYZ>
RDEF	33,<$.>
RDEF	36,<0123456789>
;	MACRO TO MOVE 1 PDP11 FORMATTED FIELD TO ANOTHER (LEFT TO RIGHT)
DEFINE MOV.(.ORIGIN,.DESTINATION,.OFFSET<[0]>),<
	PUSHJ	P,[JSP U0,MOV..
		     CAI .ORIGIN	;;POINT AT ORIGIN DATA
		     CAI A.'.DESTINATION';;POINT AT DESTINATION STRUCTURE
		     CAI O.'.DESTINATION';;SPECIFY OFFSET FROM DESTINATION
		     CAI S.'.DESTINATION';;SPECIFY # OF BYTES TO MOVE
		     CAI .OFFSET	;;POINT AT POSSIBLE ADDITIONAL OFFSET
		   POPJ  P,0]>

;	MACRO TO MOVE 1 PDP10 FORMATTED FIELD TO A PDP11 FIELD (4 BYTES MAX)
DEFINE	STOR.(.ORIGIN,.DESTINATION,.OFFSET<[0]>),<
	PUSHJ	P,[JSP U0,STOR..
		     CAI .ORIGIN	;;POINT AT ORIGIN PDP10 DATA
		     CAI A.'.DESTINATION';;POINT AT DESTINATION FIELD
		     CAI O.'.DESTINATION';;GIVE BYTE OFFSET FROM DESTINATION
		     CAI S.'.DESTINATION';;#BYTES IN DESTINATION FIELD
		     CAI .OFFSET	;;ADDRESS OF ADDITIONAL OFFSET
		   POPJ P,0]>

;	MACRO TO MOVE 1 PDP11 FORMATTED FIELD TO A PDP10 FIELD (4 BYTES MAX)
DEFINE	LOAD.(.ORIGIN,.DESTINATION,.OFFSET<[0]>),<
	PUSHJ	P,[JSP U0,LOAD..
			CAI .ORIGIN	;;POINT AT DESTINATION PDP10 FIELD
			CAI A.'.DESTIN'	;;POINT AT ORIGIN PDP11 FIELD
			CAI O.'.DESTIN'	;;BYTEOFFSET FROM PDP11 FIELD
			CAI S.'.DESTIN'	;;#BYTES IN PDP11 FIELD
			CAI .OFFSET	;;ADDRESS OF ADDITIONAL OFFSET
		   POPJ P,0]>
;	MACRO TO GENERATE PDP11 WORD STRINGS OF PDP11 RAD50 CHARACTERS
DEFINE	.RAD50(S),<
	COUNT==0
	IRPC	S,<COUNT==COUNT+1>	;;FIRST COMPUTE TOTAL # CHARACTERS
	WORDS==COUNT/3			;;WORDS=# PDP11 WORDS GENERATED
	REMAIN==COUNT-<WORDS*3>		;;REMAIN=REMAINDER FROM COUNT/3
	IFN REMAIN,<WORDS==WORDS+1>	;;ACCOUNT FOR NON-ZERO REMAINDER
	PAIRS==WORDS/2			;;PAIRS=# PDP11 WORD PAIRS
					;;(IE: # OF PDP10 WORDS NEEDED)
	IFN WORDS&1,<PAIRS==PAIRS+1>	;;IF ODD WORDS, ONE MORE PAIR NEEDED

	C==0			;; CURRENT CHARACTER POSITION = 1ST CHAR IN STR
	REPEAT PAIRS,<		;; FOR I=1 TO (#PDP10.WORDS.REQUIRED)

	 TWV==0			;; TWO-WORD-VALUE=0
	 REPEAT 2,<		;;  FOR J=1 TO 2 (TO GET BOTH PDP11 WORDS)
	  RAD3(<S>,C,OWV)	;;    GO GET 1 WORD OF 3 RAD50 CHARACTERS
	  TWV==TWV_^D18		;;    MAKE ROOM BY PUTTING OLD IN LH
	  TWV==TWV+OWV		;;    ADD IN NEXT 3 CHARACTERS
	  C==C+3		;;    POSITION TO GET NEXT 3 CHARACTERS
		    >		;;    LOOP TO GET BOTH PDP11 WORDS

	 EXP	TWV		;; DUMP OUT TWO PDP11 WORDS (INTO 1 PDP10 WORD)
	> ;;END REPEAT PAIRS	;; NEXT I (LOOP FOR ALL PDP10 WORDS NEEDED)
>;;END DEFINE .RAD50
;;	MACRO TO EXTRACT 3 .RAD50 CHARACTERS FROM A STRING ARGUMENT
DEFINE	RAD3(S,C,OWV),<
	OWV==0			;; ONE-WORD-VARIABLE STARTS OFF = 0
	RC==0			;; # OF RETURNED CHARACTERS = 0
	CC==0			;; CURRENT CHARACTER POSITION = 0
	IRPC	S,<
		IFL RC-3,<IFGE CC-C,<OWV==OWV*50+$R.'S'
				      RC==RC+1>>
		CC==CC+1>
	REPEAT	3-RC,<OWV==OWV*50>;;LEFT JUSTIFY IT
>
;;	MACRO TO GENERATE PDP11 .ASCII STRINGS
DEFINE	.ASCII(S),<

	COUNT==0			;; COUNT OF CHARACTERS TOTAL = 0
	IRPC	S,<COUNT==COUNT+1>	;; COUNT THE NUMBER OF CHARACTERS IN STRING

	WORDS==COUNT/2		;; COMPUTE # OF PDP11 WORDS
	IFN COUNT&1,<WORDS==WORDS+1>;; ACCOUNT FOR POSSIBLE TRAILING BYTE
	PAIRS==WORDS/2		;; COMPUTE # OF PDP10 WORDS (PAIRS OF PDP11 WDS)
	IFN WORDS&1,<PAIRS==PAIRS+1>;; ACCOUNT FOR POSSIBLE TRAILING PDP11 WORD


	C==0			;; START AT FIRST CHARACTER
	REPEAT	PAIRS,<		;; FOR I = 1 TO (#PDP10.WORDS.NEEDED)
	 TWV==0
	 REPEAT 2,<		;;  FOR J= 1 TO 2 (ONCE FOR EACH HALF OF PDP10)
	  ASC2(S,C,OWV)		;;	GO GET 2 MORE BYTES
	  TWV==TWV_^D18		;;	PUT PREVIOUS IN LH
	  TWV==TWV+OWV		;;	MERGE IN CURRENT 2 BYTES
	  C==C+2			;;	ADVANCE PAST 2 MORE BYTES
		>;;END REPEAT 2	;;  NEXT J

	 EXP TWV		;; DUMP OUT 4 ACCUMLATED BYTES
	>;;END REPEAT PAIRS
>;;END DEFINE .ASCII
;	MACRO TO EXTRACT (UP TO ) 2 ASCII BYTES FROM A LONG STRING
DEFINE	ASC2(S,C,OWV),<
	CC==0		;;CURRENT CHARACTER POSITION
	RC==0		;;# OF RETURNED CHARACTERS (IE: 0,1, OR 2)
	OWV==0		;;16 BIT VALUE OF RETURNED CHARACTERS
	IRPC	S,<IFL RC-2,<IFGE CC-C,<
			IFE RC,<OWV=="S">	;;RETURN 1ST CHAR IN "RH"
			IFN RC,<OWV==OWV+<"S"_^D8>>;;RETURN 2ND IN "LH"
					RC==RC+1>>
		CC==CC+1>
>
	SUBTTL	CODE

F11:	TDZA	T1,T1			;SET T1=0 FOR NORMAL ENTRY
	SETO	T1,			;SET T1=-1 FOR CCL ENTRY
	MOVEM	T1,CCLFLG		;INITIALIZE A FLAG TO REMEMBER
	RESET				;
	MOVE	P,[IOWD PLEN,PSTAK]	;INIT THE STACK POINTER
	SETZ	F,			;INIT THE FLAGS

	PUSHJ	P,IMPURE		;GO INITIALIZE NECESSARY IMPURE DATA
PROMPT:	RELEAS	TTY,			;FORCE FINAL STUFF OUT

	RESET				;FORGET FILES, ETC
	HLRZ	T1,.JBSA##		;GET ORIGINAL SIZE
	CORE	T1,			;RESTORE ORIGINAL SIZE
	JFCL				;IGNORE IT
	MOVE	P,[IOWD PLEN,PSTAK]	;INIT THE STACK
	EXCH	T1,LASTCH		;GET LAST CHARACTER
	CAIN	T1,32			;SKIP IF NOT ^Z
	EXIT	1,			;DO A SOFT EXIT IF ^Z SEEN
	SETZ	F,			;INIT FLAGS
	SKPINL				;CLEAR ^O IF ANY
	JFCL				;IGNORE LIKELY NONSKIP RETURN

	SETZM	BUF111			;INDEXF NOT IN CORE
;<	MATCH BRAKET IN LINE BELOW
	OUTSTR	[ASCIZ .F11> .]		;PROMPT FOR INPUT

	PUSHJ	P,SIXIN			;READ A POSSIBLE COMMAND VERB
	PUSHJ	P,TRMSKP		;SKIP IFF END OF LINE AFTER VERB
	TDOA	F,[X%REEAT]		;REEAT TERMINATOR
	JUMPE	T1,.ERR			;REPROMPT ON BLANK LINES

	PUSHJ	P,FNDIDX		;FIND INDEX OF COMMAND FROM TABLE
	  CAI	CMDSIX			;...USE SIXBIT TABLE "CMDSIX"
	SKIPGE	T1			;SKIP IF VALID COMMAND KEYWORD
ILLCMD:	  ERROR	<Illegal syntax>	;CATCH ALL ERROR MESG
	HRRZM	T1,CMDIDX		;SAVE THE COMMAND INDEX FOR LATER
	PUSHJ	P,DOGETS		;GO DO UP-TO-THE-MINUTE GETTABs
	HRRZ	T1,CMDIDX		;GET INDEX OF COMMAND
	PUSHJ	P,@CMDADR(T1)		;GO EXECUTE THE COMMAND
.ERR:	PUSHJ	P,SKEOL			;GET RID OF INPUT IF ANY LEFT
	JRST	PROMPT			;AND LOOP FOR ANOTHER COMMAND
	SUBTTL	COMMANDS

DEFINE CC,<
C	ASSIGN,<
ASSIGN	(no arguments)
	List all currently assigned logical volume names.

ASSIGN	vol:=
	Forget logical volume name.

ASSIGN	vol:=str:file.ext[path]
	Create a logical volume.
	Logical volumes cannot be used in INI or DESTROY commands.

>
C	BOOT,<
BOOT	vol:=str:file.ext[path]
	Copy the .BIN formatted input file onto the boot area of the volume.

>
C	DELETE,<
DELETE	vol:file.typ;gen[uic]{,vol:file.typ;gen[uic],...}
	Delete a FILES-11 file.
	"Vol:" must be explicit.
	All other fields default to "*".
	N.B.: DELETE VOL: is the same as DELETE VOL:*.*;*[*,*]

		/FILE:<file number>	delete file # from IBM, but don't try
					to deallocate FHB storage and don't try
					to fixup owning directory

>

C	DESTRO,<
DESTROY	str:{,str:,str:,str:}
	Destroy the FILES-11 volume (if any) on the specified MOUNTed
	TOPS-10 file structure.  "str:FE.SYS[1,4]" is deleted and the home
	blocks on "str:" are rewritten to remove the pointers to FE.SYS.

>

C	DIRECT,<
DIRECT	{log file=}vol:file.typ;gen[uic]{,vol:file.typ;gen[uic],...}
	Give a "directory" ordered directory of a FILES-11 volume.
	List the FHB information for every file matching the FILES-11 file spec.
	Choose only files found in the system directory files.
	If "log file" is missing, the default is TTY:.
	"Vol:" must be explicit.
	All other missing components default to "*".

		/DETAILS	list attribute and mapping information as well

>
C	EXIT,<
EXIT
	Exits from F11.
>

C	GET,<
GET	{str:file.ext[p,pn]=}vol:file.typ;generation[uic]
	Copy files from the FILES-11 volume to the specified TOPS-10 structure.
	If "str:" is missing, DSK: is the default.
	If "[p,pn]" is missing, [-] is the default.
	"vol:" must be explicit.
	All other missing components default to "*".

		/IMAGE		don't do data conversion
		/ASCII		convert from PDP11 variable length ASCII

	(Generally speaking,  a reasonable /IMAGE or /ASCII will
	 be defaulted if both are omitted)
>

C	HELP,<
HELP
	Lists out brief list of commands.

>

C	INDEX,<
INDEX	{log file=}str:{,str:,str:,str:,...}
	Give an "index" ordered directory of a FILES-11 volume.
	List the FHB information for every file on the structure.
	Choose files from the Index-bit-map rather than the directory files.
	If "log file" is missing, the default is TTY:.

		/DETAILS	list attribute and mapping information as well

>

C	INI,<
INI	str:{volumelabel}{[owner's UIC]}
	Create and initialize a FILES-11 volume on the MOUNTed TOPS10 str:.
	str: must be explicit.
	volumelabel is optional and defaults to blank.
	[owner's UIC] is optional and defaults to [1,1].

		/CHARACTERISTIC:ATTACH	allow 20F task to attach to volume.
		/CHARACTERISTIC:DCFUNC	allow 20F device control functions.
		/EXTEND:<increment of disk blocks during extend operations>
			(Default 5, minimum 1, maximum 127)
		/FPROTECTION:[default file protection for files on this volume]
			(Default is <RWED,RWED,RWE,R>)
			(/FPROTECTION can be given with <RWED,...> notation,
			 without giving a /FPROTECTION switch)
		/FULL		allocate entire disk to RSX20F volume
				(N.B.: TOPS10 structures is destroyed!!)
		/INDEX:BEG	allocate INDEXF.SYS near block 0 if possible
		/INDEX:BLK:nnn	allocate INDEXF.SYS near block "nnn" if possible
		/INDEX:END	allocate INDEXF.SYS on highest block possible
		/INDEX:MID	allocate INDEXF.SYS near mid point of volume
		/MAXFIL:<maximum allowed # of files on volume>
			(default 65535, minimum 5, maximum 65535)
		/SIZE:<number of disk blocks to allocate to FILES-11 volume>
			(Default 2048, minimum about 150, no maximum)
		/VPROTECTION:<protection applied to the volume>
			(Default is <,,,>)

>
C	PATH,<
PATH	vol:[uic]
	Setup defaults for "vol:" and "[uic]"; default default is vol:[*,*].

>
C	PUT,<
PUT	vol:file.typ;gen[uic]=str:file.ext[path]{,str:file.ext[path],...}
	Copy file(s) onto the front end area from the TOPS10 file system.
	"Vol:" must be explicit.
	"[uic]" must be explicit, but can be defaulted from PATH command.
	"[path]" defaults to [-].
	";gen" defaults to the "first free" gen number above the highest used.
	"str:" defaults to DSK:.
	All other missing fields default to "*".

		/FILE:n		use file number "n" on output
		/IMAGE		don't do any data conversion
		/ASCII		convert to PDP11 varible length ASCII records
		/CONTIG		set the "contiguous" bit in the FHB

	(Generally speaking, reasonable /IMAGE/ASCII/CONTIG switches
	 will be defaulted if all are omitted)
>

C	UFD,<
UFD	str:[uic]{,str:[uic],str:[uic...}
	Create a file directory for the specified UIC on the specified volume.
	str: is the TOPS10 name of the FILES-11 volume and must be explicit.
	[uic] must be explicit.
	The protection may be specified either via <RWED,...> or /FPROTECTION.

		/ALLOCATE:<preallocate space for this many files, default=32>
		/FPROTECTION:<protection to be given to the directory file>

>

C	VOLUME,<
VOLUME	{log file=}str:{,str:,str:,str:,...}
	List some FILES-11 volume statistics to the TOPS10 log file.
	"str:" must be a MOUNTed TOPS-10 file structure.
	str: must be explicit.
	If "log file" is missing, the default is "TTY:".

>
>
;	CREATE A BUNCH OF TABLES INDEXED BY COMMAND VERB'S INDEX

DEFINE	C(.a1,.a2),<SIXBIT	@'.a1'@>;BUILD SIXBIT TABLE OF COMMAND VERBS
XLIST
CMDSIX:	CC
	0
LIST
DEFINE	C(.a1,.a2),<EXP	C$'.a1'>;BUILD ADDRESS TABLE OF COMMAND DISPATCHS
XLIST
CMDADR:	CC
LIST
DEFINE	C(.a1,.a2),<EXP T$'.a1'>;CREATE TABLE OF HELP TEXT POINTERS
XLIST
CMDTXT:	CC
LIST
DEFINE	c(.a1,.a2),<T$'.a1':ASCIZ @'.a2'@>;CREATE HELP TEXTS
XLIST
CC
LIST
	SUBTTL	COMMANDS -- ASSIGN

;	THE ASSIGN COMMAND ALLOWS THE USER TO CREATE A "LOGICAL VOLUME".
;	BY REFERRING TO A LOGICAL VOLUME NAME, THE USER CAN ACCESS A
;	"FE.SYS" TYPE FILE WHICH NEED NOT RESIDE ON ANY TYPE OF DISK
;	BLOCK NUMBER BOUNDRY, ETC.  THUS, YOU CAN USE ORDINARY PIP COPY
;	COMMANDS TO KEEP AN FE.SYS SOMEWHERE AND STILL BE ABLE TO ACCESS IT.

C$ASSI:	PUSHJ	P,FILIN			;READ IN A FILE LIST
	SKIPN	FP,IPLIST		;SKIP IF A LIST WAS GIVEN
	  JRST	C$VLSA			;LIST ALL OF THEM

	SKIPN	.FXNAM(FP)		;MUST NOT BE A FILE NAME
	SKIPE	.F2NAM(FP)		;...
	  JRST	ILLCMD			;COMPLAIN IF FILE NAME
	SKIPE	.FXDEV(FP)		;MUST BE A VOLUME NAME
	SKIPE	.FXDIR(FP)		;MUST NOT BE A DIRECTORY
	  JRST	ILLCMD			;COMPLAIN
	MOVE	T1,[FX.EQL]		;
	TDNN	T1,.FXMOD(FP)		;MUST BE AN =
	  JRST	C$VLST			;GO DO A LIST COMMAND
	HRRZ	FP,.FXLNK(FP)		;ADVANCE TO FILE SPEC AFTER =
	JUMPE	FP,C$VCLR		;BRANCH IF "CLEAR" REQUEST
	HRRZ	FP,.FXLNK(FP)		;ADVANCE TO NEXT SPE
	JUMPN	FP,ILLCMD		;MUST BE 2 AND ONLY 2 SPEX
	PJRST	C$ASS1			;GO DO ASSIGN
;	HERE TO CLEAR AN ASSIGNED LOGICAL VOLUME NAME
C$VCLR:	PUSHJ	P,SAVE1
	MOVSI	P1,-VOLMAX		;MAX # OF ENTRIES
	HRRZ	FP,IPLIST		;LOAD PTR TO 1ST SPEC
	MOVE	T1,.FXDEV(FP)		;LOAD VOLUME NAME
	SKIPN	T2,VOLTBL(P1)		;GET IT'S VOLUME NAME
C$CLR2:	AOBJN	P1,.-1			;DO THEM ALL
	JUMPG	P1,[ERROR <Volume not found>]
	CAME	T2,.FXDEV(FP)		;IS THIS IT?
	JRST	C$CLR2			;BRANCH IF NO MATCH, TRY NEXT NAME
	MOVE	FP,VOLPTR(P1)		;GET POINTER
	PUSH	P,VOLTBL(P1)		;SAVE NAME
	SETZM	VOLTBL(P1)		;ZERO NAME SO WE FORGET IT
	TYPE	<Deleted:	>
	POP	P,T1			;GET BACK THE DELETED NAME
	PUSHJ	P,SIXOUT		;TYPE NAME OF DELETED VOLUEM
	TYPE	<:=>			;PRETTY STUFF
	PUSHJ	P,TYPFDB		;TYPE USER'S FILE SPEC
	PJRST	CRLF
;	HERE TO LIST ALL LOGICAL VOLUMES
C$VLSA:	PUSHJ	P,SAVE1
	MOVSI	P1,-VOLMAX
C$VLA1:	MOVE	FP,VOLPTR(P1)		;GET POINTER TO THE FDB
	SKIPE	VOLTBL(P1)		;SKIP IF NOT USED
	PUSHJ	P,C$VLS0		;JOIN COMMON CODE TO TYPE ONE DEF
	AOBJN	P1,C$VLA1		;LOOP FOR ALL
	POPJ	P,
;	HERE TO LIST A LOGICAL VOLUME
C$VLST:	PUSHJ	P,SAVE1
	MOVSI	P1,-VOLMAX
C$VLS1:	MOVE	T1,VOLPTR(P1)		;GET FDB POINTER
	CAME	T1,.FXDEV(FP)		;SKIP IF WE FOUND A MATCH
	AOBJN	P1,C$VLS1		;KEEP TYRING
	JUMPGE	P1,[ERROR <No matching volume name>]
	MOVE	FP,T1			;COPY FDB POINTER
C$VLS0:	MOVE	T1,VOLTBL(P1)		;GET NAME
	PUSHJ	P,SIXOUT		;TYPE VOLUME NAME
	TYPE	<:=>
	PUSHJ	P,TYPFDB		;TYPE FILE SPEC FOR VOLUME
        MOVE    T1,[S$IMAGE]            ;GET THE /IMAGE MODE BIT
        TDNE    T1,.FXSWT(FP)           ;SKIP IF NOT /IMAGE MODE
        TYPE    </IMAGE>
        MOVE    T1,[S$IMAGE]
        TDNE    T1,.FXSWT(FP)
        TYPE    </IMAGE>
	PJRST	CRLF
;	HERE TO CREATE A LOGICAL VOLUME NAME
C$ASS1:	HRRZ	FP,IPLIST		;SET FP=1ST SPEC
	MOVE	T1,.FXDEV(FP)		;GET VOLUME NAME
	MOVSI	P1,-VOLMAX
	CAME	T1,VOLTBL(P1)		;SKIP IF VOLUME ALREADY EXISTS
	AOBJN	P1,.-1			;BRANCH IF MORE VOLUMES TO CHECK
	JUMPLE	P1,C$ASS2		;BRANCH IF VOLUME ALREADY EXISTS

	MOVSI	P1,-VOLMAX
	SKIPE	VOLTBL(P1)		;SKIP IF VOLUME ENTRY FREE
	AOBJN	P1,.-1			;BRANCH IF MORE ENTRIES TO CHECK
	JUMPG	P1,[ERROR <Volume table full>]

C$ASS2:	MOVEM	T1,VOLTBL(P1)		;INSERT LOGICAL NAME
	HRRZ	FP,.FXLNK(FP)		;STEP FP TO FILE NAME

	MOVEI	T1,(FP)			;POINT AT FILE SPEC BLOCK
	MOVEI	T2,OPNBLK		;POINT TO TOPS-10 OPEN/INIT BLOCK
	MOVEI	T3,LERBLK		;POINT AT LOOKUP/RENAME/ENTER BLOCK
	MOVEI	T4,PTHBLK		;POINT AT TOPS-10 PATH. BLOCK
	PUSHJ	P,.STOPB##		;CALL SCAN TO EXPAND FILE SPEC BLOCKS
	  ERROR	<Can't "setup" logical volume file name/path>

	MOVEI	T1,.IODMP		;.IODMP IS TOPS-10 DUMP MODE
	MOVEM	T1,OPNBLK		;FIXUP THE OPEN/INIT BLOCK
	OPEN	FIO,OPNBLK		;ATTEMPT ACCESS TO HIS SPECIFIED DEVICE
	  ERROR	<Can't OPEN logical volume device>

	MOVEI	T1,.RBSPL		;SETUP "LENGTH" WORD FOR LOOKUP BLOCK
	MOVEM	T1,LERBLK+.RBCNT	;...INTO THE LOOKUP BLOCK
	LOOKUP	FIO,LERBLK		;ATTEMPT ACCESS TO HIS SPECIFIED FILE
	  ERROR	<Can't LOOKUP logical volume file>

	MOVSI	T1,(FP)			;GET POINTER = TEMP_FDB_ADR,,0
	HRR	T1,VOLPTR(P1)		;INSERT POINTER=TEMP_FDB_ADR,,PERM_ADR
	MOVEI	T2,.FXLEN(T1)		;CALCULATE T2=LAST ADR IN PERM_FDB
	BLT	T1,-1(T2)		;COPY TEMP FDB TO PERM FDB FOR THIS VOL

	MOVE	T1,VOLTBL(P1)		;GET HIS SPECIFIED VOLUME NAME
	PUSHJ	P,SIXOUT		;TYPE HIS SPECIFIED VOLUME NAME
	TYPE	<:=>			;...
	PUSHJ	P,TYPFIO		;TYPE REAL INFO
	PUSHJ	P,CRLF
	RELEAS	FIO,			;DROP CONNECTION TO VOLUME FILE
	POPJ	P,			;DONE
	SUBTTL	COMMANDS -- BOOT

;	"BOOT" READS A PDP11 .BIN FORMATTED FILE.
;	IT CONSTRUCTS AN INCORE IMAGE OF WHAT THE PDP11 WOULD HAVE.
;	IT WRITES THAT IMAGE TO DISK TO ABSOLUTE BLOCK NUMBERS IN 1:1 STYLE.
;	IE: PDP11 ADDRESS 0 GOES TO BLOCK 0 WORD 0, ADDRESS 1000 GOES
;	TO BLOCK 1 WORD 0, ETC.  USED TO PUT "FELOAD" (IN PARTICULAR) ONTO
;	BLOCKS 0 THRU 3 WHICH ARE STILL (APPARENTLY) NOT USED BY TOPS-10.

C$BOOT:	PUSHJ	P,FILIN			;READ IN A FILE LIST
	SKIPN	FP,IPLIST		;SKIP IF A LIST GIVEN
	  JRST	ILLCMD			;

	SKIPN	.FXNAM(FP)		;SKIP IF OUTPUT FILE NAME GIVEN
	SKIPE	.F2NAM(FP)		;SKIP IF OUTPUT FILE NAME NOT GIVEN
	  JRST	ILLCMD			;COMPLAIN IF OUTPUT FILE NAME GIVEN
	SKIPE	.FXDIR(FP)		;SKIP IF OUTPUT PATH NOT GIVEN
	  JRST	ILLCMD			;COMPLAIN IF OUTPUT PATH GIVEN

	MOVE	T1,[FX.EQL]		;GET THE "EQUAL SEEN" BIT
	TDNN	T1,.FXMOD(FP)		;MUST BE = SIGN IN OUTPUT SPEC
	  JRST	ILLCMD			;COMPLAIN IF NO = SEEN AFTER OUTPUT SPEC
	HRRZ	FP,.FXLNK(FP)		;GET LINK TO NEXT FILE
	JUMPE	FP,ILLCMD		;COMPLAIN IF NO FILE AFTER THE =
	HRRZ	FP,.FXLNK(FP)		;GET LINK TO NEXT FILE
	JUMPN	FP,ILLCMD		;COMPLAIN IF THERE IS MORE THAN 1 INPUT
	PUSHJ	P,SAVFF			;SAVE CORE BOUNDS
	PJRST	C$BOT1			;GO DO BOOT
;	SETUP THE OUTPUT FILE (IE: THE VOLUME)
C$BOT1:	HRRZ	FP,IPLIST		;LOAD FP TO POINT AT VOLUME NAME
	PUSHJ	P,OPNVIO		;OPEN FOR I/O
	SKIPE	FAKVOL			;SKIP IF VOLUME IS REAL
	  ERROR	<Can't put boot on logical volume>

;	SETUP THE INPUT FILE, THE .BIN FORMATTED FILE
	HRRZ	FP,.FXLNK(FP)		;POINT AT INPUT FILE
	MOVEI	T1,(FP)			;POINT AT FILE SPEC BLOCK
	MOVEI	T2,OPNBLK		;POINT AT OPEN DEVICE BLOCK
	MOVEI	T3,LERBLK		;POINT AT LOOKUP BLOCK
	MOVEI	T4,PTHBLK		;POINT AT PATH BLOCK
	PUSHJ	P,.STOPB##		;SET ALL UUO BLOCKS
	  ERROR	<Cannot setup input files>
	MOVE	T1,[.IODMP]		;DUMP MODE
	MOVEM	T1,OPNBLK+0		;SET IT
	SETZM	OPNBLK+2		;NO BUFFERS
	OPEN	FIO,OPNBLK		;OPEN IT
	  ERROR	<Cannot OPEN input device>

	MOVEI	T1,.RBVER		;GET T1=SIZE OF LOOKUP BLOCK
	MOVEM	T1,LERBLK+.RBCNT	;SETUP LOOKUP BLOCK SIZE
	LOOKUP	FIO,LERBLK		;FIND INPUT FILE
	  ERROR	<Cannot find input file>
;	SHARP OBSERVERS WILL NOTE A SIMILARITY TO THE LOAD .BIN FILE CODE
;	UPON KLDCP, UPON WHICH THIS CODE WAS LIGHTLY BASED
	SETZM	BOTCNT			;
	SETZM	BOTPTR			;
	SETZM	LASTHI

;	LOAD A "CHUNK" OF PDP11 BINARY CODE
LDBINY:	SETZM	CHKVAL			;INIT CHECKSUM FOR THIS RECORD
	PUSHJ	P,G10BYT		;GET PDP11 BYTE FROM PDP10 FILE
	  SOJN	T1,LDBINY		;IGNORE EVERYTHING TILL WE FIND A "1"

	PUSHJ	P,G10BYT		;IGNORE BYTE FOLLOWING THE "1"

	PUSHJ	P,G10WRD		;GET PDP11 WORD FROM PDP10 FILE
	SUBI	T1,6			;SUBTRACT 6 FROM THIS WORD COUNT
	  JUMPE	T1,LJMP			;IF WC=6, THEN THIS IS AN XFER RECORD
	MOVEM	T1,LBC			;SAVE COUNT OF REMAINING DATA

	PUSHJ	P,G10WRD		;GET PDP11 WORD, LOAD ADDRESS
	MOVE	P1,T1			;SAVE P1=LOAD ADDRESS
	CAIL	P1,BOTBLK*200*4		;SKIP IF IN RANGE
	  ERROR	<Address in .BIN file is out of range>
	PUSHJ	P,TELHGH		;MENTION PREVIOUS HIGH

	TYPE	<Loading >
	MOVE	T1,P1			;GET BACK THE LOAD ADDRESS
	PUSHJ	P,OCTOUT		;TYPE THE LOAD ADDRESS
LDBIN2:	PUSHJ	P,G10BYT		;GET A BYTE
	SOS	T2,LBC			;ADJUST BYTE COUNT TO ACCOUNT FOR IT
	JUMPGE	T2,LDBIN3		;BRANCH IF THAT WAS NOT LAST BYTE
	SKIPE	CHKVAL			;SKIP IF CHECKSUM ENDED UP 0S
	  error	<Checksum error while reading .BIN file>
	JRSt	LDBINY			;GO IF CHECKSUM WAS OK

LDBIN3:	MOVE	P2,P1			;COPY ADDRESS OF BYTE
	IDIVI	P2,4			;CONVERT TO PDP10 WORD IN P2, BYTEIN P3
	DPB	T1,[POINT 8,BOTBUF(P2),17	; 0
			POINT 8,BOTBUF(P2),9	; 1
			POINT 8,BOTBUF(P2),35	; 2
			POINT 8,BOTBUF(P2),27](P3)	; 3
	MOVEM	P1,LASTHI		;REMEMBER HIGHEST ADDRESS SO FAR
	CAML	P1,HIHIGH		;SKIP IF NOT ABSOLUTE HIGHEST SO FAR
	MOVEM	P1,HIHIGH		;REMEMBER ABSOLUTE HIGHEST
	AOJA	P1,LDBIN2		;LOOP BACK TO LOAD MORE BYTES

;	HERE WHEN ALL DONE
LJMP:	PUSHJ	P,TELHGH		;MENTION HIGHEST ADDR EVER LOADED
	PUSHj	P,G10WRD		;GO GET POSSIBLE XFER ADDRESS
	PUSH	P,T1			;SAVE WHAT MAY BE XFER ADDR
	PUSHJ	P,G10BYT		;GET NEXT BYTE
	SKIPE	CHKVAL			;MAKE SURE WE ENDED UP WITHOUT ERROR
	ERROR	<checksum error at ljmp>
	POP	P,T1			;RESTORE XFER ADDR
	TYPE	<
Xfer address = >
	PUSHJ	P,OCTOUT		;TYPE XFER ADDR
	TYPE	<
Highest address loaded = >
	CAMG	P1,HIHIGH		;SKIP IF LAST RECORD WAS HIGHEST
	SKIPA	T1,HIHIGH		;ELSE LOAD AND SKIP IF NOT
	SOS	T1,P1			;CONVERT TO LAST LOADED FROM FIRST FREE
	PUSHJ	P,OCTOUT		;MENTION HIGHEST ADDRESS
	MOVSI	T3,-BOTBLK		;# OF BLOCKS IN BOOT BUFFER
;SCAN THE INCORE BUFFER AND FIND NON-ZERO BLOCKS TO WRITE TO DISK
LDBNLP:	MOVEI	T1,(T3)			;COPY BLOCK #
	IMULI	T1,^O200		;CONVERT TO OFFSET ADDRESS
	MOVEI	T2,(T1)			;COPY CURRENT memory ADDRESS
	HRLI	T2,-200			;CONSTRUCT AOBJN
	SKIPN	BOTBUF(T2)		;ANYTHING IN THIS WORD
	AOBJN	T2,.-1			;OR IN THIS BLOCK?
	JUMPGE	T2,SKPBLK		;NO, SKIP THIS BLOCK

	MOVEI	T1,(T3)			;GET BLOCK NUMBER
	PUSHJ	P,SUSET			;POSITION TO IT
	MOVEI	T1,(T3)			;COPY DISK BLOCK #
	IMULI	T1,^O200		;COMPUTE OFFSET
	ADDI	T1,BOTBUF-1		;CONVERT TO ABSOLUTE DF10 ADDRESS
	HRLI	T1,-200			;# OF WORDS TO WRITE TO DISK
	SETZ	T2,			;END THE IO LIST
	OUTPUT	VIO,T1			;OUTPUT THE BLOCK

SKPBLK:	AOBJN	T3,LDBNLP		;ADVANCE AND LOOP
	PJRST	CRLF
;	G10WRD - GET A PDP11 WORD (2 BYTES)

G10WRD:	PUSHJ	P,G10BYT	;GET A BYTE
	PUSH	P,T1		;SAVE IT
	PUSHJ	P,G10BYT	;GET ANOTHER BYTE
	LSH	T1,^D8		;MAKE ROOM FOR 1ST BYTE GOTTEN
	POP	P,T2		;GET BACK 1ST BYTE
	OR	T1,T2		;COMBINE
	POPJ	P,0		;RETURN THE WORD
;	G10BYT - GET A PDP11 BYTE
G10BYT:	SKIPE	PFLAG		;SKIP IF NOT PACKED 4 PER PDP10 WORD
	  JRST	GETPAK		;  BRANCH TO GET DATA FROM PACKED WORDS
	SOSGE	BOTCNT		;SKIP IF THERE ARE BYTES LEFT IN BUFFER
	  JRST	GETBUF		;  BRANCH IF THE BUFFER IS EMPTY
	AOS	T1,BOTPTR	;GET POINTER TO BYTE
	MOVE	T1,(T1)		;GET BYTE FROM BUFFER
	MOVE	T2,CHKVAL	;GET CURRENT CHECKSUM
	ADD	T2,T1		;COMPUTE NEW CHECKSUM
	ANDI	T2,377		;KEEP ONLY LOW BYTE OF CHECKSUM DATA
	MOVEM	T2,CHKVAL	;RESTORE CHECKSUM
	POPJ	P,0

;HERE TO EXTRACT THE NEXT BYTE IF BUFFER IS IN PACKED MODE
GETPAK:	MOVE	T1,BYTNUM	;GET NUMBER OF THIS BYTE
	IDIVI	T1,4		;COMPUTE WORD/BYTE IT FALLS IN
	CAIN	T1,^D128
	JRST	GETBUF		;GET NEXT BOTDAT
	MOVE	T1,BOTDAT(T1)	;GET THE WORD
	LDB	T1,[POINT ^D8,T1,17
		    POINT ^D8,T1,9
		    POINT ^D8,T1,35
		    POINT ^D8,T1,27](T2)
	AOS	T2,BYTNUM	;GET NEXT BYTE NEXT TIME
	POPJ	P,0
;HERE TO READ ANOTHER PDP10 DISK BLOCK FROM .BIN FILE
GETBUF:	INPUT	FIO,[IOWD 200,BOTDAT
		 0]
	SETZM	BYTNUM		;START WITH BYTE 0
	MOVEI	T1,^D128;INITIALIZE COUNT TO 128 (IE: 1 BYTE / 1 PDP10 WORD)
	MOVEM	T1,BOTCNT	;INITIALIZE THE COUNTER
	MOVEI	T1,BOTDAT-1	;POINT AT DATA
	MOVEM	T1,BOTPTR	;INITIALIZE THE POINTER
;LOOP THRU DATA AND SET "PFLAG" IF THE HIGH BITS ARE USED IN THE
;PDP10 WORD (WHICH WOULD IMPLY DATA IS PACKED 4 PDP11 BYTES PER 1 PDP10 WORD)
	MOVE	T1,[-200,,BOTDAT]
	MOVE	T2,[-1,,777400]
	TDNE	T2,(T1)
	SETOM	PFLAG		;PACKED AFTER ALL
	AOBJN	T1,.-2		;LOOK THRU ENTIRE BOTDAT IN CASE PATHOGENIC DATA
	JRST	G10BYT
;ROUTINE TO MENTION THE RANGE OF THE LAST LOADED RECORD FROM THE .BIN FILE
TELHGH:	SKIPN	LASTHI
	POPJ	P,
	TYPE	<  THRU >
	MOVE	T1,LASTHI
	PUSHJ	P,OCTOUT
	PJRST	CRLF
	SUBTTL	COMMANDS -- EXIT

C$EXIT:	MONRT.				;EXIT TO MONITOR
	POPJ	P,			;IF CONTINUE TYPED
	SUBTTL	COMMANDS -- PATH

C$PATH:	PUSHJ	P,TTYPHY		;SETUP TTY:
	PUSHJ	P,FILIN			;READ IN A SPEC
	SKIPN	FP,IPLIST		;MUST BE 1 SPEC
	PUSHJ	P,ILLCMD		;ELSE SYNTAX ERROR
	SKIPE	.FXLNK(FP)		;MUST BE *ONLY* ONE
	PUSHJ	P,ILLCMD

	MOVSI	T1,(FP)			;ORIGIN FDB
	HRRI	T1,DEFFDB		;DEFAULT FDB
	BLT	T1,DEFFDB+.FXLEN-1	;COPY TO DEFAULT FDB
	POPJ	P,
	SUBTTL	COMMANDS -- HELP

.HELPR::ERROR	<.HELPR is not loaded>
C$HELP:	PUSHJ	P,TTYPHY		;SETUP TTY:
	TYPE	<
F11 is a simple minded program to maintain a front end disk pack

>
	MOVEI	T1,CMDTXT
C$HEL0:	SKIPN	CMDSIX-CMDTXT(T1)	;SKIP ANY MORE COMMANDS
	JRST	C$HEL1
	MOVE	P1,(T1)
	HRLI	P1,(POINT 7,0)

	PUSHJ	P,TYPE.1
	AOJA	T1,C$HEL0

C$HEL1:	PUSHJ	P,TYPE..
	CAI	ENDING
	PJRST	CRLF

ENDING:	ASCIZ	@


The str:/vol: must be MOUNTed to TOPS10 for all commands, except INI/FULL.
The disk: must be DIS-MOUNTed to TOPS10 for INI/FULL.
INI/FULL will COMPLETELY DESTROY the TOPS10 file structure on disk:.

All switches in all commands are optional - a (hopefully) reasonable
action is taken in their absence.

All missing parts of all file specifications are always wild, except vol:.
vol: must always be specified and can never be wild.

F11 should not be used at all if the vol/str/disk is "MOU"nted to RSX20F.
@
	SUBTTL	COMMANDS -- INDEX

C$INDE:	PUSHJ	P,FILIN			;GET A FILE SPECIFICATION
	SKIPN	FP,IPLIST		;LOAD POINTER TO LIST OF FILES
	MOVEI	FP,DEFFDB
	PUSHJ	P,SETTTY		;SETUP TERMINAL OUTPUT FILE
C$IND0:	PUSHJ	P,C$IND1		;CALL INDEX SUBROUTINE
	HRRZ	FP,.FXLNK(FP)		;STEP TO NEXT SPEC, IF ANY
	JUMPN	FP,C$IND0		;LOOP IF ANOTHER
	POPJ	P,			;RETURN
;	SUBROUTINE TO DO AN "INDEX" OF THE "CURRENT" FILE SPEC (IE: @FP)
C$IND1:	PUSHJ	P,SAVFF			;SAVE CORE FOR COLLAPSE LATTER
	PUSHJ	P,OPNVOL		;GO OPEN THE VOLUME
	MOVEI	P1,1			;START WITH FILE #1
C$IND2:	MOVEI	T1,-1(P1)		;GET IBM NUMBER
	IDIVI	T1,^D32			;
	ADD	T1,IBMINC		;COMPUTE WORD ADDRESS FOR THAT FHB
	MOVE	T2,B32TBL(T2)		;FIND MASK FOR THAT FHB
	TDNN	T2,@T1			;SKIP IF THAT FHB IN USE
	JRST	C$IND3			;BRANCH IF FHB NOT IN USE

	MOVEI	T1,(P1)			;COPY FILE #
	MOVEI	T2,FHBBUF		;READ INTO NORMAL BUFFER
	PUSHJ	P,REDFHB		;READ THE FHB FOR THAT FILE
	MOVEI	T1,FHBBUF
	PUSHJ	P,TYPFHB		;TYPE INFO ON THAT FHB

C$IND3:	ADDI	P1,1			;STEP TO NEXT FILE #
	LOAD.	T1,FMAX			;GET MAX # FILES
	CAMG	P1,T1			;SKIP IF END OF FILES
	JRST	C$IND2			;GO DO NEXT ONE TOO
	POPJ	P,			;RETURN TO CALLER,INDIRECTLY THRU SAVFF
	SUBTTL	COMMANDS -- DELETE

C$DELE:	PUSHJ	P,TTYPHY		;FORCE OUTPUT TO PHYSICAL TTY ONLY
	PUSHJ	P,FILIN			;GO GET FILE LIST
	SKIPN	FP,IPLIST		;MUST BE AT LEAST 1 FILE
	PUSHJ	P,ILLCMD		;GO COMPLAIN IF NO FILES SEEN
C$DEL0:	MOVE	T1,[FX.EQL]		;MUST NOT BE ANY =S
	TDNE	T1,.FXMOD(FP)		;SKIP IF NO =S SEEN
	PUSHJ	P,ILLCMD		;COMPLAIN IF =S SEEN
	HRRZ	FP,.FXLNK(FP)		;STEP TO NEXT FILE IF ANY
	JUMPN	FP,C$DEL0		;AND LOOP TO CHECK FOR = IN ALL FILES

	MOVE	FP,IPLIST		;POINT AT 1ST FILE AGAIN
	PUSHJ	P,C$DEL1		;GO DELETE A FILE
	HRRZ	FP,.FXLNK(FP)		;STEP TO NXT FILE, IF ANY
	JUMPN	FP,.-2			;LOOP FOR ALL FIELS
	POPJ	P,0
;	HERE TO DELETE ALL FILES IN A SINGLE SPEC
C$DEL1:	PUSHJ	P,SAVFF			;SAVE CORE
	TDZ	F,[X%INTRO]		;INDICATE HERALD NOT YET TYPED
	PUSHJ	P,OPNVOL		;OPEN THE FILES-11 VOLUME
	PUSH	P,VOLTAL		;SAVE VOLUME FREE TALLY FOR LATER
	PUSHJ	P,RLDINI		;INITIALIZE THE WILD CARD READER

	MOVE	T1,.FXSWT(FP)		;GET SWITCHES
	TDNE	T1,[S$FILE]		;/FILENUMBER?
	  JRST	C$DEL5			;YES, GO DO SPECIAL WORK
C$DEL2:	MOVEI	T1,(FP)			;POINT AT THIS BLOCK
	MOVEI	T2,DELFDB		;POINT AT THE DELETE FDB
	PUSHJ	P,NXTFDB		;FIND A FILE TO DELETE
	  JRST	C$DEL4			;GO UPDATE THE IBM/SBM
	MOVE	T1,.FXNUM+DELFDB	;GET FILE NUMBER
	MOVEI	T2,FHBBUF		;GET BUFFER FOR FHB
	PUSHJ	P,REDFHB		;GO READ THE FHB FOR THAT FILE
	PUSHJ	P,DELCHK		;SKIP IF PERMISSIBLE TO DELETE
	  TYPE	<% Cannot delete file >,C$DEL3
	MOVEI	T1,FHBBUF		;POINT AT INCORE FHB
	PUSHJ	P,DELFHB		;GO DLEETE IT
	TDON	F,[X%INTRO]		;SKIP IF HERALD ALREADY TYPED
	TYPE	<Files deleted:
>
C$DEL3:	MOVEI	T1,FHBBUF		;POINT AT INCORE FHB
	PUSHJ	P,TYPFHU		;TYPE INFO ON THAT FHB
	PUSHJ	P,CRLF			;TYPE CRLF
	JRST	C$DEL2			;LOOP FOR ANOTHER MATCH

;HERE AFTER DELETING ALL FILES MATCHES A SINGLE FILE SPEC
C$DEL4:	PUSHJ	P,WRTSBM		;UPDATE THE SBM
	PUSHJ	P,WRTIBM		;UPDATE THE IBM
	POP	P,T1			;GET BACK THE ORIGINAL FREE TALLY
	MOVNS	T1			;-VE FREE TALLY
	ADD	T1,VOLTAL		;COMPUTE # OF BLOCKS FREED
	JUMPE	T1,CPOPJ		;DON'T MENTION IT IF NONE HAPPENED
	PUSHJ	P,DECOUT
	TYPE	< blocks freed>
	PJRST	CRLF			;ALL DONE

;HERE IF USER GAVE DELETE/FILE:n
C$DEL5:	MOVE	T1,V$FILE(FP)		;GET FILE NUMBER OF FILE TO DELETE
	SUBI	T1,1			;GET BIT NUMBER FOR THE FILE
	IDIVI	T1,^D32			;COMPUTE WORD IN MAP
	ADD	T1,IBMINC		;COMPUTE ADDRESS OF CORRECT BIT
	MOVE	T2,B32TBL(T2)		;GET CORRECT BIT
	ANDCAM	T2,@T1			;TURN OFF BIT IN INDEX MAP
	JRST	C$DEL4			;REJOIN COMMON CODE

;ROUTINE TO CHECK IF DELETING A FILE MIGHT CAUSE A CORRUPT STRUCTURE
DELCHK:	SKIPE	.FXDIR+DELFDB		;SKIP IF FILE RESIDES IN [0,0]
	JRST	CPOPJ1			;GIVE GOOD RETURN IF NOT IN [0,0]
	MOVE	T1,.FXNUM+DELFDB	;GET FILE'S NUMBER
	HLRZ	T2,.FXEXT+DELFDB	;GET FILE'S TYPE
	CAILE	T1,4			;SKIP IF NOT A KNOWN FILE
	CAIN	T2,'DIR'		;SKIP IF NOT DIRECTORY FILE
	POPJ	P,			;BAD RETURN IF KNOWN FILE OR DIRECTORY
        CAIN    T2,'NDL'                ;DON'T DELETE PROTECTED FILES
        POPJ    P,                      ;
	JRST	CPOPJ1			;ELSE GIVE GOOD RETURN
;ROUTINE TO ZERO THE OWNING DIRECTORY'S POINTERS TO A FILE
;WHICH HAS BE LOCATED VIA THE "WILD 20F" MECHANISM
DELFHB:	PUSHJ	P,RETFHB		;RETURN FHB TO FREE POOL
	MOVE	P1,WDIOFF		;GET POINTER USED BY WILD SCANNER
	SUBI	P1,.DIROFF		;BACK OFF TO PREVIOUS (MATCHING) RECORD
	STOR.	[0],UFN1,P1		;STORE 0S
	STOR.	[0],UFN2,P1		;...INTO ALL
	STOR.	[0],UFN3,P1		;...OF THE
	STOR.	[0],UFTY,P1		;...DIRECTORY
	STOR.	[0],UFNO,P1		;...ENTRY
	STOR.	[0],UFSQ,P1		;...
	STOR.	[0],UFX0,P1		;...
	STOR.	[0],UVER,P1		;...
	PUSHJ	P,UPDDIR		;GO UPDATE THE DIRECTORY
	  TYPE	<% OUT UUO failed to update directory and remove file reference
>
	POPJ	P,0
;ROUTINE TO RE-WRITE THE LAST DIRECTORY BLOCK SCANNED BY THE WILD SCANNER
;USED TO HANDLE INSERTS, DELETES, RENAMES, ETC
UPDDIR:	MOVE	T1,WDIPBN		;GET BLOCK WHERE FILE NAME IS
	PUSHJ	P,SUSET			;POSITION DISK
	OUT	VIO,[IOWD 200,WDIBUF	;...WRITE OUT DIRECTORY BLOCK WITHOUT FILE
			0]		;
	JRST	CPOPJ1
	POPJ	P,			;RETURN
	SUBTTL	COMMANDS -- DIRECT

C$DIRE:	PUSHJ	P,FILIN			;GET A FILE SPECIFICATION
	SKIPN	FP,IPLIST		;SKIP IF THERE WAS A FILE
	MOVEI	FP,DEFFDB		;USE DEFAULT VOL SPEC IF OMITTED
	PUSHJ	P,C$DIR0		;CALL SUBROUTINE TO DO "DIR" COMMAND
	HRRZ	FP,.FXLNK(FP)		;POINT TO NEXT FILE SPEC, IF ANY
	JUMPN	FP,.-2			;LOOP IF ANOTHER
	POPJ	P,			;RETURN
;SUBROUTINE TO DO A "DIRECT" COMMAND ON THE CURRENT INPUT SPEC
C$DIR0:	PUSHJ	P,SAVFF			;SAVE CORE LIMITS FOR COLLAPSE LATTER
	PUSHJ	P,SETTTY		;SETUP TTY OUTPUT FILE IF ANY
	PUSHJ	P,OPNVOL		;OPEN THE VOLUME FOR I/O
	PUSHJ	P,RLDINI		;INITIALIZE RSX20F WILD CARD FILE
	SETZM	UFDOLD			;REMEMBER OLD UFD NAME
C$DIR1:	MOVEI	T1,(FP)			;POINT AT INPUT FDB
	MOVEI	T2,INPFDB		;PUT RSX20F FILE IN INPFDB
	PUSHJ	P,NXTFDB		;GET A FILE BLOCK
	JRST	[RELEAS	TTY,
		POPJ	P,0]		;RETURN WHEN NO MORE MATCHES
	PUSHJ	P,UFDCHK		;CHECK FOR DIRECTORY CHANGE
	MOVE	T1,.FXNUM+INPFDB	;GET ABSOLUTE FILE #
	MOVEI	T2,FHBBUF		;READ INTO NORMAL BUFFER
	PUSHJ	P,REDFHB		;READ FHB
	PUSHJ	P,CHKFNM		;CHECK IF FILE NAME IN DIRECTORY AND
					; FHB MATCH, PRINT MESSAGE IF NOT
	MOVEI	T1,FHBBUF		;POINT AT THIS FILE'S FHB
	PUSHJ	P,TYPFHB		;TYPE FHB
	JRST	C$DIR1			;GO TO NEXT FILE

;ROUTINE TO GIVE A CRLF BETWEEN DIRECTORYS
UFDCHK:	MOVE	T1,UFDNAM		;GET NEW NAME
	CAMN	T1,UFDOLD		;NO NEED TO CHANGE ANYTHING
	POPJ	P,			;JUST RETURN IF NO NEED TO CHANGE
	PUSHJ	P,CRLF			;GIVE A BLANK LINE
	MOVE	T1,FEUNIT		;GET NAME OF CURRENT FILE'S VOLUME
	PUSHJ	P,SIXOUT		;TYPE CURRENT FILE'S VOLUME
	TYPE	<:[>			;TYPE SEPERATOR
	HLLZ	T1,UFDNAM		;GET SIXBIT OF UFD'S FILE NAME
	PUSHJ	P,SIXOUT		;TYPE PROJECT NUMBER
	TYPE	<,>			;SEPERATOR
	HRLZ	T1,UFDNAM		;GET SIXBIT OF UFD'S PROGRAMMER NUMBER
	PUSHJ	P,SIXOUT		;TYPE PROGRAMMER NUMBER
	TYPE	<]>			;SEPERATOR
	MOVE	T1,UFDNAM		;GET THE NEW NAME
	MOVEM	T1,UFDOLD		;AND REMEMBER IT AS CURRENT
	PJRST	CRLF
;ROUTINE TO CHECK IF FILE NAME IN DIRECTORY ENTRY AND FHB MATCH.
;IF NOT, A MESSAGE IS PRINTED.  WDIOFF CONTAINS DIRECTORY, FHBBUF
;CONTAINS FHB.

CHKFNM:	PUSHJ	P,SAVE2			;FREE UP AN AC OR TWO
	MOVE	P1,WDIOFF		;GET DIRECTORY ENTRY ADDRESS
	SUBI	P1,.DIROFF		;(WAS POST-INCREMENTED)
	MOVEI	P2,FHBBUF-FHBBUF	;OFFSET FOR FHB
	LOAD.	T1,UFN1,P1		;GET FIRST PART OF NAME
	LOAD.	T2,FNM1,P2		;DITTO FROM FHB
	CAME	T1,T2			;MATCH?
	JRST	CHKFNE			;NO
	LOAD.	T1,UFN2,P1		;GET SECOND PART OF NAME
	LOAD.	T2,FNM2,P2		;DITTO FROM FHB
	CAME	T1,T2			;MATCH?
	JRST	CHKFNE			;NO
	LOAD.	T1,UFN3,P1		;GET THIRD PART OF NAME
	LOAD.	T2,FNM3,P2		;DITTO FROM FHB
	CAME	T1,T2			;MATCH?
	JRST	CHKFNE			;NO
	LOAD.	T1,UFTY,P1		;GET TYPE
	LOAD.	T2,FTYP,P2		;DITTO FROM FHB
	CAME	T1,T2			;MATCH?
	JRST	CHKFNE			;NO
	LOAD.	T1,UVER,P1		;GET VERSION
	LOAD.	T2,FVER,P2		;DITTO FROM FHB
	CAMN	T1,T2			;MATCH?
	POPJ	P,			;FHB AND DIRECTORY MATCH
CHKFNE:	TYPE	<% Name in header block of >
	LOAD.	T1,UFN1,P1		;GET 1ST WORD OF FILE NAME
	LOAD.	T2,UFN2,P1		;GET 2ND WROD OF FILE NAME
	LOAD.	T3,UFN3,P1		;GET 3RD WORD OF FILE NAME
	PUSHJ	P,FILE5O		;TYPE OUT FILE NAME
	TYPE	<.>
	LOAD.	T1,UFTY,P1
	SETZB	T2,T3			;DON'T WANT EXTRA SPACING
	PUSHJ	P,FILE5O
	TYPE	<;>
	LOAD.	T1,UVER,P1		;GET VERSION #
	PUSHJ	P,OCTOUT		;TYPE IT
	TYPE	< is >
	LOAD.	T1,FNM1,P2		;GET 1ST WORD OF FILE NAME
	LOAD.	T2,FNM2,P2		;GET 2ND WROD OF FILE NAME
	LOAD.	T3,FNM3,P2		;GET 3RD WORD OF FILE NAME
	PUSHJ	P,FILE5O		;TYPE OUT FILE NAME
	TYPE	<.>
	LOAD.	T1,FTYP,P2
	SETZB	T2,T3			;DON'T WANT EXTRA SPACING
	PUSHJ	P,FILE5O
	TYPE	<;>
	LOAD.	T1,FVER,P2		;GET VERSION #
	PUSHJ	P,OCTOUT		;TYPE IT
	PJRST	CRLF			;END WITH NEW LINE
	SUBTTL	COMMANDS -- VOLUME

C$VOLU:	PUSHJ	P,FILIN			;GET A FILE SPECIFICATION
	SKIPN	FP,IPLIST		;LOAD INPUT FILE LIST POINTER
	MOVEI	FP,DEFFDB
	PUSHJ	P,SETTTY		;SETUP TERMINAL OUTPUT FILE
	PUSHJ	P,C$VOL0		;DO THE "VOLUME" COMMAND TO ONE SPEC
	HRRZ	FP,.FXLNK(FP)		;STEP TO NEXT FIEL SPEC, IF ANY
	JUMPN	FP,.-2			;LOOP IF ANOTHER FILE SPEC
	POPJ	P,0
;TYPE RANDOM INFORMATION EXTRACTED FROM A VOLUME'S FILES-11 HOME BLOCK
C$VOL0:	PUSHJ	P,SAVFF			;SAVE .JBFF
	PUSHJ	P,OPNVOL		;GO OPEN THE VOLUME

	TYPE	<Volume creation: >
	MOVE	T1,[XWD O.VDAY,A.VDAY]	;GET PDP11 BYTE POINTER
	SETZ	P1,			;NO OFFSET
	PUSHJ	P,TYPDAT		;TYPE DATE

	TYPE	< >
	MOVE	T1,[XWD O.VHOR,A.VHOR]	;GET BYTE POINTER
	SETZ	P1,			;NO OFFSET
	PUSHJ	P,TYPTIM		;TYPE CREATION TIME

	PUSHJ	P,CRLF
	TYPE	<FILES-11 home block at block >
	MOVE	T1,H11LBN		;GET BLOCK NUMBER OF HOME BLOCK
	PUSHJ	P,OCTOUT		;TYPE BLOCK NUMBER OF HOME BLOCK

	PUSHJ	P,CRLF
	TYPE	<Volume spans blocks >
	MOVE	T1,FSTLBN		;GET FIRST BLOCK # ALLOCATED TO VOLUME
	PUSHJ	P,OCTOUT		;TYPE FIRST BLOCK # ALLOCATED TO VOLUME
	TYPE	< through block >
	MOVE	T1,LSTLBN		;GET LAST BLOCK # ALOCATED TO VOLUME
	PUSHJ	P,OCTOUT		;TYPE LAST BLOCK # ALLOCATED TO VOLUME

	PUSHJ	P,CRLF
	MOVE	T1,LSTLBN		;GET LAST LBN IN VOLUME
	SUB	T1,FSTLBN		;GET FIRST LBN IN VOLUME
	ADDI	T1,1			;1 MORE
	PUSHJ	P,DECOUT		;TYPE COMPUTED # BLOCKS IN VOLUME
	TYPE	< blocks allocated to FILES-11 volume, >
	MOVE	T1,VOLTAL		;GET # BLOCKS SEEN AS FREE
	PUSHJ	P,DECOUT		;TYPE # BLOCKS SEEN AS FREE
	TYPE	< blocks free>

	PUSHJ	P,CRLF
	TYPE	<Index-bit-map at block >
	MOVE	T1,IBMLBN		;GET INDEX-BIT-MAP LOCATION
	PUSHJ	P,OCTOUT		;TYPE LOCATION OF INDEX-BIT-MAP
	TYPE	<, >
	LOAD.	T1,IBSZ			;GET SIZE OF INDEX-BIT-MAP
	PUSHJ	P,DECOUT		;TYPE SIZE OF INDEX-BIT-MAP
	TYPE	< blocks long>

	PUSHJ	P,CRLF
	LOAD.	T1,FMAX			;GET MAX # OF FILES PERMITTED
	PUSHJ	P,DECOUT		;TYPE MAX# OF FILES PERMITTED
	TYPE	< files possible, >
	MOVE	T1,FHBTAL		;GET TALLY OF FREE FHBS
	PUSHJ	P,DECOUT		;TYPE TALLY OF FREE FHBS
	TYPE	< files remain unallocated>
;	MORE OF THE VOLUME INFO CODE

	PUSHJ	P,CRLF
	TYPE	<Storage-bit-map cluster size >
	LOAD.	T1,SBCL			;GET VOLUME'S SBM CLUSTER SIZE
	PUSHJ	P,DECOUT		;TYPE CLUSTER SIZE

	PUSHJ	P,CRLF
	TYPE	<Volume name: ">
	MOVE	T1,[XWD O.VNAM,A.VNAM]	;GET PDP11 BYTE POINTER
	PUSHJ	P,TYPS12		;TYPE 12 BYTES (IE: VOLUME NAME)
	TYPE	<">

	PUSHJ	P,CRLF
	TYPE	<Volume owner's uic: >
	LOAD.	T1,VOWN			;GET UIC
	LSH	T1,-^D8			;CHOP OFF RIGHT HALF
	PUSHJ	P,OCTOUT		;TYPE FIRST PART OF UIC
	TYPE	<,>
	LOAD.	T1,VOWN			;GET UIC
	ANDI	T1,377			;CHOP OFF LEFT HALF
	PUSHJ	P,OCTOUT		;TYPE 2ND PART OF UIC

	PUSHJ	P,CRLF
	TYPE	<Volume protection: >
	LOAD.	T1,VPRO			;GET VOLUME PROTECION
	PUSHJ	P,P11OUT		;TYPE VOLUME PROTECTION

	PUSHJ	P,CRLF
	TYPE	<Volume characteristics: >
	LOAD.	T1,VCHA			;GET VOLUME CHARACTERISTICS BYTE
	PUSHJ	P,OCTOUT		;TYPE OCTAL VALUE OF CHARACTERITSTICS

	PUSHJ	P,CRLF
	TYPE	<Default file protection: >
	LOAD.	T1,DFPR			;GET DEFAULT FILE PROTECTION
	PUSHJ	P,P11OUT		;TYPE FILE PROTECTION

	PUSHJ	P,CRLF
	TYPE	<# of retrieval pairs in a window: >
	LOAD.	T1,WISZ			;GET # OF PAIRS
	PUSHJ	P,DECOUT		;TYPE SIZE OF WINDOW

	PUSHJ	P,CRLF
	TYPE	<Default # of blocks in file extends: >
	LOAD.	T1,FIEX			;GET SIZE OF EXTENSION
	PUSHJ	P,DECOUT		;TYPE SIZE TO USE WHEN EXTENDING
;	STILL MORE VOLUME INFO CODE
	PUSHJ	P,CRLF
	TYPE	<# Entries in a directory LRU: >
	LOAD.	T1,LRUC			;GET SIZE OF LRU
	PUSHJ	P,DECOUT		;TYPE SIZE OF LRU

	PUSHJ	P,CRLF
	TYPE	<System independent volume name: ">
	MOVE	T1,[O.INDN,,A.INDN]	;GET BYTE POINTER TO VOLUME NAME
	PUSHJ	P,TYPS12		;TYPE 12 BYTE OF VOLUME NAME
	TYPE	<">

	PUSHJ	P,CRLF
	TYPE	<System independent owners name: ">
	MOVE	T1,[O.INDO,,A.INDO]	;GET BYTE POINTER TO OWNER'S NAME
	PUSHJ	P,TYPS12		;TYPE OWNER'S NAME
	TYPE	<">

	PUSHJ	P,CRLF
	TYPE	<System independent format type: ">
	MOVE	T1,[O.INDF,,A.INDF]	;GET BYTE POINTER TO FORMAT TYPE
	PUSHJ	P,TYPS12		;TYPE 12 BYTES OF FORMAT TYPE
	TYPE	<">

	PUSHJ	P,CRLF
	PJRST	TYPSBM
;	ROUTINE TO TYPE 12 PDP11 ASCII BYTES GIVEN PDP11 BYTE POINTER IN T1
TYPS12:	PUSHJ	P,SAVE1			;SAVE AN AC
	MOVEI	P1,^D12			;INIT THE COUNTER

TYPS13:	PUSHJ	P,TYPBYT		;GET&TYPE BYTE USING BYTE POINTER IN T1
	SOJG	P1,TYPS13		;LOOP TILL ALL BYTES TYPED
	POPJ	P,			;RETURN TO CALLER
	SUBTTL	COMMANDS -- GET

C$GET:	PUSHJ	P,FILIN			;GET FILE SPEX
	SKIPN	FP,IPLIST		;GET FILE INPUT LIST
	MOVEI	FP,DEFFDB
C$GET1:	PUSHJ	P,SETOUT		;GRAB AN OP FDB IF ANY THERE
	PUSHJ	P,C$GETA		;GO DO PER VOLUME INIT
	HRRZ	FP,.FXLNK(FP)		;STEP TO NEXT INPUT SPEC
	JUMPN	FP,C$GET1		;LOOOP IF MORE
	POPJ	P,			;RETURN TO CALLER
;	HERE TO START A FILE COPY USING THE CURRENT INPUT FILE SPEC
C$GETA:	PUSHJ	P,SAVFF			;SAVE PER-VOLUME CORE SIZE
	PUSHJ	P,OPNVOL		;OPEN THE FILES-11 VOLUME
	PUSHJ	P,RLDINI		;YES, INITIALIZE THE WILD READER
C$GET2:	MOVEI	T1,(FP)			;POINT T1 AT USER'S FILE SPEC
	MOVEI	T2,TMPFDB		;POINT AT OUTPUT FDB
	PUSHJ	P,NXTFDB		;GET THE NEXT MATCHING FILE
	  POPJ	P,			;  NO MORE WILD FILES, EXIT THIS LEVEL
	PUSHJ	P,C$GETB		;GO DO COPY FOR THIS FILE
	JRST	C$GET2			;AND LOOP FOR ANOTHER
;	HERE TO COPY A SINGLE NON-WILD FILE FROM FILES11 TO TOPS10
C$GETB:	PUSHJ	P,SAVFF			;SAVE .JBFF SO WE CAN COLAPSE CORE LATER
	SETOM	RSXCTR			;INIT THE BYTE COUNTER
	SETOM	RSXVBN			;INIT THE BLOCK POINTER

	MOVE	T1,.FXNUM+TMPFDB	;GET THE FILE NUMBER OF THE MATCH
	MOVEI	T2,FHBBUF		;NORMAL HEADER BUFFER
	PUSHJ	P,REDFHB		;GO READ THAT FILE'S FFHB

	PUSHJ	P,G$ENTER		;GO DO THE ENTER FOR "GET" COMMAND

	MOVE	T1,.FXSWT+TMPFDB	;GET MODE FLAGS
	TDNN	T1,[S$ASCI]		;SKIP IF EXPLICIT /ASCII
	TDNN	T1,[S$IMAG!S$BINA]	;SKIP IFF EXPLICIT BINARY
	JRST	C$GET5			;BRANCH IF ASCII COPY 

;FALL THROUGH TO DO IMAGE MODE COPY
;HERE TO XFER A FILE FROM FE DISK TO 10 DISK IN BINARY MODE
C$GET3:	MOVEI	T1,FHBBUF		;POINT AT FHB BUFFER FOR THAT FILE
	AOS	T2,RSXVBN		;LOAD T2=NEXT VBN
	PUSHJ	P,SCNRET		;SCAN "RIB" AND FIND NEXT BLOCK #
	  JRST	C$GET4			;FAILED, MUST BE EOF
	PUSHJ	P,SUSET			;POSITION TO IT
	IN	VIO,[IOWD 200,TMPBUF	;READ THAT BLOCK INTO BUFFER
			0]		;...
	SKIPA	T2,RSXVBN		;GET VBN AGAIN
	  PUSHJ	P,G$IER			;GO REPORT INPUT ERROR, THEN RETURN HERE
	MOVEI	T1,FHBBUF		;POINT AT FHB FOR INPUT FILE
	PUSHJ	P,EOFBYT		;GET # OF PDP11 BYTES IN BLOCK
	IDIVI	T1,4			;COMPUTE T1=# PDP10 WORDS
	CAIE	T2,0			;ANY LEFT OVER BYTES?
	ADDI	T1,1			;IF SO, USE ONE MORE PDP10 WORD
	IMUL	T1,[-1,,0]		;CONVERT INTO -VE.COUNT,,0
	SKIPE	T1			;SHOULD NOT HAPPEN, BUT AVOID GOTO WORDS
	HRRI	T1,TMPBUF-1		;INSERT BUFFER ADDRESS INTO IOWD WORD
	SETZ	T2,			;END IOLIST WITH A 0 IOWD
	OUT	FIO,T1			;WRITE THAT BLOCK INTO FILE
	  SKIPA				;SKIP IF OUTPUT GOOD
	   PUSHJ P,G$OER		;REPORT ERROR, THEN RETURN HERE
	JRST	C$GET3			;LOOP TO XFER NEXT BLOCK IN FILE
;ROUTINE TO TYPE OUT DETAILS OF AN INPUT ERROR DURING "GET" COMMAND
G$IER:	TYPE	<% Input error >	;HERALD THE ERROR
	GETSTS	VIO,T1			;GET I/O STATUS OF THAT CHANNEL
	PUSHJ	P,OCTOUT		;TYPE OUT I/O STATUS IN OCTAL
	TYPE	< on PBN >		;...
	MOVE	T1,LASSET		;GET PHYSICAL BLOCK# LAST SUSET'D TO
	PUSHJ	P,OCTOUT		;TYPE LAST BLOCK# SUSET'D TO
	TYPE	< (RBN >		;...
	MOVE	T1,RSXVBN		;GET RELATIVE BLOCK # IN FILE
	PUSHJ	P,OCTOUT		;TYPE RELATIVE BLOCK # IN FILE
	TYPE	<) of >			;...
	MOVEI	T1,FHBBUF		;POINT AT FHB FOR INPUT FILE
	PUSHJ	P,TYPFHU		;TYPE COMPLETE FILE11 FILE SPEC
	PJRST	CRLF			;END WITH CRLF

;ROUTINE TO TYPE OUT DETAILS OF AN OUTPUT ERROR DURING "GET" COMMAND
G$OER:	TYPE	<% Output error >	;HERALD THE ERROR
	GETSTS	FIO,T1			;GET THE I/O STATUS OF THAT CHANNEL
	PUSHJ	P,OCTOUT		;TYPE I/O STATUS IN OCTAL
	TYPE	< on RBN >		;...
	MOVE	T1,RSXVBN		;GET RELATIVE BLOCK# IN OUTPUT FILE
	PUSHJ	P,OCTOUT		;TYPE BLOCK # IN OCTAL
	TYPE	< of >			;...
	PUSHJ	P,TYPFIO		;TYPE FILE SPEC FOR OUTPUT FILE
	PJRST	CRLF			;END WITH CRLF
;	HERE WHEN WE GET EOF ON THE FILES-11 VOLUME'S FILE
C$GET4:	MOVEI	T1,FIO			;LOAD T1=CHANNEL # OF OUTPUT FILE
	DEVCHR	T1,			;GET DEVICE CHARACTERISTICS
	TDNE	T1,[DV.TTY]		;SKIP IF NOT USER'S TTY
	OUTPUT	FIO,			;GIVE HIM HIS OUTPUT IMMEDIATELY
	PUSH	P,FP			;SAVE FP
	MOVEI	FP,TMPFDB		;POINT AT OUTPUT FDB
	PUSHJ	P,TYPFIO		;TYPE ACTUAL OUTPUT SPEC
	POP	P,FP			;RESTORE FP
	TYPE	<=>
	MOVEI	T1,FHBBUF		;POINT AT INPUT FILE'S FHB
	PUSHJ	P,TYPFHU		;TYPE ACTUAL INPUT SPEC
	MOVE	T1,.FXSWT+TMPFDB	;GET MODE FLAGS
	TDNN	T1,[S$ASCI]		;SKIP IF EXPLICIT ASCII
	TDNN	T1,[S$IMAG!S$BINA]	;SKIP IF EXPLICIT BINARY
	SKIPA	T1,[SIXBIT ./ASCII.]	;HERE IF EXPLICIT OR IMPLICIT ASCII
	MOVE	T1,[SIXBIT ./IMAGE.]	;HERE IF EXPLICIT (ONLY) BINARY
	PUSHJ	P,SIXOUT		;TYPE MODE OF FILE XFER
	TDZE	F,[X%PEOF]		;DID WE HAVE A PROBLEM COPYING?
	TYPE	<(Unexpected end-of-file)>
	PUSHJ	P,CRLF			;END LINE
	RELEASE	FIO,			;RELEASE IT
	SETZB	T3,TTYOBF+.BFCTR	; ZERO TTY'S BYTE COUNT
	PJRST	TYO			;TYPE A NULL TO FORCE LINE OUT NOW
;HERE TO COPY AN ASCII TEXT FILE FROM THE FE DISK
C$GET5:	LOAD.	P4,RTYP		;GET RECORD TYPE BYTE FROM FHB
	LOAD.	P3,RATT		;GET RECORD ATTRIBUTE BYTE FROM FHB

C$GET6:	LOAD.	P2,RSIZ		;GET RECORD SIZE FROM FHB
	TDZ	F,[X%ODD]	;INITIALIZE ODD/EVEN RECORD SIZE FLAG
	MOVE	T3,P2		;COPY RECORD SIZE
	CAIN	P4,R.FIX	;SKIP IF VARIABLE LENGTH RECORDS
	  JRST	.+3		;BRANCH IF FIXED RECORD SIZE
	PUSHJ	P,DVWORD	;GET RECORD SIZE FROM RECORD ITSELF
	  JRST	C$GET4		;BRANCH IF DVWORD FAILS (EOF, APPARENTLY)
	MOVE	P1,T3		;COPY FINAL RECORD SIZE
	CAIN	P4,R.SEQ	;SKIP IFF NOT SEQUNCED RECORD
	  PUSHJ	P,GETSEQ	;GET SEQUENCE NUMBER FROM RECORD HEADER
	MOVE	P2,P1		;COPY BYTE COUNT AGAIN
	CAIN	P4,R.FIX	;SKIP IF VARIABLE LENGTH RECORD
	  JRST	C$GET7		;BRANCH IF FIXED LENGTH RECORD
	TRNE	P1,1		;SKIP IF VARIABLE LENGTH RECORD WITH EVEN COUNT
	TDO	F,[X%ODD]	;REMEMBER IF VARIABLE LENGTH ODD COUNT

	MOVEI	T3,15		;LOAD T3=CARRIAGE-RETURN
	TRNE	P3,FD.CR	;SKIP IF NO IMPLIED CR'S AT HEAD OF RECORD
	  PUSHJ	P,PUTC		;INSERT IMPLIED CR AT HEAD OF RECORD
	JUMPE	P1,C$GET8	;BRANCH IF BLANK LINE

;HERE TO COPY THE LINE
C$GET7:	PUSHJ	P,RDBYTE	;GET A BYTE FROM THE INPUT RECORD
	  JRST	C$G7B		;BRANCH IF WE GET AN EOF DURING COPY OF RECORD
	ANDI	T3,177		;TRUNCATE 8-BIT ASCII TO 7-BIT ASCII
	CAIE	T3,14		;SKIP IF EMBEDDED <FORM-FEED> FOUND
	CAIN	T3,13		;NONSKIP IF EMBEDDED <VERTICAL-TAB> FOUND
	TDO	F,[X%VMS]	;REMEMBER EXPLICIT VERTICAL MOTION SEEN
	CAIE	T3,12		;SKIP IF EXPLICIT <LINE-FEED> FOUND
	CAIN	T3,15		;NONSKIP IF EMBEDDED <CARRIAGE-RETURN> FOUND
	JRST	[TDO F,[X%VMS]	;REMEMBER VERTICAL MOTION SEEN
		MOVE T4,[S$NOVM];GET THE "DON'T COPY CRLF" BIT
		TDNE T4,.FXSWT(FP);SKIP IF ALLOWED TO COPY CR,LFS
		JRST .+2	;SKIP OVER "PUTC" SO CRLF IS NOT COPIED
		JRST .+1]	;FALL THROUGH AND COPY CRLF
	PUSHJ	P,PUTC		;PUT INPUTED BYTE INTO OUTPUT FILE
	SOJG	P1,C$GET7	;LOOP TO COPY MORE BYTES IF COUNT NOT EXPIRED

;HERE WHEN BYTE COUNT EXPIRES
C$GET8:	MOVEI	T3,12		;LOAD T3=LINE FEED
	TRNE	P3,FD.CR	;SKIP IF NO IMPLIED CR AT END OF RECORD
	PUSHJ	P,PUTC		;INSERT IMPLIED CR AT END OF THIS RECORD
	TDZN	F,[X%VMS]	;SKIP IF VERTICAL MOTION CHARACTER WAS SEEN
	TRNE	P3,FD.CR	;SKIP IF NO IMPLIED CR/LFS
	SKIPA			;NO NEED TO INSERT MOTION
	PUSHJ	P,FCRLF		;INSERT A CR, LF INTO THE OUTPUT TEXT FILE
	TDZN	F,[X%ODD]	;SKIP IF ODD BYTE STILL LEFT IN INPUT FILE
	JRST	C$GET6		;BRANCH IF NO EXTRA ODD BYTE TO TAKE CARE OF
	PUSHJ	P,RDBYTE	;TRASH THE EXTRA ODD BYTE IF NECESSARY
	JRST	C$GET4		;BRANCH TO EOF HANDLER IF RDBYTE FAILS
	JRST	C$GET6		;LOOP FOR ANOTHER LINE

;ROUTINE TO GET FILES-11 SEQUENCE NUMBER FROM INPUT FILE
;...AND TYPE IT OUT TO TOPS-10 OUTPUT FILE
GETSEQ:	PUSHJ	P,DVWORD	;GET THE SEQ# FOR THIS RECORD
	  TYPE	<% EOF while reading line sequence number>,C$GET4
	SUBI	P1,2		;FIXUP BYTE COUNT WRT SEQUENCE # BYTES
	PJRST	TYPSQN		;RE-TYPE SEQUENCE # INTO OUTPUT FILE

;COME HERE DURING COPY OF A RECORD THAT RUNS OUT OF BYTES
C$G7B:	CAME	P1,FFBYTE	;SKIP IF EOF IN EXPECTED PLACE
	TDO	F,[X%PEOF]	;REMEMBER IF EOF WAS IN UNEXPECTED PLACE
	JRST	C$GET4		;JOIN COMMON EOF HANDLER
;	ROUTINE TO DO THE ENTER TO A TOPS10 FILE
;	USED BY THE SINGLE FILE LOOP OF THE "GET" COMMAND
G$ENTE:	PUSHJ	P,GE$FIL		;SETUP ENTER'S FILE NAME DATA
	PUSHJ	P,GE$TYP		;SETUP ENTER'S FILE TYPE DATA
	PUSHJ	P,GE$SWT		;GO GET THE SWITCH INFO

	MOVE	T1,.FXDEV+OUTFDB	;GET OUTPUT DEVICE FROM WILD'S BLOCK
	MOVEM	T1,.FXDEV+TMPFDB	;INSERT DEVICE INTO SCAN'S BLOCK

	MOVE	T1,[OUTFDB+.FXDIR,,TMPFDB+.FXDIR] ;POINT AT WILD_PATH,,SCAN_PATH
	BLT	T1,TMPFDB+.FXDIR+.FXLND-1 ;XFER WILD'S PATH INTO SCAN'S BLOCK

	MOVE	T1,OUTFDB+.FXMOD	;GET WILD'S SWITCH BITS
	MOVEM	T1,TMPFDB+.FXMOD	;INSERT WILD'S BITS INTO SCAN'S BLOCK

	MOVEI	T1,TMPFDB		;POINT AT FILE SPEC BLOCK
	MOVEI	T2,OPNBLK		;POINT AT OPEN BLOCK
	MOVEI	T3,LERBLK		;POINT AT L/E/R BLOCK
	MOVEI	T4,PTHBLK		;POINT AT PATH BLOCK
	PUSHJ	P,.STOPB##		;CONSTRUCT OPEN/LER/PATH BLOCKS
	  ERROR	<Cannot "setup" output file>

	MOVEI	T1,.RBSPL		;GET T1=LENGTH OF ENTER BLOCK
	MOVEM	T1,LERBLK+.RBCNT	;INSERT LENGTH INTO COUNT WORD

	PUSHJ	P,GE$CDT		;GO INSERT CREATE DATE/TIME

	LOAD.	T1,FVER			;GET ;GENERATION
	MOVEM	T1,LERBLK+.RBVER	;MAKE IT PDP10 VERSION "(nnn)-0"

	MOVEI	T1,.IOASC		;USE ASCII MODE FOR OUTPUT
	MOVE	T2,.FXSWT+TMPFDB	;GET MODE FLAGS
	TDNE	T2,[S$IMAG!S$BINA]	;/BINARY OR /IMAGE?
	MOVEI	T1,.IODMP		;THEN USE IMAGE MODE
	MOVE	T2,OPNBLK+1		;GET SCAN'S CHOICE OF DEVICE
	MOVSI	T3,DOBUF		;
	OPEN	FIO,T1			;OPEN IT
	  ERROR	<Cannot OPEN output device>

	ENTER	FIO,LERBLK		;GO ENTER THE FILE
	  ERROR	<Cannot ENTER output file>,LSTLER
	SETZM	PUTCTR			;INIT COUNTER
	POPJ	P,
;ROUTINE TO SETUP THE FILE NAME DATA PRIOR TO THE ENTER FOR A "GET" CMD
GE$FIL:	LOAD.	T1,FNM1			;GET 1ST 3RD OF FILE NAME
	PUSHJ	P,C5T6			;CONVERT TO SIXBIT
	MOVSI	P1,(T1)			;SAVE IT
	LOAD.	T1,FNM2			;GET 2ND 3RD OF FILE NAME
	PUSHJ	P,C5T6			;CONVERT TO SIXBIT
	HRRI	P1,(T1)			;COMBINE IT WITH 1ST 3RD
	CAME	P1,TMPFDB+.FXNAM	;SKIP IF FHB NAME MATCHS DIR NAME
	  TYPE	<% FHB name doesn't match directory name
>

	MOVE	T1,.FXNAM+TMPFDB	;GET FILE NAME FROM FHB
	TDZ	T1,.FXNMM+OUTFDB	;AND EXTRACT CHARACTERS HE DIDN'T GIVE
					;IN THE OUTPUT SPEC ON LEFT OF =
	MOVE	T2,.FXNAM+OUTFDB	;GET OUTPUT SPEC FROM LEFT OF =
	AND	T2,.FXNMM+OUTFDB	;KEEP ONLY NON WILD CHARACTERS
	OR	T1,T2			;MERGE THE TWO FOR FINAL OUTPUT NAME
	MOVEM	T1,.FXNAM+TMPFDB	;RESSAVE OUTPUT FILE NAME
	POPJ	P,

;ROUTINE TO SETUP THE FILE TYPE DATA PRIOR TO THE ENTER
GE$TYP:	LOAD.	T1,FTYP			;GET FILE TYPE FROM FHB
	PUSHJ	P,C5T6			;CONVERT TO SIXBIT
	HLRZ	T2,.FXEXT+TMPFDB	;GET FILE TYPE FROM DIRECTORY ENTRY
	CAME	T1,T2			;SKIP IF FHB TYPE IS SAME AS DIR TYPE
	  TYPE	<% FHB type doesn't match directory type
>
	HRLZ	T3,.FXEXT+OUTFDB	;GET WILD CARD MASK TO LEFT OF =
	HLLZ	T1,.FXEXT+TMPFDB	;GET FILE TYPE FROM DIRECTORY ENTRY
	TDZ	T1,T3			;TURN OFF  WILD CHARACTERS
	HLLZ	T2,.FXEXT+OUTFDB	;GET FILE TYPE FROM LEFT OF =
	AND	T2,T3			;KEEP ONLY WILD CHARACTERS
	OR	T1,T2			;MERGE THE TWO TOGETHER
	HLLOM	T1,.FXEXT+TMPFDB	;SAVE RECOMPUTED EXT NAME
	POPJ	P,			;RETURN TO CALLER
;ROUTINE TO SETUP THE OUTPUT SWITCHES FOR THE FILE IN A "GET" COMMAND
GE$SWT:	HLRZ	T1,.FXEXT+TMPFDB	;GET FILE TYPE FROM DIRECTORY
	PUSHJ	P,C6T5			;CONVERT TO RAD50 FOR EXTCHK
	PUSHJ	P,EXTCHK		;GO CHECK AND SETUP FLAGS
					;LEAVE RECOMMENDED SWITCHES IN T1
	MOVE	T2,.FXSWT(FP)		;GET INPUT SWITCHES
	MOVE	T3,.FXSWT+OUTFDB	;GET DEFAULT OUTPUT SWITCHES
	TDNE	T3,[S$IMAG!S$BINA!S$ASCI];DID HE GIVE AN ALL INCLUSIVE OUTPUT?
	MOVE	T1,T3			;USE SWITCHES FROM INCLUSIVE OUTPUT
					;RATHER THAN THOSE IMPLIED BY EXT
	TDNE	T2,[S$IMAG!S$BINA!S$ASCI];GIVE A SPEC ON THIS INPUT FFILE?
	MOVE	T1,T2			;USE SWITCHES APPLIED SPECIFICALLY
					;TO THIS FILE IN PLACE OF ANY OTHER
	MOVEM	T1,.FXSWT+TMPFDB	;SAVE THE ADJUSTED FLAGS
	POPJ	P,
;ROUTINE TO EXTRACT ASCII DATE FROM FHB
; AND INSERT IT INTO ENTER BLOCK FOR "GET" COMMAND
GE$CDT:	MOVE	T1,[O.CRDT,,A.CRDT]		;T1=BYTE POINTER TO CREATE DATE
	MOVEI	T2,FHBBUF			;OFFSET TO FHB TO ACCESS
	PUSHJ	P,REDDAT			;GO READ THE DATE FROM FHB
	DPB	T1,[POINT 12,LERBLK+.RBPRV,35]	;INSERT LO 12 BITS OF DEC10 DATE
	LSH	T1,^D-12			;DUMP LOW 12 BITS
	DPB	T1,[POINT 3,LERBLK+.RBEXT,20]	;INSERT HI 3 BITS OF DEC10 DATE

	MOVE	T1,[O.CRTI,,A.CRTI]		;T1=BYTE POINTER TO CREATE TIME
	MOVEI	T2,FHBBUF			;T2=OFFSET TO FHB TO ACCESS
	PUSHJ	P,REDTIM			;GO READ THE TIME FROM FHB
	DPB	T1,[POINT 11,LERBLK+.RBPRV,23]	;INSERT TIME INTO LER BLOCK
	POPJ	P,				;RETURN TO CALLER
	SUBTTL	COMMANDS -- PUT

C$PUT:	PUSHJ	P,FILIN			;GET OUTPUT SPEX
	SKIPN	FP,IPLIST		;LOAD UP POINTER TO FILE LIST
	PUSHJ	P,ILLCMD
	PUSHJ	P,TTYPHY		;SETUP TTY:
	SETZ	T2,			;COUNT NUMBER OF OUTPUT FILE SPEX

C$PUT0:	MOVE	T1,[FX.EQL]		;= SEEN IN THIS SPEC
	TDNE	T1,.FXMOD(FP)		;SKIP IF INPUT SPEC
	PUSHJ	P,POCHEK		;RETURN IF OUTPUT SPEC LOOKS VALID
	HRRZ	FP,.FXLNK(FP)		;STEP TO NEXT FILE SPEC, IF ANY
	JUMPN	FP,C$PUT0		;BRANCH IF ANY FILE SPEC

	JUMPE	T2,[PUSHJ P,ILLCMD]	;MUST BE AT LEAST 1 OUTPUT FILE
	HRRZ	FP,IPLIST		;LOAD UP POINTER TO START OF FILE LIST
	PUSHJ	P,C$PUTA		;GO DO A FILE SPEC
	HRRZ	FP,.FXLNK(FP)		;STEP TO NEXT FILE SPEC, IF ANY
	JUMPN	FP,.-2			;LOOP IF ANOTHER FILE THERE
	POPJ	P,			;DONE IF NO MORE

;ROUTINE TO LOOK AT OUTPUT SPEC TO DETERMINE VALIDITY
POCHEK:	MOVE T1,.FXDIM(FP)	;GET DIRECTORY MASK
	  AOJN	T1,ILLPPN	;BRANCH IF UIC HAD A WILD CARD
	SKIPE   .FXDIR+2(FP)	;SKIP IF NO SFD SPEC APPEARS IN OUTPUT FILE
	  JRST	ILLPPN		;COMPLAIN IF OUTPUT FILE CONTAINS A SFD
	MOVE	T1,.FXDIR(FP)	;GET THE DIRECTORY NAME
	TDNE T1,[777400,,777400];SKIP IF UIC IS OUT OF RANGE
	JRST    ILLPPN		;UIC MUST NOT HAVE MORE THAN 8 BITS OF #
	AOJA	T2,CPOPJ	;SET FLAG AND RETURN
;	COME HERE WITH A POSSIBLY WILD INPUT SPEC AT (FP)
C$PUTA:	PUSHJ	P,SAVFF			;SAVE .JBFF
	PUSHJ	P,SETOUT		;SETUP THE OUTPUT FDB (GOING TO 20F DISK)
	PUSHJ	P,SAVFP			;SAVE FP
	MOVEM	FP,FPCOPY		;SAVE FP
	MOVEI	FP,OUTFDB		;POINT AT OUTPUT FDB
	PUSHJ	P,OPNVOL		;OPEN THAT VOLUME

	SETZM	FPWILD			;INIT FILE POINTER THAT WILD USES
$PUTA0:	MOVSI	T1,'DSK'
	SKIPN	@FPCOPY
	MOVEM	T1,@FPCOPY		;THIS DEPENDS ON .FXDEV=0
	MOVE	T1,[XWD 5,[XWD FPCOPY,0	;	FPCOPY=POINTER TO CURRENT SPEC
			   XWD OPNBLK,LERBLK;	OPENBLOCK,,LOOKUP BLOCK
			   XWD .FXLEN,177;	FDB LENGTH,,LER LENGTH
			   XWD <(1B0)>!WLD,FPWILD
			   0]]		;
	PUSHJ	P,.LKWLD##		;EXPAND FILE SPEC
	  POPJ	P,			;ALL DONE
	PUSHJ	P,C$PUTB		;GO XFER THE FILE WE FOUND
	  POPJ	P,			;HERE IF NO POINT IN CONTINUING WITH THIS FDB
	JRST	$PUTA0			;LOOP FINDING FILES
;	HERE WHEN WE FIND AN INPUT FILE TO COPY TO THE 20F DISK

;	COMPUTE NAME AS IT WILL APPEAR ON THE 20F DISK
C$PUTB:	PUSHJ	P,SAVFF			;SAVE .JBFF, WE MIGHT EXPAND DURING I/O
	TDZ	F,[X%SUPER]		;NOT SUPERCEEDING (YET)
	SETZM	TMPFDB
	SETZM	BLKCNT
	MOVE	T1,[TMPFDB,,TMPFDB+1]
	BLT	T1,TMPFDB+.FXLEN-1
	MOVE	T1,LERBLK+.RBNAM	;GET THE FILE NAME ON PDP10 DISK
	TDZ	T1,OUTFDB+.FXNMM	;KEEP THE OUTPUT FILE'S WILD CHARACTERS
	MOVE	T2,OUTFDB+.FXNAM	;GET THE FILE NAME ON 20F DISK
	AND	T2,OUTFDB+.FXNMM	;TURN OFF THE WILD CHARACTERS
	IOR	T1,T2			;COMPUTE FINAL NAME
	MOVEM	T1,TMPFDB+.FXNAM	;SAVE THE FINAL NAME
	MOVE	T1,OUTFDB+.F2NAM	;GET 2ND HALF OF OUTPUT NAME
	MOVEM	T1,TMPFDB+.F2NAM	;SPECIFY 2ND HALF OF OUTPUT NAME

	HLRZ	T1,LERBLK+.RBEXT	;GET FILE TYPE ON PDP10 DISK
	TDZ	T1,OUTFDB+.FXEXT	;KEEP OUTPUT FILE'S WILD CHARACTERS
	HLRZ	T2,OUTFDB+.FXEXT	;GET FILE TYPE ON 20F DISK
	AND	T2,OUTFDB+.FXEXT	;TURN OFF THE WILD CHARACTERS
	IOR	T1,T2			;MERGE AND COMPUTE FINAL TYPE
	HRLOM	T1,TMPFDB+.FXEXT	;SPECIFY FILE TYPE

	MOVE	T1,OUTFDB+.FXDIR	;GET DIRECTORY SPEC
	MOVEM	T1,TMPFDB+.FXDIR	;STORE IT
	SETOM	TMPFDB+.FXDIM		;MAKE DIRECTORY FULLY SPECIFIED
	SETOM	TMPFDB+.FXNMM		;MAKE FILE NAME FULLY SPECIFIED
	SETOM	TMPFDB+.F2NMM		;MAKE .....
;	FIND INPUT FILE
	MOVE	T1,[UU.PHS!.IOASC]	;BY DEFAULT, USE ASCII MODE
	MOVE	T1,OPNBLK+0		;...
	MOVEI	T1,DIBUF		;BY DEFAULT, USE DISK INPUT BUFFER
	MOVEM	T1,OPNBLK+2		;...
	OPEN	FIO,OPNBLK		;OPEN INPUT DISK FOR INPUT
	  JRST	PUTER4			;COMPLAIN IF DEVICE DISAPPEARED
	LOOKUP	FIO,LERBLK		;FIND INPUT FILE
	  JRST	PUTER5			;GO COMPLAIN IF YOU CAN'T

	SKIPN	T1,OUTFDB+.FXGEN	;SKIP IF HE GAVE EXPLICIT VERSION #
	HRRZ	T1,LERBLK+.RBVER	;FETCH EDIT # IF GIVEN ON FILE RIB
	MOVEM	T1,TMPFDB+.FXGEN	;REMEMBER VERSION NUMBER FOR OUTPUT
;	SCAN THE SPECIFIED 20F DIRECTORY FOR THE PROPER SPOT TO INSERT THIS FILE.
;	IF THE CORRECT FILE/GENERATION ALREADY EXISTS, PREPARE TO SUPERCEED IT.
;	IF THE FILE IS BRAND NEW, FIND A NULL ENTRY AND INSERT THE FILE THERE.
;	IF THE DIRECTORY IS FULL, EXPAND BY A BLOCK AND INSERT THE FILE THERE.
	PUSHJ	P,RLDINI		;INITIALIZE 20F WILD CARD INTERFACE
	SETO	P4,			;P4=BEST GENERATION NUMBER
$PUTB1:	MOVEI	T1,TMPFDB		;GET FDB WITH FULLY SPECIFIED FILE
	MOVEI	T2,FAKFDB		;GET AN FDB TO OUTPUT TO
	PUSHJ	P,NXTFDB		;SEARCH 20F DISK FOR OLD VERSION OF FILE
	  JRST	$PUTB2			;BRANCH IF NO MORE FILES
	CAMGE	P4,.FXGEN+FAKFDB	;IS GENERATION HIGHER THAN BEST SO FAR?
	MOVE	P4,.FXGEN+FAKFDB	;KEEP HIGHEST GEN# IN P4
	SKIPE	T1,TMPFDB+.FXGEN	;SKIP IF NO EXPLICIT GENERATION #
	CAME	T1,FAKFDB+.FXGEN	;SKIP IF EXPLICIT AND THEY MATCH TOO
	JRST	$PUTB1			;LOOP IF NOT THE RIGHT FILE
	MOVE	T1,.FXNUM+FAKFDB	;GET FILE # OF MATCHING FILE
	MOVEM	T1,.FXNUM+TMPFDB	;AND REMEMBER IT
	TDO	F,[X%SUPER]		;FILE IS BEING SUPERCEEDED
	MOVEI	T2,DELBUF		;WHERE TO GET OLD FHB
	PUSHJ	P,REDFHB		;READ IN OLD FHB
	JRST	$PUTB3			;YES, USE THIS SLOT

;	HERE WHEN NXTFDB HAS SCANNED ALL OF THE DIRECTORY AND HAS NOT FOUND
;	AN EXPLICIT MATCHING FILE TO SUPERCEED.  NOW SCAN THE SAME DIRECTORY
;	FOR A NULL SLOT WE CAN USE TO INSERT THIS NEW FILE.
$PUTB2:	MOVE	T1,DIRMAT		;GET # OF DIRECTORIES SCANNED
	CAIE	T1,1			;000000.DIR AND OUR DIR
	JRST	PUTER1			;GO MENTION ERROR AND ABORT
	PUSHJ	P,RLDINI		;INITIALIZE WILD CARDER
	MOVE	T1,OUTFDB+.FXDIR	;GET UIC WE WANT
	MOVEM	T1,NULFDB+.FXDIR	;STUFF IT INTO THE NUL FDB
	MOVEI	T1,NULFDB		;EXPLICIT FDB OF 0S
	MOVEI	T2,FAKFDB		;FDB TO EXPAND INTO
	PUSHJ	P,NXTFDB		;FIND AN EMPTY SLOT
	  JRST	UFDGRO			;GROW THE UFD 1 BLOCK AND TRY AGAIN
	CAIN	P4,177777		;SKIP IF WE HAVEN'T RUN OUT OF VERSIONS
	  JRST	PUTER3			;COMPLAIN IF NO VERSION #S LEFT
	AOSN	P4			;INCREMENT TO NEXT HIGHEST GENERATION
	HRRZ	P4,TMPFDB+.FXGEN	;GET GENERATION
	ANDI	P4,177777		;ONLY KEEP LOW ORDER BITS
	CAIN	P4,0			;CHECK FOR OVERFLOW
	MOVEI	P4,1			;AND CONVERT TO VERSION#1 IF SO
	MOVEM	P4,TMPFDB+.FXGEN	;SAVE GENERATION NUMBER
	MOVE	T1,IPLIST		;POINT AT FIRST FILE BLOCK
	MOVE	T1,V$FILE(T1)		;GET /FILE SWITCH ON OUTPUT FILE
	PUSHJ	P,ALCFHB		;GO GET A FILE NUMBER
	MOVEM	T1,TMPFDB+.FXNUM	;AND REMEMBER IT FOR LATER
;	HERE WHEN WE KNOW WHERE IN THE DIRECTORY WE WANT TO INSERT THIS FILE.
$PUTB3:	MOVNI	T1,.DIROFF		;OFFSET TO MATCHING SLOT
	ADDM	T1,WDIOFF		;ADJUST POINTER TO POINT AT MATCH
	MOVEI	T1,<TMPBUF-FHBBUF>*4	;GET OFFSET FOR OUR FHB
	MOVEM	T1,FHBFOO		;SAVE IT
;NOW, "FHBFOO" IS AN OFFSET STYLE POINTER INTO THE FHB WE'RE BUILDING
;AND "WDIOFF" IS AN OFFSET POINTER INTO THE SLOT IN THE DIRECTORY WE'RE USING.
	MOVE	T1,TMPFDB+.FXNUM	;GET DESIRED FILE #
	STOR.	T1,UFNO,WDIOFF		;STORE FILE # INTO DIRECTORY
	MOVEI	T2,TMPBUF		;GET FHB ADDRESS
	PUSHJ	P,INIFHB		;CREATE THE INITIAL FHB FOR ME
	LOAD.	T1,RVNO,[<DELBUF-FHBBUF>*4]
	TDNE	F,[X%SUPER]		;SKIP IF NOT SUPERCEEDING
	STOR.	T1,RVNO,FHBFOO		;STORE REV # IN FHB
	LOAD.	T1,FSEQ,FHBFOO		;GET SEQ#
	STOR.	T1,UFSQ,WDIOFF		;STORE SEQ# IN DIRECTORY
	HLRZ	T1,TMPFDB+.FXNAM	;GET SIXBIT NAME 1ST 3RD
	PUSHJ	P,C6T5			;CONVERT 1ST 3RD TO RAD50
	STOR.	T1,FNM1,FHBFOO		;STORE FILE NAME PART 1 INTO FHB
	STOR.	T1,UFN1,WDIOFF		;INSERT INTO DIRECTORY TOO
	HRRZ	T1,TMPFDB+.FXNAM	;GET SIXBIT NAME PART 2
	PUSHJ	P,C6T5			;CONVERT 2ND 3RD TO RAD50
	STOR.	T1,FNM2,FHBFOO		;STORE FILE NAME PART 2 IN FHB
	STOR.	T1,UFN2,WDIOFF		;INSERT INTO DIRECTORY TOO
	HLRZ	T1,TMPFDB+.F2NAM	;GET 3RD PART OF FILE NAME
	PUSHJ	P,C6T5			;CONVERT TO RAD50
	STOR.	T1,FNM3,FHBFOO		;PUT INTO FHB
	STOR.	T1,UFN3,WDIOFF		;PUT INTO DIRECTORY FILE TOO
	HLRZ	T1,TMPFDB+.FXEXT	;GET FILE TYPE
	PUSHJ	P,C6T5			;CONVERT TO RAD50
	STOR.	T1,FTYP,FHBFOO		;STORE INTO FHB
	STOR.	T1,UFTY,WDIOFF		;STORE INTO DIRECTORY TOO
	MOVE	T1,.FXGEN+TMPFDB	;GET GENERATION #
	STOR.	T1,UVER,WDIOFF		;STORE INTO DIRECTORY
	STOR.	T1,FVER,FHBFOO		;AND STORE INTO FHB
	SKIPE	T1,V$FPRO+OUTFDB
	STOR.	T1,FPRO,FHBFOO		;STORE PROTECTION IF SPECIFIED
;HERE TO SETUP AND PREPARE FOR ACTUAL TRANSFER OF DATA
	LOAD.	T1,FTYP,FHBFOO		;GET THE FILE TYPE IN RAD50
	PUSHJ	P,EXTCHK		;GO IMPLY SOME FLAGS
	MOVE	T2,.FXSWT+OUTFDB	;GET OUTPUT SWITCHES
	TDZ	T2,[S$IMAG!S$BINA!S$ASCI!S$CONT];FORGET MODE FLAGS
	MOVE	T3,.FXSWT+OUTFDB	;GET OUTPUT SWITCHES
	TDNE	T3,[S$IMAG!S$BINA!S$ASCI!S$CONT];GIVE AN OUTPUT SWITCH?
	MOVE	T1,T3			;YES, GET MODE FLAGS FROM THAT
	AND	T1,[S$IMAG!S$BINA!S$ASCI!S$CONT];ISOLATE MODE SWITCHES ONLY
	OR	T1,T2			;MIX UP ALL THE FLAGS
	TDNN	T1,[S$IMAG!S$BINA!S$ASCI]
	TDO	T1,[S$ASCI]		;FORCE /ASCII IF NOTHING ELSE
	MOVEM	T1,TMPFDB+.FXSWT	;GO TURN ON THE SWITCHES, IF ANY

	MOVE	T1,LERBLK+.RBSIZ	;GET # OF BLOCKS IN THE FILE
	IDIVI	T1,200			;COMPUTE # OF BLOCKS FROM +VE WORDS
	IMULI	T2,4			;NOW T2=#PDP11 BYTES
	CAIE	T2,0			;SKIP IF EXACT FIT
	ADDI	T1,1			;ONE MORE BLOCK IF NOT EXACT FIT
	MOVEM	T1,LERBLK+.RBALC	;.RBALC NOW EQUALS # OF DATA BLOCKS
	MOVEM	T2,LERBLK+.RBEST	;.RBEST NOW EQUALS # WORD OF SPILLAGE

	MOVE	T1,[O.CRDT,,A.CRDT]	;SETUP PDP11 BYTE POINTER TO CREATE DATE
	MOVEI	T2,TMPBUF		;POINT AT OUTPUT FILE'S FHB
	LDB	T4,[POINT 3,LERBLK+.RBEXT,20]	;FETCH PDP10'S CREATE DATE
	LSH	T4,^D12			;MAKE ROOM FOR MORE BITS
	LDB	T3,[POINT 12,LERBLK+.RBPRV,35]	;GET LOW ORDER PDP10 DATE
	OR	T3,T4			;COMPUTE PDP10 CREATE DATE
	PUSHJ	P,STODAT		;INSERT CREATE DATE INTO FHB

	MOVE	T1,[O.CRTI,,A.CRTI]	;GET PDP11 BYTE POINTER TO CREATE TIME
	MOVEI	T2,TMPBUF		;GET POINTER TO OUTPUT FILE'S FHB
	LDB	T3,[POINT 11,LERBLK+.RBPRV,23]	;GET CREATE TIME FROM RIB
	PUSHJ	P,STOTIM		;STORE CREATE TIME INTO FHB

	PUSHJ	P,SAVE4			;SAVE SOME ACS
	SETOB	P1,P3
	TDZ	F,[X%EOF]

	MOVEI	T1,BLKBFR-1
	PUSHJ	P,ZAPBFR		;CLEAR TRAILING TRASH
	MOVE	T1,TMPFDB+.FXSWT	;GET OUTPUT MODE FLAGS
	TDNN	T1,[S$IMAG!S$BINA]
	JRST	C$PUTC			;DO ASCI MODE XFER TO RSX20F
	JRST	C$PUTD			;DO IMAGE MODE XFER TO 20F
;ROUTINE TO GROW THE UFD BY ONE BLOCK TO MAKE ROOM FOR MORE FILES
UFDGRO:	TYPE	<% Expanding User File Directory>
	PUSHJ	P,CRLF
        MOVEI   T1,WDIFHB               ;POINT AT THE FHB
        PUSHJ   P,EXPDIR                ;EXPAND T
          JRST  PUTER2                  ;GO COMPLAIN
        JRST    $PUTB2                  ;GO SCAN NEW UFD BLOCK FOR 0S








        SUBTTL  EXPDIR
 
;       ROUTINE TO EXPAND THE UFD WHOSE FHB IS (T1)
;
;ENTER:
;       T1/     ADDRESS OF FHB
;EXIT:
;       <nonskip - we failed>
;       <skip - we expanded by 1 block>
 
EXPDIR: PUSHJ   P,SAVE4                 ;SAVE SOME ACS
        MOVE    P1,T1                   ;SAVE THE FHB ADDRESS
        MOVEI   T1,1                    ;SPECIFY A MAX OF 1 BLOCK NEEDED
        PUSHJ   P,SCNSBM                ;
          JRST  EXPER0                  ;GO COMPLAIN
        MOVEI   T1,1                    ;ONLY USE 1 BLOCK, NO MATTER HOW MANY
        MOVE    P2,T2                   ;REMEMBER THE BLOCK WE GOT
        MOVEI   T3,(P1)                 ;POINT AT THE FHB CONVERNED
        PUSHJ   P,STORET                ;INSERT RIB POINTER FOR NEW BLOCK
 
        MOVE    P4,P1                   ;COPY ADDRESS OF FHB
        SUBI    P4,FHBBUF               ;GET PDP10 OFFSET BETWEEN FHB BUFFRS
        IMULI   P4,4                    ;COMPUTE # PDP11 BYTES IN OFFSET
 
        LOAD.   T1,EFBL,P4              ;GET # OF EOF BLOCK (LOW)
        ADDI    T1,1                    ;ONE MORE BLOCK ADDED
        STOR.   T1,EFBL,P4              ;INSERT INC'ED BLOCK #
        LOAD.   T2,EFBH,P4              ;GET HGH #
        ADDI    T2,1                    ;ASSUME CARRY OCCURRED
        TRNE    T1,400                  ;SKIP IFF CARRY DID NOT HAPPPEN
        STOR.   T2,EFBH,P4              ;INSERT HGH ORDER IF CARRY HAPPENED
 
        MOVE    T1,P1                   ;T1=ADDR OF FHB
        PUSHJ   P,WRUFHB                ;GO (RE)WRITE THE FHB
        MOVE    T1,P2                   ;GET BACK THE NEWLY ALLOCATED BLOCK #
        PUSHJ   P,SUSET                 ;POSITION THE DISK TO THAT BLOCK
        OUTPUT  VIO,[IOWD 1,LOWZRO      ;ZERO THE NEW BLOCK
                        0]              ;...
        JRST    CPOPJ1
 
EXPER0: TYPE    <% Cannot extend directory
>
        POPJ    P,
;
;		VARIOUS RANDOM OUTPUT ERRORS FOR PUT COMMAND

;	HERE IF OUTPUT DIRECTORY FOR "PUT" COMMAND DOESN'T EXIST OR
;	IF (HOW?) THERE IS MORE THAN 1 DIRECTORY
PUTER1:	TYPE	<% Output directory does not exist for >
PUTER0:	PUSHJ	P,VOLOUT		;TYPE NAME OF VOLUME
	MOVE	T1,OUTFDB+.FXDIR	;GET PPN
	PUSHJ	P,PPNOUT		;TYPE IT
	MOVE	T1,TMPFDB+.FXNAM	;GET FILE NAME
	PUSHJ	P,SIXOUT		;TYPE 1ST PART OF FILE NAME
	SKIPE	T1,TMPFDB+.F2NAME	;GET 2ND PART OF FILE NAME
	PUSHJ	P,SIXOUT		;TYPE 2ND PART OF FILE NAME
	TYPE	<.>			;SEPERAT
	HLLZ	T1,TMPFDB+.FXEXT	;GET EXTENSION
	PJRST	SIXOUT			;TYPE FILENAME EXTENSION

PUTER2:	TYPE	<% Cannot extend directory for >
	JRST	PUTER0

PUTER3:	TYPE	<% All generation numbers already used for >
	AOS	(P)
	JRST	PUTER0

PUTER4:	TYPE	<% Cannot OPEN input device for >
	PUSHJ	P,PUTR4B
	PUSHJ	P,CRLF
	JRST	CPOPJ1

PUTR4B:	SKIPN	T1,OPNBLK+1		;GET DEVICE NAME
	MOVSI	T1,'???'		;GET ERROR DEVICE NAME
	PUSHJ	P,SIXOUT		;TYPE DEVICE NAME
	TYPE	<:>			;TRAIL WITH SEPERATOR
	MOVE	T1,LERBLK+.RBNAM	;GET FILE NAME FROM RIB
	PUSHJ	P,SIXOUT		;TYPE FILE NAME
	TYPE	<.>			;DOT SEPERATOR FOR FILENAME EXTENSION
	HLLZ	T1,LERBLK+.RBEXT	;GET FILENAME EXTESION FROM RIB
	SKIPE	T1			;SKIP IF BLANK EXTENSION
	PUSHJ	P,SIXOUT		;TYPE OUT FILENAME EXTENSION
	PJRST	TYPPTH			;TYPE OUT PATH SPEC

PUTER5:	TYPE	<% LOOKUP error >
	HRRZ	T1,LERBLK+.RBEXT	;GET LOOKUP ERROR FROM L/E/R BLOCK
	PUSHJ	P,OCTOUT		;TYPE ERROR NUMBER IN OCTAL
	TYPE	< for >			;
	PUSHJ	P,PUTR4B		;TYPE FILENAME.TYPE
	PUSHJ	P,CRLF			;END WITH CRLF
	JRST	CPOPJ1
;HERE TO XFER AN IMAGE MODE FILE
C$PUTD:	STOR.	[R.FIX],RTYP,FHBFOO	;SHOW FIXED TYPE RECORDS
	STOR.	[^D512],RSIZ,FHBFOO	;FIXED LENGTH IS 512 BYTES=1 DISK BLOK
;	^^^ THIS IS THE PLACE TO SETUP OTHER RANDOM FHB VALUES!
	SETSTS	FIO,.IOIMG		;OVERRIDE ASCII, USE IMAGE MODE
	MOVSI	T1,(POINT 36,0,35)	;GET IMAGE MODE BYTE POINTER
	HLLM	T1,DIBUF+.BFPTR		;SO CALCULATIONS BELOW COME OUT RIGHT
	PUSHJ	P,OUT21F		;SETUP FIRST RETRIEVAL PAIR
;HERE TO READ ANOTHER BLOCK
$PUTD1:	IN	FIO,			;READ BLOCK FROM 10 DISK
	SKIPA
	  JRST	$PUTD2			;BRANCH IF INPUT FROM TOPS10 FAILED
$PUTD3:	HRRZ	T1,DIBUF+.BFCTR		;GET PDP10 WORD COUNT
	IMULI	T1,4			;CONVERT TO PDP11 BYTE COUNT
	MOVNS	T1			;MAKE IT -VE
	ADDI	T1,1000			;COMPUTE RSX COUNT
	MOVEM	T1,RSXCTR		;SAVE RSX COUNT FOR OUT20F
	HRRZ	T1,DIBUF+.BFPTR		;POINT AT BUFFER
	ADDI	T1,1			;POINT AT DATA PORTION
	PUSHJ	P,OUT20F		;OUTPUT THAT BLOCK
	JRST	$PUTD1			;LOOP

;HERE IF ERROR READING TOPS10 FILE 
$PUTD2:	STATZ	FIO,IO.ERR		;SKIP IF JUST AN EOF ERROR
	JRST	$PUTD4			;BRANCH IF REAL SERIOS ERROR
	JRST	PTIEOF			;JOIN COMMON EOF PROCESSOR
$PUTD4:	TYPE	<% Input error >	;HERALD THE ERROR
	GETSTS	FIO,T1			;GET I/O STATUS FOR THAT CHANNEL
	PUSHJ	P,OCTOUT		;TYPE THE STATUS
	TYPE	< for >			;
	PUSHJ	P,PUTR4B		;TYPE FILE SPEC
	TYPE	<, block  >
	MOVE	T1,BLKCNT		;GET RELATIVE BLOCK NUMBER
	PUSHJ	P,DECOUT		;TYPE RELATIVE BLOCK # IN DECIMAL
	PUSHJ	P,CRLF			;END MESG WITH CRLF
	GETSTS	FIO,T1			;GET STATUS AGAIN
	TDZ	T1,[IO.ERR]		;TURN OFF ANY ERROR BITS
	SETSTS	FIO,(T1)		;FORCE ERROR-FREE STATUS TO TAKE EFFECT
	JRST	$PUTD3			;GO OUTPUT BLOCK ANYWAY TO PRESERVE SIZE
;ROUTINE TO WRITE ONE BLOCK TO THE CURRENT 20F OUTPUT FILE
OUT20F:	SOJL	P1,OUT21F		;BRANCH IF FIRST ONE
	PUSH	P,T1			;SAVE T1
	PUSH	P,T2			;SAVE T2
	MOVN	T2,RSXCTR		;GET -VE BYTE COUNT FOR BLOCK
	ADDI	T2,1000			;COMPUTE T2=BYTES USED
	STOR.	T2,EFBL,FHBFOO		;REMEMBER FF BYTE
	HRLI	T1,-200			;CONSTRUCT 200 WORD IOWD WORD
	SUBI	T1,1			;-1 FOR "DF10" FORMAT
	SETZ	T2,			;END IOLIST WITH 0 IOWD
	OUTPUT	VIO,T1			;WRITE BLOCK OUT TO 20F VOLUME
	PUSHJ	P,ZAPBFR		;CLEAR BLOCK'S BUFFER FOR NEXT TIME
	STATZ	VIO,IO.ERR		;SKIP IF NO ERROR
	  JRST	OUT22F			;BRANCH IF OUTPUT FAILED
	POP	P,T2			;RESTORE T2
	POP	P,T1			;RESTORE T1
	AOS	BLKCNT			;COUNT SUCCESSFULLY XFER'D BLOCK
	STOR.	BLKCNT,HIBL,FHBFOO	;KEEP TRACK OF HIGHEST VBN ALLOCATED
	POPJ	P,			;RETURN

;HERE WHEN NO MORE BLOCKS LEFT IN THIS GROUP
OUT21F:	PUSH	P,T1			;SAVE BUFFER ADDRESS
	PUSH	P,T2			;SAVE T2
	PUSH	P,T3			;SAVE T3
	DMOVE	T1,P3			;GET ORIGINAL SBM POINTERS
	MOVEI	T3,TMPBUF		;WHICH BUFFER TO STORETIZE
	SKIPL	P3			;SKIP IF FIRST TIME
	PUSHJ	P,STORET		;STORE A RETRIEVAL POINTER
	PUSH	P,P3			;SAVE MAGIC FLAG

	SKIPGE	T1,LERBLK+.RBALC	;GET # OF BLOCKS LEFT IN FILE
	MOVEI	T1,1			;JUST ONE IF WE'RE BEYOND EXPECTED EOF
	CAILE	T1,^D256		;SKIP IF SIZE IS OK
	MOVEI	T1,^D256		;REDUCE SIZE IF TOO BIG
	PUSHJ	P,SCNSBM		;GO GET SOME BLOCKS
	  TYPE	<? 20F volume out of space >,OUT23F
	CAILE	T1,^D256		;TOO BIG FOR RETRIEVAL POINTER?
	MOVEI	T1,^D256		;YES, TRUNCATE IT THEN
	DMOVE	P1,T1			;SAVE RET APRI
	DMOVE	P3,T1			;SAVE RET PAIR
	MOVN	T3,T1			;GET -VE SIZE IN THIS GROUP
	ADDM	T3,LERBLK+.RBALC	;ADJUST COUNT FOR NEXT TIME
	MOVE	T1,T2			;GET BASE LBN
	PUSHJ	P,SUSET			;POSITION DISK
	POP	P,T1			;GET BACK THE OLD P3
	JUMPL	T1,[POP	P,T3
		POP	P,T2
		POP	P,T1
		POPJ	P,]
	POP	P,T3
	POP	P,T2
	POP	P,T1
	JRST	OUT20F			;TRY AGAIN

OUT22F:	TYPE	<% Output error >
	GETSTS	VIO,T1
	PUSHJ	P,OCTOUT
OUT23F:	TYPE	< for >
	PUSHJ	P,PUTER0
	TYPE	<, block >
	MOVE	T1,BLKCNT
	PUSHJ	P,DECOUT
	PUSHJ	P,CRLF
	JRST	.ERR
;	ROUTINE TO CLEAR OUT THE I/O BUFFER
ZAPBFR:	PUSHJ	P,SAVE2
	HRRZI	P1,1(T1)
	SETZM	(P1)
	MOVEI	P2,177(P1)
	HRLI	P1,(P1)
	ADDI	P1,1
	BLT	P1,(P2)
	POPJ	P,
;HERE TO XFER AN ASCII MODE FILE
C$PUTC:	SETOM	RSXCTR			;START OFF BUFFERED POINTER
	SETZM	BLKCNT			;# BLOCKS IN FILE
	STOR.	[R.VAR],RTYP,FHBFOO	;VARIABLE LENGTH RECORDS
	STOR.	[FD.CR],RATT,FHBFOO	;CR/LF PAIRS IMPLIED
	INPUT	FIO,			;READ A BLOCK
	STATZ	FIO,IO.EOF!IO.ERR	;EOF OR ERROR?
	JRST	$PUTC1			;YES, GO HANDLE THAT
	MOVE	T1,DIBUF+.BFPTR		;GET THE POINTER
	IBP	T1			;MAKE SURE IT'S VALID
	MOVE	T1,(T1)			;GET THE 1ST WORD OF THE FILE
	TRNE	T1,1B35			;LINE # BIT ON?
	JRST	C$PUTE			;COPY A SEQ'ED FILE
	JRST	C$PUTF			;COPY A VARIABLE FILE

$PUTC1:	STATO	FIO,IO.EOF		;SKIP IF EOF (IE: NULL FILE)
	ERROR	<I/O error on input file>
	JRST	PUTEOF			;ODD, NULL FILE
;HERE TO XFER A NORMAL ASCII MODE FILE
C$PUTF:	MOVSI	T1,-<1000*5-1>		;COUNT OF MAX CHARACTERS PER LINE
	MOVE	T2,[POINT 7,LINBUF]	;POINT AT LINE BUFFER

$PUTF1:	PUSHJ	P,GETC			;GET A BYTE
	  JRST	[TDO F,[X%EOF]		;REMEMBER EOF
		JRST	$PUTF2]		;SKIP AHEAD
	JUMPE	T3,$PUTF1		;IGNORE NULLS
	CAIN	T3,15			;IGNORE CR'S
	JRST	$PUTF1			;...
	PUSHJ	P,TRMSK0		;SKIP IF A TERMINATOR CHARACTER
	AOBJN	T1,[IDPB T3,T2		;LOOP IF STILL ROOM, INSERT CHAR
		JRST $PUTF1]		;...

	HRRZS	T1			;ISOLATE CHARACTER COUNT
;HERE IF WE FIND END OF LINE
$PUTF2:	PUSH	P,T1			;SAVE BYTE COUNT
	MOVE	T3,(P)			;GET LOW BYTE
	PUSHJ	P,PUT20F		;SAVE LOW BYTE OF COUNT IN 20F FILE
	LDB	T3,[POINT 8,T1,27]	;GET HIGH BYTE OF COUNT
	PUSHJ	P,PUT20F		;SAVE HIGH BYTE TOO
	MOVE	T2,[POINT 7,LINBUF]	;GET POINTER

	HRRZ	T1,(P)			;RESTORE T1
	JUMPE	T1,$PUTF4		;SKIP XFER OF BYTES IF NONE THERE
$PUTF3:	ILDB	T3,T2			;GET A BYTE
	PUSHJ	P,PUT20F		;PUT BYTE IN 20F FILE
	SOJG	T1,$PUTF3		;LOOP TILL LINE XFERRED
$PUTF4:	POP	P,T1			;RESTORE BYTE COUNT
	MOVEI	T3,0
	TRNE	T1,1
	PUSHJ	P,PUT20F		;INSERT DUMMY IF ODD BYTE COUNT
	TDZN	F,[X%EOF]		;SKIP IF END OF FILE
	JRST	C$PUTF			;GO GET ANOTHER LINE
	JRST	PTAEOF			;JOIN COMMON CLOSE FILE CODE
;HERE TO XFER A LINE SEQUENCED ASCII MODE FILE
C$PUTE:	SETOM	LINNUM			;ZERO LINE SEQ #
	STOR.	[R.SEQ],RTYP,FHBFOO	;DECLARE A SEQ'D FILE
$PUTE0:	SETZ	T1,			;ZERO COUNT OF CHARACTERS IN THIS LINE
	MOVE	T2,[POINT 7,LINBUF]	;POINT AT LINE BUFFER

$PUTE1:	PUSHJ	P,GETC			;GET A BYTE
	  JRST	[TDO F,[X%EOF]		;REMEMBER EOF
		JRST	$PUTE2]		;SKIP AHEAD
	MOVE	T4,DIBUF+.BFPTR		;GET POINTER
	MOVE	T4,(T4)			;GET THE 5 CHARS THERE
	TRNE	T4,1			;CHECK FOR START OF A NEW LINE
	JRST	$PUTE2			;GO GET LINE NUMBER, FLUSH OLD ONE
	JUMPE	T3,$PUTE1		;IGNORE NULLS
	IDPB	T3,T2			;STORE THE BYTE WE JUST GOT
	AOJA	T1,$PUTE1		;LOOP TILL END OF LINE

;HERE IF WE FIND A LINE SEQ# FLAG
$PUTE2:	SKIPGE	LINNUM			;SKIP IF NOT FIRST TIME
	JRST	$PUTE4			;BRANCH IF FIRST TIME
;HERE IF WE FIND END OF LINE
	ADDI	T1,2			;ACCOUNT FOR THE SEQ# BYTES
	PUSH	P,T1			;SAVE BYTE COUNT
	MOVE	T3,T1			;GET LOW BYTE OF COUNT
	PUSHJ	P,PUT20F		;SAVE LOW BYTE OF COUNT IN 20F FILE
	LDB	T3,[POINT 8,(P),27]	;GET HIGH BYTE OF COUNT
	PUSHJ	P,PUT20F		;SAVE HIGH BYTE TOO

	MOVE	T3,LINNUM		;GET LOW BYTE OF SEQ#
	PUSHJ	P,PUT20F		;PUT HIGH BYTE OF COUNT IN FILE
	LDB	T3,[POINT 8,LINNUM,27]	;GET HIGH BYTE OF SEQ#
	PUSHJ	P,PUT20F		;PUT HIGH BYTE IN 20F FILE

	MOVE	T1,(P)			;RESTORE BYTE COUNT
	SUBI	T1,2			;DISCOUNT THE SEQ# BYTES
	MOVE	T2,[POINT 7,LINBUF]	;GET POINTER

$PUTE3:	ILDB	T3,T2			;GET A BYTE
	PUSHJ	P,PUT20F		;PUT BYTE IN 20F FILE
	SOJG	T1,$PUTE3		;LOOP TILL LINE XFERRED
	POP	P,T1			;RESTORE BYTE COUNT
	TRNE	T1,1
	PUSHJ	P,PUT20F		;INSERT DUMMY IF ODD BYTE COUNT
	TDZE	F,[X%EOF]		;SKIP IF NOT END OF FILE
	JRST	PTAEOF			;CLOSE UP FILE, START ANOTHER

;HERE TO START A NEW LINE STARTING AT LINE NUMBER
$PUTE4:	SETZ	T1,			;START OFF AT 0
	LDB	T3,DIBUF+.BFPTR		;GET BACK 1ST DIGIT OF LINE NUMBER
REPEAT	4,<
	IMULI	T1,^D10
	ADDI	T1,-"0"(T3)
	PUSHJ	P,GETC
	ERROR	<EOF IN MIDDLE OF LINE SEQUENCE NUMBER>
>
	IMULI	T1,^D10
	ADDI	T1,-"0"(T3)
	MOVEM	T1,LINNUM		;SAVE LINE #
	JRST	$PUTE0			;DO ANOTHER
;HERE WHEN WE ARE FINISHED XFER'ING AN ASCII MODE 20F OUTPUT FILE
PTAEOF:	MOVEI	T1,BLKBFR
	PUSHJ	P,OUT20F		;PUT OUT LAST PARTIAL BUFFER
PTIEOF:	MOVEI	T1,1000			;SIZE OF A BLOCK
	SUB	T1,RSXCTR		;GET EOF BYTE
	STOR.	T1,FFBY,FHBFOO		;STORE NUMBER BYTES
	MOVE	T1,BLKCNT		;GET BLOCK COUNT
	STOR.	T1,EFBL,FHBFOO		;STORE LOW ORDER EOF BLOCK #
	LSH	T1,-^D16		;DROP LOW ORDER PART OF EOF BLOCK
	STOR.	T1,EFBH,FHBFOO		;STORE HIGH ORDER EOF BLOCK #
;FALL INTO PUTEOF
;HERE WHEN WE ARE FINISHED XFER'ING TO A 20F OUTPUT FILE
PUTEOF:	SUB	P3,P1			;COMPUTE P3=# BLOCKS THIS GROUP USED
	DMOVE	T1,P3			;GET RET PAIR FOR THIS GROUP
	MOVEI	T3,TMPBUF		;WHICH BUFFER TO STORETIZE
	SKIPE	T1			;SKIP IF GROUP WAS LEFT UNUSED
	PUSHJ	P,STORET		;STORE FINAL RETRIEVAL POINTER PAIR

	MOVE	T1,[S$CONT]		;/CONTIGUOUS OUTPUT?
	LOAD.	T2,UCHA,FHBFOO		;GET OLD CHARACTERISTICS
	TDNE	T1,.FXSWT+TMPFDB	;CHECK
	TDO	T2,[UC.CON]		;TURN ON CONTIGUOUS BIT
	STOR.	T2,UCHA,FHBFOO		;STORE NEW CAHRACTERISTICS

	MOVEI	T1,TMPBUF		;POINT AT THE FHB WE BUILT
	PUSHJ	P,WRUFHB		;WRITE OUT FHB AS IS
	MOVEI	T1,TMPBUF
	PUSHJ	P,TYPFHU
	TYPE	<=>
	MOVEI	FP,TMPFDB
	PUSHJ	P,TYPFIO

	MOVE	T1,.FXSWT(FP)
	TDNE	T1,[S$ASCI]
	TYPE	</ASCII>
	TDNN	T1,[S$ASCI]
	TYPE	</IMAGE>
	MOVE	T1,.FXSWT+TMPFDB
	TDNE	T1,[S$CONT]
	TYPE	</CONTIG>
	RELEAS	FIO,			;RELEASE INPUT FILE
	PUSHJ	P,WRTSBM		;WRITE OUT STORAGE BIT MAP
	PUSHJ	P,WRTIBM		;WRITE OUT INDEX BIT MAP
	PUSHJ	P,UPDDIR		;WRITE OUT DIRECTORY BLOCK
	  ERROR	<PUTEOF cannot update directory>

;NOW GET RID OF OLD FILE'S STORAGE, IF ANY
	AOS	(P)			;FORCE SKIP RETURN
	TDZN	F,[X%SUPER]		;SKIP IF OLD FILE EXISTED
	JRST	[PUSHJ P,CRLF
		 OUTPUT TTY,
		 POPJ P,]
	SOS	(P)			;FORGET SKIP AFTER ALL
	MOVEI	T1,DELBUF		;FILE TO GET RID OF
	PUSHJ	P,RETFHB		;RETURN STORAGE, ETC
	PUSHJ	P,WRTSBM		;REWRITE SBM
					;IBM WILL BE THE SAME, SO WILL DIR
	TYPE	</SUPERCEED
>
	OUTPUT	TTY,
	JRST	CPOPJ1			;GIVE SKIP RETURN
;ROUTINE TO PUT 1 BYTE IN 20F OUTPUT FILE
PUT20F:	SOSGE	RSXCTR			;CHECK FOR ROOM IN OUTPUT
	JRST	PUT21F			;NO ROOM, MAKE ANOTHER BUFFER
	PUSH	P,T1			;USE NO ACS
	MOVS	T1,RSXPTR		;GET PDP11 BYTE POINTER INTO BUFFER
	PUSHJ	P,PUTBYT		;INSERT BYTE
	AOS	RSXPTR			;INCREMENT BYTE POINTER
	POP	P,T1			;RESTORE T1
	POPJ	P,			;RETURN

PUT21F:	PUSH	P,T1			;USE NO ACS
	MOVEI	T1,BLKBFR		;POINT AT OUTPUT BLOCK
	PUSHJ	P,OUT20F		;OUTPUT THE BLOCK
	MOVEI	T1,1000			;GET NEW BYTE COUNT
	MOVEM	T1,RSXCTR		;INIT THE NEW COUNT
	MOVSI	T1,BLKBFR		;GET NEW BYTE POINTER
	MOVEM	T1,RSXPTR		;INIT NEW BYTE POINTER
	POP	P,T1
	JRST	PUT20F			;TRY AGAIN
;ROUTINE TO GET ONE BYTE FROM THE PDP10 INPUT FILE
GETC:	SOSGE	DIBUF+.BFCTR		;SKIP IF BYTES REMAIN IN BUFFER
	JRST	GETC2			;BRANCH IF CURRENT BUFFER EMPTY
	ILDB	T3,DIBUF+.BFPTR		;GET A BYTE FROM BUFFER
	JRST	CPOPJ1			;GIVE GOOD RETURN

GETC2:	IN	FIO,			;TRY TO GET ANOTHER INPUT BUFFER
	JRST	GETC			;BRANCH TO TRY TO GET BYTE AGAIN
	STATO	FIO,IO.EOF		;SKIP IF END OF FILE FOR INPUT
	ERROR	<I/O error reading input file>
	POPJ	P,			;GIVE NON SKIP IF EOF ON INPUT
;ROUTINE TO GET ONE BYTE FROM 20F INPUT FILE
RDBYTE:	PUSHJ	P,SAVE4
	DMOVE	P1,T1			;SAVE T ACS
	DMOVE	P3,T3			;SAVE T ACS
RDBYT0:	SOSGE	RSXCTR			;CHECK FOR MORE BYTES IN THIS BLOCK
	JRST	RDBYT1			;NO, GET ANOTHER BLOCK (IF POSSIBLE)
	MOVS	T1,RSXPTR		;GET PDP11 BYTE POINTER
	PUSHJ	P,GETBYT		;GET BYTE FROM BUFFER
	AOS	RSXPTR			;INCREMENT PDP11 BYTE POINTER
	DMOVE	T1,P1			;RESTORE T ACS
	MOVE	T4,P4			;RESTORE T ACS
	JRST	CPOPJ1			;GIVE GOOD RETURN
RDBYT1:	MOVEI	T1,FHBBUF		;POINT AT THE INPUT FILE FHB
	AOS	T2,RSXVBN		;GET VBN #
	PUSHJ	P,SCNRET		;CONVERT VBN TO LBN
	JRST	[DMOVE T1,P1		;RESTORE T ACS
		 DMOVE T3,P3		;RESTORE T ACS
		 POPJ  P,]		;GIVE EOF RTURN
	PUSHJ	P,SUSET			;POSITION TO READ THAT LBN
	IN	VIO,[IOWD 200,TMPBUF
			0]		;READ THAT BLOCK
	SKIPA
	TYPE	<% INPUT ERROR READING FILE FROM FE DISK>
	MOVEI	T1,FHBBUF
	MOVE	T2,RSXVBN
	PUSHJ	P,EOFBYT
	MOVEM	T1,RSXCTR		;INIT THE BYTE COUNT
	MOVNS	T1			;GET -VE
	ADDI	T1,1000			;GET FFBYTE
	MOVEM	T1,FFBYTE
	MOVEI	T1,TMPBUF		;PDP11 BYTE POINTER
	MOVSM	T1,RSXPTR		;SAVE IT
	JRST	RDBYT0			;GO GET A BYTE
;ROUTINE TO GET ONE PDP11 WORD FROM 20F INPUT FILE
DVWORD:	PUSHJ	P,SAVE2			;SAVE SOME ACS
	PUSHJ	P,RDBYTE		;GET LOW ORDER BYTE
	  POPJ	P,			;PASS ALONG ERROR RETURN
	MOVE	P1,T3			;SAVE LOW BYTE
	PUSHJ	P,RDBYTE		;GET HIGH ORDER BYT
	  ERROR	<NO WORD AVAILABLE FOR INPUT>
	LSH	T3,^D8			;PUT HIGH ORDER BYTE IN HIGH POSITION
	OR	T3,P1			;MERGE HIGH+LOW
	JRST	CPOPJ1			;GIVE GOOD RETURN
;	ROUTINE TO COMPUTE THE # OF BYTES IN THE REQUESTED BLOCK #
;ENTER:	T1/ FHB ADR	T2/ BLOCK # (BASED ON 0)

EOFBYT:	PUSHJ	P,SAVE4			;SAVE SOME ACS
	DMOVE	P1,T1			;SAVE INPUTS
	PUSHJ	P,SCNRET		;TRY TO USETI TO THAT BLOCK
	JRST	[SETZ T1,		;ILLEGAL, SO RETURN 0
		 POPJ P,]		;...
	SUBI	P1,FHBBUF		;COMPUTE PDP10 OFFSET
	IMULI	P1,4			;THEN COMPUTE PDP11 OFFSET

	MOVEI	T1,1000			;DEFAULT TO FULL BLOCK OF BYTES
	LOAD.	T3,EFBL,P1		;GET LOW EOF BLOCK #
	LOAD.	T4,EFBH,P1		;GET HIGH EOF BLOCK #
	LSH	T4,^D8
	OR	T3,T4
	JUMPE	T3,CPOPJ		;IF EOF NOT SET, GIVE A FULL BLOCK
	ADDI	P2,1
	MOVEI	T1,0
	CAMLE	P2,T3
	POPJ	P,			;NONE IF BEYOND EOF!
	MOVEI	T1,1000
	CAME	P2,T3
	POPJ	P,0
	LOAD.	T1,FFBY,P1		;GET FIRST FREE BYTE #(EXACTLY=COUNT)
	POPJ	P,			;RETURN
;	ROUTINE TO TYPE OUT LITERALLY THE FDB FILE SPEC
TYPFDB:	PUSHJ	P,SAVE1
	SKIPE	T1,.FXDEV(FP)		;GET VOLUME/DEVICE NAME
	PUSHJ	P,SIXOUT		;TYPE THE DEVIEC NAME
	SKIPE	.FXDEV(FP)
	TYPE	<:>			;TYPE SEPERATOR
	SKIPE	T1,.FXNAM(FP)		;GET FILE NAME
	PUSHJ	P,SIXOUT
	SKIPE	T1,.F2NAM(FP)		;GET 2ND PART OF FILE NAME
	PUSHJ	P,SIXOUT		;TYPE IT TOO
	HLLZ	T1,.FXEXT(FP)		;GET EXTENTION
	JUMPN	T1,[TYPE <.>
		PUSHJ P,SIXOUT
		JRST .+1]
	SKIPN	.FXDIR(FP)		;SKIP IF EXPLICIT DIRECTORY GIVEN
	POPJ	P,			;EXIT EARLY IF NO DIRECTORY
	MOVSI	T1,-6			;GET # OF DIRECTORY PAIRS
	MOVEI	T2,.FXDIR(FP)		;POINT AT THEM
TYPFD1:	MOVE	T3,(T2)			;GET A DIRECTORY
	MOVEM	T3,PTHBLK+.PTPPN(T1)	;STORE IT
	ADDI	T2,2			;STEP TO NEXT PAIR
	AOBJN	T1,TYPFD1			;LOOP
	PUSHJ	P,TYPPTH
	POPJ	P,
;	ROUTINE TO TYPE OUT THE FILE SPEC ASSOCIATED WITH CHANNEL "FIO"

TYPFIO:	PUSHJ	P,SAVE2			;SAVE SOME ACS
	SETZM	PTHBLK			;INITIALIZE THE PTHBLK TO ZEROS
	MOVE	T1,[PTHBLK,,PTHBLK+1]	;...SETUP BLT POINTER
	BLT	T1,PTHBLK+PTHLEN-1	;...AND INSERT THE ZEROS

	MOVEI	T2,FIO			;GET CHANNEL NUMBER
	DEVNAM	T2,			;GET DEVICE OPEN'ED ON THAT CHANNEL
	MOVSI	T2,'NUL'		;DEFAULT IN CASE IT FAILS
	MOVEI	T1,FIO			;GET CHANNEL NUMBER
	MOVEM	T1,PTHBLK+.PTFCN	;STORE FUNCTION CODE
	MOVE	T1,[XWD PTHLEN,PTHBLK]	;ARG POINTER FOR PATH. UUO
	PATH.	T1,			;RETURN PATH INFO FOR THAT CHANNEL
	  MOVEM	T2,PTHBLK+0		;INSERT DEVICE IF IT FAILS
	MOVE	T1,PTHBLK		;GET DEVICE NAME
	PUSHJ	P,SIXOUT		;TYPE THE DEVICE NAME
	TYPE	<:>			;GIVE SEPERATOR
;	MOVE	T1,.FXNAM(FP)		;GET OUTPUT FILE NAME
	MOVE	T1,LERBLK+.RBNAM	;GET FILE NAME
	PUSHJ	P,SIXOUT		;TYPE OUTPUT FILE NAME
	TYPE	<.>			;GIVE SEPERATOR
	HLLZ	T1,LERBLK+.RBEXT	;GET FILE EXTENSION FROM RIB
	PUSHJ	P,SIXOUT		;TYPE OUTPUT FILE TYPE
;ROUTINE TO TYPE THE PATH SPEC IN THE PTHBLK
TYPPTH:	TYPE	<[>			;START PATH OFF WITH [
	HLRZ	T1,PTHBLK+2		;GET THE P, PART OF P,PN
	PUSHJ	P,OCTOUT		;TYPE P, PART
	TYPE	<,>			;GIVE SEPERATOR
	HRRZ	T1,PTHBLK+2		;GET THE ,PN PART
	PUSHJ	P,OCTOUT		;TYPE THE ,PN PART

	MOVEI	P1,PTHBLK+3		;POINT AT NEXT SFD
TYPPT1:	SKIPN	T1,(P1)			;PICK UP NEXT SFD NAME
	JRST	TYPPT2			;DONE
	TYPE	<,>			;GIVE SEPERATOR
	MOVE	T1,(P1)			;PICK UP SFD NAME
	PUSHJ	P,SIXOUT		;TYPE SFD NAME
	AOJA	P1,TYPPT1		;LOOP FOR ALL SFD NAMS

TYPPT2:	TYPE	<]>			;END PATH WITH ]
	POPJ	P,0			;RETURN
;ROUTINE TO TYPE OUT A L/E/R ERROR GIVEN THE L/E/R BLOCK
LSTLER:	TYPE	<? LOOKUP/ENTER/RENAME code >
	HRRZ	T1,LERBLK+.RBEXT	;GET THE ERROR CODE
	PUSHJ	P,OCTOUT		;TYPE ERROR CODE IN OCTAL
	TYPE	< for >
	MOVE	T1,LERBLK+.RBNAM	;GET FILE NAME FROM LER BLOCK
	PUSHJ	P,SIXOUT		;TYPE FILE NAME
	TYPE	<.>			;TYPE SEPERATOR
	HLLZ	T1,LERBLK+.RBEXT	;GET FILE NAME EXTENSION
	PUSHJ	P,SIXOUT		;TYPE FILE NAME EXTENSION
	MOVE	T1,LERBLK+.RBPPN	;GET PPN OF FILE
	JUMPE	T1,LSTDSH		;BRANCH IF USER SPECIFIED DEFAULT PATH
	TLNN	T1,-1			;SKIP IF USER SPECIFIED EXPLICIT PPN
	JRST	LSTPTH			;GO LIST PATH FROM BLOCK
	PUSH	P,T1			;SAVE T1
	HLRZS	T1			;GET LEFT HALF OF PPN
	TYPE	<[>			;TYPE [ TO START PPN
	PUSHJ	P,OCTOUT		;TYPE LEFT HALF OF PPN
	TYPE	<,>			;TYPE PPN SEPERATOR
	HRRZ	T1,(P)			;RECOVER RIGHT HALF OF PPN
	PUSHJ	P,OCTOUT		;TYPE RIGHT HALF
	TYPE	<]>			;END PPN WITH ]
	POP	P,(P)			;WASTE COPY OF PPN
	PUSHJ	P,CRLF			;END WITH CRLF
	JRST	.ERR			;RESUME ERROR PROCESSING

LSTDSH:	TYPE	<[-]>
	PUSHJ	P,CRLF
	JRST	.ERR

LSTPTH:	TYPE	<[path]>
	PUSHJ	P,CRLF
	JRST	.ERR
	SUBTTL	COMMANDS -- UFD

C$UFD:	PUSHJ	P,TTYPHY
	PUSHJ	P,FILIN			;MUST GET SOME SPEX
	SKIPN	FP,IPLIST		;MUST BE A LIST
	PUSHJ	P,ILLCMD
	MOVE	T1,[FX.EQL]		;DID WE SEEN AN EQUAL?
	MOVE	T2,[777400,,777400]	;MUST BE NICE AND SMALL UIC
	SETO	T3,			;T3=-1=COMPLETELY SPECIFIED
C$UFD0:	SKIPE	.FXNAM(FP)		;
	  ERROR	<Volume labels not supported>
	TDNN	T1,.FXMOD(FP)		;
	SKIPE	.FXEXT(FP)		;
	PUSHJ	P,ILLCMD
	CAMN	T3,.FXDIM(FP)		;NO WILD CARDS IN PPN
	SKIPE	.FXDIR+2(FP)		;NO SFDS PLEASE
	PUSHJ	P,ILLCMD
	TDNE	T2,.FXDIR(FP)		;UIC MUST BE IN RANGE
	PUSHJ	P,ILLCMD
	HRRZ	FP,.FXLNK(FP)		;STEP TO NEXT SPEC IF ANY
	JUMPN	FP,C$UFD0		;CHECK ANOTHER SPEC IF PRESENT

	HRRZ	FP,IPLIST		;POINT AT FIRST SPEC
C$UFD1:	PUSHJ	P,C$UFDA		;GO PROCESS ONE OF THEM
	HRRZ	FP,.FXLNK(FP)		;STEP TO NEXT FILE SPEC, IF ANY
	JUMPN	FP,C$UFD1		;BRANCH IF MORE TO PROCESS
	POPJ	P,			;DONE
C$UFDA:	PUSHJ	P,SAVFF			;SAVE THE FIRST FREE CORE POINTER
	PUSHJ	P,SAVFP			;SAVE THE FILE POINTER
	PUSHJ	P,OPNVOL		;OPEN THE VOLUME FOR FILE I/O
;	LOOK FOR AN ALREADY EXISTING DIRECTORY FILE FOR THE SAME UIC
;	IF IT IS PRESENT, ABORT WITH AN ERROR
	HLRZ	T1,.FXDIR(FP)		;GET PROJECT #
	IDIVI	T1,100			;MAKE T1=1ST DIGIT, T2=2ND*10+3RD
	IDIVI	T2,10			;MAKE T2=2ND, T3=3RD
	LSH	T1,^D12			;MAKE T1=1ST DIGIT IN SIXBIT POSITION
	LSH	T2,^D6			;MAKE T2=2ND DIGIT IN SIXBIT POSITION
	IORI	T1,'000'(T2)		;MAKE T1=1ST DIGIT+2ND DIGIT, SIXBIT FMT
	IORI	T1,(T3)			;MAKE T1=OLD + 3RD DIGIT
	HRLZM	T1,UFDFDB+.FXNAM	;SPECIFY NAME OF FILE

	HRRZ	T1,.FXDIR(FP)		;GET PROGRAMMER NUMBER
	IDIVI	T1,100			;MAKE T1=1ST DIGIT, T2=2ND*10+3RD
	IDIVI	T2,10			;MAKE T2=2ND, T3=3RD
	LSH	T1,^D12			;MAKE T1=1ST DIGIT IN SIXBIT POSITION
	LSH	T2,^D6			;MAKE T2=2ND DIGIT IN SIXBIT POSITION
	IORI	T1,'000'(T2)		;MAKE T1=1ST DIGIT + 2ND DIGIT IN SIXBIT
	IORI	T1,(T3)			;MAKE T1=OLD + 3RD DIGIT TOO
	HRRM	T1,UFDFDB+.FXNAM	;SPECIFY NAME OF FILE
	SETOM	UFDFDB+.FXNMM		;MAKE NAME NOT APPEAR WILD
	SETZM	UFDFDB+.F2NAM		;MAKE SURE NAME IS "SHORT" 6 LETTER FORM
	SETOM	UFDFDB+.F2NMM		;MAKE SURE 2ND 6 LETTERS APPEAR NOT WILD
	HRRZI	T1,'DIR'		;PICK UP FILE TYPE FOR DIRECTORY FILE
	HRLOM	T1,UFDFDB+.FXEXT	;SPECIFY FILE TYPE AND ENSURE NOT WILD
	SETZM	UFDFDB+.FXDIR		;SPECIFY EXPLICIT OWNER UIC OF [0,0]
	SETOM	UFDFDB+.FXDIM		;MAKE SURE UIC FIELD IS NOT WILD
	SETZM	UFDFDB+.FXDIR+2		;MAKE SURE UIC FIELD HAS NO SFD!

	PUSHJ	P,RLDINI		;INITIALIZE THE 20F .LKWLD ROUTINE
	MOVEI	T1,UFDFDB		;POINT AT FDB TO FIND
	MOVEI	T2,FAKFDB		;POINT AT FDB TO EXPAND INTO
	PUSHJ	P,NXTFDB		;SCAN FOR ANY MATCHING FILES
	SKIPA				;SKIP OUT IF NONE FOUND (GOOD!)
	  ERROR	<Directory already exists>
;	SCAN THE OWNING DIRECTORY (IE: [0,0]) FOR A HOLE WE CAN USE
	SETZ	P1,			;0S
	EXCH	P1,UFDFDB+.FXNAM	;REMEMBER FILE NAME IN SIXBIT
	SETZM	UFDFDB+.FXDEV		;ENSURE ALL ZEROS
	HRRZS	UFDFDB+.FXEXT		;EXPLICIT EXT OF 0S
C$UFD2:	PUSHJ	P,RLDINI		;INITIALIZE THE 20F FILE FINDER
	MOVEI	T1,UFDFDB		;FDB TO FIND
	MOVEI	T2,FAKFDB		;FDB TO WRITE INTO
	PUSHJ	P,NXTFDB		;SEARCH FOR THE ENTRY
	  JRST	C$UFD3			;DARN, AREN'T ANY. EXTEND AND TRY AGAIN

;	ALLOCATE AN FHB, FILL IT IN AND WRITE IT OUT.
	MOVEI	P2,<UFDFHB-FHBBUF>*4	;GET OFFSET
	MOVE	P3,WDIOFF
	SUBI	P3,.DIROFF

	SETZ	T1,			;NO SPECIAL FILENUMBER
	PUSHJ	P,ALCFHB		;GO ALLOCATE AN FHB #
;?	MOVEM	T1,UFDFHB		;SAVE IT
	MOVEI	T2,UFDFHB
	PUSHJ	P,INIFHB		;GO MAKE UP AN FHB FOR ME
	HLRZ	T1,P1			;GET 1ST PART OF NAME
	PUSHJ	P,C6T5			;CONVERT TO RAD50
	STOR.	T1,FNM1,P2		;STORE INTO OUR FHB
	STOR.	T1,UFN1,P3		;STORE 1ST PART IN DIRECTORY TOO
	HRRZ	T1,P1			;GET 2ND PART OF NAME
	PUSHJ	P,C6T5			;CONVERT TO RAD50
	STOR.	T1,FNM2,P2		;STORE INTO OUR FHB
	STOR.	T1,UFN2,P3		;STORE 2ND PART IN DIRECTORY TOO
	MOV.	[.RAD50 <DIR>],FTYP,P2	;STORE FILE TYPE INTO OUR FHB
	MOV.	[.RAD50 <DIR>],UFTY,P3	;STORE FILE TYPE IN DIRECTORY TOO

	STOR.	[1],UFSQ,P3		;STORE SEQ# IN DIRECTORY
	STOR.	[1],FSEQ,P2		;STORE SEQ# IN FHB
	STOR.	[UC.CON],UCHA,P2	;SPECIFY CONTIGUOUS FILE
	STOR.	[1],RTYP,P2		;FILE TYPE=#1, FIXED LENGTH RECORDS
	STOR.	[20],RSIZ,P2		;RECORD SIZE=16. BYTES (8 WORDS)

	SKIPN	T1,V$ALLOC(FP)		;GET /ALLOC:n VALUE
	MOVEI	T1,^D32
	IDIVI	T1,^D32			;COMPUTE NUMBER OF BLOCKS REQUIRED
	CAIE	T2,0			;EXACT FIT?
	ADDI	T1,1			;NO, ADD ONE MORE BLOCK
	MOVEM	T1,V$SIZE(FP)
	LDB	T2,[POINT 8,T1,27]	;GET HI BYTE
	STOR.	T2,HIBH,P2		;REMEMBER IT
;	STOR.	[0],HIBH,P2		;...
	STOR.	T1,HIBL,P2		;HIGH BLOCK IN USE IS 1
	AOS	T1			;UP BY ONE TO GET EOF BLOK#
	LDB	T2,[POINT 8,T1,27]	;GET HI BYTE
	STOR.	t2,EFBH,P2		;...
	STOR.	t1,EFBL,P2		;...SO BLOCK HAVING EOF IS #2

	SKIPE	V$FPRO(FP)		;?
	STOR.	V$FPRO(FP),FPRO		;USE HIS PROTECTION IF REQUESTED

	SKIPN	T1,V$SIZE(FP)
	MOVEI	T1,1
	MOVEM	T1,V$SIZE(FP)
	PUSHJ	P,SCNSBM		;GO FIND 1 BLOCK
	  ERROR	<Cannot allocate space to the UFD file>
	CAMLE	T1,V$SIZE(FP)		;BACK UP?
	MOVE	T1,V$SIZE(FP)		;YES, PLEASE
	MOVEM	T1,V$SIZE(FP)		;SAVE SIZE WE ACTUALLY GOT
	IMULI	T1,^D32			;COMPUTE # OF ENTRIES
	MOVEM	T1,V$ALLO(FP)		;SAVE # OF ENTRIES
	MOVE	P1,T2			;SAVE THE BLOCK #
	MOVEI	T3,UFDFHB		;POINT AT FHB TO STORETIZE
	MOVE	T1,V$SIZE(FP)		;GET # OF BLOCKS TO GET
	PUSHJ	P,STORET		;STORE RETRIEVAL PAIR, FIXUP SBM
	MOVEI	T1,UFDFHB		;POINT AT FHB
	PUSHJ	P,WRUFHB		;WRITE A USER FHB

	MOVE	T1,P1			;GET BLOCK # ALLOCATED
	MOVE	T2,V$SIZE(FP)		;GET NUMBER OF BLOCKS ALLOCATED
	PUSHJ	P,SUSET			;POSITION TO IT
C$UFD4:	OUT	VIO,[IOWD 1,LOWZRO		;
		     0]			;GO ZERO IT
	SKIPA
	TYPE	<% Cannot initialize directory to zeroes
>
	SOJG	T2,C$UFD4		;LOOP ZEROING IT ALL
	PUSHJ	P,WRTIBM		;WRITE INDEX BIT MAP
	PUSHJ	P,WRTSBM		;WRITE STORAGE BIT MAP
	LOAD.	T1,FNUM,P2		;GET ALLOCATED FILE NUMBER
	STOR.	T1,UFNO,P3		;STORE IN DIRECTORY ENTRY
	STOR.	[0],UFX0,P3		;STORE 0 IN THE MAGIC PLACE
	STOR.	[1],UVER,P3		;STORE GENERATION # IN DIRECTORY
	MOVE	T1,WDIPBN		;GET PHYSICAL BLOCK #
	PUSHJ	P,SUSET			;POSITION TO DIRECTORY BLOCK
	OUT	VIO,[IOWD 200,WDIBUF	;REWRITE THE MODIFIED DIRECTORY BLOCK
			0]		;
	SKIPA
	TYPE	<% Failed to insert new ufd name in owning directory
>
	TDON	F,[X%INTRO]
	TYPE	<Directories created:
>
	MOVEI	T1,UFDFHB
	PUSHJ	P,TYPFHU
	LOAD.	T1,FPRO,P2
	PUSHJ	P,P11OUT
	TYPE	</ALLOCATE:>
	MOVE	T1,V$ALLO(FP)
	PUSHJ	P,DECOUT
	PUSHJ	P,CRLF
	POPJ	P,			;ALL DONE
;HERE TO EXPAND THE 000000.DIR TO MAKE ROOM FOR NEW UFD
C$UFD3: MOVEI   T1,BUF444               ;POINT AT MFD
        PUSHJ   P,EXPDIR                ;TRY
          ERROR <Cannot expand size of [0,0].DIR>
        JRST    C$UFD2                  ;GO RESCAN
	SUBTTL	COMMANDS -- DESTROY

C$DEST:	PUSHJ	P,TTYPHY		;FORCE OUTPUT TO PHYSICAL TTY
	PUSHJ	P,FILIN			;GET LIST OF VOLUMES
	SKIPN	FP,IPLIST		;SKIP IF A LIST GIVEN
	PUSHJ	P,ILLCMD		;COMPLAIN IF NO VOLUMES TO DESTROY

C$DES0:	PUSHJ	P,D$RSX			;DESTROY AN RSX FILE SYSTEM
	HRRZ	FP,.FXLNK(FP)		;FETCH LINK TO NEXT VOLUME, IF ANY
	JUMPN	FP,C$DES0		;BRANCH IF ANOTHER VOLUME TO DESTROY
	POPJ	P,0			;RETURN IF ALL VOLUMES DESTROYED
;	ROUTINE TO DESTROY THE FRONT END AREA OF RSX
D$RSX:	PUSHJ	P,OPNVIO		;OPEN VOLUME FOR I/O
	SKIPE	FAKVOL			;SKIP IF REAL VOLUME NAME GIVEN
	  ERROR	<Can't DESTROY logical volume>
	TYPE	<Do you really want to DESTROY >
	PUSHJ	P,VOLOUT		;TYPE VOLUME NAME
	PUSHJ	P,YESNO
	POPJ	P,			;NO
	DMOVE	T1,[SIXBIT .FE.
		    SIXBIT .SYS.]	;LOAD FILENAME, EXTENSION FOR LOOKUP
	DMOVE	T3,[0
		    1,,4]		;LOAD PPN FOR LOOKUP
	LOOKUP	VIO,T1			;FIND FE.SYS
	  TYPE	<% FE.SYS not found>,D$RSX0

	SETZM	BLKBFR+.RBNAM		;GET RID OF FILE NAME
	USETI	VIO,0			;SET TO READ RIB
	INPUT	VIO,[IOWD 200,BLKBFR	;
			0]		;READ RIB OF FE.SYS
	CAME	T1,BLKBFR+.RBNAM	;SIMPLISTIC CHECK
	ERROR	<Cannot acquire rib for FE.SYS>
; **** N.B. ****	THIS MIGHT NOT WORK TOO WELL ON A MULTI UNIT STRUCTURE
	MOVE	T1,BLKBFR+.RBSLF	;GET BLOCK # OF THE RIB
	PUSHJ	P,SUSET			;POSITION TO IT
	MOVE	T1,[RP.NDL]		;GET THE NO DELETE BIT
	ANDCAM	T1,.RBSTS+BLKBFR	;TURN IT OFF
	OUTPUT	VIO,[IOWD 200,BLKBFR
			0]		;ULP - REWRITE RIB
	CLOSE	VIO,CL.DAT		;DELETE THE ACCESS TABLE
	DMOVE	T1,[SIXBIT .FE.
		    SIXBIT .SYS.]	;RELOAD THE FILE NAME FOR THE LOOKUP
	DMOVE	T3,[0
		    1,,4]		;RELOAD THE PPN FOR THE LOOKUP
	LOOKUP	VIO,T1			;LOOKUP THE FILE AGAIN
	ERROR	<FE.SYS disappeared>
	SETZB	T1,T2			;ZERO THE FILE NAME FOR DELETE UUO
	SETZB	T3,T4			;MAKE WHOLE BLOCK ZEROS
	RENAME	VIO,T1			;DELETE FE.SYS
	ERROR	<Cannot delete FE.SYS>
	TYPE	<[>
	MOVE	T1,FEUNIT
	PUSHJ	P,SIXOUT
	TYPE	<:FE.SYS[1,4] deleted, >
	MOVE	T1,BLKBFR+.RBALC	;GET SIZE OF FILE
	PUSHJ	P,DECOUT		;TYPE SIZE OF FILE IN BLOCKS
	TYPE	< blocks freed]>
D$RSX0:	PUSHJ	P,CRLF
	PUSHJ	P,G10HOM		;READ HOME BLOCKS
	SETZM	HOME1+HOMFE0		;BREAK LINK IN HOME BLOCK TO FE.SYS
	SETZM	HOME1+HOMFE1		;BREAK LENGTH IN HOME BLOCK
	SETZM	HOME2+HOMFE0		;BREAK DATA IN 2ND HOME BLOCK TOO...
	SETZM	HOME2+HOMFE1		;...
	PUSHJ	P,ZERHOM		;
	RELEASE	VIO,			;RELEASE THE VOLUME
	POPJ	P,0			;RETURN
	SUBTTL	COMMANDS -- ZERO

;	ZERO {unit name}{/SIZE:<# OF BLOCKS>}

C$INI:	PUSHJ	P,TTYPHY		;...OPEN UP THE TTY OUTPUT CHANNEL
	PUSHJ	P,FILIN			;GET UNIT, SWITCHES, ETC
	SKIPN	FP,IPLIST		;SKIP IF ANYTHING TO DO
	PUSHJ	P,ILLCMD
C$ZER0:	PUSHJ	P,Z$RSX			;GO ZERO IT
	HRRZ	FP,.FXLNK(FP)		;STEP TO NEXT FILE SPEC
	JUMPN	FP,C$ZER0		;LOOP IF ANOTHER LEFT
	POPJ	P,			;RETURN WHEN ALL DONE
;	HERE TO ZERO RSX20F FILE SYSTEM

Z$RSX:	PUSHJ	P,DOGETS		;GO DO GETTABS AS NEEDED
	PUSHJ	P,OPNVIO		;OPEN UP FOR VOLUME I/O
	SKIPN	DSKBLK+.DCSNM		;MUST BE MOUNTED VOLUME
	  ERROR	<Cannot ZERO an offline volume>
	PUSHJ	P,MKFESY		;MAKE THE FE.SYS FILE
	PUSHJ	P,MAK11H		;MAKE THE FILES11 HOME BLOCK
	PUSHJ	P,MAKSBM		;MAKE THE STORAGE BIT MAPS
	PUSHJ	P,MAKIBM		;MAKE THE INDEX BIT MAP

	PUSHJ	P,WRT111		;GO WRITE (1,1,0) INDEXF.SYS
	PUSHJ	P,WRT222		;GO WRITE (2,2,0) BITMAP.SYS
	PUSHJ	P,WRT333		;GO WRITE (3,3,0) BADBLK.SYS
	PUSHJ	P,WRT444		;GO WRITE (4,4,0) 000000.DIR;1
	PUSHJ	P,WRT555		;GO WRITE (5,5,0) CORIMG.SYS;1
        PUSHJ   P,MAKLOS                ;GO MAKE TOPS10.SYS;1,2,3,4,5 files

	PUSHJ	P,WRTMFD		;WRITE OUT THE MFD DATA
	PUSHJ	P,WRTSBM		;WRITE THE STORAGE BIT MAPS
	PUSHJ	P,WRTIBM		;WRITE THE INDEX BIT MAP
	PJRST	WRTHOM			;WRITE TOPS-10 HOME BLOCKS
;	SUBROUTINE TO "CREATE" THE INDEXF.SYS (1,1,0) FILE

WRT111:	MOVEI	T1,1		;REQUEST FILE #1
	MOVEI	T2,FHBBUF	;WHICH ONE TO INITIALIZE
	PUSHJ	P,INIFHB	;INITIALIZE THE FILE HEADER BLOCK
	MOV.	[.RAD50 <INDEXF>],FNAM	;STORE FILE NAME
	MOV.	[.RAD50 <SYS>],FTYP	;STORE FILE TYPE

; ATTACH THE BOOT BLOCK TO THIS FILE
	MOVE	T1,[1]		;1 BLOCK
	MOVE	T2,[0]		;AT BLOCK 0
	MOVEI	T3,FHBBUF	;POINT AT FHB TO STORETIZE
	PUSHJ	P,STORET	;...STORE RETRIEVAL POINTERS

; ATTACH THE FILES11 HOME BLOCK
	MOVE	T1,[1]		;1 BLOCK
	MOVE	T2,H11LBN	;AT THE HOME BLOCK
	MOVEI	T3,FHBBUF	;POINT AT FHB TO STORETIZE
	PUSHJ	P,STORET	;...STORE RETRIEVAL POINTERS

; ATTACH THE FHB SAT
	LOAD.	T1,FMAX		;GET # OF FILE HEADERS PERMITTED
	IDIVI	T1,^D4096	;COMPUTE # OF BLOCKS NEEDED FOR FHB SAT
	CAIE	T2,0		;ON THE NOSE?
	ADDI	T1,1		;NO, SO ADD ONE MORE
	MOVE	T2,H11LBN	;GET THE HOME BLOCK ADDRESS
	ADDI	T2,1		;HOME BLOCK ADR+1 IS FHB SAT ADR
	MOVEM	T2,IBMLBN	;BLOCK# OF FHB SAT
	MOVE	T3,T1		;COPY THE # OF BLOCKS
	ADD	T3,T2		;COMPUTE 1ST FHB BLOCK
	MOVEM	T3,FHBLBN	;REMEMBER IT
	MOVEI	T3,FHBBUF	;POINT AT FHB TO STORETIZE
	PUSHJ	P,STORET	;...STORE RETRIEVAL POINTERS

; ATTACH THE FHB LIST
	MOVEI	T1,M.INFH	;GET INITIAL NUMBER OF FILE HEADERS
	MOVE	T2,FHBLBN	;GET WHERE THEY START
	MOVEI	T3,FHBBUF	;POINT AT FHB TO STORETIZE
	PUSHJ	P,STORET	;...STORE RETRIEVAL POINTERS

; WRITE THE FHB
	PUSHJ	P,WRTFHB	;GO WRITE IT (AND FHB SATS)

	POPJ	P,		;ALL DONE
;	SUBROUTINE TO "CREATE" THE BITMAP.SYS (2,2,0) FILE

WRT222:	MOVEI	T1,2		;REQUEST FILE #2
	MOVEI	T2,FHBBUF	;
	PUSHJ	P,INIFHB	;INITIALIZE THE FILE HEADER BLOCK DATA
	MOV.	[.RAD50 <BITMAP>],FNAM	;STORE FILE NAME
	MOV.	[.RAD50 <SYS>],FTYP	;STORE FILE TYPE

; ATTACH THE BM BUFFER BLOCK TO BITMAP.SYS
	MOVE	T1,[1]		;1 BLOCK
	MOVE	T2,FFBLOK	;1ST FREE BLOCK
	MOVEM	T2,SBMLBN	;SAVE LBN OF IT
	MOVEI	T3,FHBBUF	;POINT AT FHB TO STORETIZE
	PUSHJ	P,STORET	;...STORE RETRIEVAL POINTER

; ATTACH THE SAT BLOCKS TO BITMAP.SYS
	MOVE	T1,LSTLBN	;GET LAST BLOCK # AVAILABLE TO OUR "VOLUME"
	IDIVI	T1,^D4096	;COMPUTE # OF BLOCKS IN SAT FOR OUR VOLUME
	CAIE	T2,0		;FIT EXACTLY?
	ADDI	T1,1		;NO, SO ADD ANOTHER BLOCK
	MOVE	T2,FFBLOK	;1ST FREE BLOCK
	MOVEI	T3,FHBBUF	;POINT AT FHB TO STORETIZE
	PUSHJ	P,STORET	;...STORE RETRIEVAL POINTER

	PUSHJ	P,WRTFHB	;WRITE THE FILE HEADER OUT
	POPJ	P,		;RETURN
;	SUBROUTINE TO WRITE OUT (3,3,0) BADBLK.SYS
WRT333:	MOVEI	T1,3		;REQUEST FILE #3
	MOVEI	T2,FHBBUF
	PUSHJ	P,INIFHB	;INITIALIZE THE FILE HEADER BLOCK DATA
	MOV.	[.RAD50 <BADBLK>],FNAM	;STORE FILE NAME
	MOV.	[.RAD50 <SYS>],FTYP	;STORE FILE TYPE

;;	N.B.: NO BLOCKS NEED TO BE ATTACHED!

	PUSHJ	P,WRTFHB	;WRITE THE FILE HEADER OUT
	POPJ	P,		;RETURN
;	SUBROUTINE TO WRITE (4,4,0) 000000.DIR (IE: THE MFD)

WRT444:	MOVEI	T1,4		;REQUEST FILE #4
	MOVEI	T2,FHBBUF
	PUSHJ	P,INIFHB	;INITIALIZE THE FHB
	MOV.	[.RAD50 <000000>],FNAM	;STORE THE FILE NAME
	MOV.	[.RAD50 <DIR>],FTYP	;STORE THE FILE TYPE

	STOR.	[UC.CON],UCHA	;DECLARE FILE IS CONTIGUOUS
	STOR.	[1],RTYP	;RECORD TYPE=#1, FIXED LENGTH RECORDS
	STOR.	[20],RSIZ	;RECORD SIZE=16 (BYTES, ONLY 8 WORDS)
;	STOR.	[1],HIBK	;HIGHEST BLOCK IN USE=1
	STOR.	[0],HIBH
	STOR.	[1],HIBL
;	STOR.	[2],EFBK	;SO EOF BLOCK = 2
	STOR.	[0],EFBH	;
	STOR.	[2],EFBL	;

	MOVEI	T1,1		;1 BLOCK
	MOVE	T2,FFBLOK	;AT NEXT FREE PLACE
	MOVEM	T2,MFDLBN
	MOVEI	T3,FHBBUF	;POINT AT FHB TO STORETIZE
	PUSHJ	P,STORET	;STORE RETRIEVAL POINTERS

	MOVE	T1,MFDLBN	;GET THE BLOCK WE WANT TO USE
        PUSHJ   P,SUSET                 ;POSITION TO IT
        OUTPUT  VIO,[IOWD 1,LOWZRO
                        0]      ;INITIALIZE IT TO ZEROES
        MOVE    T1,MFDLBN
        PUSHJ   P,TAKSBM        ;TAKE IT AWAY FROM SAT
        JFCL
        PJRST   WRTFHB
;	ROUTINE TO WRITE OUT THE MFD DATA AFTER [0,0] CHANGES

WRTMFD:	MOVE	T1,MFDLBN		;GET BLOCK AGAIN
	PUSHJ	P,SUSET			;POSITION DISK
	OUT	VIO,[IOWD 200,MFDDAT	;WRITE OUT THE MFD DATA
			0]		;...
	POPJ	P,			;RETURN IF I/O WAS GOOD
	  ERROR	<Write failed trying to init MFD data>
;	SUBROUTINE TO WRITE (5,5,0) CORIMG.SYS

WRT555:	MOVEI	T1,5		;REQUEST FILE #5
	MOVEI	T2,FHBBUF
	PUSHJ	P,INIFHB	;INITIALIZE THE FHB
	MOV.	[.RAD50 <CORIMG>],FNAM
	MOV.	[.RAD50 <SYS>],FTYP
	STOR.	[UC.CON],UCHA	;DECLARE FILE IS CONTIGUOUS

	MOVEI	T1,^D100	;100 BLOCKS
	MOVE	T2,FFBLOK	;GET THE FIRST FREE BLOCK
	MOVEI	T3,FHBBUF	;POINT AT FHB TO STORETIZE
	PUSHJ	P,STORET	;STORE RETRIEVAL POINTERS

	PUSHJ	P,WRTFHB	;GO WRITE IT OUT
	POPJ	P,0
;       ROUTINE TO CREATE A BUNCH OF FILES IN [0,0] THAT ARE ACTUALLY
;       THE BLOCKED TIED UP TO THE TOPS-10 FILE STRUCTURE (IF ANY)
;       AND WILL THUS ACCOUNT FOR THE "LOST" BLOCKS.
;       (THIS IS NEEDED ONLY TO KEEP "VFY" FROM COMPLAINING.
 
MAKLOS: PUSHJ   P,SAVE4                 ;SAVE SOME ACS
        MOVEI   P4,6                    ;START WITH FILE #6
        MOVE    P3,FSTLBN               ;GET END OF REGION (IE: BLK CNT)
        MOVEI   P2,1                    ;CURRENT BASE LBN #
                                        ;BLOCK 0 IS ALREADY CLAIMED!
 
MAKLO1: MOVE    T1,P3                   ;T1=NUMBER OF BLOCKS
        CAILE   T1,^D26010              ;SKIP IF IT WILL ALREADY FIT
        MOVEI   T1,^D26010              ;REDUCE IT SO IT WILL
        SUB     P3,T1                   ;AND ACCOUNT FOR BLOCKS USED
        MOVEI   T2,(P4)                 ;T2=FILE #
        MOVE    T3,P2                   ;T3=BASE LBN#
        ADD     P2,T1                   ;UPDATE BASE LBN# FOR NEXT PASS
        PUSHJ   P,LOSFIL                ;MAKE A "LOST" FILE
        ADDI    P4,1                    ;GO FOR NEXT FILE NUMBER
        JUMPN   P3,MAKLO1               ;MAKE ANOTHER IF NEEDED
 
 
        POPJ    P,








;ROUTINE TO MAKE A LOST FILE
;T1=# BLOCKS (DO NOT CALL WITH T1 .GT. ^D26000 (APPROX)
;T2=FILE#
;T3=BASE LBN#
LOSFIL: PUSHJ   P,SAVE4                 ;SAVE SOME ACS
        DMOVE   P1,T1                   ;SAVE T1,T2
        DMOVE   P3,T3                   ;SAVE T3,T4
        MOVE    T1,T2                   ;GET FILE #
        MOVEI   T2,FHBBUF               ;POINT AT FHB
        PUSHJ   P,INIFHB                ;INITIALIZE FHB
        MOV.    [.RAD50 <TOPS10>],FNAM  ;INITIALIZE NAME
        MOV.    [.RAD50 <NDL>],FTYP     ;STORE UNIQUE FILE TYPE
        STOR.   P2,FVER                 ;STORE GENERATION NUMBER
        STOR.   P2,FSEQ                 ;STORE FAKE SEQUENCE # TOO
 
LOSFI1: MOVEI   T1,^D255                ;# OF BLOCKS TO GRAB
        CAMLE   T1,P1                   ;SKIP IF THAT IS OK
        MOVE    T1,P1                   ;DO ALL OF REMAINDER IF LESS THAN 255
        SUB     P1,T1                   ;ADJUST COUNT FOR NEXT PASS
        MOVE    T2,P3                   ;GET THE BASE LBN# OF THEM
        ADD     P3,T1                   ;ADJUST BASE LBN FOR NEXT PASS
        MOVEI   T3,FHBBUF               ;POINT AT BUFFER
        PUSHJ   P,STORET                ;GO ARRANGE FOR IT
        JUMPN   P1,LOSFI1               ;LOOP IF MORE BLOCKS TO GRAB
        PUSHJ   P,WRTFHB                ;GO WRITE THE FILE
 
        POPJ    P,








;	SUBROUTINE TO MAKE THE FILES11 HOME BLOCK (AND WRITE IT OUT)
MAK11H:	SETZM	H11BUF		;
	MOVE	T1,[H11BUF,,H11BUF+1]
	BLT	T1,H11BUF+177	;CLEAR FILES-11 HOME BLOCK ('CEPT DECFILE11A)

	MOVE	T1,[TMP166,,H11BUF+166]
	BLT	T1,H11BUF+177	;INSERT MAGIC CONSTANTS
	SKIPN	T1,V$MAXF(FP)	;
	MOVE	T1,[M.FMAX]	;GET DEFAULT
	IDIVI	T1,^D4096	;DIVIDE BY # BITS PER DISK BLOCK
	CAIE	T2,0		;ANY LEFT OVER?
	ADDI	T1,1		;YES, NEED ONE MORE
	STOR.	T1,IBSZ		;STORE "INDEX-BIT-MAP SIZE" (FILE HEADER SAT)

	MOVE	T1,H11LBN	;GET BLOCK# OF HOME BLOCK
	ADDI	T1,1		;+1 MAKES IT BLOCK# OF INDEX BIT MAP
	STOR.	T1,IBLL		;STORE LOW PART OF ADDRESS OF FH SAT
	LSH	T1,-^D16	;GET NEXT WORD
	STOR.	T1,IBLH		;STORE HIGH PART OF ADDRESS OF FH SAT

	SKIPN	T1,V$MAXF(FP)	;
	MOVE	T1,[M.FMAX]
	STOR.	T1,FMAX		;STORE IN HOME BLOCK

	STOR.	[M.SBCL],SBCL	;STORE CLUSTER SIZE
	STOR.	[401],VLEV	;STORE STRUCTURE LEVEL

	MOVE	T1,.FXDIR(FP)	;GET OWNDER'S UIC
	HLRZ	T2,T1		;GET PROJECT #
	DPB	T2,[POINT 8,T1,27]
	SKIPN	T1
	MOVE	T1,[M.VOWN]	;DEFAULT IT
	STOR.	T1,VOWN		;STORE VOLUME OWNER'S UIC

	SKIPN	T1,V$VPRO(FP)	;GET VOLUME PROTECTION
	MOVE	T1,[M.VPRO]	;NONE, GET DEFAULT
	STOR.	T1,VPRO		;PUT INTO HOME BLOCK

	MOVE	T1,[M.VCHA]	;GET DEFAULT VOLUME CHARACTERISTICS
	TDZ	T1,V$CHAR(FP)	;TURN OFF APPROPRIATE BITS
	STOR.	T1,VCHA		;STORE VOLUME CHARACTERISTICS
	SKIPN	T1,V$FPRO(FP)	;ANYTHING?
	LDB	T1,[POINTR(.FXMOD(FP),FX.PRO)]
	SKIPN	T1
	MOVE	T1,[M.DFPR]	;FINAL DEFAULT
	STOR.	T1,DFPR		;STORE DEFAULT FILE PROTECTION
	STOR.	[M.WISZ],WISZ	;STORE # OF RET POINTERS IN WINDOW

	SKIPN	T1,V$EXTE(FP)	;GET IT IF SPECIFIED
	MOVE	T1,[M.FIEX]	;ELSE DEFAULT IT
	STOR.	T1,FIEX		;STORE DEFAULT #BLKS IN AN EXTEND OPERATION

	STOR.	[M.LRUC],LRUC	;STORE #ENTRIES IN DIRECTORY LRU

	MOVE	T1,LOCDAY	;GET TODAY
	PUSHJ	P,MAKSD		;MAKE 2 DIGITS ASCII
	MOV.	T1,VDAY		;STORE IT
	MOVE	T1,LOCMON	;GET MONTH
	MOV.	MONTAB-1(T1),VMON;STORE MONTH
	MOVE	T1,LOCYER	;GET YEAR
	SUBI	T1,^D1900	;ISOLATE xx PART OF 19xx
	PUSHJ	P,MAK2D		;MAKE INTO 2 DIGITS ASCII
	MOV.	T1,VYER		;STORE YEAR

	MOVE	T1,LOCHOR	;GET HOUR
	PUSHJ	P,MAKSD		;MAKE INTO 2 DIGITS
	MOV.	T1,VHOR		;STORE HOUR
	MOVE	T1,LOCMIN	;GET MINUTE
	PUSHJ	P,MAK2D		;MAKE INTO 2 DIGITS
	MOV.	T1,VMIN		;STORE MINUTES
	MOVE	T1,LOCSEC	;GET SECONDS
	PUSHJ	P,MAK2D		;MAKE INTO 2 DIGITS
	MOV.	T1,VSEC		;STORE SECONDS

;	DECFILE11A IS ALREADY AT OFFSETS 166-176

	MOVEI	T1,H11BUF	;POINT AT BLOCK TO CHECKSUM
	MOVEI	T2,O.CHK1/2	;COMPUTE # OF WORDS TO CHECKSUM
	PUSHJ	P,CHKSUM	;COMPUTE CHECKSUM
	STOR.	T1,CHK1		;STORE IT
	MOVEI	T1,H11BUF	;POINT AT BLOCK TO CHECKSUM
	MOVEI	T2,O.CHK2/2	;COMPUTE # OF WORDS TO CHECKSUM
	PUSHJ	P,CHKSUM
	STOR.	T1,CHK2		;STORE THAT TOO
	MOVE	T1,H11LBN	;GET ADDRESS OF HOME BLOCK
	PUSHJ	P,SUSET		;POSITION TO FILES11 HOME BLOCK
	OUT	VIO,[IOWD 200,H11BUF
			0]
	SKIPA
	  ERROR	<OUTPUT error writing FILES-11 home block>
	POPJ	P,
	SUBTTL	ROUTINES TO MANAGE THE INDEX FILE

;	THE INDEX CONSISTS OF TWO PARTS, THE INDEX-BIT-MAP AND
;	THE INDEX-LIST.
;
;	THE FILE INDEXF.SYS[0,0] CONSISTS OF THE BOOT BLOCK (BLOCK0),
;	THE HOME BLOCK, AND THE INDEX-BIT-MAP AND INDEX-LIST.
;
;	THE INDEX-BIT-MAP IS A BIT MAP WITH ENOUGH BITS TO REPRESENT
;	EACH POSSIBLE FILE-HEADER-BLOCK.  THE NUMBER OF FILE-HEADER-BLOCKS
;	PERMITTED IN A VOLUME IS IN THE H.MAXF WORD IN THE VOLUME HOME BLOCK.
;
;	EACH BLOCK IN THE INDEX-BIT-MAP ("IBM") CAN REPRESENT 4096 FHBS.
;	NO VOLUME CAN HAVE MORE THAN 15 BITS WORTH OF FILES, SO NO IBM
;	CAN BE LARGER THAN (2**15)/4096 =  8 BLOCKS.
;
;	THE INDEX-LIST CONSISTS OF ALL THE FILE HEADER BLOCKS.  IF A FHB
;	IS ACTUALLY BEING USED FOR A FILE, THEN THE CORRESPONDING BIT IN
;	THE IBM IS A "1".  (THUS, THE IBM "SAT" USES OPPOSITE LOGIC TO
;	THE SBM "SAT").
;
;	THE FIRST 5 BLOCKS OF THE INDEX-LIST MUST BE PHYSICALLY CONTIGUOUS
;	WITH THE IBM BLOCKS, BECAUSE THEY ARE USED TO FIND THE "KNOWN FILES".
;
;	THE REMAINDER OF THE INDEX-LIST MAY BE SCATTERED THROUGHOUT THE
;	FILES-11 VOLUME.  ORDINARYILY ONLY ENOUGH BLOCKS ARE ALLOCATED TO
;	THE INDEX-LIST TO ACCOUNT FOR THE FHBS IN USE (PLUS A SMALL ADDITIONAL
;	NUMBER TO REDUCE OVERHEAD).  FILE NUMBERS ARE ALWAYS ALLOCATED FROM
;	THE IBM USING THE LOWEST FREE NUMBER.
;
;	THE KNOWN FILES ARE GIVEN FILE NUMBERS OF 1 THROUGH 5.
;
;	FILE#1	INDEXF.SYS
;	FILE#2	BITMAP.SYS	THE STORAGE-ALLOCATION-BIT-MAP
;	FILE#3	BADBLK.SYS	A FILE WHOSE RETRIEVAL POINTERS ARE BAD BLOCKS
;	FILE#4	000000.DIR	A DIRECTORY FILE HOLDING THE KNOWN FILES
;	FILE#5	CORIMG.SYS	A FILE WITH (POSSIBLY) AN IMAGE OF THE MONITOR
;	ROUTINE TO MAKE AN INDEX BIT MAP FROM SCRATCH


MAKIBM:	LOAD.	T1,FMAX			;LOAD T1=MAX# OF FHBS (FROM HOME BLOCK)
	IDIVI	T1,^D4096		;LOAD T1=# BLOCKS IN IBM...
					;...BY DIVING MAX# FHBS/#BITS PER BLOCK
	CAIE	T2,0			;SKIP IFF NO REMAINDER
	ADDI	T1,1			;COUNT ONE MORE BLOCK TO COVER OVERAGE
	IMULI	T1,200			;CONVERT T1=#PDP10 WORDS FOR IBM
	MOVEM	T1,IBMSIZ		;REMEMBER #PDP10 WORDS FOR INCORE IBM
	PUSHJ	P,GETCOR		;GET MEMORY FOR INCORE IBM
	MOVEM	T1,IBMINC		;REMEMBER ADDRESS OF INCORE IBM

	SETZM	MFDDAT			;INITIALIZE THE DATA IN 000000.DIR
	MOVE	T1,[MFDDAT,,MFDDAT+1]	;...
	BLT	T1,MFDDAT+177		;...
	POPJ	P,			;RETURN
;	ROUTINE TO WRITE THE INCORE IBM ONTO DISK (IE: INTO INDEXF.SYS)

WRTIBM:	MOVE	T1,IBMLBN		;LOAD T1=LBN OF ONDISK IBM
	PUSHJ	P,SUSET			;POSITION DISK

	HRRZ	T1,IBMSIZ		;LOAD T1=SIZE OF MAP IN PDP10 WORDS
	IMUL	T1,[-1,,0]		;CONVERT T1=AOBJN INTO MAP
	HRR	T1,IBMINC		;INSERT RH(T1)=POINTER TO MAP DATA
	SUBI	T1,1			;CONVERT T1=IOWD INTO MAP DATA
	SETZ	T2,			;LOAD T2=ENDING IOWD
	OUT	VIO,T1			;XFER MAP DATA TO DISK
	POPJ	P,			;RETURN IF I/O WAS GOOD
	  ERROR	<OUT failed to write IBM>
;	ROUTINE TO READ THE IBM INTO CORE

REDIBM:	MOVE	T1,IBMLBN		;LOAD T1=LBN OF ONDISK IBM
	PUSHJ	P,SUSET			;POSITION DISK

	MOVE	T1,IBMSIZ		;GET SIZE OF IBM IN WORDS
	PUSHJ	P,GETCOR		;ALLOCATE CORE FOR IT
	MOVEM	T1,IBMINC		;SAVE ADDRESS OF INCORE IBM

	MOVE	T1,IBMSIZ		;GET SIZE OF IBM IN WORDS
	IMUL	T1,[-1,,0]		;MAKE INTO IOWD COUNT
	HRR	T1,IBMINC		;INSERT ADDRESS
	SUBI	T1,1			;IOWDIZE THE ADDRESS FIELD
	SETZ	T2,			;END THE IOWD LIST
	IN	VIO,T1			;READ THE IBM INTO CORE
	SKIPA				;SKIP IF I/O WAS GOOD
	  ERROR	<I/O error reading Index-bit-map>

	MOVEI	T3,0			;START FILE COUNT AT 0
	HRRZ	T1,IBMINC		;GET POINTER TO INCORE IBM
	HRLI	T1,(POINT 1,0)		;CONVERT TO BYTE POINTER
	MOVE	T2,IBMSIZ		;GET # OF WORDS IN IBM
	IMULI	T2,^D36			;COMPUTE MAX # OF BITS

REDIB2:	ILDB	T4,T1			;READ A BIT FROM IBM
	CAIE	T4,0			;SKIP IF FILE IS FREE
	ADDI	T3,1			;COUNT A FILE IN USE
	SOJG	T2,REDIB2		;LOOP FOR ALL POSSIBLE FILES

	LOAD.	T1,FMAX			;GET MAX POSSIBLE FILES
	SUB	T1,T3			;COMPUTE # OF FREE FILES
	MOVEM	T1,FHBTAL		;SAVE # OF FREE FIELS
	POPJ	P,			;RETRN
;	ROUTINE TO ALLOCATE A FILE #

ALCFHB:	PUSHJ	P,SAVE1			;SAVE P1
	MOVE	P1,T1			;COPY INITIAL FILE NUMBER REQUESTED
	LOAD.	T3,FMAX			;LOAD T3=MAX# OF FILES
	MOVE	T2,T3			;COPY T2=MAX FILE #
	IMUL	T3,[-1,,0]		;CONVERT T3=AOBJN COUNTER OF FILES
	HRRI	T3,1			;INSERT RH(T3)=1ST FILE NUMBER
	CAIE	T1,0			;USE 1 IF 0
	CAIL	T1,(T2)			;USE 1 IF ILLEGAL REQUEST
	SKIPA
	HRRI	T3,(T1)			;USE REQUEST IF LEGAL

ALCFH1:	MOVEI	T1,-1(T3)		;LOAD T1=CORRESPONDING BIT# OF FILE (T3)
	IDIVI	T1,^D32			;LOAD T1=WORD#, T2=BIT#
	ADD	T1,IBMINC		;CONVERT T1=ADDRESS OF CORRECT BIT
	MOVE	T2,B32TBL(T2)		;CONVERT T2=BIT MASK
	TDNE	T2,@T1			;SKIP IF THIS FILE# (IE: FHB) IS FREE
	  AOBJN T3,[JUMPE P1,ALCFH1	;  BRANCH IF NONSPECIFIC REQUEST
		    ERROR <Requested file-number already in use>]
	JUMPGE	T3,[ERROR <No free file numbers>]
	MOVEI	T1,(T3)		;LOAD T1=FILE # WE KNOW TO BE FREE
	POPJ	P,			;RETURN WITH T1=FREE FILE #
;	ROUTINE TO "RETURN AN RHB"
;	T1/	FHB BUFFER ADDRES
;
;	THIS ROUTINE RETURNS ALL THE BLOCKS ALLOCATED TO THE FILE WHOSE FHB
;	IS IN T1, AND THEN RETURNS THE FHB BLOCK BASED ON THE FILE# IN THE FHB.
;	**THE CALLER IS RESPONSIBLE FOR UPDATING ANY DIRECTORIES THAT
;	**MIGHT POINT AT THIS FHB!!
RETFHB:	PUSHJ	P,SAVE4			;SAVE P1,P2
	MOVE	P1,T1			;COPY P1=FHB BUFFER ADDRESS
	SUBI	P1,FHBBUF		;COMPUTE PDP10 OFFSET
	IMULI	P1,4			;AND THEN COMPUTE PDP11 OFFSET

	LOAD.	T1,FNUM,P1		;GET FILE NUMBER
	SUBI	T1,1
	IDIVI	T1,^D32			;
	ADD	T1,IBMINC		;MAKE P1=ADDRESS OF WORD WITH CORRECT BIT
	MOVE	T2,B32TBL(T2)		;MAKE P2=BIT MASK
	ANDCAM	T2,@T1			;TURN OFF BIT FOR THIS FHB

	LOAD.	T3,USE,P1		;GET T3=# POINTERS IN USE
	JUMPE	T3,CPOPJ		;EXIT IF A NULL FILE
	MOVE	P3,T3			;COPY P3=T3, # POINTERS IN USE
	LSH	P3,-1			;MAKE P3=# PAIRS IN USE

RETFH1:	LOAD.	T4,RCNT,P1		;GET # OF BLOCKS IN THIS PAIR
	ADDI	T4,1			;MAKE T1=TRUE # OF BLOCKS
	LOAD.	T1,RLBN,P1		;GET LOW LBN
	LOAD.	T2,HRET,P1		;GET HIGH LBN
	LSH	T2,^D16			;MAKE ROOM FOR LOW LBN
	OR	T1,T2			;T1=FINAL LBN
	PUSHJ	P,GIVSBM		;GIVE THAT BLOCK BACK
	SOJG	T4,[AOJA T1,.-1]	;RETURN ALL BLOCKS IN THAT POINTER
	ADDI	P1,4			;STEP TO NEXT RETRIEVAL PAIR
	SOJG	P3,RETFH1		;LOOP AND RELEASE THOSE BLOCKS TOO
	POPJ	P,
;	ROUTINE TO INITIALIZE THE FILE HEADER BUFFER

INIFHB:	PUSHJ	P,SAVE2			;SAVE SOME ACS
	DMOVE	P1,T1			;P1=FILE #, P2=FHB BUFFER
	SETZM	(T2)			;START TO ZERO IT OUT
	HRLI	T2,(T2)			;COPY ADDRESS
	ADDI	T2,1			;TURN INTO BLT POINTER
	BLT	T2,177(P2)		;ZERO THE INITIAL FHB

	SUBI	P2,FHBBUF		;CREATE PDP10 OFFSET
	IMULI	P2,4			;...AND THEN PDP11-IZE THAT

	STOR.	[M.IDOF],IDOF,P2	;INIT ID AREA OFFSET
	STOR.	[M.MPOF],MPOF,P2	;INIT MAP AREA OFFSET
	STOR.	P1,FNUM,P2		;INIT FILE #
	CAIG	P1,5			;SKIP IFF NOT A SYSTEM FILE
	STOR.	P1,FSEQ			;FOR KNOWN FILES, MAKE SEQ#=FILE#

	STOR.	[M.FLEV],FLEV,P2	;INIT STRUCTURE LEVEL
	STOR.	[1],PROG,P2		;INIT PROGRAMMER NUMBER=1
	STOR.	[1],PROJ,P2		;INIT PROJECT NUMBER=1
	STOR.	[M.FPRO],FPRO,P2	;INIT FILE PROTECTION
	STOR.	[1],FVER,P2		;INIT VERSION=1

        STOR.   [M.MAX],MAX,P2          ;INITIALIZE MAX # OF RET PAIRS
 
	MOVE	T1,[O.CRDT,,A.CRDT]	;POINT AT CREATION DATE
	MOVE	T2,P2			;GET OFFSET
	IDIVI	T2,4			;GET BACK WORDS
	ADDI	T2,FHBBUF		;AND RELOCATE IT
	DATE	T3,			;GET DATE RIGHT NOW
	PUSHJ	P,STODAT		;STORE THE CURRENT DATE
	MOVE	T1,[O.CRTI,,A.CRTI]	;PDP11 BYTE POINTER
	MOVE	T2,P2			;COPY OFFSET
	IDIVI	T2,4
	ADDI	T2,FHBBUF
	MSTIME	T3,			;GET TIME
	IDIVI	T3,^D1000*^D60		;CONVERT TO MINUTES
	PUSHJ	P,STOTIM		;GO STORE IT
	STOR.	[1],CTSZ,P2		;INIT "COUNT FIELD" = (ALWAYS) 1 BYTE
	STOR.	[3],LBSZ,P2		;INIT "ADDRESS FIELD"= (ALWAYS) 3 BYTES
	POPJ	P,			;RETURN
;	ROUTINE TO READ A FILE-HEADER-BLOCK INTO THE BUFFER
;
;ENTER:
;	T1/	FILE # OF FILES-11 FHB
;	T2/	ADDRESS OF BUFFER TO READ IT INTO

REDFHB:	PUSH	P,T2			;SAVE BUFFER ADDRESS
	SKIPE	BUF111			;READ INDEXF YET?
	CAIG	T1,5			;OR SYSTEM FILE?
	JRST	[ADD T1,FHBLBN		;IF NO INDEXF OR IF KNOWN FILE
		 SOJA T1,REDFH1]	;...THEN TAKE EASY PATH
	MOVEI	T2,2(T1)		;COPY FHB AND CONVERT TO INDEXF BLOK#
	LOAD.	T3,IBSZ			;GET SIZE OF IBM
	ADD	T2,T3			;ADD SIZE OF IBM TOO
	SUBI	T2,1			;BUT FILE#S START AT 1, NOT ZERO
	MOVEI	T1,BUF111
	PUSHJ	P,SCNRET		;FIND IT IF POSSIBLE
	  ERROR	<SCNRET failed to find INDEXF block>
REDFH1:	PUSHJ	P,SUSET			;POSITION DISK
	POP	P,T1			;RESTORE BUFFER ADDRESS
	HRLI	T1,-200			;WANT 200 WORDS
	SUBI	T1,1			;USE IOWD FORMAT FOR THE ADDRESS
	SETZ	T2,
	IN	VIO,T1			;READ THE BLOCK INTO THE BUFFER
	POPJ	P,			;RETURN IF I/O WAS GOOD
	  ERROR	<I/O error reading FHB>
;	ROUTINE TO WRITE A "USER" FILE-HEADER-BLOCK
;
;	T1/	POINTER TO BUFFER TO WRITE

WRUFHB:	PUSHJ	P,SAVE4			;SAVE SOME ACS
	MOVE	P1,T1			;SAVE POINTER
	MOVE	P2,P1			;SAVE ANOTHER COPY OF POINTER TO BUFFER
	SUBI	P1,FHBBUF		;CONVERT TO OFFSET POINTER
	IMULI	P1,4			;COMPUTE OFFSET IN TERMS OF PDP11 BYTES

WRUFH0:	LOAD.	T1,FNUM,P1		;GET FILE #
	SUBI	T1,1			;START AS IF FILE#S BEGAN AT 0
	JUMPL	T1,[ERROR <Illegal file number 0>]
	IDIVI	T1,^D32			;COMPUTE T1=WORD#, T2=BIT#
	ADD	T1,IBMINC		;COMPUTE T1=WORD ADDRESS
	MOVE	T2,B32TBL(T2)		;LOAD T2=BIT MASK
	ORM	T2,@t1			;TURN ON BIT FOR THIS FHB
;HERE TO INSERT A REVISION DATE AND TO "BUMP" THE REVISION NUMBER

; N.B.: IF YOU ARE UNLUCKY, YOU COULD GET TODAYS DATE AND TOMOROWS TIME
	MOVE	T1,[O.RVDT,,A.RVDT]	;MAKE PDP11 BYT POINTER
	MOVE	T2,P1			;COPY FHB
	IDIVI	T2,4			;/4
	ADDI	T2,FHBBUF		;COMPUTE CORRECT ADDRESS
	DATE	T3,			;GET DATE AS OF RIGHT NOW
	PUSHJ	P,STODAT		;STORE RIGHT NOW DATE INTO FHB

	MOVE	T1,[O.RVTI,,A.RVTI]	;GET PDP11 BYTE POINTER TO REVISE TIME
	MOVE	T2,P1			;COPY OFFSET
	IDIVI	T2,4			;GET PDP11 OFFSEt
	ADDI	T2,FHBBUF		;COMPUTE FHB ADDRESS
	MSTIME	T3,			;GET TIME OF DAY ASOF RIGHT NOW
	IDIVI	T3,^D1000*^D60		;COMPUTE SECONDS
	PUSHJ	P,STOTIM		;STORE SECONDS PAST MIDNITE

	LOAD.	T2,FNUM,P1		;GET FILE NUMBER
	LOAD.	T1,RVNO,P1		;GET OLD REVISION NUMBER
	ADDI	T1,1			;UP IT BY ONE
	CAIG	T2,5			;SKIP IF NOT A KNOWN FILE
	PUSHJ	P,[SETZ T1,		;SET REV#=0 IF SYSTEM FILE
		   STOR. T2,FSEQ,P1	;SET SEQ#=FILE# IF SYSTEM FILE
		   POPJ P,0]		;
	STOR.	T1,RVNO,P1		;STORE NEW REVISION NUMBER

	LOAD.	T1,FNUM,P1		;GET FILE #
	MOVEI	T2,2(T1)		;...
	LOAD.	T3,IBSZ			;GET SIZE OF IBM
	ADD	T2,T3			;ADD SIZE OF IBM, TOO
	SUBI	T2,1			;IBM#S START AT 0
	MOVEI	T1,BUF111		;POINT AT FHB HAVING INDEXF.SYS IN IT
	PUSHJ	P,SCNRET		;SCAN FOR THAT BLOCK
	  JRST	WRUFH2			;DARN - MUST EXTEND INDEXF.SYS FIRST
	PUSHJ	P,SUSET			;POSITION DISK
	MOVEI	T1,(P2)			;COPY ADR OF INCORE FHB
	MOVEI	T2,O.CKSM/2		;LOAD T2=SIZE OF CHECKSUM AREA
	PUSHJ	P,CHKSUM		;DO CHECKSUM OF INCORE FHB
	STOR.	T1,CKSM,P1		;INSERT CHECKSUM INTO FHB
	HRLI	P2,-200			;INSERT WORD COUNT
	SUBI	P2,1			;CONVERT TO DF10 FORMAT
	SETZ	P3,			;END THE IOWD LIST
	OUT	VIO,P2			;WRITE OUT HIS FHB
	POPJ	P,			;DONE
	  ERROR	<I/O error writing FHB>

;HERE TO EXTEND THE SIZE OF INDEXF.SYS SO THAT WE CAN WRITE THE FHB INTO IT
WRUFH2:	TYPE	<% Extending INDEXF.SYS
>
	MOVEI	T1,M.INFH		;GET INCREMENTAL SIZE TO EXPAND BY
	PUSHJ	P,SCNSBM		;TRY TO GET IT
	  ERROR	<Cannot extend INDEXF.SYS to assign disk space to the FHB>
	CAILE	T1,M.INFH
	MOVEI	T1,M.INFH
	MOVEI	T3,BUF111		;POINT AT INDEXF.SYS FHB
	PUSHJ	P,STORET		;INSERT THE NEW POINTER
	MOVEI	T1,BUF111		;POINT AT INDEXF.SYS FHB
	PUSHJ	P,WRUFHB		;CALL OURSELVES TO REWRITE INDEXF.SYS
	JRST	WRUFH0			;NOW TRY AGAIN TO WRITE REAL FHB
;	ROUTINE TO WRITE THE FILE-HEADER-BLOCK BUFFER ONTO CORRECT DISK BLOCK
WRTFHB:	LOAD.	T1,FNUM			;LOAD T1=FILE# FROM FHB BUFFER

	SUBI	T1,1			;CONVERT FILE# TO ABSOLUTE FILE INDEX#
	JUMPL	T1,[ERROR <Illegal file number 0>]
	IDIVI	T1,^D32			;LOAD T1=WORD# IN IBM, T2=RELATIVE BIT#
	ADD	T1,IBMINC		;CONVERT T1=ADDRESS OF CORRECT IBM WORD
	MOVE	T2,B32TBL(T2)		;CONVERT T2=CORRECT BIT MASK WITHIN WORD
	ORM	T2,@T1			;TURN ON BIT FOR THIS FHB IN THE IBM

	MOVEI	T1,FHBBUF		;LOAD T1=POINTER TO THE CURRENT FHB
	MOVEI	T2,O.CKSM/2		;LOAd T2=#WORDS TO CHECKSUM
	PUSHJ	P,CHKSUM		;LOAD T1=CHECKSUM OF (T1/T2) BLOCK
	STOR.	T1,CKSM			;INSERT THE CHECKSUM INTO FHB BUFFER

	LOAD.	T1,FNUM			;LOAD T1=FILE NUMBER OF FHB BUFFER
	ADD	T1,FHBLBN		;COMPUTE T1=BLOCK# WITHIN INDEX LIST
	SUBI	T1,1			;ACCOUNT FOR THE FACT FILE#S START AT 1
	PUSHJ	P,SUSET			;POSITION DISK
	OUT	VIO,[IOWD 200,FHBBUF	;WRITE THE FHB BUFFER ONTO DISK
			0]		;
	SKIPA
	  ERROR	<OUT failed at WRTFHB>

	LOAD.	T2,FNUM			;GET FILE NUMBER AGAIN
	SUBI	T2,1		;FILE#S START AT 1 NOT 0
	IMULI	T2,20		;TIMES # OF BYTES PER ENTRY

	LOAD.	T1,FNUM		;GET FILE #
	STOR.	T1,UFNO,T2	;STOR INTO MFD DATA
	LOAD.	T1,FSEQ		;GET SEQ#
	STOR.	T1,UFSQ,T2	;STORE INTO MFD
	LOAD.	T1,FNAM
	STOR.	T1,UFNM,T2
	LOAD.	T1,FTYP
	STOR.	T1,UFTY,T2
	LOAD.	T1,FVER
	STOR.	T1,UVER,T2
	POPJ	P,0
;	ROUTINE TO "TYPE" AN FHB POINTED TO BY (T1)

TYPFHU:	TDOA	F,[X%UIC]		;FLAG WE WANT TO STOP AFTER UIC FIELD
TYPFHB:	TDZ	F,[X%UIC]		;FLAG WE WANT ALL POSSIBLE INFO
	PUSHJ	P,SAVE4			;SAVE SOME ACS
	MOVE	P1,T1			;COPY THE FHB ADDRESS
	MOVE	P2,P1			;SAVE ORIGINAL TOO
	SUBI	P1,FHBBUF		;COMPUTE OFFSET...
	IMULI	P1,4			;...IN TERMS OF PDP11 BYTES
	MOVEI	T1,(P2)			;LOAD T1=FHB ADR
	MOVEI	T2,O.CKSM/2		;T2=# OF WORDS TO CHECKSUM
	PUSHJ	P,CHKSUM		;GO VERIFY FHB'S CHECKSUM WORD
	LOAD.	T2,CKSM,P1		;GET CHECKSUM
	CAME	T1,T2			;SKIP IF COMPUTE MATHES COPY IN FHB
	TYPE	<% FHB Checksum error on:
>

	TDNN	F,[X%UIC]		;SKIP IF WANT SHORT VERSION ONLY
	JRST	TYPFHV			;DON'T MENTION VOLUME IF LONG VERSION
	MOVE	T1,DSKBLK+.DCUPN	;GET PHYSICAL UNIT IN DSKCHR BLOCK
	SKIPE	T2,FAKVOL		;SKIP IF REAL VOLUME
	MOVE	T1,VOLTBL(T2)		;GET FAKE VOLUME NAME
	PUSHJ	P,SIXOUT		;TYPE VOLUME NAME
	TYPE	<:[>
	HLRZ	T1,UFDNUM		;GET FIRST PART OF UIC
	PUSHJ	P,OCTOUT		;TYPE IT
	TYPE	<,>			;SEPERATE
	HRRZ	T1,UFDNUM		;GET 2ND HALF OF UIC
	PUSHJ	P,OCTOUT
	TYPE	<]>

TYPFHV:	LOAD.	T1,FNM1,P1		;GET 1ST WORD OF FILE NAME
;	PUSHJ	P,RAD53O		;TYPE IT
	LOAD.	T2,FNM2,P1		;GET 2ND WROD OF FILE NAME
;	PUSHJ	P,RAD53O		;TYPE IT
	LOAD.	T3,FNM3,P1		;GET 3RD WORD OF FILE NAME
;	PUSHJ	P,RAD53O		;TYPE IT
	PUSHJ	P,FILE5O		;TYPE OUT FILE NAME

TYPFHZ:	TYPE	<.>
	LOAD.	T1,FTYP,P1
	PUSHJ	P,RAD53O		;TYPE IT

	TYPE	<;>
	LOAD.	T1,FVER,P1		;GET VERSION #
	PUSHJ	P,OCTOUT		;TYPE IT

	TDNE	F,[X%UIC]
	POPJ	P,

	MOVEI	T1,^D21			;COLUMN 21 STARTS SIZE FIELD
	PUSHJ	P,MOVCOL		;GO THERE

	LOAD.	T3,USE,P1		;GET NUMBER OF PAIRS IN USE
	LSH	T3,-1			;CONVERT TO # OF PAIRS
	SETZB	T1,T4			;T1=COUNT, T4=OFFSET
	ADD	T4,P1
	JUMPE	T3,TYPFH2		;SKIP IF NO POINTERS
TYPFH1:	LOAD.	T2,RCNT,T4		;GET COUNT
	ADDI	T1,1(T2)		;ADD IN THIS PAIR TOO
	ADDI	T4,S.RETP		;STEP TO NEXT PAIR
	SOJG	T3,TYPFH1		;LOOP TO COUNT THEM ALL

TYPFH2:	PUSHJ	P,DECO5			;ALLOW 5 DIGITS

	TYPE	< >
	LOAD.	T1,UCHA,P1		;GET USER CHARACTERISTICS
	TRNE	T1,UC.CON		;CONTIGUOUS?
	TYPE	<C>			;YES, SAY SO
	TRNN	T1,UC.CON		;?
	TYPE	< >			;NO

	TRNE	T1,UC.DLK		;IMPROPERLY CLOSED?
	TYPE	<I>			;YES, SAY SO
	TRNN	T1,UC.DLK		;?
	TYPE	< >			;

	LOAD.	T1,SCHA,P1		;GET SYSTEM CHARS
	TRNE	T1,SC.MDL		;MARKED FOR DELETE?
	TYPE	<D>			;YES, SAY SO
	TRNN	T1,SC.MDL
	TYPE	< >
	TRNE	T1,SC.BAD
	TYPE	<B>
	TRNN	T1,SC.BAD
	TYPE	< >

	MOVEI	T1,(P2)
	PUSHJ	P,TYPCDT
	MOVEI	T1,(P2)
	PUSHJ	P,TYPRDT
	MOVEI	T1,(P2)
	PUSHJ	P,TYPXDT
	PUSHJ	P,CRLF
	MOVE	T1,.FXSWT(FP)
	TDNN	T1,[S$DETAIL]		;/DETAIL?
	  POPJ	P,			;RETURN

	PUSHJ	P,TYPUNT		;TYPE INFO FROM UFD ENTRY
	PUSHJ	P,TYPFID		;TYPE THE FILE ID
	PUSHJ	P,TYPPRO		;TYPE OUT THE USER FILE PROTECTION
	PUSHJ	P,TYPUFA		;TYPE THE USER FILE ATTRIBUTES
	PUSHJ	P,TYPFMA		;TYPE THE FILE MAP AREA DATA
	POPJ	P,			;DONE
;	ROUTINE TO TYPE INFORMATION FROM UFD ENTRY
TYPUNT:	SKIPN	INPFDB+.FXNAM
	POPJ	P,		;FORGET IT IF INDEX COMMAND
	TYPE	<	File from directory:	>
	MOVE	T1,INPFDB+.FXNAM
	PUSHJ	P,SIXOUT
	SKIPE	T1,INPFDB+.F2NAM
	PUSHJ	P,SIXOUT
	HLLZ	T1,INPFDB+.FXEXT
	JUMPN	T1,[TYPE <.>
		PUSHJ P,SIXOUT
		JRST .+1]
	TYPE	<;>
	MOVE	T1,INPFDB+.FXGEN
	PUSHJ	P,OCTOUT
	TYPE	<	(>
	MOVE	T1,INPFDB+.FXNUM
	PUSHJ	P,R10OUT
	TYPE	<,>
	MOVE	T1,INPFDB+.FXSEQ
	PUSHJ	P,R10OUT
	TYPE	<,>
	MOVE	T1,INPFDB+.FXGEN
	TYPE	<)
>
	POPJ	P,
;	ROUTINE TO TYPE THE USER FILE PROTECTION
TYPPRO:	TYPE	<	File protection: >
	LOAD.	T1,FPRO
	PUSHJ	P,OCTOUT
	TYPE	<	>
	LOAD.	T1,FPRO
	PUSHJ	P,P11OUT
	JRST	CRLF
;	ROUTINE TO TYPE THE FILE ID
TYPFID:	TYPE	<	File ID: (>
	LOAD.	T1,FNUM			;GET FILE NUMBER
	PUSHJ	P,R10OUT		;TYPE IT
	TYPE	<,>
	LOAD.	T1,FSEQ
	PUSHJ	P,R10OUT
	TYPE	<,>
	LOAD.	T1,RVNO
	PUSHJ	P,R10OUT
	TYPE	<)
>
	POPJ	P,
;	ROUTINE TO TYPE OUT THE FILE MAP AREA
TYPFMA:	LOAD.	T1,USE			;GET # OF POINTERS IN USE
JUMPE	T1,[
TYPE	<		File mapping information:  No disk space allocated
>
PJRST	CRLF]
	MOVE	P1,T1			;COPY TO A SAFE PLACE
	LSH	P1,-1			;GET # OF PAIRS
	SETZ	P2,			;START AT 0 OFFSET
	TYPE	<		File mapping information:
>
        TYPE    <               (>
        MOVE    T1,P1           ;GET NUMBER OF POINTER PAIRS IN USE
        PUSHJ   P,DECOUT        ;TYPE IT
        LOAD.   T1,MAX          ;GET MAX USABLE
        JUMPE   T1,TYPFM2       ;SKIP CONFUSING COMMENTARY
        TYPE    < of >          ;
        LOAD.   T1,MAX          ;GET THE MAX USABLE
        LSH     T1,-1           ;COMPUTE # POINTERS POSSIBLE
        PUSHJ   P,DECOUT        ;
TYPFM2: TYPE    < pointers used)
>                               ;
        LOAD.   P4,MAX,P3               ;GET THE NUMBER WE'RE ALLOWED TO HAVE
        SKIPN   P4                      ;SKIP IF VALID
        MOVEI   P4,314                  ;CONVERT TO VALID IF NEEDED
        CAML    T2,P4                   ;ONLY ALLOW IF ROOM FOR IT
          ERROR <Ran out of retrieval pointer slots in STORET>
TYPFM1:	TYPE	<		>
	LOAD.	T1,RCNT,P2		;GET COUNT
	ADDI	T1,1			;ALWAYS +1
	PUSHJ	P,DECO3		;TYPE IT
	TYPE	< at >
	LOAD.	T1,RLBN,P2		;ET LOW LBN
	LOAD.	T2,HRET,P2		;GET HIGH LBN
	LSH	T2,^D16			;MAKE ROOM
	OR	T1,T2			;MERGE
	PUSHJ	P,OCTO7
	PUSHJ	P,CRLF
	ADDI	P2,4			;ADVANCE TO NEXT PAIR
	SOJG	P1,TYPFM1		;TYPE THAT TOO
	PJRST	CRLF
;	ROUTINE TO TYPE OUT USER FILE ATTRIBUTES BLOCK

TYPUFA:	TYPE	<	Record type = >
	LOAD.	T1,RTYP			;GET RECORD TYPE BYTE
	PUSHJ	P,OCTOUT		;TYPE IT
	LOAD.	T1,RTYP			;gET IT AGAIN
	CAIN	T1,R.FIX		;
	TYPE	<, fixed length records>
	CAIN	T1,R.VAR
	TYPE	<, variable non-sequenced records>
	CAIN	T1,R.SEQ
	TYPE	<, variable length sequenced records>

	TYPE	<
	Record attributes = >
	LOAD.	T1,RATT
	PUSHJ	P,OCTOUT
	LOAD.	T1,RATT
	TRNE	T1,FD.FTN
	TYPE	<, first byte is FORTRAN-CC>
	TRNE	T1,FD.CR
	TYPE	<, implied LF before line and CR after>
	TRNE	T1,FD.BLK
	TYPE	<, records cannot span block boundries>

	TYPE	<
	Record size = >
	LOAD.	T1,RSIZ
	PUSHJ	P,DECOUT
	TYPE	< bytes>

	TYPE	<
	Highest VBN allocated = >
;	LOAD.	T1,HIBK
	LOAD.	T1,HIBH		;
	LOAD.	T2,HIBL
	LSH	T1,^D8
	OR	T1,T2
	PUSHJ	P,OCTOUT

	TYPE	<
	EOF VBN = >
;	LOAD.	T1,EFBK
	LOAD.	T1,EFBH
	LSH	T1,^D8
	LOAD.	T2,EFBL
	OR	T1,T2
	PUSHJ	P,OCTOUT

	TYPE	<
	First Free Byte = >
	LOAD.	T1,FFBY
	PUSHJ	P,OCTOUT

	TYPE	<
	Record Access byte = >
	LOAD.	T1,RACC
	PUSHJ	P,OCTOUT
	LOAD.	T1,RACC
	TRNE	T1,FD.RWM
	TYPE	<, READ$/WRITE$ mode>
	TRNE	T1,FD.RAN
	TYPE	< GET$/PUT$ mode>

	TRNE	T1,FD.PLC
	TYPE	<, locate mode>
	TRNN	T1,FD.PLC
	TYPE	<, move mode>
	TRNN	T1,FD.INS
	TYPE	< PUT$ truncates the file>

	PJRST	CRLF
;	SUBROUTINE TO STORE A RETRIEVAL POINTER PAIR INTO THE FHB BEING BUILT
;
;	T1/	# OF BLOCKS IN RETREIVAL POINTER PAIR
;	T2/	1ST LBN DESCRIBED BY PAIR
;	T3/	POINT TO FHB TO CONTAIN THIS PAIR
STORET:	PUSHJ	P,SAVE4			;SAVE SOME ACS
	DMOVE	P1,T1			;LOAD P1=BLOCKS, P2=LBN# OF 1ST
	DMOVE	P3,T3			;LOAD P3=BUFFER ADDRESS
	SUBI	P3,FHBBUF		;COMPUTE P3=PDP10 OFFSET TO FHB BUFFER
	IMULI	P3,4			;COMPUTE P3=PDP11 OFFSET TO FHB BUFFER

	LOAD.	T1,MPOF,P3		;LOAD T1=MAP AREA OFFSET IN WORDS
	IMULI	T1,2			;CONVERT T1=MAP AREA OFFSET IN BYTES

	LOAD.	T2,USE,P3		;LOAD T2=#RETRIEVAL WORDS IN USE
	IMULI	T2,2			;CONVERT T2=#RETRIEVAL BYTES IN USE
	ADDI	T2,(P3)			;AND OFFSET BY FHB POINTER

	MOVE	T1,P1			;LOAD T1=BLOCK COUNT FROM RETRIEVAL PAIR
	SUBI	T1,1			;CONVERT T1=FORM AS APPEARS IN FHB
	STOR.	T1,RCNT,T2		;STORE BLOCK COUNT INTO FHB
	MOVE	T1,P2			;LOAD T1=1ST BLOCK IN GROUP
	STOR.	T1,RLBN,T2		;STORE (LOW) BLOCK NUMBER INTO FHB
	LSH	T1,-^D16		;ISOLATE T1=HIGH PDP11 WORD OF BLOCK #
	STOR.	T1,HRET,T2		;STORE (HIGH) BLOCK NUMBER INTO FHB
	LOAD.	T1,USE,P3		;LOAD T1=# OF RETRIEVAL WORDS IN USE
	ADDI	T1,2			;UPDATE T1=2 MORE WORDS
	STOR.	T1,USE,P3		;STORE UPDATED COUNT BACK INTO FHB

;	HERE TO ENSURE THAT THE BLOCKS JUST ATTACHED ARE REMOVED FROM THE SATS
STORE1:	MOVE	T1,P2			;COPY BLOCK #
	PUSHJ	P,TAKSBM		;GET THAT BLOCK
	  JFCL				;IGNORE ERROR RETURN
	SOJG	P1,[AOJA P2,STORE1]	;LOOP FOR ALL BLOCKS IN THE GROUP

	ADDI	P2,1			;ADVANCE TO UNUSED BLOCK
	MOVEM	P2,FFBLOK		;REMEMBER WHICH IT WAS
	POPJ	P,			;RETURN
;	ROUTINE TO SCAN RETRIEVAL POINTERS
;	T1/ POINTER TO FHB BUFFER
;	T2/ BLOCK # TO FIND, STARTS AT 0
;
;	N.B.!!! WE CONSIDER BLOCK #'S TO START AT 0 BECAUSE IT IS CONVENIENT,
;		BUT RSX CONSIDERS THEM TO START AT 1!!

SCNRET:	PUSHJ	P,SAVE4			;SAVE SOME ACS

	MOVE	P2,T1			;COPY ADDRESS OF FHB
	SUBI	P2,FHBBUF		;COMPUTE PDP10 OFFSET
	IMULI	P2,4			;THEN PDP11 OFFSET

	LOAD.	T3,EFBh,p2			;EOF BLOCK HIGH
	LOAD.	T4,EFbl,p2			;EOF BLOCK LOW
	LSH	T3,^D8
	OR	T3,T4
	JUMPE	T3,SCNRE0
;	JUMPE	T2,SCNRE0
	SUBI	T3,1			;ADJUST FOR RSX TO USE
	CAMLE	T2,T3			;REQUEST UNDER EOF BLOCK?
	  POPJ	P,			;YES, MUST BE ILLEGAL

SCNRE0:	SETZ	P1,			;LOW RELATIVE BLOCK # IN THIS GROUP
	LOAD.	T3,USE,P2		;P3=#OF POINTERS IN USE
	JUMPE	T3,CPOPJ		;EXIT IF NO DISK SPACE ASSIGNED
	MOVE	P3,T3
	LSH	P3,-1			;CONVERT TO # OF PAIRS

SCNRE1:	LOAD.	T3,RCNT,P2		;GET COUNT FOR THIS GROUP
	ADDI	T3,1			;MAKE T3=TRUE COUNT
	ADD	T3,P1			;T3=1ST RELATIVE BLOK# IN NEXT GROUP
	CAML	T2,T3			;GUARENTEED TO FALL IN THIS GROUP?
	JRST	SCNRE2			;NO
	LOAD.	T3,RLBN,P2		;GET LOW LBN FOR THIS GROUP
	LOAD.	T4,HRET,P2		;GET HIGH LBN FOR THIS GROUP
	LSH	T4,^D16			;MAKE ROOM FO LOW PART
	OR	T4,T3			;T4=LBN OF THIS GROUP
	SUB	T2,P1			;CONVERT T2=RELATIVE BLOCK# TO THIS GROUP
	ADD	T4,T2			;COMPUTE T4=BLOCK #
	MOVE	T1,T4			;COPY BLOK# TO T1
	JRST	CPOPJ1			;GIVE GOOD RETURN

SCNRE2:	MOVE	P1,T3			;LOAD FOR NEXT LOOP
	ADDI	P2,4			;ADVANCE TO NEXT GROUP
	SOJG	P3,SCNRE1		;KEEP TRYING
	POPJ	P,			;RETURN, WE NEVER FOUND IT
	SUBTTL	ROUTINES TO MANAGE THE STORAGE-BIT-MAP

;	THE STORAGE-BIT-MAP CONTROLS THE ALLOCATION OF BLOCKS WITHIN
;	THE FILES-11 VOLUME SPACE.
;
;	THE SBM CONSISTS OF TWO PARTS, THE "SAB" AND THE "BM".
;
;	THE "SAB" BLOCK IS THE FIRST BLOCK OF THE SBM FILE.
;
;	THE "SAB" CONSISTS OF ENTRIES WHICH SHOW THE CURRENT TALLY OF
;	FREE UNUSED BLOCKS AVAILABLE IN EACH BLOCK OF THE "BM". THE "SAB"
;	IS INDEXED BY THE "BM" BLOCK NUMBER TIMES 4.
;
;	THE "BM" (BIT-MAP) PART CONTAINS ENOUGH DISK BLOCKS TO REPRESENT
;	A MAP OF THE ENTIRE FILES-11 VOLUME WITH 1 BIT PER STORAGE-CLUSTER.
;	SINCE THE BM IS IN "PDP11" FORMAT, EACH PDP10 WORD MAPS ONLY
;	32 CLUSTERS.  EACH PDP10 BLOCK CAN THUS MAP 32*128=4096 CLUSTERS.
;	THE INDEX INTO THE BIT MAP IS THE "TRUE" CLUSTER NUMBER, NOT THE
;	RELATIVE CLUSTER NUMBER (IE: RELATIVE TO THE DISK'S BLOCK 0, NOT
;	RELATIVE TO "DATA BLOCK 0" OF "FE.SYS").
;
;	ORDINARYILY, ONLY THE LAST FEW BLOCKS OF THE BM INDICATE ANY FREE BLOCKS
;	BECAUSE THE FIRST BLOCKS ARE DUMMYS FILLED TO ZEROS TO MARK THE PART
;	OF THE APPARENT FILES-11 VOLUME WHICH REALLY BELONGS TO TOPS-10.
;
;	IN THE BM, A "1" BIT MEANS THE CLUSTER IS FREE.
;
;	THERE IS NO EVIDENCE THAT ANY PART OF RSX20F PAYS ANY ATTENTION
;	TO THE SAB PORTION OF THE SBM FILE, BUT THE "INI" UTILITY SETS
;	IT UP AND ALL OF RSX20F (IE: F11ACP) SEEMS TO KNOW THAT THE
;	FIRST BLOCK OF THE SBM MUST BE IGNORED.
;	ROUTINE TO CREATE AN INITIAL SBM FOR A FILES-11 VOLUME
MAKSBM:	SETZM	BMBUF			;ZERO FIRST WORD IN SAB BUFFER
	MOVE	T1,[BMBUF,,BMBUF+1]	;CONSTRUCT A BLT POINTER
	BLT	T1,BMBUF+177		;ZERO ALL WORDS IN SAB BUFFER

	MOVE	T1,LSTLBN		;GET HIGHEST LBN# IN VOLUME
	IDIVI	T1,^D4096		;COMPUTE T1=# OF BLOCKS NEEDED IN BM
	ADDI	T1,1			;ALWAYS NEED AT LEAST 1 BLOCK
	STOR.	T1,BCNT			;SAVE "SBM-SIZE-IN-BLKS" INTO SAB ITSELF

        LOAD.   T1,BCNT                 ;GET # OF SBM BLOCKS
        IMULI   T1,4                    ;TURN INTO AN OFFSET
        SUBI    T1,4                    ;BACK UP ONE SLOT
        MOVEM   T1,TMPOFF               ;SAVE OFFSET FOR STOR. BELOW
        MOVE    T2,LSTLBN               ;GET LAST BLOCK IN VOLUME
        STOR.   T2,BMXL,TMPOFF          ;INSERT LOW PART INTO BM BUF
        LSH     T2,-^D16                ;DROP LOW WORD, POSITION HIGH
        STOR.   T2,BMXH,TMPOFF          ;INSERT HIGH PART INTO BM BUF
 
;N.B.:  THERE IS SOME ODD CODE IN "INI" IN MODULE "INIBIT" WHICH
;APPARENTLY RESULTS IN PUTTING SOME STUFF IN THE PDP11 WORD IMMEDIATELY
;BEFORE THE PDP11 WORD WHERE BMAX RESIDES. IT'S NOT DUPLICATED HERE CUZ
;I CAN'T FIGURE OUT WHAT IT DOES.
	LOAD.	T1,BCNT			;GET "SBM-SIZE-IN-BLOCKS"
	IMULI	T1,^O200		;COMPUTE T1=OF WORDS IN THE SBM
	MOVEM	T1,SBMSIZ		;SAVE SIZE OF BM IN PDP10 WORDS
	PUSHJ	P,GETCOR		;GET MEMORY FOR "INCORE" BM
	MOVEM	T1,SBMINC		;SAVE POINTER TO THE "INCORE" BM
	SETZM	(T1)			;ZERO 1ST WORDN BM
	HRLS	T1			;CONSTRUCT A BLT POINTER INTO BM
	ADDI	T1,1			;...

	MOVE	T2,SBMSIZ		;GET SIZE OF INCORE BM...
	ADDI	T2,-2(T1)		;...TO COMPUTE T2=LAST WORD IN BM

	BLT	T1,(T2)			;SET INCORE BM TO "ALL BLOCKS USED"

	SETZM	VOLTAL			;SET FREE-TALLY TO 0
	MOVE	P1,FSTLBN		;SET P1=1ST BLOCK INSIDE FILES11 VOLUME
MAKSB2:	MOVE	T1,P1			;SET T1=BLOCK# INSIDE FILES11 VOLUME
	PUSHJ	P,GIVSBM		;RETURN (MAKE AVAILABLE) A BLOCK
	  JFCL				;IGNORE IF BLOCK CANNOT BE RETURNED
	ADDI	P1,1			;ADVANCE BLOCK NUMBER WITH VOLUME
;	AOS	VOLTAL			;COUNT A FREE CLUSTER
	CAMG	P1,LSTLBN		;SKIP IFF GONE BEYOND END OF VOLUME
	  JRST	MAKSB2			;BRANCH TO MARK ANOTHER BLOCK FREE
	POPJ	P,			;RETURN
;	ROUTINE TO WRITE INCORE COPIES OF THE BM AND SAB ONTO DISK

WRTSBM:	MOVE	T1,SBMLBN		;LOAD T1=1ST LBN IN BITMAP.SYS
	PUSHJ	P,SUSET		;POSITION TO THAT BLOCK
	OUT	VIO,[IOWD 200,BMBUF	;WRITE THE SAB BLOCK...
		      0]		;...AS THE FIRST BLOCK IN BITMAP.SYS
	SKIPA
	  ERROR	<OUT failed to write SAB buffer>
	MOVE	T1,SBMSIZ		;LOAD T1=SIZE (IN WORDS) OF INCORE BM
	IMUL	T1,[-1,,0]		;CONVERT T1=AOBJN TO INCORE BM
	HRR	T1,SBMINC		;...INSERT ADDRESS INTO AOBJN IN T1
	SUBI	T1,1			;CONVERT T1=IOWD POINTER TO INCORE BM
	SETZ	T2,			;LOAD T2=ENDING IOWD
	OUT	VIO,T1			;WRITE BM ONTO DISK
	POPJ	P,			;RETURN IF I/O WAS GOOD
	  ERROR	<OUT failed to write SBM blocks>
;	ROUTINE TO READ IN THE DISK COPY OF THE SBM FILE BITMAP.SYS
REDSBM:	MOVE	T1,SBMLBN		;LOAD T1=1ST LBN IN BITMAP.SYS
	PUSHJ	P,SUSET			;POSITION TO THAT BLOCK


	IN	VIO,[IOWD 200,BMBUF	;READ SAB BLOCK INTO RESERVED BUFFER
		     0]			;...
	SKIPA				;SKIP IF I/O WAS GOOD
	  ERROR	<Can't read SAB block>
	LOAD.	T1,BCNT			;GET SIZE OF THE BM PORTION
	IMULI	T1,200			;COMPUTE T1=#WORDS IN THE BM
	MOVEM	T1,SBMSIZ		;REMEMBER SIZE OFBM PORTION OF THE SBM

	PUSHJ	P,GETCOR		;GET MEMORY TO STORE SBM IN
	MOVEM	T1,SBMINC		;SAVE POINTER TO INCORE COPY OF BM

	HRRZ	T1,SBMSIZ		;LOAD T1=#WORDS IN THE BM
	IMUL	T1,[-1,,0]		;CONVERT T1=AOBJN INTO THE BM
	HRR	T1,SBMINC		;INSERT RH(T1)=POINTER TO THE BM
	SUBI	T1,1			;CONVERT T1=IOWD POINTER TO THE BM
	SETZ	T2,			;LOAD T2=ENDING IOWD
	IN	VIO,T1			;READ THE BM INTO CORE
	SKIPA				;SKIP IF I/O WAS GOOD
	  ERROR	<Can't read BM blocks in BITMAP.YSS>

	SETZM	VOLTAL			;START FREE-TALLY AT 0
	HRRZ	T1,SBMINC		;INITIALIZE A BYTE POINTER TO INCORE BM
	HRLI	T1,(POINT 1,0)		;...
	MOVE	T2,SBMSIZ		;INITIALIZE A BIT COUNT TO THE INCORE BM
	IMULI	T2,^D36			;...

REDSB2:	ILDB	T3,T1			;GET A BIT FROM THE BM
	SKIPE	T3			;SKIP IFF BLOCK IS IN USE
	AOS	VOLTAL			;COUNT A FREE BLOCK IF BLOCK IS FREE
	SOJG	T2,REDSB2		;LOOK AT ALL THE BITS IN THE BM

	MOVE	T2,SBMSIZ		;GET SIZE OF STORAGE MAP IN WORDS
	IMULI	T2,^D32			;COMPUTE # OF BLOCKS DESCRIBED (MAX)
	SUBI	T2,1			;HIGH BLOCK # IS #BLOCKS-1
	CAMGE	T2,LSTLBN		;SKIP IFF BOUNDS LOOK REASONABLE
	MOVEM	T2,LSTLBN		;MIGHT BE RP04 ON RP06 OR USED MAINT CYLS
	POPJ	P,			;EXIT
;	SUBROUTINE TO MARK A BLOCK (T1) AS AVAILABLE IN THE SAT

GIVSBM:	PUSHJ	P,SAVE4		;SAVE SOME ACS
	MOVE	P1,T1		;COPY BLOCK #
	IDIVI	P1,^D4096	;COMPUTE RELATVIE SBM BLOCK #
	MOVSI	P4,1		;
	ADDM	P4,BMBUF+1(P1)	;ADJUST SAB COUNT FOR THAT SBM BLOCK

	MOVE	P1,T1		;COPY BLOCK # AGAIN
	IDIVI	P1,^D32		;COMPUTE WHICH WORD IN THE SBM IT IS
				;(WHICH PDP10 WORD THAT IS!)
	ADD	P1,SBMINC	;ADD IN BASE OF TABLE
	MOVE	P2,B32TBL(P2)	;CONVERT TO ACTUAL BIT
	TDNN	P2,@P1		;BIT ON YET?
	AOS	VOLTAL		;NO, COUNT A FREE BLOCK
	ORM	P2,@P1		;TURN ON THE BIT
	POPJ	P,		;RETURN
;	SUBROUTINE TO MARK A BLOCK (T1) AS USED IN THE SAT
;
;	T1/ REAL BLOCK NUMBER
;
TAKSBM:	PUSHJ	P,SAVE4		;SAVE SOME ACS
	MOVE	P1,T1		;COPY BLOCK #
	IDIVI	P1,^D4096	;COMPUTE RELATVIE SBM BLOCK #
        LDB     P4,[POINT 16,BMBUF+1(P1),17]
        SKIPE   P4              ;DON'T LET IT GO "NEGATIVE"
        SUBI    P4,1
        DPB     P4,[POINT 16,BMBUF+1(P1),17]

	MOVE	P1,T1		;COPY BLOCK # AGAIN
	IDIVI	P1,^D32		;COMPUTE WHICH WORD IN THE SBM IT IS
				;(WHICH PDP10 WORD THAT IS!)
	MOVE	P2,B32TBL(P2)	;CONVERT TO ACTUAL BIT
	ADD	P1,SBMINC	;COMPUTE INCORE WORD ADDRESS
	TDNE	P2,@P1		;ALREADY OFF?
	SOS	VOLTAL		;NO, COUNT A FREE BLOCK
	ANDCAM	P2,@P1		;TURN OFF THE BIT
	POPJ	P,		;RETURN
;	ROUTINE TO SCAN THE STORAGE-BIT-MAP AND RETURN A CHUNK
;
;	T1/	0		;TREAT AS IF T1 CONTAINED 1
;	T1/	+VE		;RETURN THE SMALLEST CHUNK WHICH HAS (T1) BLOKS
;RETURN:
;	T1/	# BLOCKS
;	T2/	1ST BLOCK IN CHUNK
;
;	N.B.:	THIS ROUTINE MIGHT RETURN MORE THAN 256. BLOCKS IN WHICH CASE
;		IT IS THE CALLER'S RESPONSIBILITY TO BREAK THE CHUNK INTO
;		PIECES IN ORDER TO FIT INTO FILES-11 RETRIEVAL POINTERS

SCNSBM:	PUSHJ	P,SAVE4			;SAVE SOME ACS
	CAIG	T1,0			;-VE OR 0 BLOCKS REQUESTED?
	MOVEI	T1,1			;YES, JUST ASK FOR ONE
	PUSH	P,T3			;SAVE SOME ACS
	PUSH	P,T4			;...
	MOVEI	P1,377777
	HRLOM	P1,BEST			;SET BEST CHUNK TO WORST POSSIBLE
	SETZM	BIG			;FORGET PREVIOUS BIGGEST CHUNK
	SETZB	P1,P2
	SETZB	P3,P4

	MOVE	P1,SBMSIZ		;LOAD P1=# WORDS IN INCORE MAP
	IMUL	P1,[-1,,0]		;CONVERT P1=AOBJN COUNTER
	HRR	P1,SBMINC		;INSERT P1=POINTER TO INCORE MAP
	MOVE	P2,FSTLBN		;LOAD P2=BLOK# OF FIRST BLOK IN VOLUME
	IDIVI	P2,^D32			;COMPUTE P2=WORD# IN MAP FOR 1ST BLOK
	HRLS	P2			;CONVERT P2=WORD#,,WORD#
	ADD	P1,P2			;MAKE P1=POINTER TO 1ST (VALID) WORD

SCNSB0:	SKIPN	T3,(P1)			;SKIP IFF AT LEAST 1 FREE BLOCK
	AOBJN	P1,SCNSB0		;LOOP LOOKING FOR FREE BLOCKS
	JUMPGE	P1,SCNSB8		;BRANCH IF OUT OF BITS TO LOOK AT

	MOVSI	P2,-^D32		;START AT BIT#0
SCNSB1:	TDNN	T3,B32TBL(P2)		;SKIP IF WE FOUND THE FIRST BIT INA RUN
	AOBJN	P2,SCNSB1		;LOOP TILL WE FIND THE FREE BIT

SCNSB2:	DMOVE	P3,P1			;COPY P3=1ST WORD, P4=1ST BIT

	SETZ	T4,			;ZERO COUNT OF CONSECUTIVE BIT
SCNSB3:	TDZN	T3,B32TBL(P2)		;SKIP IF WE HAVE A FREE BLOCK
	JRST	SCNSB6			;BRANCH IF WE FIND THE END OF RUN
	ADDI	T4,1			;COUNT THE BLOK
	AOBJN	P2,SCNSB3		;LOOP TO FIND NEXT BIT
	AOBJN	P1,[MOVE T3,(P1)	;LOAD NEXT WORD OF BITS
		    MOVSI P2,-^D32	;START BIT#0
		    JRST SCNSB3]	;AND CONTINUE COUNTING BITS
; HERE IF WE RUN OUT OF BITS TO SCAN

;HERE WHEN WE REACH THE END OF A RUN
SCNSB6:	CAMLE	T4,BIG			;SKIP IF NOT ABSOLUTE BIGGEST CHUNK SEEN
	PUSHJ	P,[MOVEM T4,BIG		;...REMEMBER SIZE OF ABSOLUTE BIGGEST
		   DMOVEM P3,BIGP1	;...REMEMBER ADDRESS OF ABSOLUTE BIGST
		   POPJ P,0]		;...
	CAMGE	T4,T1			;BIG ENOUGH TO CONSIDER?
	JRST	SCNSB7			;GO TO NEXT REGION
	CAML	T4,BEST			;YES, IS IT SMALLER THAN BEST SO FAR?
	JRST	SCNSB7			;NO, GO ON TO NEXT FREE REGION
	MOVEM	T4,BEST			;YES, REMEMBER IT'S SIZE
	DMOVEM	P3,BESTP1		;YES, REMEMBER IT'S LOCATION
SCNSB7:	AOBJN	P2,SCNSB2		;IF MORE BITS THIS PDP11 WORD, CONTINUE
	AOBJN	P1,SCNSB0		;ELSE RESTARTT HE SEARCH


SCNSB8:	MOVE	T1,BEST			;GET BEST SIZE FOUND
	CAMN	T1,[377777,,777777]	;CHECK FOR FAILURE
	JRST	SCNSB9			;
	HRRZ	T2,BESTP1		;LOAD T2=BEST 32WORD BLOCK
	SUB	T2,SBMINC		;COMPUTE T2=OFFSET
	IMULI	T2,^D32			;
	HRRZ	T3,BESTP2
	ADD	T2,T3
	POP	P,T4
	POP	P,T3
	JUMPE	T1,SCNS11		;OH DARN, SOME SORT OF BUG
	JRST	CPOPJ1			;GIVE GOOD RETURN
	
SCNSB9:	MOVE	T1,BIG			;GET BIGGEST
	JUMPE	T1,SCNS10		;GIVE UP, TOTAL FAILURE, NO BLOCKS
	HRRZ	T2,BIGP1		;GET P1 OF BIGGEST CHUNK
	SUB	T2,SBMINC		;COMPUTE T2=OFFSET
	IMULI	T2,^D32
	HRRZ	T3,BIGP2
	ADD	T2,T3
	POP	P,T4
	POP	P,T3
	JUMPE	T1,SCNS11		;OH DARN, SOME SORT OF IMPOSSIBLE BUG
	JRST	CPOPJ1			;GIVE GOOD RETURN

SCNS10:	POP	P,T4			;RESTORE T4
	POP	P,T3			;RESTORE T3
	POPJ	P,			;GIVE ERROR RETURN

SCNS11:	TYPE	<?? SCNSBM RETURNED 0 BLOCKS
>
	POPJ	P,
;	ROUTINE TO "TYPE" OUT THE STORAGE BIT MAP

TYPSBM:	MOVE	P1,SBMSIZ		;GET SIZE OF SBM IN WORDS
	IMULI	P1,^D32			;GET SIZE OF SBM IN BITS
	SETZ	P2,			;START AT BLOCK 0
	MOVEI	P4,0			;P4=PROTOTYPE=NOT FREE

TYPSB1:	SETZ	P3,			;ZERO COUNT OF BLOCK IN REGION
TYPSB2:	SOJL	P1,TYPSB3		;BRANCH IF OUT OF BITS
	MOVE	T1,P2			;COPY BLOCK NUMBER
	IDIVI	T1,^D32			;COMPUTE WORD,BIT #S
	ADD	T1,SBMINC		;COMPUTE WORD-ADDRESS
	MOVE	T2,B32TBL(T2)		;COMPUTE BIT MASK
	TDNN	T2,@T1			;SKIP IF BIT IS FREE
	TDZA	T1,T1
	MOVEI	T1,1			;BIT IS FREE
	CAMN	T1,P4			;SAME AS CURRENT REGION?
	AOJA	P3,[AOJA P2,TYPSB2]	;YES, COUNT BLOCK, ADVANCE AND LOOP

TYPSB3:	MOVE	T1,P3			;GET BLOCK COUNT
	PUSHJ	P,DECOUT		;TYPE IT
	TYPE	< blocks >
	SKIPE	P4			;SKIP IF NOT FREE
	TYPE	<free >
	SKIPN	P4
	TYPE	<used >

	MOVE	T1,P2			;GET HIGH BLOCK NUMBER
	SUB	T1,P3			;COMPUTE LOW BLOCK
	PUSHJ	P,OCTOUT		;TYPE LOW BLOCK
	TYPE	< to >			;
	MOVE	T1,P2			;
	SUBI	T1,1
	PUSHJ	P,OCTOUT		;TYPE HIGH BLOCK
	PUSHJ	P,CRLF
	TRC	P4,1			;REVERSE LOGIC FOR SCAN
	JUMPGE	P1,[AOJA P1,TYPSB1]	;LOOP IF MORE TO SCAN
	POPJ	P,			;ELSE DONE
	SUBTTL	WILD CARD ROUTINES

;	ROUTINE TO INITIALIZE THE WILD CARD RSX20F FDB ROUTINE

RLDINI:	SETZM	WDICNT			;#RECORDS IN THE CURRENT DIRECTORY BLOK
	SETOM	WDIBNO			;RELATIVE BLOK# OF CURRENT D'RECTRY BLOK
	SETZM	MASCNT			;#RECORDS LEFT IN CURRENT MFD BLOK
	SETOM	MASBNO			;RELATIVE BLOK# OF CURRENT MFD BLOK
	SETZM	DIRCNT			;# OF DIRECTORY FILES FOUND ON VOLUME
	SETZM	DIRMAT			;# OF DIRECTORY FILES FOUND TO MATCH
	SETZM	FILCNT			;# OF FILES FOUND ON VOLUME
	SETZM	FILMAT			;# OF FILES FOUND TO MATCH
	POPJ	P,			;ALL INIT'ED
;	ROUTINE TO TAKE 1 RIGHT JUSTIFIED PDP11 WORD OF .RAD50 FORMAT
;	AND CONVERT TO 1 RIGHT JUSTIFIED PDP10 WORD OF SIXBIT

C5T6:	IDIVI	T1,50*50		;GET 1ST RAD50 LETTER IN T1
	IDIVI	T2,50			;GET 2ND IN T2, 3RD IN T3

	MOVE	T1,R2STBL(T1)		;CONVERT TO SIXBIT
	MOVE	T2,R2STBL(T2)		;CONVERT TO SIXBIT
	MOVE	T3,R2STBL(T3)		;CONVERT TO SIXBIT

	LSH	T1,^D12			;MAKE 1ST LETTER HIGHEST ORDER
	LSH	T2,^D6			;MAKE 2ND LETTER MIDDLE ORDER
	IOR	T1,T2			;MERGE HIGH AND MIDDLE ORDER
	IOR	T1,T3			;MERGE THOSE WITH LOW ORDER

	POPJ	P,
;	ROUTINE TO TAKE 1 RIGHT JUSTIFIED PDP10 WORD OF SIXBIT
;	AND CONVERT IT TO 1 RIGHT JUSTIFIED PDP11 WORD OF .RAD50

C6T5:	IDIVI	T1,100*100		;GET 1ST 6BIT CHAR IN T1, 2ND&3RD IN T2
	IDIVI	T2,100			;GET 2ND IN T2, 3RD IN T3

	MOVE	T1,S2RTBL(T1)		;CONVERT TO RAD50
	MOVE	T2,S2RTBL(T2)		;...
	MOVE	T3,S2RTBL(T3)		;...

	IMULI	T1,50
	ADDI	T1,(T2)
	IMULI	T1,50
	ADDI	T1,(T3)
	POPJ	P,
;	ROUTINE TO RETURN CONSECUTIVE MATCHING FILE BLOCKS
;
;ENTER:
;	T1/	FDB WE'RE TRYING TO MATCH
;	T2/	FDB TO EXPAND MATCHING SPEC INTO

NXTFDB:	PUSHJ	P,SAVE4			;GET SOME ACS
	DMOVE	P1,T1			;COPY THE ARGUMENT ACS
	SETOM	.FXNMM(P2)
	SETOM	.F2NMM(P2)
	SETOM	.FXEXT(P2)

NXTFD1:	SOSGE	WDICNT			;SKIP IF MORE FILE RECORDS
	JRST	NXTDBK			;NO MORE IN THIS BLOCK OF DIRECTORY

	LOAD.	T1,UFN1,WDIOFF		;READ FROM THE DIRECTORY BUFFER
	PUSHJ	P,C5T6			;CONVERT RAD50 FILENAME PART 1 TO SIXBIT
	HRLZM	T1,.FXNAM(P2)		;STASH INTO OUTPUT FDB TEMPORARILY
	LOAD.	T1,UFN2,WDIOFF		;GET 2RD 3RD OF FILE NAME FROM DIR BUF
	PUSHJ	P,C5T6			;CONVERT RAD50 FILENAME PART 2 TO SIXBIT
	HRRM	T1,.FXNAM(P2)		;STASH INTO OUTPUT FDB TEMPORARILY
	LOAD.	T1,UFN3,WDIOFF		;GET 3RD 3RD OF FILE NAME FROM DIRBUF
	PUSHJ	P,C5T6			;CONVERT 3RD 3RD TO SIXBIT
	HRLZM	T1,.F2NAM(P2)		;STASH THAT TOO

        LOAD.   T1,UFTY,WDIOFF          ;GET FILE TYPE FROM DIRECTORY BUFFER
        PUSHJ   P,C5T6                  ;CONVERT TO SIXBIT
        HRLZM   T1,.FXEXT(P2)           ;STASH INTO OUTPUT FDB TEMPORARILY
        SKIPE   .FXEXT(P2)              ;SKIP IF FILE TYPE IS NULL
          JRST  NOTNUL                  ;BRANCH IF FILE TYPE *NOT* NULL
NOTNUL: LOAD.   T1,UFNO,WDIOFF          ;GET FILE NUMBER
	SKIPN	.FXNAM(P2)		;SKIP IF NOT NULL FILE NAME
	SKIPE	.F2NAM(P2)		;SKIP IF FILE IS COMPLETELY NULL
	SKIPA
	JRST	[SKIPN .FXDEV(P1)	;SKIP IF NOT LOOKING FOR NULL
		SKIPE .FXNAM(P1)	;SKIP IF WE WERE LOOKING FOR NULL SLOT
		 JRST  NULREC		;FORGET IT IF WE WERE'NT
		 JRST NULGOT]		;GIVE IT

	LOAD.	T1,UFNO,WDIOFF		;GET FILE NUMBER
	JUMPE	T1,NULREC		;IGNORE THIS FHB IF FILE NUMBER IS ZERO
	AOS	FILCNT			;COUNT A FOUND FILE
	MOVE	T1,.FXNAM(P2)		;GET FILE NAME IN DIRECTORY
	AND	T1,.FXNMM(P1)		;TURN OFF WILD CHARACTERS
	MOVE	T2,.FXNAM(P1)		;GET FILE NAME IN REQUEST
	AND	T2,.FXNMM(P1)		;TURN OFF IT'S WILD CAHRACTERS TOO
	CAME	T1,T2			;SKIP IF THEY MATCH
	JRST	NULREC			;NO, SKIP REMAINDER

	MOVE	T1,.F2NAM(P2)		;GET 2ND HALF OF FILE NAME
	AND	T1,.F2NMM(P1)		;TURN OFF WILD CHARACTERS
	MOVE	T2,.F2NAM(P1)		;GET 2ND PART OF REQ'D NAME
	AND	T2,.F2NMM(P1)		;TURN OF WILD CHARACTERS IN IT TOO
	CAME	T1,T2
	JRST	NULREC			;GIVE UP IF NO MATCH THERE

	LOAD.	T1,UFTY,WDIOFF		;GET FILE TYPE FROM DIRTORY BUFFER
	PUSHJ	P,C5T6			;CONVERT TO SIXBIT
	HRLZM	T1,.FXEXT(P2)		;STASH INTO OUTPUT FDB TEMPORARILY
	AND	T1,.FXEXT(P1)		;ISOLATE THE NON-WILD CHARACTERS
	HLRZ	T2,.FXEXT(P1)		;GET FILE TYPE
	AND	T2,.FXEXT(P1)		;TURN OFF WILD BYTES
	CAME	T1,T2
	JRSt	NULREC

	LOAD.	T1,UVER,WDIOFF		;GET GENERATION NUMBER FROM UFD ENTRY
	SKIPE	.FXGEN(P1)		;DID THEY GIVE A GENERATION TO MATCH?
	CAMN	T1,.FXGEN(P1)		;YES, DOES THIS MATCH?
	AOSA	FILMAT			;COUNT A MATCHING FILE
	JRST	NULREC			;NO, NO MATCH SO IGNORE THIS FILE
NULGOT:	LOAD.	T1,UFNO,WDIOFF		;GET FILE NUMBER
	MOVEM	T1,.FXNUM(P2)		;STORE FILE NUMBER
	LOAD.	T1,UVER,WDIOFF		;GET FILE GENERATION #
	MOVEM	T1,.FXGEN(P2)		;SAVE GENERATION #
	LOAD.	T1,UFSQ,WDIOFF		;GET FILE SEQUENCE
	MOVEM	T1,.FXSEQ(P2)		;STORE SEQ #
	MOVE	T1,UFDNUM
	MOVEM	T1,.FXDIR(P2)
	MOVEI	T1,.DIROFF		;GET OFFSET FOR A DIRECTORY RECORD
	ADDM	T1,WDIOFF		;STEP TO NEXT RECORD NEXT PASS
	DMOVE	T1,P1			;RESTORE THE ACS
	JRST	CPOPJ1			;GIVE GOOD RETURN

NULREC:	MOVEI	T1,.DIROFF		;GET OFFSET FOR A DIRECTORY RECORD
	ADDM	T1,WDIOFF		;ADVANCE TO NEXT RECORD
	JRST	NXTFD1			;LOOP TO LOOK AT NEXT RECORD
;HERE IF A DIRECTORY RUNS OUT OF RECORDS IN A BLOCK
NXTDBK:	SKIPGE	WDIBNO			;SKIP IF WDIBNO IS VALID
	JRST	NXTDIR			;NO, GO TO NEXT ONE
	MOVE	T2,WDIBNO		;GET RELATIVE BLOCK # OF NEXT BLOCK
	AOS	WDIBNO			;STEP TO NEXT BLOCK NEXT TIME
	MOVEI	T1,WDIFHB		;LOOK AT DIRECTORY'S FHB
	PUSHJ	P,SCNRET		;FIND THAT BLOCK #
	JRST	NXTDIR			;GO ON TO NEXT DIRECTORY
	MOVEM	T1,WDIPBN		;REMEMBER PHYSICAL BLOCK #
	PUSHJ	P,SUSET			;POSITION DISK TO READ THAT NEXT
	IN	VIO,[IOWD 200,WDIBUF
			0]		;READ INTO DIRECTORY BUFFER
	SKIPA
	ERROR	<I/O error reading directory file>
	MOVEI	T1,<WDIBUF-MFDDAT>*4	;MAKE Uxxx POINT AT WDIBUF
	MOVEM	T1,WDIOFF		;MAKE LOAD./STOR. WORK
	MOVEI	T1,WDIFHB
	MOVE	T2,WDIBNO
	SUBI	T2,1
	PUSHJ	P,EOFBYT
	IDIVI	T1,.DIROFF		;COMPUTE T1=# RECORDS THIS BLOCK
	MOVEM	T1,WDICNT		;INITIALIZE COUNT FOR THIS BLOCK
	JRST	NXTFD1			;LOOP TO READ THIS BLOCK
;HERE IF WE EXHAUST A DIRECTORY, STEP TO THE NEXT RECORD IN THE MFD
NXTDIR:	SOSGE	MASCNT			;SKIP IF MORE MFD RECORDS IN THIS BLOK
	JRST	NXTMBK			;NO MORE, READ NEXT MFD BLOCK

	LOAD.	T1,UFTY,MASOFF		;GET FILE TYPE OF NEXT RECORD
	TSC	T1,[.RAD50 <DIR>]	;COMPARE TO "DIR"
	JUMPN	T1,NXTDI2		;BRANCH IF NOT A DIR FILE
	LOAD.	T1,UFN3,MASOFF		;CHECK 3RD 3RD OF "DIR" FILE'S NAME
	JUMPN	T1,NXTDI2		;BRANCH IF BAD DIR FILE

	LOAD.	T1,UFN1,MASOFF		;GET NAME OF IT
	PUSHJ	P,C5T6			;GET SIXBIT
	HRLZM	T1,UFDNAM		;SAVE IT
	SUBI	T1,'000'
	IDIVI	T1,^O100*100
	IDIVI	T2,^O100
	LSH	T1,3
	ADD	T1,T2
	LSH	T1,3
	ADD	T1,T3
	HRLZM	T1,UFDNUM
	LOAD.	T1,UFN2,MASOFF		;GET RH OF FILE NAME
	PUSHJ	P,C5T6			;GET SIXBIT OF IT
	HRRM	T1,UFDNAM		;REMEMBER IT
	SUBI	T1,'000'
	IDIVI	T1,^O100*100
	IDIVI	T2,^O100
	LSH	T1,3
	ADD	T1,T2
	LSH	T1,3
	ADD	T1,T3
	HRRM	T1,UFDNUM

	AOS	DIRCNT
	MOVE	T1,.FXDIR(P1)
	AND	T1,.FXDIM(P1)
	MOVE	T2,UFDNUM
	AND	T2,.FXDIM(P1)
	CAME	T1,T2
	JRST	NXTDI2

	AOS	DIRMAT			;COUNT A MATCHING DIRECTORY
	LOAD.	T1,UFNO,MASOFF		;GET FILE NUMBER OF IT
	MOVEI	T2,WDIFHB		;GET DIRECTORY FHB BUFFER
	PUSHJ	P,REDFHB		;READ THAT DIRECTORY

	MOVEI	T1,.DIROFF
	ADDM	T1,MASOFF		;STEP TO NEXT RECORD NEXT TIME
	SETZM	WDIBNO			;START WITH BLOCK 0
	SETZM	WDICNT			;START WITH NO RECORDS
	JRST	NXTFD1			;GO DO IT

NXTDI2:	MOVEI	T1,.DIROFF	;
	ADDM	T1,MASOFF		;STEP TO NEXT RECORD NEXT TIME
	JRST	NXTDIR			;READ NEXT RECORD IN MFD
;HERE IF WE EXHAUST A SET OF MFD RECORDS, READ NEXT MFD BLOCK
NXTMBK:	MOVEI	T1,BUF444		;LOOK AT MFD'S FHB
	AOS	T2,MASBNO		;GET MFD BLOK #
	PUSHJ	P,SCNRET		;SCAN IT
	JRST	EOFMFD
	PUSHJ	P,SUSET			;POSITION DISK
	IN	VIO,[IOWD 200,MASBUF	;
			0]
	SKIPA
	ERROR	<I/O error reading MFD>
	MOVEI	T1,BUF444
	MOVE	T2,MASBNO
	PUSHJ	P,EOFBYT
	IDIVI	T1,.DIROFF
	MOVEM	T1,MASCNT		;PLENTY NOW
	MOVEI	T1,<MASBUF-MFDDAT>*4
	MOVEM	T1,MASOFF
	JRST	NXTDIR

EOFMFD:	SKIPE	DIRCNT			;ANY DIRECTORIES SEEN AT ALL?
	POPJ	P,			;YES, DON'T MENTION FAILURE
	TYPE	<% No directory files found
>
	POPJ	P,
MAK2D:	IDIVI	T1,^D10		;DIVIDE INTO 2 PARTS
	LSH	T2,^D8		;MAKE ROOM
	IORI	T1,<"0"_^D8>+"0"(T2);TURN INTO PDP10 ASCII
	MOVSI	T1,(T1)		;CONVERT TO PDP11 FORMAT
	POPJ	P,0


MAKSD:	IDIVI	T1,^D10		;DIVIDE INTO 2 PARTS
	LSH	T2,^D8		;MAKE ROOM
	JUMPE	T1,MAK1D
	IORI	T1,<"0"_^D8>+"0"(T2);TURN INTO PDP11 ASCII
	MOVSI	T1,(T1)
	POPJ	P,0

MAK1D:	IORI	T1,<"0"_^D8>+" "(T2);TURN INTO PDP11 ASCII
	MOVSI	T1,(T1)
	POPJ	P,0
IMPURE:	GETPPN	T1,
	JFCL
	MOVEM	T1,MYPPN
	SETZM	LOWZRO

	SETZM	NULFDB+.FXNAM	;NULL NAME
	SETOM	NULFDB+.FXNMM	;EXPLICITLY
	SETZM	NULFDB+.F2NAM	;...
	SETOm	NULFDB+.F2NMM	;...
	SETZM	NULFDB+.FXEXT	;
	HLLOS	NULFDB+.FXEXT	;...
	SETZM	NULFDB+.FXGEN	;...
	SETOM	NULFDB+.FXDIM	;UIC IS EXACTLY SPECIFIED

	SETZM	DEFFDB+.FXDEV
	SETZM	DEFFDB+.FXDIR
	SETZM	DEFFDB+.FXLNK
	SETZM	DEFFDB+.FXSWT
	SETZM	DEFFDB+.FXMOD
	POPJ	P,0
;	ROUTINE TO FIND IMPLIED FLAGS FOR RAD50 EXTENSION IN T1
;ENTER:	T1/ RIGHT JUSTIFIED RAD50 FILE TYPE WORD
;EXIT:	T1/ IMPLIED FLAGS OR 0
EXTCHK:	PUSHJ	P,SAVE4		;SAVE SOME ACS
	PUSHJ	P,C5T6			;CONVERT RAD50 TO SIXBIT
	MOVE	P1,T1			;COPY FILE TYPE TO SAFER AC
	SETZ	T1,			;T1=FLAGS WHICH THIS ROUTINES WANTS SET
	MOVE	P2,[POINT 36,IMGTBL,35]	;P2=POINTER INTO /IMAGE LIST
EXTCH1:	ILDB	P3,P2			;GET NEXT POSSIBLE EXT
	JUMPE	P3,EXTCH2		;NO MOR LEFT
	CAME	P3,P1			;SKIP IF THIS TYPE IMPLIES /IMAGE
	JRST	EXTCH1			;BRANCH IF THIS TYPE DON'T IMPLY /IMAGE
	TDO	T1,[S$IMAG]		;IMPLY /IMAGE

EXTCH2:	MOVE	P2,[POINT 36,CTGTBL,35]	;P2=POINTER TO /CONTIG TABLE
EXTCH3:	ILDB	P3,P2			;GET P3=NEXT FILE TYPE
	JUMPE	P3,EXTCH4		;BRANCH IF END OF /CONTIG TABLE
	CAME	P3,P1			;SKIP IFF THIS FILE TYPE IMPLIES /CONTIG
	JRST	EXTCH3			;BRANCH IF FILE TYPE DON'T IMPLY /CONTIG
	TDO	T1,[S$CONT]		;IMPLY /CONTIG

EXTCH4:	POPJ	P,

DEFINE	XT(.LIST),<IRP .LIST,<''.LIST''>>
IMGTBL: XT <ABS,BIN,BIC,CFG,CIL,DIR,EXB,LBO,LDA,LDR,LOD,MCB,MFD,OBJ,OLB,SAV,SML,SYM,SYS,TSK,UFD>
	0

CTGTBL:	XT	<SML,OLB,TSK,SYS,DIR>
	0
;	SUBROUTINE TO CHECKSUM A BLOCK OF PDP11 MEMORY

CHKSUM:	PUSHJ	P,SAVE4		;SAVE SOME ACS
	SETZ	P1,		;ZERO IT
	MOVE	P2,[POINT 18,(T1)]
CHKSU1:	ILDB	P3,P2		;GET A WORD
	ADDI	P1,(P3)		;COMPUTE CHECKSUM
	SOJG	T2,CHKSU1	;LOOP TILL DONE
	HRRZ	T1,P1		;RETURN IT IN T1
	ANDI	T1,177777	;TURN OFF CARRY BITS
	POPJ	P,0
;	ROUTINE TO OPEN A FILES-11 VOLUME

OPNVOL:	PUSHJ	P,OPNVIO		;OPEN THE DISK FOR I/O
	PUSHJ	P,G11HOM		;GET THE FILES-11 HOME BLOCK
	SETZM	BUF111			;MAKE SURE WE KNOW INDEXF NOT IN CORE
	LOAD.	T2,IBLL			;GET DISK ADDRESS OF IBM LOW WORD
	LOAD.	T1,IBLH			;GET HIGH WORD
	LSH	T1,^D16			;POSITION HIGH PART
	OR	T1,T2			;COMPUTE T1=DISK ADDRESS OF IBM
	MOVEM	T1,IBMLBN		;SAVE ADDRESS OF IBM
	LOAD.	T2,IBSZ			;GET SIZE OF IBM IN BLOCKS
	ADD	T1,T2			;COMPUTE
	MOVEM	T1,FHBLBN		;SAVE ADDRESS OF KNOWN FHBS
	LOAD.	T2,IBSZ			;GET SIZE OF IBM IN BLOCKS
	IMULI	T2,200			;COMPUTE # OF PDP10 WORDS
	MOVEM	T2,IBMSIZ		;SAVE SIZE
	PUSHJ	P,REDIBM		;READ THE IBM

	MOVEI	T1,2			;FILE#2=BITMAP.SYS
	MOVEI	T2,FHBBUF		;USE THE NORMAL BUFFER
	PUSHJ	P,REDFHB		;READ THAT FHB INTO FHBBUF
	LOAD.	T2,RLBN			;GET LOW LBN OF BITMAP (IE: SAB)
	LOAD.	T1,HRET			;GET HIGH LBN OF BITMAP
	LSH	T1,^D16			;MAKE ROOM FOR LOW
	OR	T1,T2			;COMPUTE T1=DISK ADDRESS OF SAB BLOK
	MOVEM	T1,SBMLBN		;SAVE SBM LBN
	PUSHJ	P,REDSBM		;READ IT

	MOVEI	T1,1			;FILE#1=INDEXF.SYS
	MOVEI	T2,BUF111		;READ INDEXF.SYS FHB INTO BUF111
	PUSHJ	P,REDFHB		;READ IN FHB FOR INDEXF

	MOVEI	T1,4			;FILE#4=000000.DIR
	MOVEI	T2,BUF444		;READ 000000.DIR FHB INTO BUF444
	PUSHJ	P,REDFHB		;READ IN FHB FOR 000000.DIR
	POPJ	P,			;RETURN
;	ROUTINE TO FIND AND LOAD THE FILES-11 HOME BLOCK

G11HOM:	PUSHJ	P,SAVE2			;SAVE P1
	SKIPE	FAKVOL
	JRST	L11HOM			;GO GET LOGICAL INFO
	PUSHJ	P,G10HOM		;GET THE PDP10 HOME BLOCKS
	MOVE	T1,HOME1+HOMNAM		;
	MOVE	T2,HOME2+HOMNAM		;GET HOMNAM FROM BOTH
	CAME	T1,[SIXBIT .HOM.]	;DUE TO AN ERROR IN ONE?
	CAMN	T1,[SIXBIT .HOM.]	;...?
	  JRST	G11HO3			;BRANCH IF WE EXPECT TOPS10 HOME BLOCK
	MOVEI	P1,1			;CURRENT BLOCK #
	SETZM	FSTLBN			;FIRST LBN IN VOLUME
	MOVE	T1,DSKBLK+.DCUSZ	;GET HIGH LBN
	SUBI	T1,1			;...
	MOVEM	T1,LSTLBN		;SAVE IT

G11HO1:	MOVE	T1,P1			;
	PUSHJ	P,SUSET			;POSITION DISK
	IN	VIO,[IOWD 200,H11BUF	;READ HOME BLOCK INTO BUFFER
		    0]			;...
	SKIPA	T1,H11BUF+HOMNAM	;GET TOPS-10 HOME NAME
	  ERROR	<I/O error reading FILES-11 home block>
	JUMPL	T1,G11HO2		;SKIP IF TOPS10 HOME BLOCK
	MOVE	T1,TMP166
	CAME	T1,H11BUF+166
	  JRST	G11HO2			;NOT HOME
	MOVEI	T1,H11BUF		;POINT AT HOME BLOCK
	MOVEI	T2,O.CHK1/2		;# WORDS TO CHECKSUM
	PUSHJ	P,CHKSUM		;COMPUTE CHECKSUM
	LOAD.	T2,CHK1			;GET CHECKSUM RECORDED IN HOME BLOCK
	CAME	T1,T2			;SKIP IF THEY MATCH
	  JRST	G11HO2			;NOT HOME BLOCK, TRY NEXT 400 MULTIPLE
	MOVEI	T1,H11BUF		;POINT AT HOME BLOCK
	MOVEI	T2,o.CHK2/2		;# WORDS TO CHECKSUM
	PUSHJ	P,CHKSUM		;COMPUTE CHECKSUM
	LOAD.	T2,CHK2			;GET CHECKSUM RECORDED IN HOME BLOCK
	MOVEM	P1,H11LBN		;REMEMBER HOME BLOCK LBN
	CAMN	T1,T2			;SKIP IF THEY MATCH
	  JRSt	G11HO4			;GO DO MORE IF NEEDED

G11HO2:	SKIPE	FAKVOL
	AOJA	P1,.+3
	TRZ	P1,377			;TURN OFF POSSIBLE GARBAGE BITS
	ADDI	P1,400			;STEP TO NEXT MULTIPLE
	CAMG	P1,LSTLBN		;TOO FAR?
	JRST	G11HO1			;LOOP AGAIN
	ERROR	<NO HOME BLOCK IN BOUNDS OF VOLUME>

G11HO3:	DMOVE	T1,HOME1+HOMFE0		;GET ADDRESS+VALID BIT
	TLZN	T1,100000		;IS IT VALID?
	  ERROR	<No valid FILES-11 volume present>
	HRRZM	T1,1(P)			;SAVE RH OF 18/18 FORMAT
	HLLZS	T1			;ISOLATE HIGH BITS
	LSH	T1,-2
	OR	T1,1(P)			;INSERT LOW ORDER BITS
	MOVEM	T1,FSTLBN		;STORE 1ST BLOCK # IN VOLUME
	HRRZM	T2,1(P)			;SAVE LENGTH
	HLLZS	T2
	LSH	T2,-2
	OR	T2,1(P)
	ADD	T1,T2			;ADD IN LENGTH
	SUBI	T1,1			;AND -1 TO COMPUTE LAST BLOCK #
	MOVEM	T1,LSTLBN		;SAVE THAT TO
	MOVE	P1,FSTLBN		;GET 1ST LBN
	JRST	G11HO2			;FIND HOME BLOCK

L11HOM:	SETZM	FSTLBN
	USETI	VIO,0			;PREPARE TO READ RIB
	IN	VIO,[IOWD 200,LERBLK	;INTO THE LOOKUP BLOCK
		0]			;
	SKIPA
	ERROR	<Can't read rib of logical volume file>
	SETZM	FAKOFS
	MOVE	T1,LERBLK+.RBALC
	MOVEM	T1,LSTLBN
	MOVEI	P1,0
	JRST	G11HO1

G11HO4: SKIPN   T1,FAKVOL
        POPJ    P,                      ;ALL DONE
        MOVE    T1,VOLPTR(T1)           ;GET "FP" FOR THIS VOLUME
        MOVE    T1,.FXSWT(T1)           ;GET /SWITCHES FOR THIS VOLUME
        TDNE    T1,[S$IMAGE]            ;SKIP IF NOT IMAGE MODE
        POPJ    P,                      ;FAKOFS=0 IF IMAGE MODE

	LOAD.	T2,IBLL
	LOAD.	T1,IBLH
	LSH	T1,^D16
	OR	T1,T2
	TRZ	T1,377		;NOW T1 HAS THE BLOK# THAT HOME BLOK IS
	MOVNS	T1		;MAKE IT AN OFFSET
	ADD	T1,H11LBN
	MOVEM	T1,FAKOFS
	POPJ	P,
;	SUBROUTINE TO OPEN UP THE FILES-11 VOLUME

OPNVIO:	PUSHJ	P,SETVOL		;GO APPROVE VOLUME AND RETURN IT IN T1
	SKIPE	T1,FAKVOL
	JRST	OPNVIL
	MOVE	T2,T1			;PUT IT WHERE WE wANT IT
	MOVE	T1,[UU.PHS!.IODMP]
	MOVE	T2,FEUNIT
	SETZ	T3,
	OPEN	VIO,T1
	  ERROR	<Can't OPEN FILES-11 volume for I/O>
	POPJ	P,0

OPNVIL:	MOVE	T1,VOLPTR(T1)
	MOVEI	T2,OPNBLK
	MOVEI	T3,LERBLK
	MOVEI	T4,PTHBLK
	PUSHJ	P,.STOPB##
	JFCL
	MOVEI	T1,17
	MOVEM	T1,OPNBLK
	MOVEI	T1,.RBEXT
	MOVEM	T1,LERBLK
	OPEN	VIO,OPNBLK
	  ERROR	<Can't OPEN FILES-11 volume for I/O>
	MOVE	T1,OPNBLK+1
	MOVEM	T1,FEUNIT
	LOOKUP	VIO,LERBLK
	  ERROR	<Can't LOOKUP volume for I/O>
	HLLZS	LERBLK+.RBEXT
	ENTER	VIO,LERBLK
	  TYPE	<% Can't ENTER volume for writing
>
	POPJ	P,
;	ROUTINE TO TAKE USER'S VOLUME NAME AND SPIFF IF UP

SETVOL:	MOVE	T1,.FXDEV(FP)		;GET VOLUME NAME
	CAIN	T1,0			;IF NO VOLUME NAME
	MOVE	T1,DEFFDB+.FXDEV	;...TRY FOR DEFAULT INSTEAD
	MOVEM	T1,DSKBLK+.DCNAM	;SAVE THE USER'S NAME
	SETZM	FAKVOL
	MOVE	T1,DSKBLK+.DCNAM
	MOVSI	T2,-VOLMAX
	CAME	T1,VOLTBL(T2)
	AOBJN	T2,.-1
	JUMPLE	T2,SETVO5
	MOVE	T1,[XWD 200,DSKBLK]	;
	DSKCHR	T1,			;
ILLVOL:	  ERROR	<Illegal volume name>	;COMPLAIN
	LDB	T1,[POINT 3,T1,17]	;GET UNIT TYPE
	CAIE	T1,.DCTUF		;DSKB0?
	CAIN	T1,.DCTPU		;OR RPA0?
	JRST	SETVO2			;YES, THATS OK
	CAIE	T1,.DCTFS		;DSKB?
	  JRST	ILLVOL			;NO, TOO VAGUE
SETVO2:	MOVE	T1,DSKBLK+.DCNAM
	CAMN	T1,DSKBLK+.DCUPN
	JRST	SETVO3
	TYPE	<[>
	MOVE	T1,DSKBLK+.DCNAM
	PUSHJ	P,SIXOUT
	TYPE	< will be treated as >
	MOVE	T1,DSKBLK+.DCUPN
	PUSHJ	P,SIXOUT
	TYPE	<]
>
SETVO3:	MOVE	T1,DSKBLK+.DCNAM
	SKIPE	DSKBLK+.DCSNM
	CAMN	T1,DSKBLK+.DCSNM
	JRST	SETVO4
	TYPE	<[>
	MOVE	T1,DSKBLK+.DCUPN
	PUSHJ	P,SIXOUT
	TYPE	< is >
	MOVE	T1,DSKBLK+.DCULN
	PUSHJ	P,SIXOUT
	TYPE	<]
>
SETVO4:	MOVE	T1,DSKBLK+.DCUPN
	MOVEM	T1,FEUNIT
	POPJ	P,0

SETVO5:	MOVEM	T2,FAKVOL
	POPJ	P,
;	SUBROUTINE TO MAKE FE.SYS FILE

MKFESY:	MOVE	T1,.FXSWT(FP)		;GET SWITCHES
	TDNE	T1,[S$FULL]		;FULL REQUESTED?
	JRST	MAKFUL			;YES, DO DIFFFERENTLY
	PUSHJ	P,G10HOM		;LOAD HOME BLOCKS
	DMOVE	T1,HOME1+HOMFE0		;GET THE RSX20F WORDS FROM HOME BLOCK #1
	CAMN	T1,HOME2+HOMFE0		;SKIP IF COPIES DON'T MATCH
	CAME	T2,HOME2+HOMFE1		;SKIP IF COPIES DO MATCH
	  ERROR	<TOPS-10 home blocks HOMFE0/HOMFE1 don't match>
	JUMPN	T1,[ERROR <FE.SYS already exists>]

	MOVE	T1,[RB.NSE+.RBPOS]	;RB.NSE - DON'T SUPERCEED, .RBPOS=LENGTH
	MOVEM	T1,LERBLK+.RBCNT	;NONSUPERCEEDING ENTRY
	MOVE	T1,[1,,4]		;SYS:'S PPN, SAVE A GETTAB UUO
	MOVEM	T1,LERBLK+.RBPPN	;SPECIFY IT
	MOVSI	T1,'FE '		;DEFAULT NAME
	MOVEM	T1,LERBLK+.RBNAM	;SPECIFY NAME OF 'FE'
	MOVSI	T1,'SYS'		;DEFAULT EXTENSION OF 'SYS'
	MOVEM	T1,LERBLK+.RBEXT	;SPECIFY EXT OF 'SYS'
	SETZM	LERBLK+.RBSIZ		;THIS IS IGNORED ANYWAY
	MOVE	T1,.JBVER		;GET OUR VERSION NUMBER
	MOVEM	T1,LERBLK+.RBVER	;SPECIFY AS FILE'S VERSION NUMBER
	MOVE	T1,[SIXBIT .RSX20F.]	;GET A SPOOLING NAME
	MOVEM	T1,LERBLK+.RBSPL	;SPECIFY CLEVER SPOLLING NAME
	SETZM	LERBLK+.RBEST		;WE NEED CONTIGUOUS FILE
	SKIPN	T1,V$SIZE(FP)		;GET SIZE IN BLOCKS
	MOVEI	T1,M.HLEN		;USE DEFAULT SIZE
	MOVEM	T1,V$SIZE(FP)		;FORCE A SPECIFIC SIZE
	ADDI	T1,3			;2RIBS + 1 FOR LUCK
	MOVEM	T1,LERBLK+.RBALC	;SPECIFY ALLOCATED SIZE
	MOVEM	T1,REQALC		;REQUIRED ALLOCATION SIZE

	PUSHJ	P,MAKPOS		;GO GET THE POSITION TO PUT IT IN
	MOVEM	T1,LERBLK+.RBPOS	;REMEMBER IT
POSLOP:	MOVSI	T1,455000		;FOOLISHLY LOW PROTECTION
	MOVEM	T1,LERBLK+.RBPRV	;SPECIFY EXPLICIT PRIV WORD
	MOVE	T1,REQALC		;GET REQUIRED SIZE
	MOVEM	T1,LERBLK+.RBALC	;RESPECIFY IT IN CASE OF PAO ERRORS
	HLLZS	LERBLK+.RBEXT		;GET RID OF JUNK FROM LAST PASS
	ENTER	VIO,LERBLK		;ENTER NEW FE.SYS FILE
	  JRST	[HRRZ T1,LERBLK+.RBEXT	;GET ERROR CODE
		CAIN T1,ERBNF%		;THAT BLOCK NOT FREE?
NXTCLU:		JRST [MOVE T1,LERBLK+.RBPOS	;GET BLOCK WE TRIED FOR
			ADD T1,CLUSIZ		;ADVANCE TO NEXT CLUSTER
			JUMPL T1,POSERR		;GIVE UP IF OUT OF PLACES TO TRY
			CAML T1,DSKBLK+.DCUSZ	;MAKE SURE STILL ON DISK
		POSERR: ERROR <Cannot allocate at requested position>
			MOVEM T1,LERBLK+.RBPOS	;UPDATE CLUSTER POSITION
			MOVE T1,[S$DOTS];GET THE "I WANT DOTS" BIT
			TDNE T1,.FXSWT(FP);SKIP IF I DON'T WANT DOTS
			TYPE <.>	;TYPE .'S TO LET HIM KNOW WE'RE TRYING
			CLOSE VIO,CL.RST;GET RID OF WRONGLY POS'D FILE
			JRST  POSLOP]	;AND TRY AGAIN
		CAIE T1,ERPOA%		;PARTIAL ONLY?
		ERROR	<Cannot ENTER FE.SYS>,LSTLER
		SKIPE	V$INDEX(FP)	;SKIP IF NO /INDEX SWITCH
		JRST	NXTCLU		;DEMAND FULL SIZE IF /INDEXed
		TYPE	<% Only >	;WARN HIM
		MOVE	T1,.RBALC+LERBLK;GET SIZE WE ACTUALLY ALLOCATED
		PUSHJ	P,R10OUT	;TYPE SIZE THAT GOT ALLOCATED
		TYPE	< blocks available>
		PUSHJ	P,CRLF
		JRST	.+1]
	MOVE	T1,LERBLK+.RBALC	;GET ACTUAL SIZE ALLOCATED
	SUBI	T1,3			;TAKE OFF BOTH RIBS + 1 FOR LUCK
	MOVEM	T1,V$SIZE(FP)		;AND REMEMBER THAT AS THE REAL SIZE

	CLOSE	VIO,CL.DLL		;DON'T DEALLOCATE THE UNWRITTEN BLOCKS
	TYPE	<[Created >
	MOVE	T1,FEUNIT		;GET UNIT NAME FOR FE.SYS FILE
	PUSHJ	P,SIXOUT		;TYPE UNIT NAME
	TYPE	<:FE.SYS[1,4], >	;FAKE THE FILE NAME, EXT, AND PATH
	MOVE	T1,LERBLK+.RBALC	;GET SIZE ACTUALLY ALLOCATED
	PUSHJ	P,DECOUT		;TYPE SIZE OF FILE
	TYPE	< blocks allocated to FILES-11 volume]>
	PUSHJ	P,CRLF

	MOVSI	T1,'FE '		;
	MOVSI	T2,'SYS'		;
	SETZ	T3,
	MOVE	T4,[1,,4]
	LOOKUP	VIO,T1			;FIND FILE
	  ERROR	<LOOKUP failed for known file>
	HLLZS	T2
	SETZ	T3,
	MOVE	T4,[1,,4]
	ENTER	VIO,T1			;PUT FE.SYS INTO UPDATE MODE
	  ERROR	<Can't enter update mode for FE.SYS>
	USETI	VIO,0			;POSITION TO READ THE RIB
	IN	VIO,[IOWD 200,TMPBUF	;READ RIB INTO TEMPORARY BUFFER
		    0]			;...
	SKIPA
	  ERROR	<IN uuo failed while reading RIB of FE.SYS>
	CLOSE	VIO,CL.DLL+CL.DAT	;CLOSE IT
	MOVE	T1,[RP.NDL!RP.ABC]	;GET NO-DELETE BIT & BAD-CHECKSUM BIT
	IORM	T1,TMPBUF+.RBSTS	;TURN THEM ON
	MOVE	T1,.RBALC+TMPBUF
	SUBI	T1,2
	IMULI	T1,200
	MOVEM	T1,.RBSIZ+TMPBUF	;MAKE FILE APPEAR BIG ALREADY
	MOVE	T1,TMPBUF+.RBSLF	;POINT AT IT
	PUSHJ	P,SUSET			;POSITION TO IT
	OUTPUT	VIO,[IOWD 200,TMPBUF
			0]		;REWRITE RIB
; ****
; **** I HAVEN'T REALLY THOUGHT ABOUT THIS VERY CAREFULLY,
; **** THIS MAY CAUSE A DIASTER IS THE OUTPUT STRUCTURE
; **** CONSISTS OF MORE THAN 1 PDP10 UNIT
	AOS	T1,TMPBUF+.RBSLF	;READ THE BLOCK NUMBER THAT GOT USED
	TRZ	T1,377			;TURN OFF LOW BYTE
	ADDI	T1,400			;COMPUTE HOME BLOCK ADDRESS
	MOVEM	T1,H11LBN		;AND REMEMBER IT

	MOVE	T1,TMPBUF+.RBSLF	;GET RIB BLOCK AGAIN
	MOVEM	T1,FSTLBN		;REMEMBER 1ST LBN IN VOLUME
	ADD	T1,V$SIZE(FP)		;COMPUTE LAST LBN IN VOLUME
	SUBI	T1,1
	MOVEM	T1,LSTLBN		;REMEMBER LAST LBN IN USE TOO
	POPJ	P,			;RETURN TO CALLER
MAKPOS:	HLRZ	T1,DSKBLK+.DCUCH	;GET CLUSTER DATA
	LSH	T1,-^D9			;ISOLATE CLUSTER SIZE IN T3
	MOVEM	T1,CLUSIZ		;REMEMBER CLUSTER SIZE FOR SCAN

	SKIPN	T1,V$INDEX(FP)		;FIND VALUE OF /INDEX SWITCH
	POPJ	P,			;RETURN 0 FOR DON'T CARE IF NO SWITCH
	CAMN	T1,[SIXBIT .END.]	;END OF PACK?
	  JRST	MAKPO1
	CAMN	T1,[SIXBIT .BEG.]	;BEGINNING OF PACK?
	  JRST	MAKPO2			;...
	CAMN	T1,[SIXBIT .MID.]	;MID POINT?
	  JRST	MAKPO3
	CAMN	T1,[SIXBIT .BLK.]	;AT SPECIFIC BLOCK?
	  JRST	MAKPO4			;
	ERROR	<Internal error - V$INDEX isn't BEG,MID,END or BLK>

;	HERE FOR /INDEX:END
MAKPO1:	MOVE	T1,DSKBLK+.DCUSZ	;GET SIZE OF UNIT
	SUB	T1,V$SIZE(FP)		;BACK OFF BY SIZE OF FILE
	SUBI	T1,400			;BACK OFF FOR HOME BLOCK OFFSET
	IDIV	T1,CLUSIZ		;COMPUTE LOWEST CLUSTER #
	IMUL	T1,CLUSIZ		;COMPUTE LOWEST LBN FALLING ON CLUSTER
	MOVNS	CLUSIZ			;DO SCAN IN REVERSE DIRECTION
	POPJ	P,			;RETURN

;	HERE FOR /INDEX:BEG
MAKPO2:	MOVE	T1,CLUSIZ		;GET FIRST CLUSTER LBN ADDRESS
	POPJ	P,			;(CUZ 0 MAKES MONITOR PICK IT OUT)

;	HERE FOR /INDEX:MID
MAKPO3:	MOVE	T1,DSKBLK+.DCUSZ	;GET SIZE OF UNIT
	SUB	T1,V$SIZE(FP)		;BACK OFF BY SIZE OF FILE
	SUBI	T1,400			;BACK OFF BY HOME BLOCK OFFSET
	LSH	T1,-1			;COMPUTE RAW MIDPOINT OF IT
	IDIV	T1,CLUSIZ		;COMPUTE LOWEST CLUSETER #
	IMUL	T1,CLUSIZ		;COMPUTE LBN ADDRESS OF CLUSTER #
	POPJ	P,			;RETURN

;	HERE FOR /INDEX:BLK
MAKPO4:	MOVE	T1,IDXBLK
	MOVE	T2,DSKBLK+.DCUSZ	;GET SIZE OF UNIT
	LSH	T2,-1			;COMPUTE MIDPOINT
	CAMLE	T1,T2			;
	MOVNS	CLUSIZ			;SCAN REVERSE IF HIGH END OF DISK
	SUB	T1,V$SIZE(FP)		;BACK OFF BY SIZE OF FILE
	SUBI	T1,400			;BACK OFF BY MAXIMUM HOME BLOCK OFFSET
	IDIV	T1,CLUSIZ		;
	IMUL	T1,CLUSIZ
	POPJ	P,
;	ROUTINE TO DO THE SAME WORK MKFESYS DOES WHEN USER HAS ASKED FOR /FULL
MAKFUL:	TYPE	<Do you really want to do a /FULL for >
	MOVE	T1,FEUNIT
	PUSHJ	P,SIXOUT
	PUSHJ	P,YESNO
	JRST	ILLCMD
	TYPE	<It will DESTROY THE STRUCTURE THERE, are you POSITIVE>
	PUSHJ	P,YESNO
	JRST	ILLCMD

	SKIPE	DSKBLK+.DCSNM
	ERROR	<Cannot INI/FULL an online structure>
	MOVE	T1,DSKBLK+.DCUSZ		;GET HIGHEST BLOCK #
	MOVEM	T1,V$SIZE(FP)			;PRETEND HE GAVE /SIZE SWITCH
	SUBI	T1,1			;COMPUTE HIGHEST BLOK#
	MOVEM	T1,LSTLBN		;SAVE IT
	SETZM	FSTlBN			;START WITH BLOCK 0
	MOVEI	T1,400			;HOME BLOCK AT 400
	MOVEM	T1,H11LBN
	POPJ	P,
;	ROUTINE TO GET THE TOPS10 HOME BLOCKS IN CORE

G10HOM:	SETOM	HOME1+HOMNAM		;MAKE 1ST HOME BLOCK ILLEGAL
	SETOM	HOME2+HOMNAM		;MAKE 2ND HOM BLOCK ILLEGAL TOO
	HLLZS	HOME2+HOMNAM		;BUT STILL DIFFERENT FROM FIRST
	MOVEI	T1,1			;1ST HOME BLOCK AT 1
	PUSHJ	P,SUSET			;POSITION
	IN	VIO,[IOWD 200,HOME1	;READ INTO HOME BUFFER 1
		       0]		;
	SKIPA
	  TYPE	<% IN uuo failed reading LBN 1
>,G10HO1
G10HO1:	MOVEI	T1,12			;2nd HOME BLOCK AT ^D10
	PUSHJ	P,SUSET
	IN	VIO,[IOWD 200,HOME2	;READ INTO HOME BUFFER 2
		       0]
	SKIPA
	  TYPE	<% IN uuo failed reading LBN 12
>,G10HO2

G10HO2:	POPJ	P,
WRTHOM:	SKIPN	FSTLBN			;SKIP IF NOT /FULL
	POPJ	P,			;DON'T WRITE PDP10 HOME BLOCKS IF /FULL
	MOVE	T1,FSTLBN	;GET 1ST DATA BLOCK LBN OF FE.SYS
	IDIVI	T1,200000
	IMUL	T1,[1,,0]
	HRR	T1,T2
	TLO	T1,100000	;TURN ON THE VALID BIT
	MOVEM	T1,HOME1+HOMFE0	;STORE IT IN THE HOME BLOCK
	MOVE	T1,LSTLBN	;GET LAST BLOCK IN VOLUME
	SUB	T1,FSTLBN	;COMPUTE LENGTH OF VOLUME
	IDIVI	T1,200000
	IMUL	T1,[1,,0]
	HRR	T1,T2
	MOVEM	T1,HOME1+HOMFE1	;STORE IT IN THE HOME BLOCK
ZERHOM:	DMOVE	T1,HOME1+HOMFE0	;GET FE.SYS DATA
	DMOVEM	T1,HOME2+HOMFE0	;STORE INTO REDUNDENT BLOCK TOO
	MOVEI	T1,1
	PUSHJ	P,SUSET
	OUT	VIO,[IOWD 200,HOME1
			0]
	SKIPA
	  ERROR	<OUT failed writing 1st home block>
	MOVEI	T1,12
	PUSHJ	P,SUSET
	OUT	VIO,[IOWD 200,HOME2
			0]
	SKIPA
	  ERROR	<OUT failed writing 2nd home block>
	POPJ	P,0
	SUBTTL	TERMINAL I/O

SIXOUT:	SETZ	T2,		;MAKE ROOM
	ROTC	T1,6
	MOVEI	T3,40(T2)
	PUSHJ	P,TYO
	JUMPN	T1,SIXOUT
	POPJ	P,0
;ROUTINE TO PRINT OUT THE "PROTECTION" INDICATED BY T1
P11OUT:	PUSHJ	P,SAVE2		;SAVE SOME ACS
	MOVEI	T3,"<"		;
	MOVEI	T2,">"		;DUMMY
	PUSHJ	P,TYO
	MOVEI	P1,4		;4 GROUPS
	SKIPA
P11OU1:	TYPE	<,>		;SEPERATE GROUPS
	TRNN	T1,1		;READ INHIBITED?
	TYPE	<R>		;NO, READ PERMITTED
	TRNN	T1,2		;WRITE INHIBITED?
	TYPE	<W>		;NO, WRITE PERMITTED
	TRNN	T1,4		;EXTEND INHIBITED?
	TYPE	<E>		;NO, EXTEND PERMITTED
	TRNN	T1,10		;DELETE INHIBITED?
	TYPE	<D>		;NO, DELETE PERMITTED
	LSH	T1,-4		;GET NEXT GROUP
	SOJG	P1,P11OU1	;LOOP FOR NEXT GROUP
	MOVEI	T2,"<"		;
	MOVEI	T3,">"		;
	PJRST	TYO		;EXIT
;ROUTINE TO TYPE FILE NAME WITHOUT TRAILING SPACES
;
;	T1/	1ST 3RD OF FILE NAME
;	T2/	2ND 3RD
;	T3/	3RD 3RD
FILE5O:	PUSHJ	P,SAVE4
	DMOVE	P1,T1
	MOVE	P3,T3
	SETZ	P4,
	PUSHJ	P,SPIT3
	MOVE	T1,P2
	PUSHJ	P,SPIT3
	MOVE	T1,P3
	PUSHJ	P,SPIT3
	POPJ	P,

SPIT3:	IDIVI	T1,^O50*^O50
	IDIVI	T2,^O50
	PUSHJ	P,SPIT1
	MOVE	T1,T2
	PUSHJ	P,SPIT1
	MOVE	T1,T3

SPIT1:	JUMPE	T1,[AOJA P4,CPOPJ]
	JUMPE	P4,SPIT0
	PUSH	P,T3
	MOVEI	T3," "
	PUSHJ	P,TYO
	POP	P,T3
	SOJA	P4,SPIT1
SPIT0:	PUSHJ	P,RAD5O
	POPJ	P,
;TYPE T1 AS 3 RADIX 50 CHARACTERS
RAD53O:	IDIVI	T1,^O50*^O50
	IDIVI	T2,^O50
	PUSH	P,T3
	PUSH	P,T2
	PUSHJ	P,RAD5O
	POP	P,T1
	PUSHJ	P,RAD5O
	POP	P,T1
RAD5O:	PUSH	P,T3
	MOVE	T3,R2STBL(T1)
	ADDI	T3,40
	PUSHJ	P,TYO
	POP	P,T3
	POPJ	P,
;ROUTINES TO TYPE T1 AS A DECIMAL NUMBER

DECOUT:	PUSHJ	P,R10OUT	;TYPE NONFILLED DECIMAL NUMBER
	MOVEI	T3,"."		;AND THEN...
	PUSHJ	P,TYO		;TYPE A DOT TO SHOW IT'S DECIMAL
	POPJ	P,0		;EXIT

;ROUTINE TO TYPE AN UNFILLED DECIMAL NUMBER
R10OUT:	IDIVI	T1,^D10
	PUSH	P,T2
	CAIE	T1,0
	PUSHJ	P,R10OUT
	POP	P,T2
	MOVEI	T3,"0"(T2)
	PUSHJ	P,TYO
	POPJ	P,

;ROUTINE TO TYPE A DECIMAL NUMBER WITH AT LEAST 2 DIGITS
DECO2:	CAIG	T1,^D9
	TYPE	< >
	JRST	DECOUT

DECO3:	CAIG	T1,^D99
	TYPE	< >
	JRST	DECO2

DECO4:	CAIG	T1,^D999
	TYPE	< >
	JRST	DECO3

DECO5:	CAIG	T1,^D9999
	TYPE	< >
	JRST	DECO4
;	ROUTINE TO TYPE OUT A "SEQUENCE NUMBER" TO THE OUTPUT FILE

TYPSQN:	PUSHJ	P,SAVE4			;SAVE SOME ACS
	MOVE	P1,T3			;COPY THE SEQUENCE NUMBER
	MOVEI	T3,0			;GET A ZERO
	MOVE	P2,PUTCTR		;GET COUNTER
	IDIVI	P2,5			;FIND OUT WHERE WE ARE
	SKIPE	P3			;WE AT THE RIGHT BOUNDRY
	JRST	[PUSHJ P,XPUTC		;PAD OUT
		 JRST .-3]		;UNTILL WE ARE AT THE RIGHT BOUNDRY

	MOVE	T1,P1			;GET SEQUENCE NUMBER
	MOVEI	P1,5			;ALWAYS EXACTLY 5 DIGITS
TYPSQ1:	IDIVI	T1,^D10			;GET ANOTHER DIGIT
	PUSH	P,T2			;SAVE REMAINDER
	SOSLE	P1			;SKIP IF END OF NUMBER
	JRST	TYPSQ1			;LOOP FOR ANOTHER DIGIT
	MOVEI	P1,5			;5 DIGITS AGAIN
TYPSQ2:	POP	P,T3
	ADDI	T3,"0"			;CONVERT TO ASCII
	PUSHJ	P,PUTC			;PUT IT IN FILE
	SOJG	P1,TYPSQ2		;LOOP FOR ALL DIGITS

	MOVE	T1,DOBUF+.BFPTR		;GET POINTER TO LAST DIGIT
	MOVEI	T2,1			;GET LINE # BIT
	IORM	T2,(T1)			;TURN IT ON
	POPJ	P,			;RETURN
;ROUTINE TO TYPE T1 AS OCTAL NUMBER
OCTOUT:	IDIVI	T1,^O10
	PUSH	P,T2
	CAIE	T1,0
	PUSHJ	P,OCTOUT
	POP	P,T2
	MOVEI	T3,"0"(T2)
	PUSHJ	P,TYO
	POPJ	P,0

;...AS OCTAL USING AT LEAST 2 DIGITS
OCTO2:	CAIG	T1,^O7
	TYPE	< >
	JRST	OCTOUT

OCTO3:	CAIG	T1,^O77
	TYPE	< >
	JRST	OCTO2

OCTO4:	CAIG	T1,^O777
	TYPE	< >
	JRST	OCTO3

OCTO5:	CAIG	T1,^O7777
	TYPE	< >
	JRST	OCTO4

OCTO6:	CAIG	T1,^O77777
	TYPE	< >
	JRST	OCTO5

OCTO7:	CAIG	T1,^O777777
	TYPE	< >
	JRST	OCTO6
;ROUTINE TO TYPE THE CURRENTLY OPENED VOLUME
VOLOUT:	MOVE	T1,FEUNIT		;GET PHYSICAL UNIT
	SKIPE	T2,FAKVOL		;SKIP IF REAL UNIT IN USE
	MOVE	T1,VOLTBL(T2)		;ELSE GET LOGICAL NAME
	PUSHJ	P,SIXOUT
	TYPE	<:>
	POPJ	P,
;ROUTINE TO TYPE T1 AS A PPN
PPNOUT:	PUSH	P,T1
	TYPE	<[>
	HLRZ	T1,(P)
	PUSHJ	P,OCTOUT
	TYPE	<,>
	POP	P,T1
	HRRZS	T1
	PUSHJ	P,OCTOUT
	TYPE	<]>
	POPJ	P,
;ROUTINE TO TYPE A CRLF TO OUTPUT
; LESS MESSY THAN INCLUDING A CRLF IN TYPEOUT LITERALS
CRLF:	TYPE	<
>
	POPJ	P,0

FCRLF:	PUSH	P,T3
	MOVEI	T3,15
	PUSHJ	P,PUTC
	MOVEI	T3,12
        PUSHJ   P,PUTC
        POP     P,T3
        POPJ    P,
;ROUTINE TO READ IN A SINGLE CHARACTER FROM THE KEYBOARD
TYI:	MOVE	T3,LASTCH	;GET LAST CHARACTER IN CASE OF RE-EAT
	TDZE	F,[X%REEAT]	;RETURN IT?
	JRST	TYI1		;YES, DO IT
	INCHWL	T3		;GET A CHARACTER
	CAIN	T3,15		;BUT REJECT A CR AND TRY FOR LF
	JRST	TYI		;...

TYI1:	MOVEM	T3,LASTCH	;REMEMBER LAST CHARACTER RETURNED
	POPJ	P,0

;ROUTINE TO READ IN A SINGLE CHARACTER FROM THE KEYBOARD
;...AND CONVERT TO UPPERCASE ALPHABETIC IF LOWERCASE ALPHABETIC
TYIUC:	PUSHJ	P,TYI		;GET CHARACTER
	CAIL	T3,"a"		;AND CHECK FOR LOWER CASE
	CAILE	T3,"z"		;...?
	POPJ	P,		;UPPER, JUST RETURN
	SUBI	T3,40		;CONVERT LOWER TO UPPER
	POPJ	P,

;ROUTINE TO READ IN A SINGLE CHARACTER FROM THE KEYBOARD
;...BUT TO SKIP OVER ANY LEADING WHITE SPACE
TYINB:	MOVE	T3,LASTCH	;ALREADY GOT ONE?
	CAIE	T3," "		;SKIP IF LAST WAS BLANK
	CAIN	T3,"	"	;SKIP IF LAST WAS TAB
	JRST	[PUSHJ P,TYIUC	;IF LEADING WHITE SPACE, GOBBLE IT, TRY AGAIN
		 JRST TYINB]	;NO, GET ONE
	POPJ	P,		;THATS ALL
;	ROUTINE TO SETUP AN OUTPUT FDB, IF ANY

SETOUT:	MOVE	T1,.FXMOD(FP)		;GET FLAGS FOR THIS SPEC
	TDNE	T1,[FX.EQL]		;= SEEN?
	JRST	SETOU1			;YES, SET REAL OUTPUT FILE
	HRLZI	T1,'*  '		;WILD CARD FILE NAME
	MOVEM	T1,.FXNAM+OUTFDB	;
	SETZM	.F2NAM+OUTFDB		;...
	MOVEM	T1,.FXEXT		;WILD FILE TYPE
	SETZM	.FXNMM+OUTFDB
	SETZM	.F2NMM+OUTFDB
	SETZM	.FXDIR+OUTFDB
	SETZM	.FXDIR+2+OUTFDB
	SETOM	.FXDIM+OUTFDB
	SETZM	.FXDEV+OUTFDB
	POPJ	P,

SETOU1:	MOVSI	T1,(FP)
	HRRI	T1,OUTFDB
	BLT	T1,OUTFDB+.FXLEN-1
	HRRZ	FP,.FXLNK(FP)
	JUMPE	FP,[ERROR <File specification required to define input>]
	POPJ	P,
;	ROUTINE TO SETUP WHERE "TTY," GOES TO
;
;	IF THE STATIC FILE SPEC SHOWS AN "=" SIGN, THEN USE IT AS OUTPUT
;	OTHERWISE, USE PHYSICAL TTY:

SETTTY:	MOVE	T1,.FXMOD(FP)		;GET FLAGS FOR CURRENT FILE SPEC
	TDNE	T1,[FX.EQL]		;= SEEN?
	JRST	SETTT1			;YES, SETUP REAL OUTPUT FILE
TTYPHY:	TDO	F,[X%INT]		;AN INTERACTIVE DEVICE
	MOVE	T1,[UU.PHS!.IOASC]	;NO, PREPARE FOR TTY
	MOVSI	T2,'TTY'		;
	MOVSI	T3,TTYOBF		;
	OPEN	TTY,T1			;OPEN TTY FOR OUTPUT
	  HALT .				;THIS MUST NOT HAPPEN
	OUTBUF	TTY,1			;ONLY ONE BUFFER, ALLOCATE IT NOW
	POPJ	P,			;WE'RE DONE

SETTT1:	TDZ	F,[X%INT]		;NOT AN INTERACTIVE DEVICE
	SKIPE	.F2NAM(FP)			;MUST BE SHORT FILE NAME
ILLFL0:	  ERROR	<Illegal output file name>
	SKIPE	.FXNAM(FP)
	AOSN	.FXNMM(FP)
	SKIPA
	JRST	ILLFL0
	SETOM	.FXNMM(FP)

	MOVE	T2,CMDIDX
	SKIPN	T1,.FXNAM(FP)		;HE GIVE EXPLICIT FILE NAME?
	MOVE	T1,CMDSIX(T2)
	MOVEM	T1,.FXNAM(FP)		;REMEMBER WHATEVER FILE NAME
	SKIPN	T1,.FXEXT(FP)		;SKIP IF HE GAVE NO EXT
	HRLOI	T1,'OUT'		;NO, USE .OUT
	MOVEM	T1,.FXEXT(FP)		;REMEMBER FINAL EXT WE CHOSE
	HRRES	T1			;EXTEND WILD CARD MASK
	AOJN	T1,[ERROR <Illegal output file extension>]
	MOVEI	T1,(FP)			;POINT AT FILE SPEC BLOCK
	MOVEI	T2,OPNBLK		;POINT AT OPEN BLOCK
	MOVEI	T3,LERBLK		;POINT AT L/E/R BLOCK
	MOVEI	T4,PTHBLK		;POINT AT PATH BLOCK
	PUSHJ	P,.STOPB##		;GO BUILD UP THE UUO BLOCKS
	  ERROR	<Cannot "setup" log output file>
	MOVEI	T1,.IOASC
	MOVEM	T1,OPNBLK+0
	MOVSI	T1,TTYOBF
	MOVEm	T1,OPNBLK+2
	OPEN	TTY,OPNBLK		;OPEN CHANNEL FOR OUTPUT
	  ERROR	<Cannot OPEN output device>
	MOVEi	T1,.RBSPL
	MOVEm	T1,LERBLK
	ENTER	TTY,LERBLK		;
	  ERROR	<ENTER failed for output file>,LSTLER
	OUTBUF	TTY,1			;ONLY USE 1 BUFFER
	HRRZ	FP,.FXLNK(FP)		;STEP TO 1ST INPUT SPEC
	JUMPE	FP,[ERROR <Input specification required>]
	POPJ	P,			;RETURN
;	ROUTINE TO READ IN A FILE SPEC PLUS ANY LEADING/TRAILING SWITCHES
;
;RETURN:
;	T1/	POINTER TO FILE SPEC BLOCK

FILIN:	PUSHJ	P,SAVE4		;SAVE P1-P4
	PUSHj	P,SAVFP
	SETZM	IPLIST			;START OFF WITH NO INPUT
	SETZM	IPLAST			;...
FILINL:	PUSHJ	P,TRMSKP		;END OF LINE?
	SKIPA				;NO, ALL'S OK
	POPJ	P,			;GIVE NO FILES RETURN
	MOVEI	FP,STATIC		;MAKE FILIN USE THE STATIC FDB
	PUSHJ	P,FILINZ		;GO GET A FILE SPEC
	MOVE	T1,.FXDEV+STATIC	;GET DEVICE
	IOR	T1,.FXNAM+STATIC	;AND FILE NAME
	IOR	T1,.FXEXT+STATIC	;AND EXT
	MOVE	T2,.FXMOD+STATIC	;AND MODIFIER
	SKIPN	T1			;ANY PART OF FILE SPEC
	TDNE	T2,[FX.CMA!FX.EQL]	;OR ANY REASON TO IMPLY ONE?
	SKIPA				;SKIP IF SOME SORT OF FILE SPEC SEEN
	POPJ	P,			;JUST RETURN IF NO FILE SPEX
	MOVEI	T1,.FXLEN		;SIZE OF A FILE SPEC
	PUSHJ	P,GETCOR		;GO ALLOCATE ONE
	SKIPN	IPLIST			;IS THIS THE 1ST?
	MOVEM	T1,IPLIST		;YES, REMEMBER IT
	SKIPE	T2,IPLAST		;IS THERE A LAST ONE?
	MOVEM	T1,.FXLNK(T2)		;YES, REMEMBER THE LINK TO THIS ONE
	MOVEM	T1,IPLAST		;REMEMBER THIS BLOCK FOR NEXT TIME
	HRLI	T1,STATIC
	MOVEI	T2,.FXLEN-1(T1)		;LAST WORD TO MOVE
	BLT	T1,(T2)			;MOVE THE FILE SPEC TO PERMANENT PLACE
	JRST	FILINL			;LOOP
FILINZ:	SETZM	(FP)			;CLEAR THE FILE BLOCK
	MOVEI	T1,1(FP)		;
	HRLI	T1,(FP)
	BLT	T1,.FXLEN-1(FP)		;...CLEAR ENTIRE BLOCK TO ZEROES
	MOVE	T1,[FX.NDV]
	IORM	T1,.FXMOD(FP)

FILIN1:	PUSHJ	P,SIXIN			;READ A POSSIBLE FILE NAME
	CAIN	T3,":"			;TERMINATING CHARACTER ":"?
	JRST	FILIN3			;YES, GO PARSE OFF A DEVICE NAME
	JUMPE	T4,FILIN2		;SKIP IF NO FILE NAME THERE
	SKIPE	STATIC+.FXNAM		;SKIP IFF NEVER SEEN FILE NAME
	  ERROR	<Illegal file name>
	MOVEM	T1,STATIC+.FXNAM	;SAVE FILE NAME
	MOVEM	T2,STATIC+.F2NAM	;SAVE ALL OF FILE NAME
	MOVEM	M1,STATIC+.FXNMM	;SAVE NAME MASK
	MOVEM	M2,STATIC+.F2NMM	;SAVE 2ND NAME MASK

FILIN2:	CAIE	T3," "			;SKIP IFF ENDED WITH BLANK
	CAIN	T3,"	"		;SKIP IFF ENDED WITHOUT BLANK OR TAB
	JRST	FILIN1			;LOOP IF BLANK OR TAB

	CAIN	T3,"."			;FILE TYPE COMING UP?
	  JRST	FILIN4			;YES, GO GET FILE TYPE
	CAIN	T3,"["			;FILE PATH/UIC COMING UP?
	  JRST	FILIN5			;YES, GO GET PATH/UIC
	CAIN	T3,"<"			;PDP10 PROTECTION FIELD COMING? ">"
	  JRST	FILIN8			;YES, GO GET PDP10 PROTECTION
	CAIN	T3,"/"			;SWITCH COMING UP?
	  JRST	FILIN9			;YES, GO GET SWITCH
	CAIN	T3,";"			;GENERATION COMING UP?
	  JRST	FILING			;YES, GO GET IT

;HERE WHEN WE CANNOT PARSE ANYTHING MORE FROM FILE SPECIFICATION
	MOVE	T1,[FX.EQL]		;EQUAL SEEN BIT
	CAIN	T3,"="			;EQUAL SEEN?
	IORM	T1,STATIC+.FXMOD	;REMEMBER SEEN WITH THAT SPEC
	MOVE	T1,[FX.CMA]		;COMMA SEEN BIT
	CAIN	T3,","			;COMMA SEEN?
	IORM	T1,STATIC+.FXMOD	;REMEBER COMMA SEEN
;	THIS SECTION SAVES TIME AND DOES THE INITIAL WILD CARDING
;	ON THE INPUT FILE NAMES

	POPJ	P,			;RETURN
;HERE TO GET OCTAL GENERATION NUMBER
FILING:	PUSHJ	P,OCTIN			;GO GET THE GENERATION NUMBER
	JUMPE	T4,ILLCHR		;SHOULD BE AT LEAST 1 DIGIT IN IT
	AOJN	M1,ILLCHR		;MUST NOT BE WILD
	MOVEM	T1,.FXGEN(FP)		;SAVE THE GENERATION NUMBER
	JRST	FILIN2			;CONTINUE PARSE
;HERE TO GET A DEVICE NAME
FILIN3:	JUMPN	T2,ILLDEV		;IF MORE THAN 6 CHARS, ITS BAD
	AOJN	M1,ILLDEV		;MUST BE NO WILD CHARACTERS
	SKIPE	STATIC+.FXDEV		;SKIP IFF 1ST DEVICE NAME SEEN
ILLDEV:	ERROR	<Illegal device>	;...THAT IS ALSO BAD
	MOVEM	T1,STATIC+.FXDEV	;SAVE DEVICE NAME
	MOVE	T1,[FX.NDV]
	ANDCAM	T1,.FXMOD(FP)
	JRST	FILIN1			;TRY TO GET ANOTHER FIELD

;HERE TO GET A FILE EXTENSION
FILIN4:	SKIPE	STATIC+.FXEXT		;SKIP IF NOT FILE TYPE SEEN BEFORE
ILLEXT:	ERROR	<Illegal extension>	;
	PUSHJ	P,SIXIN			;GET THE EXTENSION
	CAILE	T4,3			;NEVER MORE THAN 3 CHARACTERS
	JRST	ILLEXT			;COMPLAIN IF MORE THAN 3
	HLLZM	T1,STATIC+.FXEXT	;SAVE EXTENSION NAME
	HLRM	M1,STATIC+.FXEXT	;SAVE EXTENSION WILD INFO
	JRST	FILIN2			;GO GET ANOTHER FIELD
;HERE TO GET A FILE PATH/UIC
FILIN5:	MOVE	T1,[FX.DIR]		;GET THE DIRECTORY SEEN BIT
	TDNE	T1,STATIC+.FXMOD	;SKIP IF DIRECTORY NEVER SEEN
	JSP	U0,ILLPPN		;GO COMPLAIN IF MULTIPLE DIRECTORIES
	IORM	T1,STATIC+.FXMOD	;SET THE DIRECTORY SEEN BIT
	PUSHJ	P,OCTIN			;READ FIRST PART OF UIC/PPN
	SKIPE	M1			;* ?
	TDNN	T1,[-1,,400000]		;MUST NOT HAVE EXTRA BITS ON
	SKIPA				;SKIP IF NO EXTRA BITS
	JSP	U0,ILLPPN		;GO COMPLAIN IF EXTRA BITS
	HRLZM	T1,STATIC+.FXDIR	;STORE OCTAL PROJECT NUMBER
	HRLM	M1,STATIC+.FXDIM	;STORE PROJECT MASK

	CAIE	T3,","			;CHECK FOR LEGAL SEPERATOR
	JSP	U0,ILLPPN		;GO COMPLAIN IF , MISSING

	PUSHJ	P,OCTIN			;GET SECOND HALF OF UIC/PPN
	SKIPE	M1			; *?
	TLNN	T1,-1			;MUST NOT HAVE EXTRA BITS ON
	SKIPA				;SKIP IF NO EXTRA BITS
	JSP	U0,ILLPPN		;BRANCH IF MORE THAN 18 BITS OF USER #
	HRRM	T1,STATIC+.FXDIR	;STORE 2ND HALF OF PPN
	HRRM	M1,STATIC+.FXDIM	;SAVE 2ND HALF OF MASK

	MOVE	P1,[-5,,STATIC+.FXDIR+2];POINT AT SFD LIST
FILIN6:	SKIPGE	P1			;DON'T ZERO MEMORY OUTSIDE SFD LIST
	SETZM	(P1)			;MAKE SURE LIST ENDS IN 0
	CAIE	T3,","			;SFD PATH LIST COMING?
	  JRST	[CAIN T3,"]"
		 JRST FILIN1		;LOOP IF PPN LIST ENDED PROPERLY
		 TDO F,[X%REEAT]	;ELSE SETUP TO REEAT SEPERATOR
		 JRST FILIN1]		;...AND THEN LOOP
	PUSHJ	P,SIXIN			;GET A SFD NAME
	CAILE	T4,6			;SFD MUST BE 6 CHARACTERS OR LESS
	JSP	U0,ILLPPN		;GO COMPLAIN IF SFD NAME TOO BIG
	SKIPGE	P1			;DON'T SAVE SFD NAMES BEYOND LEGAL DEPTH
	MOVEM	T1,(P1)			;SAVE SFD NAME
	SKIPGE	P1			;DON'T SAVE SFD MASKS BEYOND LEGAL DEPTH
	MOVEM	M1,.FXDIM-.FXDIR(P1)	;SAVE SFD MASK
	AOBJN	P1,[AOJA P1,FILIN6]	;LOOP FOR MORE SFD NAMES
	JRST	FILIN6			;LOOP FOR MORE

;HERE IF PATH SPEC IS SCREWY, IF DEBUGGING LOOK AT U0 FOR CALLER'S ADDRESS
ILLPPN:	ERROR	<Illegal format for PPN or UIC>
;HERE TO READ IN PROTECTION FIELD
FILIN8:	PUSHJ	P,TYIUC			;GET NEXT CHARACTER
	CAIL	T3,"0"			;SKIP IF NOT NUMERIC PROTECTION
	CAILE	T3,"7"			;SKIP IF NUMERIC PROTECTION
	JRST	FIL8B			;GO READ RWED STYLE PROTECTION
	TDO	F,[X%REEAT]		;RE-EAT THE FIRST DIGIT
	PUSHJ	P,OCTIN			;GO GET THE NUMERIC PROTECTION CODE
	CAIN	T4,3			;MUST BE EXACTLY 3 DIGITS
	CAIE	T3,">"			;...AND MUST END WITH >
	ERROR	<Illegal character in protection field>
	AOJN	M1,.-1			;BRANCH IF USER SAID <???>
	LDB	T2,[POINTR(.FXMOD(FP),FX.PRO)]
	JUMPN	T2,[PUSHJ P,ILLCMD];BRANCH TO COMPLAIN IF NOT 1ST PROTECTION
	DPB	T1,[POINTR(.FXMOD(FP),FX.PRO)]	;INSERT THE PROTECTION INTO FDB
	JRST	FILIN1			;LOOP FOR REMAINDER OF SPEC

;HERE TO READ SYMBOLIC RWED PROTECTION CODE
FIL8B:	PUSHJ	P,PRTIN
	MOVEM	T1,V$FPRO(FP)
	JRST	FILIN1
;HERE TO READ IN SWITCH
FILIN9:	PUSHJ	P,SIXIN			;GET SWITCH NAME
	SKIPN	T2			;NOT MORE THAN 6 CHARS
	AOSE	M1			;SKIP IF NOT WILD
ILLSWT:	ERROR	<Illegal switch>
	PUSHJ	P,FNDIDX
	  CAI	SWTSIX
	JUMPL	T1,ILLSWT
	MOVE	T2,SWTBIT(T1)		;GET THE BIT
	IORM	T2,.FXSWT+STATIC
        CAIN    T3,":"                  ;ANY INDICATION WE SHOULD DO IT?
	PUSHJ	P,@SWTSRV(T1)		;GO SERVICE THE ARG, IF ANY
	JRST	FILIN2
;	SOME SWITCH TABLE DATA


DEFINE	S(.name,.serve),<SIXBIT @'.name'@>
SWTSIX:	SS
	0

DEFINE	S(.name,.serve<ILLSWT>),<EXP .serve>
SWTSRV:	SS

DEFINE	S(.name,.serve),<S$'.name'==.bit
			EXP S$'.name'
			.BIT==.BIT_-1>
.bit==1B0
SWTBIT:	SS
;	HERE TO READ A PDP11 PROTECTION CODE
PRTIN:	PUSHJ	P,SAVE2			;SAVE SOME ACS
	SETZ	P1,			;START OFF
	MOVEI	P2,4			;# OF GROUPS
NXTGRP:	LSH	P1,-4			;MAKE ROOM FOR NEXT GROUP
	TRO	P1,170000		;START OFF WITH EVERYTHING INHIBITED
	SOJL	P2,[ERROR <Too many protection groups>]
REDGRP:	PUSHJ	P,TYIUC
	CAIN	T3,","			;GROUP SEPERATOR?
	JRST	NXTGRP			;YES, START NEXT GROUP
	CAIN	T3,">"			;PROTECTION END?
	JRST	ENDPRO			;YES
	CAIN	T3,"R"			;
	HRROI	T3,10000
	CAIN	T3,"W"
	HRROI	T3,20000
	CAIN	T3,"E"
	HRROI	T3,40000
	CAIN	T3,"D"
	HRROI	T3,100000
	JUMPGE	T3,[ERROR <Illegal character in protection group>]
	TDZ	P1,T3			;TURN OFF INHIBIT BIT
	JRST	REDGRP

ENDPRO:	JUMPN	P2,[ERROR <Too few protection groups>]
	MOVE	T1,P1			;RETURN IT IN T1
	POPJ	P,

FPRTIN:	PUSHJ	P,PRTIN
	MOVEM	T1,V$FPRO(FP)
	POPJ	P,

VPRTIN:	PUSHJ	P,PRTIN
	MOVEM	T1,V$VPRO(FP)
	POPJ	P,
;	HERE TO READ /FILENUMBER:nnn SWITCH
FILEIN:	PUSHJ	P,DECIN		;GET FILE NUMBER
	SKIPLE	T1		;FILES -VE OR 0 NOT LEGAL
	CAIG	T1,4		;IN FACT, DON'T DELETE 0-4 EITHER
	JRST	ILLSWT
	CAIL	T1,200000	;AND DON'T ALLOW MORE THAN FILE #S
	JRST	ILLSWT
	MOVEM	T1,V$FILE(FP)	;SAVE FILE #
	POPJ	P,
;	HERE TO READ /ALLOC:nnn  SWITCH
ALCIN:	PUSHJ	P,DECIN		;GET SIZE
	CAIL	T1,177777	;PLEASE, NO MORE THAN POSSIBLE # FILES
	JRST	ILLSWT		;BAD VALUE
	MOVEM	T1,V$ALLOC(FP)	;SAVE VALUE
	POPJ	P,
;	HERE TO READ ARGUMENT FOR /EXTEND SWITCH
EXTDIN:	PUSHJ	P,DECIN
	CAILE	T1,0
	CAIL	T1,^D128
	JRST	ILLSWT
	MOVEM	T1,V$EXTE(FP)
	POPJ	P,
;	HERE TO READ ARGUMENT FOR /SIZE SWITCH
SIZIN:	PUSHJ	P,DECIN
	CAIGE	T1,400
	JRST	ILLSWT
	MOVEM	T1,V$SIZE(FP)
	POPJ	P,
;	HERE TO READ ARGUMENT FOR /MAXFIL
MAXFIN:	PUSHJ	P,DECIN
	CAIL	T1,5			;MUST BE AT LEAST 5 FILES!!
	CAILE	T1,177777		;AND CANNOT EXCEED FIELD SIZE!
	JRST	ILLSWT
	MOVEM	T1,V$MAXFIL(FP)
	POPJ	P,
;	HERE TO READ ARGUMENT FOR /INDEX
IDXIN:	PUSHJ	P,SIXIN
	PUSHJ	P,FNDIDX
	  CAI	IDXSIX
	JUMPL	T1,ILLSWT
	MOVE	T1,IDXSIX(T1)
	MOVEM	T1,V$INDEX(FP)
	CAME	T1,[SIXBIT .BLK.]
	POPJ	P,
	MOVE	T3,LASTCH
	CAIE	T3,":"
	JRST	ILLSWT
	PUSHJ	P,OCTIN
	AOJN	M1,ILLCHR
	JUMPE	T1,ILLCHR
	MOVEM	T1,IDXBLK
	POPJ	P,
IDXSIX:	'BEG   '
	'MID   '
	'END   '
	'BLK   '
	0
ILLCHR:	ERROR	<Illegal character>
ILLNUM:	ERROR	<Ilegal digit>
;	HERE TO READ ARG FOR /CHARACTERISTICS
CHAIN:	PUSHJ	P,SIXIN
	PUSHJ	P,FNDIDX
	  CAI	CHASIX
	JUMPL	T1,ILLSWT
	MOVE	T1,CHABIT(T1)
	IORM	T1,V$CHAR(FP)
	POPJ	P,

CHASIX:	'ATTACH'
	'DCFUNC'
	0
CHABIT:	20
	10
;	ROUTINE TO READ IN A SIXBIT STRING, UP TO 12 CHARACTERS
;
;	PUSHJ	P,SIXIN
;	<ALWAYS RETURN HERE,	T1/ 1ST 6 CHARACTERS OF STRING
;				T2/ 2ND 6 CHARACTERS OF STRING
;				M1/ 1ST 6 CHARACTERS OF MASK FOR STRING IN T1
;				M2/ 2ND 6 CHARACTERS OF MASK, FOR STRING IN T2
;				T3/ TERMINATING CHARACTER
;				T4/ COUNT OF ACTUAL CHARACTERS IN STRING>

SIXIN:	SETZB	T1,T2		;START OFF WITH NULL STRING
	SETOB	M1,M2		;START OFF WITH NO WILD CHARACTERS
	MOVE	U0,[POINT 6,T1]	;POINT AT TOP OF STRING
	SETZ	T4,		;ZERO COUNT OF CHARACTERS
SIXILP:	PUSHJ	P,TYIUC		;GET A CHARACTER, UPPER CASE ONLY
	CAIE	T3," "		;SKIP IFF CHARACTER IS A BLANK
	CAIN	T3,"	"	;SKIP IFF CHARACTER IS NOT BLANK OR TAB
	JUMPE	T4,SIXILP	;IGNORE LEADING BLANKS, TABS
	CAIN	T3,"?"		;WILD CARD?
	JRST	SIXIN2		;YES, SKIP LEGALITY CHECK
	CAIN	T3,"*"		;WILD CARD?
	JRST	SIXIN3		;YES, SKIP LEGALITY CHECK

	CAIL	T3,"0"		;SKIP IF OUT OF POSSIBLE SIXBIT RANGE
	CAILE	T3,"9"		;SKIP IFF IN RANGE OF SIXBIT DIGIT
	CAIL	T3,"A"		;SKIP IF OUT OF RANGE OF POSSIBLE SIXBIT
	CAILE	T3,"Z"		;SKIP IF IN RANGE OF SIXBIT DIGIT OR LETTER
	POPJ	P,0		;RETURN IF OUT OF SIXBIT RANGE

SIXIN2:	TRNE	T2,77		;SKIP IF STRING NOT YET FULLY FULL
	JRST	SIXILP		;BRANCH IF NO MORE ROOM, JUST EAT THIS CHARACTER
	SUBI	T3,40		;CONVERT CHARACTER TO SIXBIT
	IDPB	T3,U0		;INSERT THE CHARACTER
	CAIN	T3,'?'		;WILD CHARACTER?
	PUSHJ	P,[ADDI U0,M1-T1; POINT U0 AT THE PARALLEL MASK WORD
		   MOVEI T3,00	; GET THE VALUE FOR "WILD"
		   DPB  T3,U0	; STORE A WILD MARKER IN THE MASK WORD
		   SUBI U0,M1-T1; RE-POINT U0 BACK AT INPUT WORD
		   POPJ P,0]
	AOJA	T4,SIXILP	;AND COUNT IT
;HERE IF WE SEE A "*"
SIXIN3:	MOVEI	T3,^D9		;SAY WE GOT ALL 9 CHARACTERS
	CAILE	T4,^D9		;UNLESS THATS FALSE
	MOVEI	T3,^D12		;THEN SAY WE GOT 12
	SUB	T3,T4		;GET NUMBER REMAINING
	PUSH	P,T3		;SAVE COUNTER
SIXIN4:	SOSG	(P)		;COUNT IT
	JRST	SIXIN5
	MOVEI	T3,'?'
	IDPB	T3,U0		;STORE IT
	ADDI	U0,M1-T1
	MOVEI	T3,00
	DPB	T3,U0
	SUBI	U0,M1-T1
	JRST	SIXIN4		;DON'T COUNT THE "?"

SIXIN5:	POP	P,T3
	AOJA	T4,SIXILP	;COUNT ONE MORE CHARACTER
;	ROUTINE TO ACCEPT YES OR NO
YESNO:	PUSHJ	P,SKEOL		;GET RID OF TYPE AHEAD
YESNO1:	CLRBFI			;REALLY GET RID OF IT
	TYPE	<, YES or NO? >
	OUTPUT	TTY,
	PUSHJ	P,SIXIN		;READ RESPONSE
	AOJN	M1,ILLYES	;WILD CHARACTERS MEAN NO
	PUSHJ	P,TRMSKP	;MUST NOT BE GARBAGE ON THE LINE
ILLYES:	ERROR	<Abort via NO>
	CAME	T1,[SIXBIT .Y.]	;ACCEPT ONLY "Y"
	CAMN	T1,[SIXBIT .YES.];OR "YES"
	JRST	CPOPJ1
	CAMN	T1,[SIXBIT .YE.]
	JRST	YESNO1		;CONSIDER ACCEPTING "YE"
	JRST	ILLYES
SKEOL0:	PUSHJ	P,TYI		;GET ANOTHER CHARACTER
SKEOL:	PUSHJ	P,TRMSKP	;LAST CH AN EOL?
	JRST	SKEOL0		;NO, TRY NEXT ONE THEN
	POPJ	P,		;YES, JUST RETURN
;ROUTINE TO READ A DECIMAL NUMBER INTO T1, DIGIT COUNT INTO T2
DECIN:	SETZB	T1,T2
DECILP:	PUSHJ	P,TYI
	CAIL	T3,"0"
	CAILE	T3,"9"
	POPJ	P,0
	IMULI	T1,^D10
	ADDI	T1,-"0"(T3)
	AOJA	T2,DECILP
;	ROUTINE TO READ AN OCTAL NUMBER FROM THE KEYBOARD
;
;	PUSHJ	P,OCTIN
;	<ALWAYS RETURN HERE,	T1/	VALUE
;				M1/	MASK
;				T3/	TERMINATING CHARACTER
;				T4/	COUNT OF VALID DIGITS>
OCTIN:	SETZ	T1,
	SETO	M1,
	SETZ	T4,

OCTILP:	PUSHJ	P,TYI
	CAIN	T3,"?"
	JRST	OCTQST
	CAIN	T3,"*"
	JRST	OCTSTR
	CAIL	T3,"0"
	CAILE	T3,"7"
	POPJ	P,0
	CAIL	T4,6
	ERROR	<Illegal number>
	IMULI	T1,^O10
	IMULI	M1,^O10
	ADDI	T1,-"0"(T3)
	TRO	M1,7
	AOJA	T4,OCTILP

OCTQST:	CAILE	T4,6
	JRST	ILLNUM
	IMULI	T1,^O10
	IMULI	M1,^O10
	ADDI	T1,7
;	TRZ	M1,7
	AOJA	T4,OCTILP

OCTSTR:	JUMPN	T4,ILLCHR
	CAILE	T4,6
	JRST	ILLNUM
	SETO	T1,	;set #=all 7s
	SETZ	M1,	;set mask = all wild
	MOVEI	T4,6
	JRST	OCTILP
;ROUTINE TO SKIP IF LAST CHARACTER WAS A TERMINATOR
TRMSKP:	MOVE	T3,LASTCH
TRMSK0:	CAIE	T3,12
	CAIN	T3,13
	JRST	CPOPJ1
	CAIE	T3,14
	CAIN	T3,33
	JRST	CPOPJ1
	CAIN	T3,32
CPOPJ1:	AOS	(P)
CPOPJ:	POPJ	P,0
FNDIDX:	MOVE	U0,@(P)		;PICK UP THE CAIA
	PUSHJ	P,SAVE4		;SAVE SOME ACS
	MOVE	P3,U0		;MAKE A SAFER COPY
	SETZ	P4,		;NOTHING SEEN YET
FNDID1:	MOVE	P1,(U0)		;PICK UP A POSSIBLE
	JUMPE	P1,FNDID4	;DONE WITH POSSIILITIES LIST
	AND	P1,MASKS(T4)	;CHOP OFF EXCESS CHARACTERS
	CAME	P1,T1		;CHECK FOR MATCH
	AOJA	U0,FNDID1	;TRY FOR OTHER MATCHES

	JUMPN	P4,FNDID3	;BRANCH IF TOO MANY MATCHES
	MOVE	P4,U0		;REMEMBER MATCH POINTER FOR LATER
	AOJA	U0,FNDID1	;LOOP FOR MORE

FNDID3:	SETO	T1,		;MARK ILLEGAL
	POPJ	P,		;RETURN

FNDID4:	JUMPE	P4,FNDID5	;BRANCH IF NEVER FOUND ONE
	MOVE	T1,P4		;COPY MATCHING MARK
	SUB	T1,P3		;COMPUTE OFFSET
	POPJ	P,

FNDID5:	HRROI	T1,-2	;MARK NO MATCH
	POPJ	P,		;RETURN

MASKS:	0			;0
	770000,,000000		;1
	777700,,000000		;2
	777777,,000000		;3
	777777,,770000		;4
	777777,,777700		;5
	777777,,777777		;6
	SUBTTL	VARIOUS SAVING CO-ROUTINES

SAVFF:	PUSH	P,.JBFF##		;SAVE CURRENT CORE BOUNDS
	PUSHJ	P,@-1(P)		;CALL CALLER
	SKIPA
	AOS	-2(P)
	POP	P,.JBFF##		;RESTORE CORE BOUND POINTER
	PUSH	P,T1			;SAVE AN AC
	HRRZ	T1,.JBFF##		;GET UPPER LIMIT
	IORI	T1,777			;ROUND TO NEAREST PAGE
	CAMLE	T1,.JBREL##		;ALREADY BELOW THAT?
	CORE	T1,			;NO, SHRINK CORE
	JFCL
	POP	P,T1
	POP	P,(P)
	POPJ	P,			;RETURN TO CALLER'S CALLER

SAVE1:	PUSH	P,P1		;SAVE P1
	PUSHJ	P,@-1(P)		;CALL CALLER AS A SUBROUTINE
	SKIPA
	AOS	-2(P)		;PROPOGATE SKIP RETURN
	POP	P,P1
	POP	P,(P)		;WASTE CALLER'S ADDRESS
	POPJ	P,

SAVE2:	PUSH	P,P1		;SAVE P1
	PUSH	P,P2		;SAVE P2
	PUSHJ	P,@-2(P)	;CALL CALLER AS A SUBROUTINE
	SKIPA
	AOS	-3(P)		;PROPOGATE THE SKIP RETURN
	POP	P,P2
	POP	P,P1
	POP	P,(P)
	POPJ	P,

SAVE4:	PUSH	P,P1
	PUSH	P,P2
	PUSH	P,P3
	PUSH	P,P4
	PUSHJ	P,@-4(P)
	SKIPA
	AOS	-5(P)
	POP	P,P4
	POP	P,P3
	POP	P,P2
	POP	P,P1
	POP	P,(P)
	POPJ	P,
SAVFP:	PUSH	P,FP
	PUSHJ	P,@-1(P)
	SKIPA
	AOS	-2(P)
	POP	P,FP
	POP	P,(P)
	POPJ	P,
	SUBTTL	GETCOR

;	ROUTINE TO RETURN A NEWLY ALLOCATED CHUNK OF CORE

GETCOR:	PUSHJ	P,SAVE2		;SAVE SOME ACS
	MOVE	P1,.JBFF##	;PRESERVE ORIGINAL VALUE
	ADDB	T1,.JBFF##	;UPDATE TO NEWEST ADDRESS
	CAMG	T1,.JBREL##	;SKIP IF WE MUST EXPAND
	JRST	GETCO1		;BRANCH
	CORE	T1,		;EXPAND OUR IMAGE
	  ERROR	<CANNOT EXPAND CORE>
GETCO1:	MOVE	T1,P1		;GET RETURN VALUE
	POPJ	P,		;RETURN
	SUBTTL	DO THE GETTABS

DEFINE GET(.a,.b),<	MOVE	T1,[.a]
GETTAB T1,
SETZ T1,
MOVEM T1,.b>
DOGETS:	GET	%CNYER,LOCYER
	GET	%CNMON,LOCMON
	GET	%CNDAY,LOCDAY
	GET	%CNHOR,LOCHOR
	GET	%CNMIN,LOCMIN
	GET	%CNSEC,LOCSEC
	POPJ	P,0
;	ROUTINE TO POSITION DISK FOR I/O

SUSET:	SKIPE	FAKVOL
	JRST	LSUSET
	MOVEM	T1,LASSET
	TLO	T1,(<Z VIO,0>!SU.SOT)
	SUSET.	T1,
	  ERROR	<SUSET. failed>
	POPJ	P,0

LSUSET:	MOVEM	T1,LASSET
	ADD	T1,FAKOFS
	USETI	VIO,1(T1)
	STATZ	VIO,IO.IMP
	  ERROR	<USETI failed>
;	USETO	VIO,1(T1)
;	STATZ	VIO,IO.IMP
;	  ERROR	<USETO failed>
	  JFCL			;LET THIS GET CAUGHT WHEN WE TRY THE OUT UUO
	SUB	T1,FAKOFS
	POPJ	P,
;	ROUTINE TO TYPE A STRING
;
;	PUSHJ	P,TYPE..
;	  CAI	[asciz .string.]

TYPE..:	HRRZM	P,SAVEP		;SAVE P A SECOND
	PUSHJ	P,SAVE4		;GET SOME ACS
	MOVE	P1,SAVEP	;GET THE CAI INSTRUCTION
	MOVE	P1,@(P1)	;..
	HRLI	P1,(POINT 7,0)	;MAKE A BYTE POINTER
TYPE.1:	ILDB	T3,P1		;GET A BYTE
	JUMPE	T3,CPOPJ	;RETURN
	PUSHJ	P,TYO		;TYPE THE BYTE
	JRST	TYPE.1		;LOOP TILL END

;	ROUTINE TO TYPE A CHARACTER

TYO:	PUSH	P,T1
	MOVEI	T1,TTY
	DEVNAM	T1,
	JFCL
	AOJGE	T1,[POP P,T1
		OUTCHR T3
		POPJ P,]
	POP	P,T1
	SOSG	TTYOBF+.BFCTR	;ROOM?
	JRST	TYO2		;NO, MAKE ROOM
	PUSHJ	P,ADJCOL	;FIXUP THE COLUMN
	IDPB	T3,TTYOBF+.BFPTR;YES, PUT IN BYTE
	TDNE	F,[X%INT]	;INTERACTIVE DEVICE? (TTY:)
	CAIE	T3,12		;YES, AND LINE FEED?
	POPJ	P,		;RETURN
	OUT	TTY,		;OUTPUT BUFFER
	POPJ	P,0
	JRST	TYO3		;ERROR

TYO2:	OUT	TTY,		;WRITE OUT A BLOCK
	JRST	TYO
TYO3:	ERROR	<OUT failed to TTY:>

;	ROUTINE TO PUT A CHARACTER INTO THE OUTPUT FILE

PUTC:	JUMPE	T3,CPOPJ	;IGNORE NULLS
XPUTC:	SOSGE	DOBUF+.BFCTR	;ROOM?
	JRST	PUTC2		;NO, MAKE ROOM
	AOS	PUTCTR		;COUNT IT
	IDPB	T3,DOBUF+.BFPTR	;PUT IN BYTE
	POPJ	P,0

PUTC2:	OUT	FIO,
	JRST	PUTC		;RETY AGAIN
	ERROR	<OUT FAILED TO DISK>
;	ROUTINE TO ENSURE THE COLUME COUNTER IS ALWAYS CORRECT
;	LEFT MARGIN IS COLUMN 0, NOT COLUMN 1

ADJCOL:	JUMPE	T3,CPOPJ
	CAIN	T3,15			;CR?
	JRST	[SETZM COLUMN		;YES, WE'RE IN COLUM 0
		 POPJ P,]		;YES, WE'RE DONE
	CAIE	T3,14			;FF
	CAIN	T3,12			;OR LF?
	POPJ	P,			;YES, THAT DOESN'T CHANGE COLUME

	CAIE	T3,11			;TAB?
	JRST	[AOS COLUMN		;NO, BUMP COLUMN BY ONE
		 POPJ P,]		;THEN EXIT

	EXCH	T3,COLUMN		;EXCHANGE COLUMN
	TRO	T3,7
	ADDI	T3,1
	EXCH	T3,COLUMN
	POPJ	P,

;	ROUTINE TO MOVE THE CURSOR TO THE CORRECT COLUMN

MOVCOL:	PUSHJ	P,SAVE2			;SAVE SOME ACS
MOVCO1:	MOVE	P1,COLUMN		;GET CURRENT COLUMN
	TRO	P1,7
	ADDI	P1,1
	CAMG	P1,T1			;IF WE TABBED NOW, SKIP IF TOO MUCH
	JRST	[TYPE	<	>	;NO, SO DO THE TAB
		 JRST	MOVCO1]		;NO, SO TRY AGAIN AFTER TAB'ING

MOVCO2:	MOVE	P1,COLUMN		;GET CURRENT COLUMN
	CAML	P1,T1			;ARE WE FAR ENOUGH YET?
	POPJ	P,			;YES, WE'RE DONE
	TYPE	< >			;NO, MOVE ONE COLUMN RIGHT
	JRST	MOVCO2			;AND CHECK AGAIN
;	ROUTINE TO TYPE THE REVISION DTM

TYPRDT:	PUSHJ	P,SAVE1			;SAVE SOME ACS
	MOVE	P1,T1			;COPY
	SUBI	P1,FHBBUF
	IMULI	P1,4
	LOAD.	T1,RDAy,P1
	JUMPE	T1,CPOPJ
	MOVEi	T1,^D56
	PUSHJ	P,MOVCOL
	MOVE	T1,[XWD O.RVDT,A.RVDT]
	PUSHJ	P,TYPDAT
	TYPE	< >
	MOVE	T1,[XWD O.RVTI,A.RVTI]
	PJRST	TYPTIM

;	ROUTINE TO TYPE THE CREATION DTM

TYPCDT:	PUSHJ	P,SAVE1
	MOVE	P1,T1
	SUBI	P1,FHBBUF
	IMULI	P1,4
	LOAD.	T1,CDAy,P1
	JUMPE	T1,CPOPJ
	MOVEI	T1,^D40
	PUSHJ	P,MOVCOL
	MOVE	T1,[XWD O.CRDT,A.CRDT]
	PUSHJ	P,TYPDAT
	TYPE	< >
	MOVE	T1,[XWD O.CRTI,A.CRTI]
	PJRST	TYPTIM

;	ROUTINE TO TYPE THE EXPIRATION DTM

TYPXDT:	MOVE	P1,T1
	SUBI	P1,FHBBUF
	IMULI	P1,4
	LOAD.	T1,XDAy,p1
	JUMPE	T1,CPOPJ
	MOVEI	T1,^D72
	PUSHJ	P,MOVCOL
	MOVE	T1,[XWD O.EXDT,A.EXDT]
	PJRST	TYPDAT
;ROUTINE TO TYPE THE PDP11 DATE
;
;	CALL WITH T1/	PDP11 BYTE POINTER
;		  P1/	OFFSET POINTER AT BLOCK CONTAINING THE DATE
TYPDAT:	ADDI	T1,(P1)		;COMPUTE FINAL BYTE POINTER
	PUSHJ	P,GETBYT	;GET 1ST DIGIT OF "DD"
	ANDI	T3,177		;CONVERT TO PDP10
	CAIN	T3,"0"		;SKIP IF NOT A LEADING ZERO IN "DD"
	MOVEI	T3," "		;CONVERT LEADING ZERO TO A BLANK
	PUSHJ	P,TYO		;TYPE 1ST "D" OF "DD"

	PUSHJ	P,TYPBYT	;TYPE 2ND "D" OF "DD"

	TYPE	<->		;TYPE SEPERATOR TO HERALD THE MONTH
	PUSHJ	P,TYPBYT	;TYPE 1ST "M" OF "MMM"
	PUSHJ	P,GETBYT	;GET 2ND LETTER
	ANDI	T3,177		;TRIM TO 7 BIT ASCII
	CAIGE	T3,"a"		;SKIP IF LOWER CASE
	ADDI	T3,40		;CONVERT TO LOWER CASE IF UPPER
	PUSHJ	P,TYO		;TYPE 2ND "M" OF "MMM"
	PUSHJ	P,GETBYT	;GET 3RD "M" OF "MMM"
	ANDI	T3,177		;TRIM TO 7 BIT ASCII
	CAIGE	T3,"a"		;SKIP IF ALREADY LOWER CASE
	ADDI	T3,40		;CONVERT TO LOWER CASE
	PUSHJ	P,TYO		;TYPE 3RD "M" OF "MMM"
	TYPE	<->		;TYPE SEPERATOR FOR YEAR

	PUSHJ	P,TYPBYT	;GET AND TYPE 1ST "Y" OF "YY"
	PJRST	TYPBYT		;GET AND TYPE 2ND "Y" OF "YY"
;ROUTINE TO TYPE PDP11 TIME
;
;	CALL WITH T1/	PDP11 BYTE POINTER
;		  P1/	OFFSET INTO CORRECT BLOCK WITH TIME
TYPTIM:	ADDI	T1,(P1)		;COMPUTE FINAL ADDRESS OF STRING
	PUSHJ	P,TYPTI2	;GO TYPE 2 DIGITS OF TIME
	TYPE	<:>		;SEPERATE

;ROUTINE TO TYPE 2 DIGITS FROM PDP11 BYTE POINTER
TYPTI2:	PUSHJ	P,TYPBYT	;GET AND TYPE A DIGIT

;ROUTINE TO GET AND TYPE A PDP11 BYTE
TYPBYT:	PUSHJ	P,GETBYT	;GET THE BYTE TO TYPE
	JRST	TYO		;TYPE IT
;	ROUTINE TO READ A PDP11 TIME AND LOAD T1=PDP10 "MINUTES PAST MIDNITE"
;
;	T1/	PDP11 BYTE POINTER
;	T2/	FHB TO READ FROM
REDTIM:	PUSHJ	P,SAVE4			;SAVE SOME ACS
	DMOVE	P1,T1			;COPY THE INPUT ARGS
	SUBI	P2,FHBBUF		;RELOCATE
	ADD	T1,P2			;...THE BYTE POINTER

	PUSHJ	P,GETBYT		;GET 1ST DIGIT OF HOURS
	CAIN	T3," "			;IF IT IS A LEADING BLANK
	MOVEI	T3,"0"			;...CONVERT TO LEADING 0
	MOVEI	P4,-"0"(T3)		;P4=1ST DIGIT OF HOUR
	PUSHJ	P,GETBYT		;GET 2ND DIGIT OF HOURS
	IMULI	P4,^D10
	ADDI	P4,-"0"(T3)		;NOW P4=HOURS
	IMULI	P4,^D60			;NOW P4=MINS IN THE HOURS PAST MIDNITE

	PUSHJ	P,GETBYT		;GET 1ST DIGIT OF MINUTES
	MOVEI	P3,-"0"(T3)		;CONVERT TO A NUMBER
	PUSHJ	P,GETBYT		;GET 2ND DIGIT OF MINUTES
	IMULI	P3,^D10			;MAKE ROOM FOR 2ND DIGIT
	ADDI	P3,-"0"(T3)		;COMBINE TO MAKE ACTUAL 2 DIGIT NUMBER
	MOVE	T1,P4			;COPY NUMBER OF MINS TO T1
	ADD	T1,P3			;ADD IN HOUR'S MINUTES
	POPJ	P,
;	ROUTINE TO STORE A PDP11 TIME FIELD INTO FHB FROM T1/PDP10 MINUTES PAST MIDNITE
;
;	T1/	PDP11 BYTE POINTER
;	T2/	FHB TO STORE INTO
;	T3/	MINUTES PAST MIDNITE

STOTIM:	PUSHJ	P,SAVE4			;SAVE SOME ACS
	DMOVE	P1,T1			;COPY THE INPUT ARGS
	MOVE	P3,T3			;COPY...

	SUBI	T2,FHBBUF		;OFFSET THE FHB BUFFER
	ADD	T1,T2			;COMPUTE ACTUAL FIELD'S BYTE POINTER

	IDIVI	P3,^D60			;NOW P3=HOURS, P4=MINUTES

	MOVE	T3,P3			;COPY HOURS
	IDIVI	T3,^D10			;SEPERATE INTO DIGITS
	MOVEI	T3,"0"(T3)		;CONVERT TO ASCII
	CAIN	T3,"0"			;SKIP IF 1ST DIGIT IS NOT A LEADING ZERO
	MOVEI	T3," "			;CONVERT LEADING ZERO INTO A BLANK
	PUSHJ	P,PUTBYT		;INSERT LEADING DIGIT
	MOVEI	T3,"0"(T4)		;T3=REMAINDER'S DIGIT IN ASCII
	PUSHJ	P,PUTBYT		;INSERT TRAILING DIGIT

	MOVE	T3,P4			;COPY T3=MINUTES
	IDIVI	T3,^D10			;NOW T3=10'S, T4=1'S OF MINUTES
	MOVEI	T3,"0"(T3)		;CONVERT 10'S TO ASCII DIGIT
	PUSHJ	P,PUTBYT		;INSERT 1ST DIGIT OF MINUTES
	MOVEI	T3,"0"(T4)		;ASCII-IZE 2ND DIGIT
	PUSHJ	P,PUTBYT		;INSERT 2ND DIGIT OF MINUTES

	MOVEI	T3,"0"			;GET AN ASCII ZERO
	PUSHJ	P,PUTBYT		;SIMPLIFY LIFE BY CLAIMING SECONDS=00
	PUSHJ	P,PUTBYT		;...SO INSERT 2 ASCII 0'S
	POPJ	P,
;	ROUTINE TO READ A PDP11 DATE AND LOAD T1=15 BIT PDP10 DATE
;
;	T1/	PDP11 BYTE POINTER
;	T2/	FHB TO READ FROM
REDDAT:	PUSHJ	P,SAVE4			;SAVE SOME ACS
	DMOVE	P1,T1			;COPY THE INPUT ARGS
	ADDI	T1,-FHBBUF(P2)
	SETZ	P4,			;P4=TEMP FOR GETTING DATE

	PUSHJ	P,GETBYT		;GET A BYTE
	CAIN	T3," "			;IS IT A LEADING BLANK?
	MOVEI	T3,"0"			;YES, CHANGE IT TO A LEADING 0
	MOVEI	P4,-"0"(T3)		;GET 10'S DIGIT OF DAY IN MONTH

	PUSHJ	P,GETBYT		;GET 2ND DIGIT OF DATE
	IMULI	P4,^D10
	ADDI	P4,-"0"(T3)		;NOW, P4=DD OF DDMMMYY


	PUSHJ	P,GETBYT		;GET 1ST LETTER OF MONTH
	HRLZ	P3,T3			;INSERT 1ST LETTER
	PUSHJ	P,GETBYT		;GET 2ND LETTER OF MONTH
	CAIL	T3,"a"			;IS IT ALREADY LOWER CASE?
	CAILE	T3,"z"			;??
	ADDI	T3,"a"-"A"		;NO, SO LOWER CASE IT FOR COMPARES
	DPB	T3,[POINT 8,P3,9]	;INSERT 2ND LETTER

	PUSHJ	P,GETBYT		;GET 3RD LETTER OF MONTH
	CAIL	T3,"a"			;IS IT ALREADY LOWER CASE?
	CAILE	T3,"z"			;??
	ADDI	T3,"a"-"A"		;NO, SO MAKE IT LOWER CASE
	HRRI	P3,(T3)			;AND INSERT IT

	PUSHJ	P,GETBYT		;GET 1ST BYTE OF YEAR
	MOVEI	P2,-"0"(T3)		;PUT 1ST BYTE INTO P2
	PUSHJ	P,GETBYT		;GET 2ND BYTE OF YEAR
	IMULI	P2,^D10			;
	ADDI	P2,-"0"(T3)		;P2=LAST 2 DIGITS OF YEAR

	MOVSI	P1,^D-12		;AOBJN INTO LEGAL MONTHS TABLE
	CAME	P3,MONTAB(P1)		;SKIP IF WE FOUND IT
	AOBJN	P1,.-1			;KEEP LOOKING
	JUMPGE	P1,[TYPE <% Illegal month in input string
>
		setz t1,
		popj p,]

	MOVEI	T1,^D1900-^D1964(P2)	;GET THE YEAR IN DESIRED FORMAT
	IMULI	T1,^D12
	ADDI	T1,(P1)			;ADD MONTH-1
	IMULI	T1,^D31			;
	ADDI	T1,-1(P4)
	POPJ	P,
;	ROUTINE TO STORE A 15 BIT PDP10 DATE IN (T3) INTO A PDP11 ASCII FIELD
;
;	T1/	PDP11 BYTE POINTER
;	T2/	FHB TO STORE INTO
;	T3/	15 BIT DATE
STODAT:	PUSHJ	P,SAVE4
	DMOVE	P1,T1			;COPY T1, T2
	DMOVE	P3,T3			;COPY T3, T4

	SUBI	P2,FHBBUF		;COMPUTE OFFSET INTO REAL FHB
	ADD	T1,P2			;COMPUTE FINAL BYTE POINTER

	MOVE	P2,P3			;COPY DATE INTO BETTER AC
	IDIVI	P2,^D31			;GET P2=YEAR,MONTH, P3=DAY-1
	ADDI	P3,1			;COMPUTE P3=DAY+0
	IDIVI	P3,^D10			;P3=1ST DIGIT IN DAY, P4=2ND DIGIT

	MOVEI	T3,"0"(P3)		;GET FIRST DIGIT
	CAIN	T3,"0"			;
	MOVEI	T3," "			;CONVERT 1ST DIGIT TO BLANK IF 0
	PUSHJ	P,PUTBYT		;STORE IT
	MOVEI	T3,"0"(P4)		;COPY 2ND DIGIT
	PUSHJ	P,PUTBYT		;STORE 2ND DIGIT

	IDIVI	P2,^D12			;P2=YEAR, P3=MONTH#

	LDB	T3,[POINT 8,MONTAB(P3),17];GET 1ST LETTER OF MONTH
	PUSHJ	P,PUTBYT		;STORE 1ST LETTER
	LDB	T3,[POINT 8,MONTAB(P3),9];GET 2ND LETTER OF MONTH
	PUSHJ	P,PUTBYT		;STORE 2ND LETTER
	HRRZ	T3,MONTAB(P3)		;GET 3RD LETTER
	PUSHJ	P,PUTBYT		;STORE 3RD LETTER

	ADDI	P2,^D1964-^D1900
	IDIVI	P2,^D10
	MOVEI	T3,"0"(P2)
	PUSHJ	P,PUTBYT
	MOVEI	T3,"0"(P3)
	PUSHJ	P,PUTBYT
	POPJ	P,
;	ROUTINE TO MOVE A PDP11 FIELD
;
;	JSP	U0,MOV..
;	  CAI	ORIGIN FIELD, ALWAYS JUSTIFIED "NORMALLY"
;	  CAI	DESTINATION BASE ADDRESS
;	  CAI	#PDP11 BYTES OFFSET FROM DESTINATION BASE
;	  CAI	#BYTES IN FIELD TO MOVE
;	  CAI	ADDRESS OF AN ADDITIONAL OFFSET

MOV..:	PUSHJ	P,SAVACS		;SAVE THE ACS
	MOVE	P1,0(U0)		;PICK UP ADDRESS OF ORIGIN FIELD
	TLZ	P1,777000		;TURN OF CAI
	TLO	P1,(MOVEI P1,0)		;TURN ON MOVEI
	MOVEM	P1,P1XCT		;SAVE IT
	MOVE	P1,SAVAC0+P1		;RESTORE ORIGINAL P1
	XCT	P1XCT			;LOAD THE ADDRESS INTO P1
	CAIG	P1,17			;ORIGIN IN THE ACS?
	ADDI	P1,SAVAC0		;YES, POINT AT SAVED COPY
	HRRZ	P2,2(U0)		;GET # OF BYTES
	DMOVEM	P1,MOV.P1		;SAVE P1, P2
	DMOVE	P1,SAVAC0+P1		;RESTORE P1, P2
	PUSH	P,@4(U0)		;SAVE ADDITIONAL BYTES ON STACK
	DMOVE	P1,MOV.P1		;GET BACK P1, P2
	POP	P,MOV.P1		;GET BACK ADDITIONAL BYTES
	ADD	P2,MOV.P1		;ADD IN ADDITIONAL BYTES
	HRLZS	P2			;PUT INTO LH HALF
	HRR	P2,1(U0)		;INSERT ADDRESS OF DESTINATION FIELD
	HRRZ	T1,1(u0)		;GET DESTINATION BASE
	CAIG	T1,17
	ADDI	P2,SAVAC0		;RELOCATE IT IF IN THE ACS
	HRRZ	P3,3(U0)		;P3=# OF BYTES TO MOVE
				;P2=POINTER TO DESTINATION BYTE
				;P1=POINTER TO ORIGIN BYTE

MOV.1:	MOVE	T1,P1		;COPY BYTE POINTER
	PUSHJ	P,GETBYT	;GET A BYTE @P1
	MOVEM	T1,P1		;PUT BYTE POINTER BACK
	MOVE	T1,P2		;GET BYTE POINTER
	PUSHJ	P,PUTBYT	;PUT A BYTE @P2
	MOVEM	T1,P2		;PUT BYTE POINTER BACK
	SOJG	P3,MOV.1	;LOOP FOR ALL BYTES TO BE MOVED

	PUSHJ	P,RESACS		;RESTORE ACS
	POPJ	P,0
;	ROUTINE TO STORE A PDP10 FORMATTED FIELD INTO A PDP11 FIELD
;
;	JSP	U0,STOR..
;	CAI	ORIGIN VALUE
;	CAI	DESTINATION BASE ADDRESS
;	CAI	#PDP11 BYTES OFFSET FROM DESTINATION BASE
;	CAI	#BYTES IN FIELD TO MOVE
;	CAI	ADDRESS OF ADDITION OFFSET

STOR..:	PUSHJ	P,SAVACS		;SAVE THE ACS
	MOVE	T3,@0(U0)		;PICK UP VALUE TO STORE
	HRRZ	T1,2(U0)		;GET # OF BYTES IN OFFSET
	ADD	T1,@4(U0)		;ADD ADDITIONAL BYTES
	MOVSI	T1,(T1)			;FORM PDP11 BYTE POINTER
	HRR	T1,1(U0)		;INSERT BASE ADDRESS
	HRRZ	T2,1(u0)		;GET BASE DESTINATION
	CAIG	T2,17
	ADDI	T1,SAVAC0		;RELOCATE IT IN GOING TO ACS
	HRRZ	P3,3(U0)		;GET SIZE OF FIELD

STOR.1:	PUSHJ	P,PUTBYT		;STORE A BYTE
	LSH	T3,-^D8			;POSITION TO NEXT BYTE
	SOJG	P3,STOR.1		;LOOP TILL PDP10 FIELD COPIED
	PUSHJ	P,RESACS		;RESTORE ACS
	POPJ	P,0			;DONE
;	ROUTINE TO GET A PDP11 BYTE
;ENTER:	T1/ PDP11 BYTE POINTER
;EXIT:	T1/ UPDATED PDP11 BYTE POINTER, T3=FETCHED BYTE
GETBYT:	PUSHJ	P,SAVE2			;SAVE SOME ACS
	HLRZ	P1,T1			;GET ONLY THE OFFSET PORTION
	IDIVI	P1,4			;CONVERT TO WORD#, BYTE#
	ADDI	P1,(T1)			;ADD IN THE BASE ADDRESS
	LDB	T3,[POINT 8,(P1),17
		    POINT 8,(P1),9
		    POINT 8,(P1),35
		    POINT 8,(P1),27](P2)
	ADD	T1,[1,,0]		;STEP TO NEXT BYTE
	POPJ	P,		;RETURN
;	ROUTINE TO STORE A PDP11 BYTE
;ENTER:	T1/ PDP11 BYTE POINTER,	T3/ BYTE TO STORE
;EXIT:	T1/ UPDATED BYTE POINTER
PUTBYT:	PUSHJ	P,SAVE2			;SAVE SOME ACS
	HLRZ	P1,T1			;COPY THE OFFSET
	IDIVI	P1,4		;CONVERT TO WORD#, BYTE#
	ADDI	P1,(T1)			;ADD IN BASE ADDRESS
	DPB	T3,[POINT 8,(P1),17
		    POINT 8,(P1),9
		    POINT 8,(P1),35
		    POINT 8,(P1),27](P2)
	ADD	T1,[1,,0]		;UPDATE POINTER
	POPJ	P,		;RETURN
;	ROUTINE TO XFER A PDP11 FORMATTED FIELD TO A PDP10 FIELD
;
;	PUSHJ	P,[JSP U0,LOAD..
;			CAI ORIGIN
;			CAI A.DEST
;			CAI O.DEST
;			CAI S.DEST
;			CAI OFFSET

LOAD..:	PUSHJ	P,SAVACS		;SAVE THE ACS
	HRRZ	T1,@4(U0)		;GET ADDITIONAL OFFSET FIRST
	ADD	T1,2(U0)		;ADD IN BASE OFFSET
	MOVSI	T1,(T1)			;CREATE PDP11 BYTE POINTER
	HRR	T1,1(U0)		;INSERT ADDRESS
	SETZ	P2,			;START PDP10 FIELD OFF AT ZEROES

	HRRZ	P3,3(U0)		;GET LENGTH OF XFER IN BYTES

LOAD.1:	LSH	P2,-^D8			;MAKE ROOM FOR ANOTHER
	PUSHJ	P,GETBYT		;GET A PDP11 BYTE
	DPB	T3,[POINT 8,P2,7]	;MERGE WITH PDP10 DATA
	SOJG	P3,LOAD.1		;LOOP FOR ALL BYTES

	HRRZ	P3,3(U0)		;GET SIZE OF FIELD IN BYTES
	MOVN	P3,[0
			^D36-^D8
			^D36-^D16
			^D36-^D24
			^D36-^D32](P3)
	LSH	P2,(P3)			;RIGHT JUSTIFY IT
	MOVEI	T1,@0(u0)		;COMPUTE DESTINATION ADDRESS
	CAIG	T1,17
	ADDI	T1,SAVAC0
	MOVEM	P2,(T1)			;STORE FIELD
	PUSHJ	P,RESACS		;RESTORE THE ACS
	POPJ	P,			;RETURN
;	ROUTINE TO SAVE THE ACS

SAVACS:	MOVEM	17,SAVAC0+17
	MOVEI	17,SAVAC0
	BLT	17,SAVAC0+16
	MOVE	17,SAVAC0+17
	POPJ	P,

RESACS:	MOVEM	P,SAVEP
	MOVSI	17,SAVAC0
	BLT	17,17
	MOVE	P,SAVEp
	POPJ	P,
	SUBTTL	IMPURE
	RELOC	LOWSEG		;LOWSEG


TMPOFF: BLOCK   1       ;
LASSET:	BLOCK	1	;LAST BLOCK NUMBER SUSET'D TO
REQALC:	BLOCK	1	;REQUIRED ALLOCATION DURING A CREATE
FAKVOL:	BLOCK	1	;FLAG THAT WE'RE REFERENCING A LOGICAL VOLUME
FAKOFS:	BLOCK	1
VOLTBL:	BLOCK	VOLMAX	;NAME TABLE
DEFINE VF(A),<VOLF'A:BLOCK .FXLEN>
A==0
XLIST	;THE VOLUME FDB'S
REPEAT VOLMAX,<
	VF \A
	A==A+1>
LIST
CLUSIZ:	BLOCK	1	;CLUSTER SIZE
HIHIGH:	BLOCK	1
LASTHI:	BLOCK	1
PFLAG:	BLOCK	1
BYTNUM:	BLOCK	1	;USED TO EXTRACT BYTES DURING BOOT COMMAND
BOTCNT:	block	1	;BYTE COUNT USED DURING BOOT COMMAND
BOTPTR:	block	1	;BYTE POINTER USED DURING BOOT COMMAND
BOTDAT:	block	200	;BUFFER USED DURING BOOT COMMAND
BOTBLK==20		;ALLOW BOOT TO WRITE ONTO BLOCKS 0-17
BOTBUF:	BLOCK	BOTBLK*200
CHKVAL:	BLOCK	1	;CHECKSUM VALUE DURING BOOT COMMAND
LBC:	BLOCK	1	;BYTE COUNT FROM BIN FILE RECORD

LINNUM:	BLOCK	1	;LINE NUMBER ON A LINE FROM LINE NUMBERED FILE
BLKCNT:	BLOCK	1	;
LINBUF:	BLOCK	1000	;BUFFER FOR A LINE FROM FILE
FHBFOO:	BLOCK	1
FPCOPY:	BLOCK	1
IDXBLK:	BLOCK	1	;USED BY /INDEX:BLK:NNN
LOWZRO:	BLOCK	1	;VALUE IN LOWSEG GUARENTEED TO BE 0
MOV.P1::BLOCK	2	;2 TEMPS USED BY MOV..
P1XCT:	BLOCK	1	;TEMP USED BY MOV.., STOR.., ETC...
.MYPPN::BLOCK	0	;MAKE PPN AVAILABLE TO SCAN
MYPPN::	BLOCK	1	;LOGGED IN PPN
FPWILD:	BLOCK	1	;USED BY WILD TO REMEMBER CONTEXT ACROSS CALLS
IPLIST:	BLOCK	1	;POINTER TO LIST OF INPUT FILES
IPLAST:	BLOCK	1	;POINTER TO PREVIOUS INPUT FILE
CCLFLG::BLOCK	1	;0 IF NO CCL ENTRY, -1 IF CCL'ED
RSXPTR:	BLOCK	1	;GETTER/PUTTER FOR DEALING WITH 20F FILES
RSXVBN:	BLOCK	1	;BLOCK# INSIDE 20F FILE (IE: "USETI" VALUE)
FFBYTE:	BLOCK	1	;BYTE WHICH IS THE "FIRST FREE" (IE: THE EOF BYTE)
RSXCTR:	BLOCK	1	;GETTER COUNT/PUTTER COUNT FOR DEALING WITH 20F FILES
PUTCTR:	BLOCK	1	;...
SAVEP:	BLOCK	1
SAVAC0:	BLOCK	20
COLUMN:	BLOCK	1
PTHLEN==20
PTHBLK:	BLOCK	PTHLEN
UFDNUM:	BLOCK	1
UFDNAM:	BLOCK	1
UFDOLD:	BLOCK	1
STATIC:	BLOCK	.FXLEN
OUTFDB:	BLOCK	.FXLEN
INPFDB:	BLOCK	.FXLEN
TMPFDB:	BLOCK	.FXLEN
DELFDB:	BLOCK	.FXLEN
UFDFDB:	BLOCK	.FXLEN
FAKFDB:	BLOCK	.FXLEN
NULFDB:	BLOCK	.FXLEN
DEFFDB:	BLOCK	.FXLEN

;
;	** FHBBUF MUST FALL PHYSICALLY BEFORE ANY OTHER BUFFER
;	** WHICH GETS USED TO HOLD AN FHB, OTHERWISE THE LOAD./STORE.
;	** MACROS WILL NOT WORK WITH THE "ADDITIONAL OFFSET" OPTION
FHBBUF:	BLOCK	200


OPNBLK:	BLOCK	4
LERBLK:	BLOCK	200	;L/E/R BLOCK
BMBUF:	BLOCK	200	;SBM BM BUFFER (IE: FUNNY SAB BLOCK)
FSTLBN:	BLOCK	1	;1ST BLOCK OF DATA IN FE.SYS
LSTLBN:	BLOCK	1	;LAST BLOCK OF DATA IN FE.SYS
LASTCH:	BLOCK	1
FEUNIT:	BLOCK	1
DSKBLK:	BLOCK	.DCUPN+1

H11LBN:	BLOCK	1	;DISK ADDRESS OF HOME BLOCK
H11BUF:	BLOCK	200
BUF111:	BLOCK	200			;COPY OF FHB FOR INDEXF
BUF444:	BLOCK	200			;COPY OF FHB FOR 000000.DIR

PLEN=100
PSTAK:	BLOCk	PLEN

IBMSIZ:	BLOCK	1	;SIZE OF INCORE INDEX-BIT-MAP
IBMINC:	BLOCK	1	;INCORE ADDRESS OF INDEX-BIT-MAP
IBMLBN:	BLOCK	1	;INDEX-BIT-MAP DISK ADDRESS
FHBLBN:	BLOCK	1	;WHERE THE INDEX LIST STARTS

SBMSIZ:	BLOCK	1	;SIZE OF INCORE STORAGE-BIT-MAP
SBMINC:	BLOCK	1	;INCORE ADDRESS OF STORAGE-BIT-MAP
SBMLBN:	BLOCK	1	;STORAGE-BIT-MAP DISK ADDRESS

FFBLOK:	BLOCK	1	;NEXT FREE BLOCK IN ORDER

TMPBUF:	BLOCK	200

HOME1:	BLOCK	200
HOME2:	BLOCK	200

LOCYER:	BLOCK	1
LOCMON:	BLOCK	1
LOCDAY:	BLOCK	1
LOCHOR:	BLOCK	1
LOCMIN:	BLOCK	1
LOCSEC:	BLOCK	1

MFDDAT:	BLOCK	200

MFDLBN:	BLOCK	1

FHBTAL:	BLOCK	1
VOLTAL:	BLOCK	1

BIG:	BLOCK	1	;SIZE OF BIGGEST SBM CHUNK
BIGP1:	BLOCK	1	;PART OF ADDRESS OF BIGGEST SBM CHUNK
BIGP2:	BLOCK	1	;2ND PART OF ADRESS OF BIGGEST SBM CHUNK

BEST:	BLOCK	1	;SIZE OF "BEST" SBM CHUNK
BESTP1:	BLOCK	1	;PART OF ADDRESS OF BEST SBM CHUNK
BESTP2:	BLOCK	1	;2ND PART OF ADDRESS

;WILD CARD STUFF
WDICNT:	BLOCK	1			;# RECORDS LEFT IN THIS BLOCK
WDIBNO:	BLOCK	1			;RELATIVE BLOK# READING DIRECTORY FILE
WDIPBN:	BLOCK	1			;PHYSICAL BLOK# FOR WDIBNO
WDIBUF:	BLOCK	200			;WILD DIRECTORY BUFFER HOLDS DIR BLOCK
WDIFHB:	BLOCK	200			;WILD DIRECTORY FHB - FHB OF DIR FILE
WDIOFF:	BLOCK	1			;OFFSET

MASCNT:	BLOCK	1			;# RECORDS LEFT IN THIS MFD BLOCK
MASBNO:	BLOCK	1			;MFD RELATIVE BLOK#
MASBUF:	BLOCK	200			;MFD BLOCK BUFFER
MASOFF:	BLOCK	1			;OFFSET

FILCNT:	BLOCK	1
FILMAT:	BLOCK	1
DIRMAT:	BLOCK	1
DIRCNT:	BLOCK	1

DIBUF:	BLOCK	3
DOBUF:	BLOCK	3
TTYOBF:	BLOCK	3
CMDIDX:	BLOCK	1	;INDEX OF THIS COMMAND


DELBUF:	BLOCK	200
UFDFHB:	BLOCK	200
BLKBFR:	BLOCK	200
	SUBTTL	PURE
	RELOC	;BACK TO HISEG

;	TABLE OF MONTH NAMES IN PDP11 ASCII, INDEXED BY MONTH NUMBER, 0=JAN, ETC
MONTAB:	.ASCII	<Jan>
	.ASCII	<Feb>
	.ASCII	<Mar>
	.ASCII	<Apr>
	.ASCII	<May>
	.ASCII	<Jun>
	.ASCII	<Jul>
	.ASCII	<Aug>
	.ASCII	<Sep>
	.ASCII	<Oct>
	.ASCII	<Nov>
	.ASCII	<Dec>

;	INDEX THIS TABLE BY "BIT NUMBER" AND YOU GET THE APROPRIATE MASK
B32TBL:	BLOCK	0
.VAL=1B18
REPEAT	^D16,<EXP <.VAL=<.VAL*2>>>
.VAL=1B18
REPEAT	^D16,<EXP <.VAL=<.VAL*2>>_-^D18>

;	THIS (TEMPORARILY) CONTAINS THE VOLUME NAME, OWNER, AND TYPE FIELDS
;	WHICH GETS COPIED INTO THE FILES-11 HOME BLOCK
tmp166:	20040,,20040
	20040,,20040
	20040,,20040	;volume name is 12 blanks

	30133,,30460
	30054,,30460
	20135,,20040	;owner name is [000,000]

	42504,,43103
	46111,,30505
	40461,,20040	;format type is "DECFILE11A  "

;	TABLE INDEXED BY RAD50 VALUE TO GIVE SIXBIT VALUE
R2STBL:	BLOCK	50			;50 SLOTS
DEFINE	R2S(.arg),<IRPC .arg,<
				RELOC $R.'.arg'+R2STBL
				EXP ''.arg''
				RELOC R2STBL+50>>
R2S	<ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 $.>

;	TABLE	INDEXED BY SIXBIT VALUE TO GIVE RAD50 VALUE
S2RTBL:	BLOCK	100			;64 SLOTS
DEFINE	S2R(.arg),<IRPC .arg,<
				RELOC S2RTBL+''.arg''
				EXP	$R.'.arg'
				RELOC S2RTBL+100>>
S2R	<0123456789 $. ABCDEFGHIJKLMNOPQRSTUVWXYZ>


DEFINE VF(A),<EXP VOLF'A>
VOLPTR:
	A==0
REPEAT	VOLMAX,<
	VF	\A
	A==A+1
>
LIT..:	BLOCK	0
	XLIST
	LIT
	VAR
	LIST
	END	F11