Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_SRC_3_19910112 - stanford/5-swskit/dirpnt.mac
There are 6 other files named dirpnt.mac in the archive. Click here to see a list.
;<TOMCZAK.EXEC>DIRPNT.MAC.5, 30-Jan-80 15:12:30, EDIT BY TOMCZAK
;Be able to print variable size FDBs
;<TOMCZAK.EXEC>DIRPNT.MAC.4, 29-Jan-80 14:49:48, EDIT BY TOMCZAK
;Reset the PDL on each command parse (or else PDL overflow!!)
;<TOMCZAK.EXEC>DIRPNT.MAC.3, 29-Jan-80 14:48:45, EDIT BY TOMCZAK
;Fix "?JFN already open" error when doing a reparse
;<TOMCZAK.EXEC>DIRPNT.MAC.2, 29-Jan-80 14:46:47, EDIT BY TOMCZAK
;UPDATES FOR V4 STUFF (EXTENDED FDBS AND DIRECTORY HEADERS)
;<V-SOURCES>DIRPNT.MAC.4, 14-Jun-79 10:28:13, EDIT BY HELLIWELL
;INCREASE SIZES OF FDB AND SYMBOL AREAS
TITLE DIRPNT - TOPS20 DIRECTORY PRINTER
SUBTTL		D. KIRSCHEN		3-3-75

;	ACCUMULATOR DEFINITIONS
;	=========== ===========

	T1=	1	;JSYS ARGUMENT AC 1
	T2=	2	;JSYS ARGUMENT AC 2
	T3=	3	;JSYS ARGUMENT AC 3
	T4=	4	;JSYS ARGUMENT AC 4
	A1=	5	;TEMPORARY AC 1
	A2=	6	;TEMPORARY AC 2
	A3=	7	;TEMPORARY AC 3
	A4=	10	;TEMPORARY AC 4
	I1=	11	;INDEX/COUNTER 1
	I2=	12	;INDEX/COUNTER 2
	FB=	13	;BASE ADDRESS OF FDB
	P1=	14	;PRESERVED AC 1
	P2=	15	;PRESERVED AC 2
	MA=	16	;MAPPING ADDRESS
	P=	17	;PUSH-DOWN POINTER

	.DIRECTIVE FLBLST
	SALL

	.REQUIRE SYS:MACREL, SYS:MONSYM
	SEARCH MACSYM, MONSYM

; VERSION NUMBERS

	VMAJOR==14		;MAJOR VERSION
	VMINOR==0		;MINOR VERSION
	VWHO==0			;WHO LAST EDITED (0=DEC DEVELOPMENT)
	VEDIT==100		;EDIT NUMBER

	VDIRPT== <VWHO>B2+<VMAJOR>B11+<VMINOR>B17+VEDIT

; MISCELLANEOUS SYMBOL DEFINITIONS

GENDEL=="."		;GENERATION DELIMITER
SDIRCH=="."		;SUBDIRECTORY DELIMITER CHARACTER
NCHPW==5		;NUMBER OF ASCII CHARACTERS PER WORD
BUFSIZ==200		;SIZE OF INPUT TEXT BUFFER
ATMSIZ==BUFSIZ		;SIZE OF ATOM BUFFER FOR COMND JSYS
GJFSIZ==.GJBFP+1	;SIZE OF GTJFN BLOCK USED BY COMND JSYS
PDLSIZ== 50		;PUSH-DOWN LIST SIZE
PRIMRY== .PRIIN,,.PRIOU	;PRIMARY JFN'S
DIRORG== 200		;PAGE WHERE DIRECTORY IS MAPPED
DIRADR== DIRORG*1000	;ADDRESS WHERE DIRECTORY IS MAPPED
PAGSIZ== 1000		;SIZE OF A PAGE
FDBPGS== 200		;# OF PAGES TO MAP FDB'S INTO
STBPGS== 40		;# OF PAGES TO MAP SYMBOL TABLE INTO
MAXREP== ^D72		;MAXIMUM OF 72 CHARS IN REPLIES
REPSIZ== MAXREP/5+1	;SIZE OF USER'S REPLY BUFFER
MAXPRT== ^D20		;MAX # OF WORDS TO PRINT IN WEIRD BLKS
HDRCOL==^D30		;COLUMN NUMBER FOR DESCRIPTIVE HEADER TEXTS
OLDV1==31		;LENGTH OF OLD V1 FDBS
SUBTTL	MACRO DEFINITIONS

; FUNCTION DESCRIPTOR BLOCK FOR COMND JSYS

DEFINE CMFDB (TYPE,FLAGS,DATA,HELP,DEFLT,LST)
<	..XX== < FLD(TYPE,CM%FNC) + FLAGS + LST >
  IFNB <HELP>,< ..XX== ..XX+CM%HPP >
  IFNB <DEFLT>,< ..XX== ..XX+CM%DPP >
	..XX
  IFNB <DATA>,<DATA>
  IFB <DATA>,<0>
  IFNB <HELP>, <POINT 7,[ASCIZ\HELP\] >
  IFB <HELP>,  <0>
  IFNB <DEFLT>, <POINT 7,[ASCIZ/DEFLT/] >
  IFB <DEFLT>, <0>
>

DEFINE TXT(TEXT) <POINT 7,[ASCIZ\TEXT\]>
SUBTTL	SYMBOL AND DATA STRUCTURE DEFINITIONS

; BLOCK TYPE DEFINITIONS

.TYNAM== 400001		;NAME BLOCK
.TYEXT== 400002		;EXTENSION BLOCK
.TYACT== 400003		;ACCOUNT BLOCK
.TYUNS== 400004		;USER NAME STRING
.TYFDB== 400100		;FILE DESCRIPTOR BLOCK
.TYLAC== 400200		;LEGAL ACCOUNT BLOCK
.TYDIR== 400300		;DIRECTORY PAGE
.TYSYM== 400400		;SYMBOL TABLE
.TYFRE== 400500		;FREE BLOCK
.TYFBT== 400600		;FREE STORAGE BIT TABLE
.TYGDB== 400700		;GROUP DESCRIPTOR BLOCK


; SYMBOL TABLE ENTRY TYPES

.STNAM== 0		;FILE NAME ENTRY, POINTER IS TO FDB
.STUNS== 2		;USER NAME STRING
.STACT== 4		;ACCOUNT ENTRY, POINTER IS TO ACT BLOCK
.STMSK== 7B2		;MASK FOR SYMBOL TABLE ENTRY TYPE
.STPTR== 77777,,-1	;MASK FOR SYMBOL TABLE ENTRY POINTER


STHSIZ== 2		;SIZE OF SYMBOL TABLE HEADER
STESIZ== 2		;SIZE OF SYMBOL TABLE ENTRIES

; STRUCTURE DEFINITION FOR FIRST PAGE OF DIRECTORY

DEFSTR (DRTYP,DIRPG0+00,17,18)	;DIRECTORY BLOCK TYPE (.TYDIR)
DEFSTR (DRLHD,DIRPG0+00,35,12)	;LENGTH OF HEADER
DEFSTR (DRPAG,DIRPG0+01,17,18)	;PAGE # WITHIN DIRECTORY
DEFSTR (DRNUM,DIRPG0+01,35,18)	;DIRECTORY NUMBER
DEFSTR (DRFFB,DIRPG0+02,35,36)	;POINTER TO FIRST FREE BLOCK
DEFSTR (DRBOT,DIRPG0+03,35,36)	;START ADDRESS OF SYMBOL TABLE
DEFSTR (DRTOP,DIRPG0+04,35,36)	;ADDRESS OF END OF SYMBOL TABLE
DEFSTR (DRFRE,DIRPG0+05,35,36)	;LAST ADR USED FOR FDB'S
DEFSTR (DRFBT,DIRPG0+06,35,36)	;POINTER TO FREE POOL BIT TABLE
DEFSTR (DRDPW,DIRPG0+07,35,36)	;DEFAULT FILE PROTECTION WORD
DEFSTR (DRPRT,DIRPG0+10,35,36)	;DIRECTORY PROTECTION
DEFSTR (DRDBK,DIRPG0+11,35,36)	;BACKUP SPECIFICATION
DEFSTR (DRLIQ,DIRPG0+12,35,36)	;MAX LOGGED-IN DISK ALLOCATION
DEFSTR (DRLOQ,DIRPG0+13,35,36)	;MAX LOGGED-OUT ALLOCATION
DEFSTR (DRCUR,DIRPG0+14,35,36)	;CURRENT DISK ALLOCATION
DEFSTR (DRNAM,DIRPG0+15,35,36)	;POINTER TO NAME STRING
DEFSTR (DRPSW,DIRPG0+16,35,36)	;POINTER TO PASSWORD STRING
DEFSTR (DRCAP,DIRPG0+17,35,36)	;PRIVILEGE BITS
DEFSTR (DRMOD,DIRPG0+20,35,36)	;MODE BITS
DEFSTR (DRDAT,DIRPG0+21,35,36)	;DATE AND TIME OF LAST LOGIN
DEFSTR (DRUGR,DIRPG0+22,35,36)	;GROUPS THIS USER BELONGS TO
DEFSTR (DIRGRP,DIRPG0+23,35,36)	;DIRECTORY GROUPS
DEFSTR (DRUDT,DIRPG0+24,35,36)	;LAST UPDATE DATE AND TIME
DEFSTR (DRSDC,DIRPG0+25,35,18)	;SUBDIRECTORY COUNT
DEFSTR (DRSDM,DIRPG0+25,17,18)	;MAX ALLOWABLE SUBDIRECTORIES
DEFSTR (DRCUG,DIRPG0+26,35,36)	;ALLOWABLE SUBDIRECTORY USER GROUPS
DEFSTR (DRACT,DIRPG0+27,35,36)	;POINTER TO DEFAULT DIRECTORY ACCOUNT
DEFSTR (DRDNE,DIRPG0+30,35,36)  ;DEFAULT ONLINE EXPIRATION DATE/INTERVAL
DEFSTR (DRDFE,DIRPG0+31,35,36)  ;DEFAULT OFFLINE EXPIRATION DATE/INTERVAL
; OFFSETS TO VALUES AT BEGINNING OF EACH DIRECTORY PAGE

.DIDPC== 0	;DIRECTORY PAGE CODE (.TYDIR)
.DITDN== 0	;THIS DIRECTORY NUMBER
.DIRPN== 1	;RELATIVE PAGE # WITHIN DIRECTORY
.DILHD== 1	;LENGTH OF HEADER AREA FOR THIS PAGE
.DIFFB== 2	;POINTER TO FIRST FREE BLOCK

; OFFSETS TO VALUES IN FREE BLOCK HEADERS

.FRTYP== 0	;BLOCK TYPE (.TYFRE)
.FRLEN== 0	;LENGTH OF BLOCK
.FRPTR== 1	;POINTER TO NEXT BLOCK ON FREE LIST

; OFFSETS TO VALUES IN THE NAME BLOCK

.NBTYP== 0	;BLOCK TYPE (.TYNAM)
.NBLEN== 0	;LENGTH OF BLOCK
.NBPTR== 1	;POINTER TO ASCIZ NAME STRING


; OFFSETS TO VALUES IN THE EXTENSION BLOCK


.EBTYP== 0	;BLOCK TYPE (.TYEXT)
.EBLEN== 0	;LENGTH OF BLOCK
.EBPTR== 1	;POINTER TO ASCIZ EXTENSION STRING


; OFFSETS TO VALUES IN THE ACCOUNT BLOCK


.ABTYP== 0	;TYPE OF BLOCK (.TYACT)
.ABLEN== 0	;LENGTH OF BLOCK
.ABCNT== 1	;SHARE COUNT
.ABPTR== 2	;POINTER TO ACCOUNT STRING

; OFFSETS TO VALUES IN USER NAME STRING BLOCKS

.UNTYP== 0	;TYPE OF BLOCK (.TYUNS)
.UNLEN== 0	;LENGTH OF BLOCK
.UNCNT==1	;USE COUNT
.UNPTR== 2	;OFFSET TO USER NAME STRING

; FIELDS IN BLOCK HEADERS

BT%TYP==-1,,0		;MASK FOR BLOCK TYPE FIELD
BT%VER==770000		;MASK FOR VERSION OF DIRECTORY BLOCKS
BT%LEN==7777		;MASK FOR LENGTH OF DIRECTORY BLOCKS
SUBTTL	MACRO DEFINITIONS


	DEFINE A.STR (STRING)
<	MOVE T1,TXTPTR
	XLIST
	HRROI T2,[ASCIZ/STRING/]
	SETZM T3
	SOUT
	MOVEM T1,TXTPTR
	LIST
>

	DEFINE ALIGN (COUNT)
<	MOVX T1,COUNT
	XLIST
	CALL LINEUP
	MOVE T1,[POINT 7,TEXT]
	MOVEM T1,TXTPTR
	LIST
>

	DEFINE O.STR (STRING)
<	MOVE T1,OUTJFN
	XLIST
	HRROI T2,[ASCIZ\STRING\]
	SETZM T3
	SOUT
	LIST
>


	DEFINE A.OCT (NUM)
<	MOVE T1,TXTPTR
	XLIST
	MOVE T2,NUM
	MOVEI T3,10
	NOUT
	 CALL PUTERR
	MOVEM T1,TXTPTR
	LIST
>

	DEFINE O.OCT(NUM)
<	MOVE T1,OUTJFN
	XLIST
	MOVE T2,NUM
	MOVEI T3,10
	NOUT
	  CALL PUTERR
	LIST
>
	DEFINE 	A.OCTM (NUM)
<	MOVE T1,TXTPTR
	XLIST
	MOVE T2,NUM
	MOVE T3,[1B0+10]
	NOUT
	 CALL PUTERR
	MOVEM T1,TXTPTR
	LIST
>


	DEFINE O.OCTM (NUM)
<	MOVE T1,OUTJFN
	XLIST
	MOVE T2,NUM
	MOVE T3,[1B0+10]
	NOUT
	  CALL PUTERR
	LIST
>


	DEFINE O.DEC (NUM)
<	MOVE T1,OUTJFN
	XLIST
	MOVE T2,NUM
	MOVEI T3,^D10
	NOUT
	  CALL PUTERR
	MOVEI T2,"."
	BOUT
	 ERCAL PUTERR
	LIST
>

;	DEFINE ASMBL.DEC (NUM)
;<	MOVE T1,TXTPTR
;	XLIST
;	MOVE T2,NUM
;	MOVEI T3,^D10
;	NOUT
;	 ERCAL PUTERR
;	MOVEM T1,TXTPTR
;	LIST
;>

	DEFINE O.CRLF
<	MOVE T1,OUTJFN
	XLIST
	MOVEI T2,.CHCRT
	BOUT
	MOVEI T2,.CHLFD
	BOUT
	LIST
>
	DEFINE MAPTST (ADR)
<	MOVE MA,ADR
	XLIST
	CAML MA,MAPBOT
	CAMLE MA,MAPTOP
	CALL MAPDIR
	LIST
>


	DEFINE GETMPW (AC,LOC)
<	MAPTST LOC
	XLIST
	HRRZ AC,MA
	ADD AC,FDBOFS
	MOVE AC,(AC)
	LIST
>


	DEFINE GETSYM (AC,LOC)
<	HRRZ AC,LOC
	XLIST
	ADD AC,STBOFS
	MOVE AC,(AC)
	LIST
>


	DEFINE PUTSYM (AC,LOC)
<	HRRZ AC,LOC
	XLIST
	ADD AC,STBOFS
	MOVEM AC,(AC)
	LIST
>
	DEFINE TLOAD (AC,LOC,ADR)
<	MOVE MA,LOC
	XLIST
	CAML MA,MAPBOT
	CAMLE MA,MAPTOP
	CALL MAPDIR
	LOAD AC,LOC,ADR
	LIST
>
	DEFINE CRLF
<	MOVEI T1,.CHCRT
	XLIST
	PBOUT
	MOVEI T1,.CHLFD
	PBOUT
	LIST
>

	DEFINE SAY (STRING)
<	HRROI T1,[ASCIZ\STRING\]
	XLIST
	MOVEM T1,LASTQ
	PSOUT
	LIST
>

	DEFINE SAYCR (STRING)
<	HRROI T1,[ASCIZ\STRING
\]
	XLIST
	MOVEM T1,LASTQ
	PSOUT
	LIST
>


	DEFINE PUTOCT
<	MOVEI	T1, 101
	XLIST
	MOVE	T3, [1B0+^D8]
	NOUT
	  CALL	PUTERR
	LIST
>


	DEFINE CHEK (AC,ADR,LOC)
<	SKIPGE ADR
IFB <LOC>,<RET>
IFNB <LOC>,<JRST LOC>
	LOAD AC,DRTOP
	CAMGE AC,ADR
IFB <LOC>,<RET>
IFNB <LOC>,<JRST LOC>
>
SUBTTL	MAIN ENTRY POINT AND INITIALIZATION

START:	RESET			;CLEAR THE UNIVERSE
	MOVE P,PDP		;SET UP STACK
	CALL CHKCAP		;GO CHECK CAPABILITIES
	MOVE T1,[POINT 7,TEXT]	;GET POINTER TO TEXT ASSEMBLY AREA
	MOVEM T1,TXTPTR		;SAVE FOR A.STR MACRO
	MOVEI A1,.PRIOU		;GET DEFAULT OUTPUT JFN
	MOVEM A1,OUTJFN		;SAVE OUTPUT JFN
	GJINF			;GET CONNECTED DIRECTORY NUMBER
	MOVEM T2,CURDIR		;SAVE DIRECTORY NUMBER
	HRROI T1,REPLY		;GET POINTER TO DIRECTORY NAME
	DIRST			;GET STRING FOR DIRECTORY NAME
	 JSERR			;UNEXPECTED ERROR
	MOVE T1,[POINT 7,REPLY]	;GET POINTER TO STR:<DIR> STRING
	MOVE T2,CURDIR		;GET DIRECTORY NUMBER
	CALL GTFILE		;SET UP TO DUMP CONNECTED DIRECTORY
	 JRST [	CALL TSTCOL	;FAILED, ISSUE NEW LINE IF NEEDED
		TMSG <% DIRPNT: Could not default to connected directory
>
		JRST CMSET ]	;CONTINUE

CMSET:	HRROI T1,PROMPT		;GET POINTER TO PROMPT STRING
	MOVEM T1,CMDBLK+.CMRTY	;PUT RE-TYPE PROMPT POINTER IN STATE BLOCK
	HRROI T1,BUFFER		;GET POINTER TO INPUT TEXT BUFFER
	MOVEM T1,CMDBLK+.CMPTR	;SAVE POINTER TO COMMAND STRING
	MOVEM T1,CMDBLK+.CMBFP	;SAVE POINTER TO START-OF-BUFFER
	MOVE T1,[.PRIIN,,.PRIOU] ;GET PRIMARY INPUT,, OUTPUT JFN'S
	MOVEM T1,CMDBLK+.CMIOJ	;SAVE PRIMARY JFN'S
	MOVEI T1,PARSE1		;GET RE-PARSE ADDRESS
	MOVEM T1,CMDBLK+.CMFLG	;SAVE RE-PARSE ADDRESS
	SETOM CMDBLK+.CMINC	;INITIALIZE # OF CHARACTERS AFTER POINTER
	MOVEI T1,BUFSIZ*NCHPW	;GET # OF CHARACTERS IN BUFFER AREA
	MOVEM T1,CMDBLK+.CMCNT	;SAVE INITIAL # OF FREE CHARACTER POSITIONS
	HRROI T1,ATMBFR		;GET POINTER TO ATOM BUFFER
	MOVEM T1,CMDBLK+.CMABP	;SAVE POINTER TO LAST ATOM INPUT
	MOVEI T1,ATMSIZ*NCHPW	;GET # OF CHARACTERS IN ATOM BUFFER
	MOVEM T1,CMDBLK+.CMABC	;SAVE COUNT OF SPACE LEFT IN ATOM BUFFER
SUBTTL	COMMAND PARSER AND DISPATCH

PARSE:	SETOM LSTFLG		;INITIALIZE LIST COMMAND SEEN FLAG
	SETOM SYMLST		;ASSUME NO SYMBOL TABLE LISTING
	SETOM FDBLST		;ASSUME NO LISTING OF A SINGLE FDB
	SETOM DIRLST		;ASSUME NO LISTING OF ENTIRE DIRECTORY
	SETOM CHNLST		;ASSUME NO LISTING OF FDB CHAINS
	SETOM HDRLST		;ASSUME THAT NO HEADER LISTING DESIRED
	MOVEI T1,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI T2,[CMFDB (.CMINI)] ;GET FUNCTION DESCRIPTOR BLOCK
	COMND			;INITIALIZE COMMAND SCANNER JSYS

PARSE1:	MOVE P,PDP		;RESET THE STACK
	MOVE T1,[JFNBLK,,JFNBLK+1] ;SET UP TO CLEAR GTJFN BLOCK
	SETZM JFNBLK		;CLEAR FIRST WORD OF BLOCK
	BLT T1,JFNBLK+GJFSIZ-1	;CLEAR GTJFN BLOCK

	MOVEI T1,JFNBLK		;GET ADDRESS OF GTJFN BLOCK
	MOVEM T1,CMDBLK+.CMGJB	;STORE POINTER TO GTJFN BLOCK
	MOVEI T1,CMDBLK		;GET POINTER TO COMMAND STATE BLOCK
	MOVEI T2,[CMFDB (.CMKEY,,CMDTAB)] ;GET FUNCTION BLOCK
	COMND			;DO INITIAL PARSE
	TXNN T1,CM%NOP		;VALID COMMAND ENTERED ?
	JRST PARSE5		;YES, GO DISPATCH TO PROCESSING ROUTINE
	CALL TSTCOL		;TEST COLUMN POSITION, NEW LINE IF NEEDED
	TMSG <? DIRPNT: No such DIRPNT command as ">
	MOVE T1,CMDBLK+.CMABP	;GET POINTER TO ATOM BUFFER
	PSOUT			;OUTPUT STRING ENTERED BY USER
	TMSG <"
>				;OUTPUT END-OF-MESSAGE
	JRST PARSE		;GO TRY TO GET A COMMAND AGAIN

PARSE5:	HRRZ T1,(T2)		;GET DISPATCH ADDRESS
	CALL (T1)		;PERFORM REQUESTED FUNCTION
	JRST PARSE		;GO PARSE NEXT COMMAND
SUBTTL	DUMP COMMAND

.DUMP:	STKVAR <DMPCMD>		;ALLOCATE SPACE FOR THING TO DUMP
	MOVEI T1,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI T2,[CMFDB (.CMKEY,,LSTTAB,,ENTIRE-DIRECTORY)] ;GET KEYWORD TABLE
	COMND			;PARSE NOISE PHRASE
	TXNN T1,CM%NOP		;VALID ARGUMENT ENTERED ?
	JRST DUMP10		;YES, GO SAVE IT AND GET CONFIRMATION
	CALL TSTCOL		;NO, ISSUE CRLF IF NEEDED
	TMSG <
? DIRPNT: Invalid argument ">	;ISSUE FIRST PART OF MESSAGE
	HRROI T1,ATMBFR		;GET POINTER TO TEXT ENTERED
	PSOUT			;OUTPUT TEXT ENTERED
	TMSG <"
>				;OUTPUT END OF MESSAGE
	RET			;RETURN

DUMP10:	MOVEM T2,DMPCMD		;SAVE DESIRED THING TO DUMP
	MOVE T2,DMPCMD		;GET THING TO DUMP
	HRRZ T1,(T2)		;GET FLAG ADDRESS
	CAIN T1,FDBLST		;LISTING OF AN FDB DESIRED ?
	JRST DUMP50		;YES, GO GET THE FDB ADDRESS
DUMP20:	MOVEI T1,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI T2,[CMFDB (.CMCFM)] ;GET CONFIRM FUNCTION
	COMND			;GET CONFIRMATION
	TXNE T1,CM%NOP		;END-OF-COMMAND SEEN OK ?
	CALLRET COMER1		;NO, ISSUE MESSAGE AND RETURN
	MOVE T1,DIRJFN		;GET DIRECTORY FILE JFN
	MOVX T2,<FLD(^D36,OF%BSZ)+OF%RD+OF%THW>
	OPENF			;OPEN THE FILE
	 JSERR			;UNEXPECTED ERROR
	MOVE T1,OUTJFN		;GET OUTPUT JFN
	MOVE T2,[070000,,OF%WR]	;ASCII TEXT, OUTPUT ACCESS
	OPENF			;OPEN THE OUTPUT FILE
	 JRST [	CALL TSTCOL	;UNEXPECTED ERROR, ISSUE NEW LINE IF NEEDED
		TMSG <? DIRPNT: Cannot open output file, >
		CALL PUTERR	;ISSUE JSYS MESSAGE
		MOVE T1,DIRJFN	;GET JFN OF DIRECTORY FILE
		CLOSF		;CLOSE THE FILE
		 JSERR		;UNEXPECTED ERROR
		RET ]		;RETURN
	CALL MAPDP0		;GO MAP FIRST PAGE OF DIRECTORY
	CALL MAPSTB		;GO MAP IN THE SYMBOL TABLE
	MOVEI MA,0		;GET AN ADDRESS TO MAP
	CALL MAPDIR		;GO MAP SOMETHING TO START
	MOVE T1,OUTJFN		;GET OUTPUT JFN
	MOVEI T2,.CHFFD		;GET A FORM FEED
	BOUT			;OUTPUT STARTING ON NEW PAGE
	O.STR (<
Dump of Directory >)		;output first part of title
	MOVE T1,OUTJFN		;GET OUTPUT JFN
	MOVE T2,CURDIR		;GET DIRECTORY NUMBER
	DIRST			;OUTPUT DIRECTORY STRING
	 JRST [	O.STR <[*** UNKNOWN DIRECTORY NAME ***]>
		JRST .+1 ]	;TRY TO RECOVER
	O.STR (<, # >)		;OUTPUT NEXT PART OF TITLE
	HRRZ A1,CURDIR		;GET RIGHT HALF OF DIRECTORY NUMBER
	O.OCT A1		;OUTPUT THE DIRECTORY #
	O.STR < at >		;OUTPUT NEXT PART OF TITLE
	MOVE T1,OUTJFN		;GET THE OUTPUT JFN
	SETOM T2		;USE CURRENT DATE AND TIME
	SETZM T3		;USE STANDARD FORMAT
	ODTIM			;OUTPUT THE DATE AND TIME
	O.CRLF			;NEW LINE
	O.CRLF			;LEAVE A BLANK LINE
; HERE TO DETERMINE WHICH PART(S) OF DIRECTORY TO DUMP

	MOVE T1,DMPCMD		;GET DESIRED ENTITY
	HRRZ T1,(T1)		;GET ADDRESS OF FLAG WORD TO SET
	CAIE T1,FDBLST		;LISTING AN FDB ?
	SETZM (T1)		;NO, MARK ENTITY TO BE DUMPED

; NOW DO THE DUMPING

	SKIPE HDRLST		;LISTING OF DIRECTORY HEADER WANTED ?
	SKIPL DIRLST		;OR ENTIRE DIRECTORY ?
	CALL DP0PNT		;YES, OUTPUT DIRECTORY HEADER
	SKIPL DIRLST		;LINEAR DIRECTORY LISTING WANTED ?
	CALL DIRPNT		;YES, GO PRINT DIRECTORY
	SKIPL CHNLST		;CHAINED LISTING WANTED ?
	CALL CHNDIR		;YES, GO OUTPUT CHAINED FDB'S
	SKIPE SYMLST		;SYMBOL TABLE LISTING WANTED ?
	SKIPL DIRLST		;OR ENTIRE DIRECTORY ?
	CALL SYMPRT		;YES, GO PRINT SYMBOL TABLE
	SKIPG FDBLST		;FDB LISTING WANTED ?
	JRST DUMP80		;NO, GO ON
	MOVE FB,FDBLST		;GET ADDRESS OF FDB TO LIST
	ADD FB,FDBOFS		;ADD OFFSET TO FDB IN CORE
	CALL FDBPRT		;YES, GO OUTPUT FDB
	O.CRLF			;OUTPUT ANOTHER CRLF

DUMP80:	SETOM T1		;INDICATE PAGES ARE TO BE REMOVED
	MOVE T2,[.FHSLF,,DIRPG0_-^D9] ;REMOVE DIRECTORY HEADER PAGE
	SETZM T3		;ONLY ONE PAGE
	PMAP			;REMOVE THE PAGE
	MOVE T2,[.FHSLF,,SYMTAB_-^D9] ;SYMBOL TABLE PAGES
	MOVX T3,PM%CNT+STBPGS	;ITERATE OVER ALL PAGES
	PMAP			;REMOVE ALL SYMBOL TABLE PAGES
	MOVE T2,[.FHSLF,,MAPPGS_-^D9] ;DIRECTORY PAGES
	MOVX T3,PM%CNT+FDBPGS	;ITERATE OVER ALL PAGES
	PMAP			;REMOVE ALL DIRECTORY PAGES
	HRRZ T1,DIRJFN		;GET DIRECTORY FILE JFN
	TXO T1,CO%NRJ		;DO NOT RELEASE THE JFN
	CLOSF			;CLOSE THE FILE
	 JSERR			;UNEXPECTED ERROR
	HRRZ T1,OUTJFN		;GET OUTPUT JFN
	TXO T1,CO%NRJ		;KEEP THE JFN
	CLOSF			;CLOSE THE OUTPUT FILE
	 JSERR			;UNEXPECTED ERROR
	RET			;RETURN TO COMMAND PARSER
; HERE TO GET THE ADDRESS OF THE FDB TO PRINT

DUMP50:	MOVEI T1,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI T2,[CMFDB (.CMNOI,,<TXT(AT)>)] ;GET DESCRIPTOR BLOCK
	COMND			;PARSE NOISE WORD
	MOVEI T2,[CMFDB (.CMNUM,,^D8)] ;GET DESCRIPTOR BLOCK
	COMND			;PARSE ADDRESS
	TXNN T1,CM%NOP		;VALID ADDRESS ENTERED ?
	JRST DUMP55		;YES, GO ON
	CALL TSTCOL		;NO, ISSUE CRLF IF NEEDED
	TMSG <? DIRPNT: Invalid FDB address
>				;OUTPUT REMAINDER OF MESSAGE
	RET			;RETURN

DUMP55:	MOVEM T2,FDBLST		;SAVE ADDRESS OF FDB TO LIST
	JRST DUMP20		;GO CHECK FOR END-OF-COMMAND AND CONTINUE
; DP0PNT - ROUTINE TO OUTPUT DIRECTORY PAGE 0 HEADER INFO.
;
; CALL:		CALL DP0PNT
;		RETURN


DP0PNT:	O.CRLF
	MOVE I1,DIRPG0		;GET BASE ADR OF PAGE 0
	A.STR <DRTYP:  >	;FIRST WORD DESCRIPTION
	MOVE T2,DIRPG0		;GET FIRST WORD OF HEADER
	MOVE T3,[1B0+10]	;PRINT MAGNITUDE, OCTAL
	CALL ASMHLF		;ASSEMBLE TWO HALFWORDS
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Directory Block Type - Version - and Length
>
	A.STR <DRRPN:  >	;DESCRIPTION FOR WORD 2
	MOVE T2,DIRPG0+1	;GET SECOND WORD OF HEADER
	MOVE T3,[1B0+10]	;PRINT MAGNITUDE, OCTAL
	CALL ASMHLF		;OUTPUT TWO HALFWORDS
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Relative Page Number - Directory Number
>
	A.STR <DRFFB:  >	;FIRST FREE BLOCK
	LOAD A1,DRFFB		;GET ADR OF FIRST FREE BLOCK
	A.OCT A1		;OUTPUT THE ADDRESS
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <First Free Block on this page
>
	A.STR <DRSTB:  >	;SYMBOL TABLE BOTTOM
	LOAD A1,DRBOT		;GET ADDRESS
	A.OCT A1		;OUTPUT THE ADDRESS
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Bottom of Symbol Table
>
	A.STR <DRSTP:  >	;SYMBOL TABLE TOP
	LOAD A1,DRTOP		;GET TOP OF TABLE
	A.OCT A1		;OUTPUT ADDRESS
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Top of Symbol Table
>
	A.STR <DRFTP:  >	;LAST WORD FOR BLOCKS
	LOAD A1,DRFRE		;GET ADDRESS
	A.OCT A1		;OUTPUT ADDRESS
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Last used word + 1
>
	A.STR <DRFBT:  >	;FREE BLOCK BIT TABLE
	LOAD A1,DRFBT		;GET ADDRESS
	A.OCT A1		;OUTPUT THE ADDRESS
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Free Pool Bit Table
>
	A.STR <DRDPW:  >	;DEFAULT PROTECTION
	LOAD T2,DRDPW		;GET DEFAULT PROTECTION
	MOVE T3,[1B0+10]
	CALL ASMHLF
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Default File Protection
>
	A.STR <DRPRT:  >	;DIRECTORY PROTECTION
	LOAD T2,DRPRT		;GET PROTECTION
	MOVE T3,[1B0+10]
	CALL ASMHLF
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Default Directory Protection
>
	A.STR <DRDBK:  >	;BACKUP SPEC
	LOAD T2,DRDBK		;GET BACKUP SPEC
	MOVE T3,[1B0+10]
	CALL ASMHLF
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Retention Count
>
	A.STR <DRLIQ:  >	;LOGGED IN QUOTA
	LOAD A1,DRLIQ		;GET LOGGED-IN QUOTA
	A.OCTM A1		;OUTPUT QUOTA
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Working Storage Quota
>
	A.STR <DRLOQ:  >	;LOGGED OUT QUOTA
	LOAD A1,DRLOQ		;GET LOGGED-OUT QUOTA
	A.OCTM A1		;OUTPUT QUOTA
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Permanent Storage Quota
>
	A.STR <DRDCA:  >	;CURRENT ALLOCATION
	LOAD A1,DRCUR		;GET ALLOCATION
	A.OCTM A1		;OUTPUT ALLOCATION
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Current Directory Allocation
>
	A.STR <DRNAM:  >	;POINTER TO NAME
	LOAD A1,DRNAM		;GET NAME ADR
	A.OCT A1		;OUTPUT THE NAME POINTER
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Pointer to Name of Directory
>
	A.STR <DRPSW:  >	;PASSWORD
	LOAD A1,DRPSW		;GET PASSWORD ADR
	A.OCT A1		;OUTPUT ADR
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Pointer to Password
>
	A.STR <DRPRV:  >	;GET PRIV BITS TITLE
	LOAD A1,DRCAP		;GET PRIV BITS
	A.OCTM A1		;OUTPUT PRIVS
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Privilege Bits
>
	A.STR <DRMOD:  >	;MODE WORD
	LOAD T2,DRMOD		;GET MODE WORD
	MOVE T3,[1B0+^D8]
	CALL ASMHLF		;OUTPUT IN HALF WORDS
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Mode Bits
>
	A.STR <DRDAT:  >	;DATE AND TIME OF LAST LOGIN
	LOAD A1,DRDAT		;GET DATE AND TIME
	A.OCTM A1		;OUTPUT DATE AND TIME
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Time and Date of Last Login [>
	MOVE T2,A1
	SKIPE T2
	ODTIM
	JUMPE T2,[ O.STR <Never>
		   JRST .+1]
	O.STR <]
>
	A.STR <DRUGP:  >	;USER GROUPS
	LOAD A1,DRUGR		;GET GROUP WORD
	A.OCTM A1		;OUTPUT GROUPS
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Pointer to User Groups
>
	A.STR <DRDGP:  >	;DIRECTORY GROUPS
	LOAD A1,DIRGRP		;GET GROUPS
	A.OCTM A1		;OUTPUT THE GROUPS
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Pointer to Directory Groups
>
	A.STR <DRUDT:  >	;DATE AND TIME OF LAST LAST UPDATE
	LOAD A1,DRUDT		;GET DATE AND TIME
	A.OCTM A1		;OUTPUT DATE AND TIME
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Last Update Time [>
	MOVE T2,A1
	SKIPE T2
	ODTIM
	JUMPE T2,[O.STR <Never>
		  JRST .+1]
	O.STR <]
>
	A.STR <DRSDC:  >
	LOAD A1,DRSDC		;GET SUBDIRECTORY COUNT
	A.OCTM A1		;OUTPUT COUNT
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Subdirectory Count
>
	A.STR <DRSDM:  >
	LOAD A1,DRSDM		;GET MAX # OF SUBDIRECTORIES ALLOWED
	A.OCTM A1			;OUTPUT NUMBER OF SUBDIRECTORIES
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Maximum # of Subdirectories Permitted
>
	A.STR <DRCUG:  >
	LOAD A1,DRCUG		;GET POINTER TO ALLOWABLE SUBDIR GROUPS
	A.OCTM A1		;OUTPUT ADDRESS
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Pointer to Allowable Subdirectory User Groups
>
	A.STR <DRACT:  >
	LOAD A1,DRACT		;GET DEFAULT SUBDIRECTORY ACCOUNT
	A.OCTM A1		;OUTPUT POINTER TO DEFAULT ACCOUNT
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Pointer to Default Account
>
	A.STR <DRDNE:  >
	LOAD A1,DRDNE
	TLNE A1,-1		;DATE OR INTERVAL?
	 JRST [	MOVE T2,A1	;DATE!
		ODTIM
		JRST DRDNE1]	;CONTINUE
	A.OCTM A1
DRDNE1:	ALIGN HDRCOL
	O.STR <Default online expiration date/interval
>
	A.STR <DRDFE:  >
	LOAD A1,DRDFE
	TLNE A1,-1		;DATE OR INTERVAL?
	 JRST [	MOVE T2,A1	;A DATE
		ODTIM
		JRST DRDFE1]	;CONTINUE
	A.OCTM A1
DRDFE1:	ALIGN HDRCOL
	O.STR <Default offline expiration date/interval
>
	O.CRLF
	O.CRLF			;BLANK LINE
	RET			;RETURN TO WHENCE WE CAME ...
; DIRPNT - ROUTINE TO OUTPUT ALL THE BLOCKS IN THE DIRECTORY
;
; CALL:		CALL DIRPNT
;		RETURN


DIRPNT:	LOAD I1,DRLHD		;GET LENGTH OF PAGE 0 HEADER
	MOVEI A1,1		;INDENT FDB'S 1 TAB
	MOVEM A1,INDVAL		;SAVE INDENTING VALUE

DIRPA1:	LOAD A1,DRFRE		;GET HIHEST ADR USED FOR BLOCKS
	CAML I1,A1		;OUTPUT ALL BLOCKS YET ?
	RET			;YES, RETURN
	GETMPW A1,I1		;NO, GET HEADER OF CURRENT BLOCK
	HLRZ A2,A1		;GET BLOCK TYPE FROM HEADER

	MOVEI A3,TYPSIZ-1	;INITIALIZE COUNTER
DIRPA2:	HLRZ A4,TYPTAB(A3)	;GET A BLOCK TYPE FROM TABLE
	CAMN A4,A2		;FOUND CORRECT BLOCK TYPE ?
	JRST DIRPA3		;YES, GO OUTPUT THE BLOCK
	SOJGE A3,DIRPA2		;NO, GO CHECK NEXT TABLE ENTRY

	CRLF
	SAYCR <? Unknown block type encountered>
	O.STR <

? Unkown block type >
	O.OCT A2		;OUTPUT THE BLOCK TYPE
	O.STR < found in directory at address >
	O.OCT I1		;OUTPUT CURRENT BLOCK ADDRESS
	O.CRLF			;OUTPUT A CRLF
	O.CRLF			;LEAVE A BLANK LINE

DIRP2B:	SAYCR <[Searching for a valid block ...]>
DIRP2C:	ADDI I1,1		;GET NEXT WORD IN DIRECTORY
	LOAD A1,DRFRE		;GET END OF FREE STORAGE
	CAMGE I1,A1		;CHECK REMAINDER OF DIRECTORY ?
	JRST DIRP2d		;nO, GO CHECK THIS WORD
	SAYCR <[End of directory - no more blocks found]>
	RET			;RETURN TO WHENCE WE CAME ...

DIRP2D:	GETMPW A1,I1		;GET A WORD
	HLRZ A2,A1		;GET POSSIBLE BLOCK TYPE

	MOVEI A3,TYPSIZ-1	;GET INDEX INTO TYPTAB
DIRP2E:	HLRZ A4,TYPTAB(A3)	;GET A VALID BLOCK TYPE
	CAMN A4,A2		;COULD THIS BE A GOOD BLOCK ?
	JRST DIRP2F		;YES, GO START OUTPUT AGAIN
	SOJGE A3,DIRP2E		;NO, CHECK NEXT TABLE ENTRY
	JRST DIRP2C		;GO CHECK NEXT WORD IN DIRECTORY
DIRP2F:	SAY <[valid block type found at >
	MOVE T2,I1	;GET ADDRESS
	PUTOCT		;OUTPUT ADDRESS OF BLOCK
	SAYCR <]>


DIRPA3:	MOVE P1,I1		;COPY ADDRESS OF BLOCK
	MOVE FB,I1		;COPY ADDRESS IN CASE FDB
	ADD FB,FDBOFS		;POINT TO ACTUAL CORE ADDRESS
	HRRZ A1,TYPTAB(A3)	;GET ADR OF ROUTINE TO OUTPUT
	CALL (A1)		;GO OUTPUT THE BLOCK
	O.CRLF			;BLANK LINE
	GETMPW A1,I1		;GET HEADER WORD AGAIN
	LOAD A2,BT%LEN,A1	;GET LENGTH OF THIS BLOCK
	ADD I1,A2		;COMPUTE ADDRESS OF NEXT BLOCK
	JRST DIRPA1		;GO OUTPUT THE NEXT BLOCK
; SYMPRT - ROUTINE TO OUTPUT THE SYMBOL TABLE
;
; CALL:		CALL SYMPRT
;		RETURN


SYMPRT:	O.STR <Symbol table at >
	LOAD I1,DRBOT		;GET START ADDRESS OF TABLE
	O.OCT I1		;OUTPUT ADDRESS OF SYMBOL TABLE
	O.STR <:

	Header: >
	GETSYM T2,I1		;GET HEADER WORD
	MOVE T3,[1B0+10]	;PRINT MAGNITUDE, OCTAL
	CALL PUTHLF		;GO OUTPUT HALFWORDS
	O.STR <
	word 2: >
	MOVEI A1,1(I1)		;GET ADDRESS OF SECOND WORD
	GETSYM A2,A1		;GET SECOND WORD OF SYMBOL TABLE
	O.OCT A2		;OUTPUT THE SECOND WORD
	O.CRLF			;OUTPUT A CRLF
	O.CRLF			;LEAVE ONE BLANK LINE
	ADDI I1,STHSIZ		;POINT TO FIRST ENTRY IN TABLE

SYMPA1:	LOAD A1,DRTOP		;GET TOP ADDRESS OF SYMBOL TABLE
	CAML I1,A1		;OUTPUT ALL ENTRIES YET ?
	RET			;YES, CONTINUE

	GETSYM A2,I1		;GET FIRST WORD OF ENTRY
	LDB A3,[POINTR(A2,.STMSK)] ;GET ENTRY TYPE
	O.OCTM A3		;OUTPUT TYPE OF ENTRY
	O.STR <	>		;OUTPUT A TAB
	GETSYM A2,I1		;GET FIRST WORD OF ENTRY AGAIN
	LDB A3,[POINTR(A2,.STPTR)] ;GET ADDRESS IN ENTRY
	MOVE FB,A3		;COPY ADDRESS OF FDB
	O.OCT A3		;OUTPUT THE ADDRESS
	O.STR <	>		;OUTPUT A TAB
	GETSYM A1,I1		;GET FIRST WORD OF ENTRY AGAIN
	LDB A2,[POINTR(A1,.STMSK)] ;GET ENTRY TYPE AGAIN
	MOVSI T1,-STBSIZ	;SET UP TO LOOP OVER SYMBOL TABLE TYPE TABLE
SYMP10:	HLRZ T2,SYMTBL(T1)	;GET A KNOWN SYMBOL TABLE ENTRY TYPE
	CAMN T2,A2		;IS THIS THE TYPE OF THIS ENTRY ?
	JRST SYMP20		;YES, GO PROCESS IT
	AOBJN T1,SYMP10		;NO, LOOP OVER ALL ENTRIES
	O.STR <	>		;NO SUCH ENTRY TYPE, OUTPUT A TAB
	O.STR <*** Not a known Entry Type ***>

; HERE WITH A VALID SYMBOL TABLE ENTRY TYPE

SYMP20:	HRRZ T1,SYMTBL(T1)	;GET ADDRESS OF PROCESSING ROUTINE
	CALL (T1)		;PROCESS THE ENTRY
SYMPA3:	O.CRLF			;OUTPUT A CRLF
	MOVEI A1,1(I1)		;GET ADR OF SECOND WORD OF ENTRY
	GETSYM A2,A1		;GET FIRST 5 CHARACTERS OF NAME
	MOVE T1,OUTJFN		;GET OUTPUT JFN
	HRROI T2,A2		;FORM POINTER TO NAME
	MOVEI T3,5		;MAX 5 CHARS OUTPUT
	SETZM T4		;OR STOP ON FIRST NULL BYTE
	SOUT			;OUTPUT THE NAME
	O.CRLF			;OUTPUT A CRLF
	O.CRLF			;SKIP ONE LINE

	ADDI I1,STESIZ		;COMPUTE ADDRESS OF NEXT ENTRY
	JRST SYMPA1		;GO PRINT NEXT TABLE ENTRY


; TABLE OF SYMBOL TABLE ENTRY TYPES

SYMTBL:	.STNAM,,FILPRT
	.STUNS,,PRTUNS
	.STACT,,PRTACT

	STBSIZ==.-SYMTBL
; ROUTINES TO PROCESS THE SYMBOL TABLE ENTRY TYPES

;PRTACT - ROUTINE TO PRINT THE ACCOUNT STRING FOR AN ACCOUNT BLOCK
;
;ACCEPTS IN A1/	ADDRESS OF ACCOUNT BLOCK
;		CALL PRTACT
;RETURNS: +1 ALWAYS

PRTACT:	LDB A2,[POINTR(A1,.STPTR)] ;GET ADDRESS OF ACCOUNT BLOCK
	ADDI A2,.ABPTR		;GET ADR OF POINTER TO STRING
	GETMPW A3,A2		;REFERENCE THE STRING TO MAP IT
	HRRZ T2,A1		;GET OFFSET TO ACCOUNT BLOCK
	ADD T2,FDBOFS		;ADD BASE ADDRESS OF MAPPED AREA
	LDB T1,[POINT 7,.ABPTR(T2),6] ;GET FIRST CHARACTER OF STRING
	JUMPE T1,R		;RETURN IF NULL STRING
	HRROI T2,(A2)		;FORM A POINTER TO THE STRING
	ADD T2,FDBOFS		;COMPUTE CORE ADDRESS OF STRING
	MOVE T1,OUTJFN		;GET OUTPUT JFN
	SETZM T3		;TERMINATE ON NULL
	SOUT			;OUTPUT THE STRING
	RET			;RETURN
;PRTUNS - ROUTINE TO PRINT THE USER NAME STRING FOR A USER NAME BLOCK
;
;ACCEPTS IN A1/	ADDRESS OF USER NAME BLOCK
;		CALL PRTUNS
;RETURNS: +1 ALWAYS

PRTUNS:	LDB A2,[POINTR(A1,.STPTR)] ;GET ADDRESS OF USER NAME BLOCK
	ADDI A2,.UNPTR		;GET ADR OF POINTER TO STRING
	GETMPW A3,A2		;REFERENCE THE STRING TO MAP IT
	HRROI T2,(A2)		;FORM A POINTER TO THE STRING
	ADD T2,FDBOFS		;COMPUTE CORE ADDRESS OF STRING
	MOVE T1,OUTJFN		;GET OUTPUT JFN
	SETZM T3		;TERMINATE ON NULL
	SOUT			;OUTPUT THE STRING
	RET			;RETURN
; CHNDIR - ROUTINE TO OUTPUT THE DIRECTORY BY CHAINING DOWN THE
;	   FDB CHAINS.
;
; CALL:		CALL CHNDIR
;		RETURN


CHNDIR:	O.CRLF
	LOAD I1,DRBOT		;GET BOTTOM ADR IN SYMBOL TABLE
	ADDI I1,STHSIZ		;POINT TO FIRST ENTRY IN TABLE

CHNDR1:	LOAD A1,DRTOP		;GET TOP ADDRESS IN SYMBOL TABLE
	CAML I1,A1		;OUTPUT ALL FDB CHAINS YET ?
	RET			;YES, RETURN
	GETSYM A1,I1		;NO, GET FIRST WORD OF ENTRY
	LDB A2,[POINTR(A1,.STMSK)] ;GET ENTRY TYPE
	CAIE A2,.STNAM		;IS THIS A FILENAME ENTRY ?
	JRST CHNDR3		;NO, GO CHECK NEXT ENTRY
	O.CRLF			;OUTPUT A CRLF
	LDB FB,[POINTR(A1,.STPTR)] ;YES, GET ADR OF FDB
	MOVEI P1,0		;INDENT FIRS FDB 0 TABS
	CALL CHNGEN		;GO OUTPUT REST OF GEN CHAIN
CHNDR2:	GETSYM A1,I1		;GET SYMBOL TABLE ENTRY AGAIN
	LDB A2,[POINTR(A1,.STPTR)] ;GET ADR OF FDB AGAIN
	MOVEI A1,.FBEXL(A2)	;GET ADR OF PTR TO EXT CHAIN
	GETMPW FB,A1		;GET ADR OF NEXT FDB ON CHAIN
	JUMPE FB,CHNDR3		;IF END-OF-CHAIN, GO CHECK NEXT
	MOVEI A1,1		;GET # OF TABS TO INDENT EXT'S
	MOVEM A1,INDVAL		;SAVE # OF TABS TO INDENT
	CALL CHNEXT		;GO OUTPUT REMAINDER OF CHAIN

CHNDR3:	ADDI I1,STESIZ		;COMPUTE ADDRESS OF NEXT ENTRY
	JRST CHNDR1		;GO OUTPUT NEXT CHAIN OF FDB'S
; CHNEXT - ROUTINE TO OUTPUT ALL THE FDB'S ON A GIVEN
;	   EXTENSION CHAIN.
;
; CALL:		MOVE FB,FILE ADDRESS OF FDB AT HEAD OF CHAIN
;		CALL CHNEXT
;		RETURN


CHNEXT:	STKVAR <SAVEFB>		;ALLOCATE TEMPORARY STORAGE
	MOVEM FB,SAVEFB		;SAVE ORIGINAL VALUE OF FB

CHNEA1:	MOVEI P1,1		;INDENT FIRST FDB 1 TAB
	CALL CHNGEN		;GO OUTPUT FIRST GEN CHAIN
	MOVEI A1,.FBEXL(FB)	;GET ADR OF POINTER TO NEXT FDB
	CHEK A2,A1,BADPTR	;CHECK POINTER TO BE SURE ITS OK
	GETMPW FB,A1		;GET POINTER TO NEXT EXT FDB
	JUMPN FB,CHNEA1		;IF NOT END-OF-CHAIN, GO DO NEXT

	MOVE FB,SAVEFB		;RESTORE ORIGINAL VALUE OF FB
	RET			;RETURN TO WHENCE WE CAME ...
; CHNGEN - ROUTINE TO OUTPUT ALL THE FDB'S ON A GIVEN GENERATION
;	   CHAIN.
;
; CALL:		MOVE FB,FILE ADDRESS OF FDB AT HEAD OF CHAIN
;		MOVE P1, # OF TABS TO INDENT FIRST FDB
;		CALL CHNGEN
;		RETURN


CHNGEN:	STKVAR <SAVFDB>		;ALLOCATE TEMPORARY STORAGE
	MOVEM FB,SAVFDB		;SAVE ORIGINAL FDB ADR
	MOVEM P1, INDVAL	;# OF TABS TO INDENT FIRST FDB

CHNGN1:	O.CRLF			;START WITH A NEW LINE
	MOVEI A1,2		;GET # OF TABS OF MOST FDB'S
	CAME FB,SAVFDB		;OUTPUTTING FIRST FDB ?
	MOVEM A1,INDVAL		;NO, SAVE # OF TABS TO INDENT
	ADD FB,FDBOFS		;COMPUTE CORE ADDRESS OF FDB
	CALL FDBPRT		;GO PRINT FDB AT HEAD OF CHAIN
	SUB FB,FDBOFS		;RESTORE ORIGINAL FDB FILE ADR
	MOVEI A1,.FBGNL(FB)	;GET ADR OF PTR TO NEXT GEN
	CHEK A2,A1,BADPTR	;CHECK ADDRESS IN A1,BADPTR
	GETMPW FB,A1		;GET POINTER TO NEXT GENERATION
	JUMPN FB,CHNGN1		;IF NOT END-OF-CHAIN, GO DO NEXT

CHNGN2:	MOVE FB,SAVFDB		;RESTORE ORIGINAL FDB ADDRESS
	SOS INDVAL		;DECREMENT # OF TABS TO INDENT
	RET			;RETURN TO WHENCE WE CAME ...
; FILPRT - ROUTINE TO PRINT THE NAME OF A FILESPEC FOR A GIVEN
;	   FILE DESCRIPTOR BLOCK.
;
; CALL:		MOVE FB,ADDRESS OF FDB
;		CALL FILPRT
;		RETURN


FILPRT:	STKVAR <TEMPI1>		;ALLOCATE TEMPORARY STORAGE
	MOVEM I1,TEMPI1		;SAVE VALUE OF I1
	GETMPW A1,FB		;GET FIRST WORD OF FDB
	HLRZ A1,A1		;GET JUST THE BLOCK TYPE
	CAIN A1,.TYFDB		;IS THIS AN FDB ?
	JRST FILP00		;YES, GO OUTPUT THE FILENAME
	O.STR <*** FILPRT: Not an FDB ***
>
	MOVE I1,TEMPI1		;RESTORE OFIGINAL I1
	RET			;RETURN TO WHENCE WE CAME ...

FILP00:	MOVEI A1,.FBNAM(FB)	;GET ADDRESS OF PTR TO NAME BLK
	GETMPW A2,A1		;GET POINTER TO NAME BLOCK
	GETMPW A1,A2		;GET FIRST WORD OF BLOCK
	HLRZ A1,A1		;GET JUST THE BLOCK TYPE
	CAIE A1,.TYNAM		;IS THIS A NAME BLOCK ?
	JRST FILP01		;NO, GO ISSUE MESSAGE
	HRROI T2,1(A2)		;YES, GET ADDRESS OF NAME STRING
	ADD T2,FDBOFS		;COMPUTE CORE ADDRESS OF STRING
	MOVE T1,OUTJFN		;GET OUTPUT JFN
	SETZM T3		;TERMINATE ON NULL
	SOUT			;OUTPUT THE NAME STRING
	JRST FILP02		;GO ON TO OUTPUT EXTENSION
FILP01:	O.STR <*** UNKNOWN NAME ***>

FILP02:	MOVEI T2,"."		;GET EXTENSION DELIMITER
	BOUT			;OUTPUT THE PERIOD
	MOVEI A1,.FBEXT(FB)	;GET ADR OF PTR TO EXT BLOCK
	GETMPW A2,A1		;GET POINTER TO EXT BLOCK
	GETMPW A1,A2		;GET FIRST WORD OF EXT BLOCK
	HLRZ A1,A1		;KEEP JUST THE BLOCK TYPE
	CAIE A1,.TYEXT		;IS THIS AN EXTENSION BLOCK ?
	JRST FILP03		;NO, GO ISSUE MESSAGE
	HRROI T2,1(A2)		;YES, GET POINTER TO EXT STRING
	ADD T2,FDBOFS		;COMPUTE CORE ADDRESS OF STRING
	MOVE T1,OUTJFN		;GET OUTPUT JFN
	SETZM T3		;TERMINATE ON NULL
	SOUT			;OUTPUT THE STRING
	JRST FILP04		;GO OUTPUT GENERATION DELIMITER
FILP03:	O.STR <*** UNKNOWN EXTENSION ***>
	; ..
	; ..
FILP04:	MOVEI T2,GENDEL	;GET GENERATION DELIMITER
	BOUT			;OUTPUT THE SEMICOLON
	MOVEI A1,.FBGEN(FB)	;GET PTR TO GENERATION #
	GETMPW A2,A1		;GET GENERATION # OF THIS FILE
	HLRZ T2,A2		;COPY THE GENERATION #
	MOVEI T3,^D10		;USE DECIMAL RADIX
	NOUT			;OUTPUT THE GENERATION NUMBER
	  CALL PUTERR		;UNEXPECTED ERROR
	MOVEI T2,";"		;GET DELIMITER
	BOUT			;OUTPUT DELIMITER
	MOVEI T2,"P"		;GET PROTECTION CHARACTER
	BOUT			;OUTPUT THE PROTECTION CHARACTER
	MOVEI A1,.FBPRT(FB)	;GET ADR OF FILE'S PROTECTION
	GETMPW T2,A1		;GET THIS FILE'S PROTECTION
	TLZ T2,500000		;TURN OFF HIGH-ORDER BITS
	MOVX T3,3B3+6B17+10	;6 COLUMNS,3B3+ OCTAL RADIX
	NOUT			;OUTPUT THE PROTECTION
	  CALL PUTERR		;UNEXPECTED ERROR
	MOVEI T2,";"		;GET DELIMITER CHARACTER
	BOUT			;OUTPUT THE DELIMITER
	MOVEI T2,"A"		;GET ACCOUNT CHARACTER
	BOUT			;OUTPUT ACCOUNT CHARACTER
	MOVEI A1,.FBACT(FB)	;GET ADR OF ACCOUNT WORD
	GETMPW A2,A1		;GET ACCOUNT WORD FROM FDB
	JUMPL A2,FILPA1		;IF NUMERIC, GO PRINT #
	ADDI A2,2		;POINT TO ACCOUNT STRING
	GETMPW A3,A2		;REFERENCE ACT STRING TO MAP IT
	HRROI T2,(A2)		;FORM POINTER TO STRING
	ADD T2,FDBOFS		;POINT TO CORE ADR OF STRING
	SETZM T3		;TERMINATE ON NULL
	SOUT			;OUTPUT THE ACCOUNT STRING
	JRST FILPA2		;GO ON TO NEXT ATTRIBUTE

FILPA1:	MOVE T2,A2		;COPY ACCOUNT #
	TLZ T2,500000		;GET JUST THE ACCOUNT #
	MOVEI T3,^D10		;USE DECIMAL RADIX
	NOUT			;OUTPUT THE ACCOUNT #
	  CALL PUTERR		;UNEXPECTED ERROR

FILPA2:	MOVE I1,TEMPI1		;RESTORE ORIGINAL VALUE OF I1
	RET			;RETURN TO WHENCE WE CAME ...
; GETNAM - ROUTINE TO GET THE ADDRESS OF THE NAME BLOCK
;	   FOR A GIVEN FDB.
;
; CALL:		MOVE FB, ADDRESS OF FDB
;		CALL GETNAM
;		  RETURN NON-SKIP IF ERROR
;		RETURN WITH ADR OF EXT BLOCK IN P1


GETNAM:	LOAD I1,DRBOT		;GET BOTTOM ADR IN SYMBOL TABLE
	ADDI I1,STHSIZ		;POINT TO FIRST ENTRY IN TABLE

GETNM1:	LOAD A1,DRTOP		;GET TOP ADR IN SYMBOL TABLE
	CAML I1,A1		;MORE ENTRIES TO CHECK ?
	JRST GETNM5		;NO, CANNOT FIND FDB - TELL USER

	GETSYM A1,I1		;GET FIRST WORD OF ENTRY
	LDB A2,[POINTR(A1,.STMSK)] ;GET TYPE OF ENTRY
	CAIE A2,.STNAM		;IS THIS AN ENTRY FOR AN FDB ?
	JRST GETNM4		;NO, GO ON TO NEXT ENTRY
	LDB A2,[POINTR(A1,.STPTR)] ;YES, GET ADDRESS OF FDB

GETNM2:	CAMN A2,FB		;FOUND DESIRED FDB YET ?
	JRST GETNM6		;YES, GO GET ADR OF NAME BLOCK
	MOVEI A3,.FBGNL(A2)	;NO, GET ADR OF PTR TO NEXT GEN

GETNM3:	GETMPW A4,A3		;GET POINTER TO FDB OF NEXT GEN
	CAMN A4,FB		;DESIRED FDB ON THIS GEN CHAIN ?
	JRST GETNM6		;YES, GO GET ADR OF NAME BLOCK
	JUMPE A4,GETNM4		;IF END-OF-CHAIN, TRY NEXT EXT
	MOVEI A3,.FBGNL(A4)	;GET ADR OF POINTER TO NEXT FDB
	JRST GETNM3		;GO CHECK NEXT FDB ON GEN CHAIN

GETNM4:	MOVEI A3,.FBEXL(A2)	;GET ADR OF PTR TO NEXT EXT FDB
	GETMPW A2,A3		;GET POINTER TO NEXT EXT CHAIN
	JUMPN A2,GETNM2		;GO CHECK THIS EXT CHAIN

	ADDI I1,STESIZ		;COMPUTE ADR OF NEXT TABLE ENTRY
	JRST GETNM1		;GO CHECK NEXT CHAIN OF FDB'S


; HERE IF FDB COULD NOT BE FOUND IN DIRECTORY

GETNM5:	O.STR <
? Internal confusion or inconsistent directory !
	GETNAM: Could not find FDB at >
	O.OCT FB		;OUTPUT THE ADDRESS
	O.CRLF			;NEW LINE
	RET			;RETURN INDICATING ERROR
; HERE WHEN FDB FOUND - HEAD OF EXT CHAIN IN A2

GETNM6:	GETSYM A1,I1		;GET FIRST WORD OF TABLE ENTRY
	LDB A2,[POINTR(A1,.STPTR)] ;GET ADR OF NAME FDB
	MOVEI A3,.FBNAM(A2)	;GET ADR OF PTR TO NAME BLOCK
	GETMPW P1,A3		;GET POINTER TO NAME BLOCK
	RETSKP			;RETURN TO WHENCE WE CAME ...
; GETEXT - ROUTINE TO GET THE ADDRESS OF THE EXTENSION BLOCK
;	   FOR A GIVEN FDB.
;
; CALL:		MOVE FB, ADDRESS OF FDB
;		CALL GETEXT
;		  RETURN HERE IF ERROR
;		RETURN WITH ADR OF EXT BLOCK IN P1


GETEXT:	LOAD I1,DRBOT		;GET BOTTOM ADR IN SYMBOL TABLE
	ADDI I1,STHSIZ		;POINT TO FIRST ENTRY IN TABLE

GETEA1:	LOAD A1,DRTOP		;GET TOP ADR IN SYMBOL TABLE
	CAML I1,A1		;MORE ENTRIES TO CHECK ?
	JRST GETEX5		;NO, CANNOT FIND FDB - TELL USER

	GETSYM A1,I1		;GET FIRST WORD OF ENTRY
	LDB A2,[POINTR(A1,.STMSK)] ;GET TYPE OF ENTRY
	CAIE A2,.STNAM		;IS THIS AN ENTRY FOR AN FDB ?
	JRST GETEA4		;NO, GO ON TO NEXT ENTRY
	LDB A2,[POINTR(A1,.STPTR)] ;YES, GET ADDRESS OF FDB

GETEA2:	CAMN A2,FB		;FOUND DESIRED FDB YET ?
	JRST GETEX6		;YES, GO GET ADR OF EXT BLOCK
	MOVEI A3,.FBGNL(A2)	;NO, GET ADR OF PTR TO NEXT GEN

GETEA3:	GETMPW A4,A3		;GET POINTER TO FDB OF NEXT GEN
	CAMN A4,FB		;DESIRED FDB ON THIS GEN CHAIN ?
	JRST GETEX6		;YES, GO GET ADR OF EXT BLOCK
	JUMPE A4,GETEA4		;IF END-OF-CHAIN, TRY NEXT EXT
	MOVEI A3,.FBGNL(A4)	;GET ADR OF POINTER TO NEXT FDB
	JRST GETEA3		;GO CHECK NEXT FDB ON GEN CHAIN

GETEA4:	MOVEI A3,.FBEXL(A2)	;GET ADR OF PTR TO NEXT EXT FDB
	GETMPW A2,A3		;GET POINTER TO NEXT EXT CHAIN
	JUMPN A2,GETEA2		;GO CHECK THIS EXT CHAIN

	ADDI I1,STESIZ		;COMPUTE ADR OF NEXT TABLE ENTRY
	JRST GETEA1		;GO CHECK NEXT CHAIN OF FDB'S


; HERE IF FDB COULD NOT BE FOUND IN DIRECTORY

GETEX5:	O.STR <
? Internal confusion or inconsistent directory !
	GETEXT: Could not find FDB at >
	O.OCT FB		;OUTPUT THE ADDRESS
	O.CRLF			;NEW LINE
	RET			;RETURN ERROR INDICATION
; HERE WHEN FDB FOUND - HEAD OF EXT CHAIN IN A2

GETEX6:	MOVEI A1,.FBEXT(A2)	;GET ADDRESS OF PTR TO EXT BLOCK
	GETMPW P1,A1		;GET ADR OF EXTENSION BLOCK
	RETSKP			;RETURN TO WHENCE WE CAME ...
; NAMPRT - ROUTINE TO OUTPUT THE CONTENTS OF A NAME BLOCK
;
; CALL:		MOVE P1,ADDRESS OF NAME BLOCK
;		RETURN


NAMPRT:	O.STR <Name Block at >	;OUTPUT FIRST PART OF HEADING
	O.OCT P1		;OUTPUT ADDRESS OF NAME BLOCK
	O.STR < is:
	header:	>		;OUTPUT REMAINDER OF HEADING
	GETMPW T2,P1		;GET HEADER WORD
	MOVE T3,[1B0+10]	;PRINT MAGNITUDE, USE OCTAL
	CALL PUTHLF		;GO OUTPUT TWO HALFWORDS
	O.STR <
	String:	>		;output ANOTHER HEADER
	MOVE T1,OUTJFN		;GET OUTPUT JFN
	HRROI T2,.NBPTR(P1)	;GET POINTER TO NAME PTRING
	ADD T2,FDBOFS		;COMPUTE CORE ADDRESS OF STRING
	SETZM T3		;TERMINATE ON NULL
	SOUT			;OUTPUT THE NAME STRING
	O.CRLF			;OUTPUT A CRLF
	RET			;RETURN TO WHENCE WE CAME ...



; EXTPRT - ROUTINE TO OUTPUT THE CONTENTS OF AN EXTENSION BLOCK
;
; CALL:		MOVE P1,ADDRESS OF EXTENSION BLOCK
;		RETURN


EXTPRT:	O.STR <Extension Block at > ;OUTPUT INITIAL HEADING
	O.OCT P1		;OUTPUT ADDRESS OF NAME BLOCK
	O.STR < is:
	header:	>		;OUTPUT REMAINDER OF HEADING
	GETMPW T2,P1		;GET HEADER WORD
	MOVE T3,[1B0+10]	;PRINT MAGNITUDE, USE OCTAL
	CALL PUTHLF		;GO OUTPUT TWO HALFWORDS
	O.STR <
	String:	> 		;OUTPUT ANOTHER HEADER
	MOVE T1,OUTJFN		;GET OUTPUT JFN
	HRROI T2,.EBPTR(P1)	;GET POINTER TO NAME PTRING
	ADD T2,FDBOFS		;COMPUTE CORE ADDRESS OF STRING
	SETZM T3		;TERMINATE ON NULL
	SOUT			;OUTPUT THE NAME STRING
	O.CRLF			;OUTPUT A CRLF
	RET			;RETURN TO WHENCE WE CAME ...
; ACTPRT - ROUTINE TO OUTPUT THE CONTENTS OF AN ACCOUNT BLOCK
;
; CALL:		MOVE P1,ADDRESS OF ACCOUNT BLOCK
;		RETURN


ACTPRT:	O.STR <Account Block at > ;OUTPUT FIRST PART OF HEADING
	O.OCT P1		;OUTPUT ADDRESS OF NAME BLOCK
	O.STR < is:
	header:	>		;OUTPUT REMAINDER OF HEADING
	GETMPW T2,P1		;GET HEADER WORD
	MOVE T3,[1B0+10]	;PRINT MAGNITUDE, USE OCTAL
	CALL PUTHLF		;GO OUTPUT TWO HALFWORDS
	O.STR <
	Count:	>		;OUTPUT MORE HEADING
	MOVEI A1,.ABCNT(P1)	;GET ADDRESS OF SHARE COUNT
	GETMPW T2,A1		;GET THE SHARE COUNT
	MOVE T1,OUTJFN		;GET OUTPUT JFN
	MOVEI T3,^D10		;USE DECIMAL RADIX
	NOUT			;OUTPUT THE SHARE COUNT
	  CALL PUTERR		;UNEXPECTED ERROR
	O.STR <.
	String:	>		;output ANOTHER HEADER
	MOVE T1,OUTJFN		;GET OUTPUT JFN
	HRROI T2,.ABPTR(P1)	;GET POINTER TO NAME PTRING
	ADD T2,FDBOFS		;COMPUTE CORE ADDRESS OF STRING
	SETZM T3		;TERMINATE ON NULL
	SOUT			;OUTPUT THE NAME STRING
	O.CRLF			;OUTPUT A CRLF
	RET			;RETURN TO WHENCE WE CAME ...

; UNSPRT - ROUTINE TO OUTPUT THE CONTENTS OF A USER NAME STRING BLOCK
;
; CALL:		MOVE P1,ADDRESS OF USER NAME STRING BLOCK
;		RETURN


UNSPRT:	O.STR <User Name String Block at > ;OUTPUT FIRST PART OF HEADING
	O.OCT P1		;OUTPUT ADDRESS OF NAME BLOCK
	O.STR < is:
	header:	>		;OUTPUT REMAINDER OF HEADING
	GETMPW T2,P1		;GET HEADER WORD
	MOVE T3,[1B0+10]	;PRINT MAGNITUDE, USE OCTAL
	CALL PUTHLF		;GO OUTPUT TWO HALFWORDS
	O.STR <
	Count:	>		;OUTPUT MORE HEADING
	MOVEI A1,.UNCNT(P1)	;GET ADDRESS OF SHARE COUNT
	GETMPW T2,A1		;GET THE SHARE COUNT
	MOVE T1,OUTJFN		;GET OUTPUT JFN
	MOVEI T3,^D10		;USE DECIMAL RADIX
	NOUT			;OUTPUT THE SHARE COUNT
	  CALL PUTERR		;UNEXPECTED ERROR
	O.STR <.
	String:	>		;output ANOTHER HEADER
	MOVE T1,OUTJFN		;GET OUTPUT JFN
	HRROI T2,.UNPTR(P1)	;GET POINTER TO NAME STRING
	ADD T2,FDBOFS		;COMPUTE CORE ADDRESS OF STRING
	SETZM T3		;TERMINATE ON NULL
	SOUT			;OUTPUT THE NAME STRING
	O.CRLF			;OUTPUT A CRLF
	RET			;RETURN TO WHENCE WE CAME ...
; FDBPRT - ROUTINE TO PRINT THE CONTENTS OF AN FDB.
;
; CALL:		MOVE FB,ADDRESS OF FDB
;		CALL FDBPRT
;		RETURN

FDBPRT:	HLRZ A1,(FB)		;GET JUST THE BLOCK TYPE
	CAIN A1,.TYFDB		;IS THIS REALLY AN FDB ?
	JRST FDBP00		;YES, GO PRINT THE FDB
	O.STR <
% Unexpected block type >
	O.OCTM A1		;OUTPUT THE BLOCK TYPE
	O.STR < found at address >
	MOVE A1,FB		;GET FDB ADDRESS
	SUB A1,FDBOFS		;COMPUTE ADDRESS IN FILE
	O.OCT A1		;OUTPUT THE ADDRESS
	O.CRLF			;OUTPUT A CRLF
	MOVE P1,FB		;GET THE ADDRESS OF THE BLOCK
	CALLRET BLKPNT		;GO OUTPUT THE FUNNY BLOCK

FDBP00:	O.CRLF			;START WITH A FREE CRLF
	SUB FB,FDBOFS		;COMPUTE FILE ADDRESS OF FDB
	CALL FILPRT		;GO OUTPUT THE FILE NAME
	ADD FB,FDBOFS		;RE-COMPUTE CORE ADR OF FDB
	O.STR <
FDB at >
	MOVE A1,FB		;COPY FDB ADDRESS
	SUB A1,FDBOFS		;COMPUTE ABSOLUTE ADDRESS
	O.OCT A1		;OUTPUT ADDRESS OF FDB
	O.STR < is:
>
	O.CRLF			;LEAVE ONE LINE BLANK
	CALL INDENT		;GO INDENT
	O.STR <.FBHDR:	>
	MOVE T2,.FBHDR(FB)	;GET HEADER WORD
	MOVE T3,[1B0+10]	;PRINT MAGNITUDE, OCTAL RADIX
	CALL PUTHLF		;GO OUTPUT HEADER IN HALFWORDS
	O.CRLF			;OUTPUT A CRLF
	CALL INDENT		;GO INDENT
	O.STR <.FBCTL:	>
	MOVE T2,.FBCTL(FB)	;GET CONTROL BITS, NAME POINTER
	MOVE T3,[1B0+10]	;MAGNITUDE, AND OCTAL RADIX
	CALL PUTHLF		;GO OUTPUT THE TWO HALFWORDS
	O.CRLF			;OUTPUT A CRLF
	CALL INDENT		;GO INDENT
	O.STR <.FBEXL:	>
	O.OCT .FBEXL(FB)	;OUTPUT ADR OF NEXT FDB
	O.CRLF			;OUTPUT A CRLF
	CALL INDENT		;GO INDENT
	O.STR <.FBADR	>
	O.OCT <.FBADR(FB)>	;OUTPUT ADDRESS OF FILE
	O.CRLF			;OUTPUT A CRLF
	CALL INDENT		;GO INDENT
	O.STR <.FBPRT:	>
	MOVE T2,.FBPRT(FB)	;GET PROTECTION WORD
	MOVE T3,[1B0+^D8]
	CALL PUTHLF		;OUTPUT AS HALFWORDS
	O.CRLF			;OUTPUT A CRLF
	CALL INDENT		;GO INDENT
	O.STR <.FBCRE:	>
	MOVE T2,.FBCRE(FB)	;GET CREATION DATE AND TIME
	MOVE T3,[1B0+6B17+10]	;MAGNITUDE, OCTAL RADIX
	CALL PUTHLF		;GO OUTPUT TWO HALFWORDS
	O.STR <	[>
	MOVE T2,.FBCRE(FB)	;GET DATE AND TIME AGAIN
	ODTIM			;OUTPUT THE DATE AND TIME
	O.STR <]
>
	CALL INDENT		;GO INDENT
	O.STR <.FBAUT:	>	;OUTPUT VERSION 1 HEADING
	MOVE T2,.FBAUT(FB)	;GET FDBUSE WORD
	MOVEI T3,10		;USE OCTAL
	CALL PUTHLF		;GO OUTPUT HALFWORDS
	O.CRLF			;OUTPUT A CRLF
	CALL INDENT		;GO INDENT
	O.STR <.FBGEN:	>
	MOVE T2,.FBGEN(FB)	;GET VERSION WORD
	MOVEI T3,10		;USE OCTAL AGAIN
	CALL PUTHLF		;GO OUTPUT HALFWORDS
	O.CRLF			;OUTPUT A CRLF
	CALL INDENT		;GO INDENT
	O.STR <.FBACT:	>
	O.OCTM <.FBACT(FB)>	;OUTPUT ACCOUNT WORD
	JUMPG T2,FDBPT0		;IF NOT NUMERIC ACCT, GO ON
	O.STR <		Account # is: >
	MOVE A1,.FBACT(FB)	;GET ACCOUNT #
	TLZ A1,500000		;TURN OFF "THIS IS # " BITS
	O.DEC A1		;OUTPUT THE ACCOUNT #
FDBPT0:	O.CRLF			;GO OUTPUT CRLF
	CALL INDENT		;GO INDENT
	O.STR <.FNBYV:	>
	MOVE T2,.FBBYV(FB)	;GET GENERATIONS, BYTE SIZE, PAGES
	MOVE T3,[1B0+10]	;MAGNITUDE, OCTAL
	CALL PUTHLF		;GO OUTPUT HALFWORDS
	O.CRLF			;GO OUTPUT A CRLF
	CALL INDENT		;GO INDENT
	O.STR <.FBSIZ:	>
	O.DEC <.FBSIZ(FB)>	;OUTPUT EOF BYTE ADDRESS
	O.CRLF
	CALL INDENT		;GO INDENT
	O.STR <.FBCRV:	>
	MOVE T2,.FBCRV(FB)	;GET CREATION DATE AND TIME
	MOVE T3,[1B0+6B17+10]	;MAGNITUDE, OCTAL RADIX
	CALL PUTHLF		;GO OUTPUT DATE ,, TIME
	O.STR <	[>
	MOVE T2,.FBCRV(FB)	;GET DATE AND TIME
	ODTIM			;OUTPUT THE DATE/TIME IN ASCII
	O.STR <]
>
	CALL INDENT		;GO INDENT
	O.STR <.FBWRT:	>
	MOVE T2,.FBWRT(FB)	;GET DATE AND TIME OF LAST WRITE
	MOVE T3,[1B0+6B17+10]	;MAGNITUDE, OCTAL RADIX
	CALL PUTHLF		;GO OUTPUT DATE,, TIME
	O.STR <	[>
	MOVE T2,.FBWRT(FB)	;GET DATE AND TIME AGAIN
	SKIPE T2
	ODTIM			;OUTPUT DATE AND TIME IN ASCII
	JUMPE T2,[O.STR <Never>	;ZERO IS SPECIAL CASE
		  JRST .+1]
	O.STR <]
>
	CALL INDENT		;GO INDENT
	O.STR <.FBREF:	>
	MOVE T2,.FBREF(FB)	;GET LAST TIME REFERENCED
	MOVE T3,[1B0+6B17+10]	;MAGNITUDE, OCTAL RADIX
	CALL PUTHLF		;GO OUTPUT DATE,, TIME
	O.STR <	[>
	MOVE T2,.FBREF(FB)	;GET DATE AND TIME AGAIN
	SKIPE T2
	ODTIM			;OUTPUT DATE AND TIME IN ASCII
	JUMPE T2,[O.STR <Never>	;ZERO DATE IS A SPECIAL CASE
		  JRST .+1]
	O.STR <]
>
	CALL INDENT		;GO INDENT
	O.STR <.FBCNT:	>
	MOVE T2,.FBCNT(FB)	;GET FDBCNT WORD
	MOVE T3,[1B0+^D10]	;USE DECIMAL !
	CALL PUTHLF		;GO OUTPUT HALFWORDS
	O.CRLF
	CALL INDENT		;GO INDENT
	O.STR <.FBBK0:	>	;BACKUP WORD 0
	MOVE T2,.FBBK0(FB)	;OUTPUT BACKUP WORDS IN HALFWORDS
	MOVE T3,[1B0+^D8]	;IN OCTAL
	CALL PUTHLF
	O.CRLF			;OUTPUT A CRLF
	CALL INDENT
	O.STR <.FBBK1:	>	;BACKUP WORD 1
	MOVE T2,.FBBK1(FB)	;OUTPUT BACKUP WORDS IN HALFWORDS
	MOVE T3,[1B0+^D8]	;IN OCTAL
	CALL PUTHLF
	O.CRLF
	CALL INDENT
	O.STR <.FBBK2:	>	;BACKUP WORD 2
	MOVE T2,.FBBK2(FB)	;OUTPUT BACKUP WORDS IN HALFWORDS
	MOVE T3,[1B0+^D8]	;IN OCTAL
	CALL PUTHLF
	O.CRLF
	CALL INDENT
	O.STR <.FBBBT:	>	;ARCHIVE STATUS BITS
	MOVE T2,.FBBBT(FB)	;OUTPUT IN HALFWORDS
	MOVE T3,[1B0+^D8]	;IN OCTAL
	CALL PUTHLF
	O.CRLF
	CALL INDENT
	O.STR <.FBNET:	>	;ONLINE EXPIRATION DATE/INTERVAL
	MOVE T2,.FBNET(FB)	;GET THE VALUE
	TLNE T2,-1		;IS THIS A DATE OR AN INTERVAL?
	 JRST [	ODTIM		;A DATE, PRINT AS SUCH
		ERCAL PUTERR
		JRST USWST]	;GO TO NEXT WORD
	O.OCT <.FBNET(FB)>
USWST:	O.CRLF
	CALL INDENT		;GO INDENT
	O.STR <.FBUSW:	>
	O.OCTM <.FBUSW(FB)>	;OUTPUT USER SETTABLE WORD
	O.CRLF			;OUTPUT A CRLF
	CALL INDENT		;GO INDENT
	O.STR <.FBGNL:	>
	O.OCT .FBGNL(FB)	;OUTPUT POINTER TO NEXT GEN FDB
	O.CRLF
	CALL INDENT		;GO INDENT
	O.STR <.FBNAM:	>
	O.OCT .FBNAM(FB)	;OUTPUT POINTER TO NAME BLOCK
	O.CRLF			;OUTPUT A CRLF
	CALL INDENT		;GO INDENT
	O.STR <.FBEXT:	>
	O.OCT .FBEXT(FB)	;OUTPUT POINTER TO EXT BLOCK
	O.CRLF			;GO OUTPUT A CRLF
	CALL INDENT		;GO INDENT
	O.STR <.FBLWR:	>	;OUTPUT HEADING FOR LAST WRITER FIELD
	O.OCT .FBLWR(FB)	;OUTPUT THE LAST WRITER WORD
	O.CRLF			;AND END THE LINE
	LOAD T2,FB%LEN,.FBHDR(FB) ;GET LENGTH OF THIS FDB
	CAIG T2,OLDV1		;NEW VERSION 1 FDB?
	RET			;NO, SO STOP HERE
	CALL INDENT
	O.STR <.FBTDT:	>	;DATE ARCHIVED
	MOVE T2,.FBTDT(FB)	;GET ARCHIVE DATE FROM FDB
	MOVE T3,[1B0+6B17+10]	;MAGNITUDE+6 COLUMNS+OCTAL
	CALL PUTHLF
	O.STR <	[>
	MOVE T2,.FBTDT(FB)
	SKIPE T2
	ODTIM
	JUMPE T2,[O.STR <Not archived>
		  JRST .+1]
	O.STR <]
>
	CALL INDENT
	O.STR <.FBFET:	>	;OFFLINE EXPIRATION DATE/INTERVAL
	MOVE T2,.FBFET(FB)	;GET THE VALUE
	TLNE T2,-1		;DATE OR INTERVAL?
	 JRST [	ODTIM		;A DATE, PRINT IT
		 ERCAL PUTERR
		JRST TP1ST]	;NEXT WORD
	O.DEC <.FBFET(FB)>
TP1ST:	O.CRLF
	CALL INDENT
	O.STR <.FBTP1:	>	;TAPE ID FOR RUN 1
	MOVE T2,.FBTP1(FB)
	CALL PUTSIX
	O.CRLF
	CALL INDENT
	O.STR <.FBSS1:	>	;RUN 1 SAVE SET NUMBER ,, TAPE FILE NUMBER
	MOVE T2,.FBSS1(FB)
	MOVE T3,[1B0+^D10]	;USE DECIMAL
	CALL PUTHLF
	O.CRLF
	CALL INDENT
	O.STR <.FBTP2:	>	;TAPE ID FOR RUN 2
	MOVE T2,.FBTP2(FB)
	CALL PUTSIX
	O.CRLF
	CALL INDENT
	O.STR <.FBSS2:	>	;RUN 2 SAVE SET NUMBER ,, TAPE FILE NUMBER
	MOVE T2,.FBSS2(FB)
	MOVE T3,[1B0+^D10]	;IN DECIMAL
	CALL PUTHLF
	O.CRLF
	RET			;RETURN TO WHENCE WE CAME ...
; GDBPNT - ROUTINE TO OUTPUT A GROUP DESCRIPTOR BLOCK
;
; CALL:		MOVE P1,ADR OF BLOCK
;		CALL GDBPNT
;		RETURN


GDBPNT:	O.STR <
Group Descriptor Block at >
	O.OCT P1		;OUTPUT ADDRESS OF BLOCK
	O.STR < is:
>
	GETMPW A1,P1		;GET FIRST WORD OF BLOCK
	LOAD A1,BT%LEN,A1	;KEEP JUST THE BLOCK LENGTH
	MOVE A2,P1		;COPY ADDRESS OF BLOCK
	SETZM A3		;INITIALIZE OFFSET INTO BLOCK
GDBPA1:	O.STR <	>		;OUTPUT A TAB
	GETMPW T2,A2		;GET WORD FROM THE BLOCK
	MOVE T3,[1B0+10]	;PRINT MAGNITUDE, OCTAL
	CALL PUTHLF		;GO OUTPUT HALFWORDS
	O.CRLF			;NEW LINE
	ADDI A3,1		;INCREMENT OFFSET INTO BLOCK
	SOJLE A1,R		;DECREMENT COUNT, RETURN IF DONE
	AOJA A2,GDBPA1		;GO OUTPUT NEXT WORD IN BLOCK
; FBTPNT - ROUTINE TO OUTPUT A FREE BIT TABLE BLOCK
;
; CALL:		MOVE P1,ADR OF BLOCK
;		CALL FBTPNT
;		RETURN


FBTPNT:	O.STR <
Free Bit Table Block at >
	O.OCT P1		;OUTPUT ADDRESS OF BLOCK
	O.STR < is:
	HEADER: >
	GETMPW T2,P1		;GET FIRST WORD OF BLOCK
	MOVX T3,NO%MAG+^D8	;USE OCTAL, PRINT MAGNITUDE
	CALL PUTHLF		;OUTPUT HEADER AS HALFWORDS
	O.STR <
>				;OUTPUT REMAINDER OF LINE
	GETMPW A1,P1		;GET FIRST WORD OF BLOCK
	LOAD A1,BT%LEN,A1	;KEEP JUST THE BLOCK LENGTH
	SUBI A1,1		;GET JUST THE LENGTH - 1
	MOVEI A2,1(P1)		;COPY ADDRESS OF BLOCK+1
	SETZM A3		;INITIALIZE OFFSET INTO BLOCK
FBTPA1:	O.STR <		>	;OUTPUT A TAB
	GETMPW T2,A2		;GET WORD FROM THE BLOCK
	O.OCTM T2		;OUTPUT A WORD FROM THE BLOCK
	O.CRLF			;NEW LINE
	ADDI A3,1		;INCREMENT OFFSET INTO BLOCK
	SOJLE A1,R		;DECREMENT COUNT, RETURN IF DONE
	AOJA A2,FBTPA1		;GO OUTPUT NEXT WORD IN BLOCK
; FREPNT - ROUTINE TO OUTPUT A FREE BLOCK
;
; CALL:		MOVE P1,ADDRESS OF FREE BLOCK
;		CALL FREPNT
;		RETURN


FREPNT:	GETMPW A1,P1		;GET FIRST WORD OF FREE BLOCK
	HLRZ A1,A1		;GET BLOCK TYPE
	CAIN A1,.TYFRE		;IS THIS A FREE BLOCK ?
	JRST FREPA1		;YES, GO PRINT IT
	O.STR <
? Incorrect block type >
	O.OCT A1		;OUTPUT THE BLOCK TYPE
	O.STR < found in Free Block at >
	O.OCT P1		;OUTPUT ADDRESS OF BLOCK
	O.CRLF			;OUTPUT A CRLF
	CALLRET BLKPNT		;GO PRINT THE FUNNY BLOCK

FREPA1:	O.STR <
Free Block at >
	O.OCT P1		;OUTPUT ADDRESS OF BLOCK
	O.STR < is:
	>
	GETMPW T2,P1	;GET FIRST WORD OF BLOCK
	MOVE T3,[1B0+10]	;PRINT MAGNITUDE, OCTAL
	CALL PUTHLF		;GO OUTPUT HALFWORDS
	O.STR <
	>
	MOVEI A1,.FRPTR(P1)	;GET ADR OF POINTER TO NEXT BLK
	GETMPW A2,A1		;GET POINTER TO NEXT FREE BLOCK
	O.OCT A2		;OUTPUT THE POINTER
	O.CRLF			;OUTPUT A CRLF
	O.CRLF			;OUTPUT A CRLF
	RET			;RETURN TO WHENCE WE CAME ...
; DPGPNT - ROUTINE TO OUTPUT THE DIRECTORY-PAGE HEADER
;	   BLOCK.
;
; CALL:		MOVE P1,ADDRESS OF BLOCK
;		CALL DPGPNT
;		RETURN


DPGPNT:	GETMPW A1,P1		;GET FIRST WORD OF BLOCK
	HLRZ A1,A1		;GET JUST THE BLOCK TYPE
	CAIN A1,.TYDIR		;IS THIS A DIRECTORY BLOCK ?
	JRST DPGPA1		;YES, GO OUTPUT IT
	O.STR <
? Incorrect Block Type >
	O.OCT A1		;OUTPUT BLOCK TYPE
	O.STR < found at address >
	O.OCT P1		;OUTPUT ADDRESS
	O.CRLF			;OUTPUT A CRLF
	O.CRLF			;ANOTHER CRLF
	CALLRET BLKPNT		;GO OUTPUT THE UNKNOWN BLOCK

DPGPA1:	O.STR <
Directory-Page Block at >
	O.OCT P1		;OUTPUT ADDRESS OF BLOCK
	O.STR < is:
	>
	GETMPW T2,P1		;GET FIRST WORD OF BLOCK
	MOVE T3,[1B0+10]	;PRINT MAGNITUDE, OCTAL
	CALL PUTHLF		;OUTPUT THE FIRST WORD
	O.STR <
	>			;OUTPUT NEW LINE, TAB
	MOVEI A1,.DIRPN(P1)	;GET ADR OF SECOND WORD
	GETMPW T2,A1		;GET SECOND WORD OF BLOCK
	MOVE T3,[1B0+10]	;PRINT MAGNITUDE, OCTAL
	CALL PUTHLF		;OUTPUT HALFWORDS
	O.STR <
	>			;OUTPUT NEW LINE, TAB
	MOVEI A1,.DIFFB(P1)	;GET ADDRESS OF THIRD WORD
	GETMPW A2,A1		;GET ADDRESS OF FIRST FREE BLOCK
	O.OCT A2		;OUTPUT THIRD WORD OF BLOCK
	O.CRLF			;OUTPUT A CRLF
	RET			;RETURN TO WHENCE WE CAME ...
; BLKPNT - ROUTINE TO OUTPUT AN UNKNOWN BLOCK TYPE IN OCTAL.
;
; CALL:		MOVE P1,ADDRESS OF BLOCK
;		CALL BLKPNT
;		RETURN


BLKPNT:	O.CRLF			;LEAVE A BLANK LINE
	CHEK A2,P1,BADPTR	;INSURE THAT ADDRESS IS KOSHER
	GETMPW A1,P1		;GET FIRST WORD OF BLOCK
	LOAD A1,BT%LEN,A1	;GET THE LENGTH OF THE BLOCK
	CAIG A1,MAXPRT		;IS BLOCK VERY LARGE ?
	JRST BLKPT0		;NO, GO OUTPUT THE BLOCK
	O.STR <First >		;START OF MESSAGE
	O.DEC [MAXPRT]		;OUTPUT # OF WORDS TO BE OUTPUT
	O.STR < of words of block are ...

>
	MOVEI A1,MAXPRT		;YES, JUST PRINT FIRST FEW WORDS
BLKPT0:	MOVEI A2,1		;INITIALIZE WORD COUNTER

BLKPA1:	CAMLE A2,A1		;MORE WORDS TO OUTPUT ?
	JRST BLKPA2		;NO, GO OUTPUT ANOTHER CRLF
	MOVE A3,P1		;GET ADDRESS OF BLOCK
	ADDI A3,-1(A2)		;COMPUTE ADR OF WORD TO OUTPUT
	CHEK A4,A3		;CHECK THE ADDRESS FOR SAFETY
	GETMPW A4,A3		;GET CONTENTS OF THE WORD
	O.OCTM A4		;OUTPUT THE WORD
	O.CRLF			;OUTPUT A CRLF
	AOJA A2,BLKPA1		;GO OUTPUT REMAINING WORDS

; HERE WHEN ALL WORDS HAVE BEEN OUTPUT

BLKPA2:	O.CRLF			;OUTPUT A CRLF
	RET			;RETURN TO WHENCE WE CAME ...
SUBTTL	OUTPUT COMMAND

.OUTPT:	STKVAR <OUTPTJ>		;ALLOCATE TEMP STORAGE FOR JFN
	MOVEI T1,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI T2,[CMFDB (.CMNOI,,<TXT(TO FILE)>)]
	COMND			;PARSE NOISE PHRASE
	MOVEI T2,[CMFDB (.CMOFI)]
	COMND			;PARSE OUTPUT FILE NAME
	TXNN T1,CM%NOP		;PARSE NAME OK ?
	JRST OUTPA2		;YES, GO CONFIRM COMMAND AND SAVE JFN
	CALL TSTCOL		;ISSUE CRLF IF NEEDED
	TMSG <? DIRPNT: Invalid file specification
>
	RET			;RETURN

OUTPA2:	MOVEM T2,OUTPTJ		;SAVE OUTPUT JFN
	MOVEI T2,[CMFDB (.CMCFM)] ;GET CONFIRM FUNCTION
	COMND			;PARSE CONFIRMATION
	TXNE T1,CM%NOP		;CONFIRMATION PARSED OK ?
	CALLRET COMER1		;NO, ISSUE ERROR MESSAGE
	SKIPE T1,OUTJFN		;GET PREVIOUS OUTPUT JFN
	CLOSF			;CLOSE THE FILE
	 JFCL			;IGNORE FAILURE
	SKIPE T1,OUTJFN		;GET OUTPUT JFN AGAIN
	RLJFN			;RELEASE THE JFN
	 JFCL
	MOVE T1,OUTPTJ		;YES, RESTORE OUTPUT FILE JFN
	MOVEM T1,OUTJFN		;SAVE OUTPUT FILE JFN
	RET			;RETURN
SUBTTL	LIST COMMAND

.LIST:	MOVEI T1,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI T2,[CMFDB (.CMNOI,,<TXT(ON PRINTER)>)]
	COMND			;PARSE NOISE PHRASE
	MOVEI T1,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI T2,[CMFDB (.CMCFM)] ;GET CONFIRM FUNCTION
	COMND			;PARSE END-OF-COMMAND
	TXNE T1,CM%NOP		;END-OF-COMMAND SEEN OK ?
	CALLRET COMER1		;NO, GO ISSUE ERROR MESSAGE
	MOVX T1,GJ%FOU!GJ%SHT	;SHORT CALL, FOR OUTPUT USE
	HRROI T2,[ASCIZ /LPT:/]	;TO PRINTER
	GTJFN			;GET A JFN FOR PRINTER
	 JSERR			;UNEXPECTED ERROR
	MOVEM T1,OUTJFN		;SAVE OUTPUT JFN
	RET			;RETURN
; TYPE COMMAND

.TYPE:	MOVEI T1,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI T2,[CMFDB (.CMNOI,,<TXT(ON TERMINAL)>)]
	COMND			;PARSE NOISE PHRASE
	MOVEI T1,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI T2,[CMFDB (.CMCFM)] ;GET CONFIRM FUNCTION
	COMND			;PARSE END-OF-COMMAND
	TXNE T1,CM%NOP		;END-OF-COMMAND SEEN OK ?
	CALLRET COMER1		;NO, GO ISSUE ERROR MESSAGE
	MOVX T1,.PRIOU		;GET PRIMARY OUTPUT JFN
	MOVEM T1,OUTJFN		;SAVE OUTPUT JFN
	RET			;RETURN
SUBTTL	DIRECTORY COMMAND

.DIREC:	STKVAR <DIRECN>		;DIRECTORY NUMBER
	MOVEI T1,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI T2,[CMFDB (.CMNOI,,<TXT(FILE)>)] ;PARSE NOISE PHRASE
	COMND			;PARSE GUIDE PHRASE
	TXNN T1,CM%NOP		;PARSED OK ?
	JRST DUMP05		;YES, GO ON
	CALL TSTCOL		;NO, ISSUE NEW LINE IF NEEDED
	TMSG <? DIRPNT: Invalid guide phrase ">
	HRROI T1,ATMBFR		;GET POINTER TO ATOM BUFFER
	PSOUT			;OUTPUT THE TEXT ENTERED
	TMSG <"
>				;TERMINATE MESSAGE
	RET			;RETURN

DUMP05:	GJINF			;GET CONNECTED DIRECTORY NUMBER
	HRROI T1,REPLY		;GET POINTER TO DIRECTORY NAME
	DIRST			;GET STRING FOR DIRECTORY NAME
	 JRST [	SETZM DIRFDB+.CMDEF ;FAILED, CLEAR DEFAULT
		JRST DUMP07 ]	;GO DO INPUT WITHOUT DEFAULT
	MOVE T1,[POINT 7,REPLY]	;GET POINTER TO STR:<DIR> STRING
	CALL GTSTR		;SET UP TO DUMP CONNECTED DIRECTORY STRING
	 JRST [	SETZM DIRFDB+.CMDEF ;FAILED, CLEAR DEFAULT
		JRST DUMP07 ]	;GO DO INPUT WITHOUT DEFAULT
	MOVEM T2,DIRFDB+.CMDEF	;SAVE POINTER TO DEFAULT STRING
DUMP07:	MOVEI T1,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI T2,DIRFDB		;GET ADDRESS OF DIRECTORY FILESPEC FDB
	COMND			;PARSE FILESPEC
	TXNN T1,CM%NOP		;FILENAME PARSED OK ?
	JRST DIREC2		;YES, GO STORE DIRECTORY NUMBER
	CALL TSTCOL		;OUTPUT CRLF IF NEEDED
	TMSG <? DIRPNT: No such directory file as ">
	HRROI T1,ATMBFR		;GET ATOM BUFFER POINTER
	PSOUT			;OUTPUT NAME ENTERED BY USER
	TMSG <"
>				;OUTPUT END OF MESSAGE
	RET			;RETURN

DIREC2:	MOVEM T2,DIRECN		;SAVE JFN
	MOVEI T2,[CMFDB (.CMCFM)]
	COMND			;CONFIRM COMMAND
	TXNE T1,CM%NOP		;END-OF-COMMAND SEEN OK ?
	CALLRET COMER1		;NO, GO ISSUE MESSAGE
	SKIPE T1,DIRJFN		;GET CURRENT DIRECTORY JFN
	CLOSF			;CLOSE THE FILE, RELEASE JFN
	 JFCL			;IGNORE ERRORS
	SKIPE T1,DIRJFN		;GET JFN AGAIN
	RLJFN			;RELEASE IT IN CASE IT WAS NOT OPENED
	 JFCL			;IGNORE FAILURE
	MOVE T1,DIRECN		;GET JFN OF DIRECTORY FILE
	MOVEM T1,DIRJFN		;SAVE DIRECTORY JFN
	HRROI T1,REPLY		;GET ADDRESS OF TEMPORARY BUFFER
	HRRZ T2,DIRJFN		;GET JFN OF DIRECTORY FILE
	MOVX T3,<FLD(.JSAOF,JS%DEV)+JS%PAF>
	JFNS			;GET THE STRUCTURE NAME
	HRROI T1,REPLY		;GET POINTER TO STR NAME
	STDEV			;GET DEV DESIGNATOR
	 ERJMP R		;FAILED, RETURN
	HRLM T2,CURDIR		;SAVE STR UNIQUE CODE
	HRRZ T1,DIRJFN		;GET DIRECTORY FILE JFN
	MOVE T2,[1,,.FBGEN]	;GET DIR # FROM FDB
	MOVEI T3,T4		;PUT DIR # INTO T4
	GTFDB			;GET DIRECTORY NUMBER
	 ERJMP R		;RETURN ON FAILURE
	HRRM T4,CURDIR		;FORM COMPLETE DIRECTORY DESIGNATOR
	RET			;YES,...
SUBTTL	HELP AND EXIT COMMANDS

; HELP COMMAND

.HELP:	MOVEI T1,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI T2,[CMFDB (.CMNOI,,<TXT(WITH DIRPNT)>)]
	COMND			;PARSE NOISE WORDS
	MOVEI T1,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI T2,[CMFDB (.CMCFM)] ;GET FUNCTION BLOCK FOR CONFIRMATION
	COMND			;WAIT FOR CONFIRMATION
	TXNE T1,CM%NOP		;VALID END-OF-COMMAND SEEN ?
	CALLRET COMER1		;NO, ISSUE ERROR MESSAGE AND RETURN
	HRROI T1,HLPMSG		;GET POINTER TO HELP MESSAGE
	PSOUT			;OUTPUT HELP MESSAGE
	RET			;GO PARSE NEXT COMMAND

; EXIT COMMAND

.EXIT:	MOVEI T1,CMDBLK		;GET ADDRESS OF COMMAND BLOCK
	MOVEI T2,[CMFDB (.CMNOI,,<TXT(TO MONITOR)>)]
	COMND			;PARSE NOISE PHRASE
	MOVEI T2,[CMFDB (.CMCFM)] ;GET FUNCTION BLOCK FOR CONFIM
	COMND			;PARSE CONFIRMATION
	TXNE T1,CM%NOP		;VALID END-OF-COMMAND SEEN ?
	CALLRET COMER1		;NO, ISSUE ERROR MESSAGE AND RETURN
	SETOM T1		;INDICATE ALL FILES SHOULD BE CLOSED
	CLOSF			;CLOSE ALL OPEN FILES
	 JSERR			;UNEXPECTED ERROR
	HALTF			;RETURN TO MONITOR
	JRST START		;IF CONTINUE'D, START OVER
SUBTTL	COMMAND ERROR SUBROUTINES

; INVALID END-OF-COMMAND

COMER1:	CALL TSTCOL		;TEST COLUMN POSITION
	TMSG <? DIRPNT: Garbage at end-of-command
>				;OUTPUT ERROR MESSAGE
	RET			;RETURN TO WHENCE WE CAME ...


; SUBROUTINE TO TEST COLUMN POSITION AND OUTPUT CRLF IF NEEDED

TSTCOL:	MOVEI T1,.PRIOU		;GET PRIMARY OUTPUT DESIGNATOR
	RFPOS			;READ FILE POSITION
	HRRZ T2,T2		;KEEP JUST THE COLUMN POSITION
	JUMPE T2,R		;IF AT COLUMN 1 DO NOT OUTPUT CRLF
	TMSG <
>				;no, output a crlf
	RET			;RETURN TO WHENCE WE CAME ...
; GTDJFN - ROUTINE TO GET A JFN FOR THE CURRENT DIRECTORY
;	   FILE.
;
; CALL:		CALL GTDJFN
;		RETURN

GTDJFN:	MOVE A1,[JFNBLK,,JFNBLK+1]  ;GET SOURCE,,DESTINATION
	SETZM JFNBLK		;CLEAR FIRST WORD OF GTJFN BLOCK
	BLT A1,JFNBLK+GJFSIZ-1	;CLEAR ENTIRE GTJFN BLOCK
	HRROI A1,REPLY		;GET POINTER TO NAME STRING
	MOVEM A1,JFNBLK+.GJNAM	;STORE POINTER TO NAME STRING
	HRROI A1,[ASCIZ/ROOT-DIRECTORY/]
	MOVEM A1,JFNBLK+.GJDIR	;SAVE DIRECTORY
	HRROI A1,[ASCIZ/DIRECTORY/]  ;GET POINTER TO EXTENSION
	MOVEM A1,JFNBLK+.GJEXT	;STORE POINTER TO EXTENSION
	MOVX A1,GJ%OLD		;GET OLD FILE BIT
	MOVEM A1,JFNBLK+.GJGEN	;SAVE THE FLAGS
	MOVE A1,[377777,,377777] ;NO ECHOING JFNS
	MOVEM A1,JFNBLK+.GJSRC	;STORE JFN'S
	MOVEI T1,JFNBLK		;GET POINTER TO GTJFN BLOCK
	SETZM T2		;NO MAIN STRING POINTER
	GTJFN			;GET A JFN FOR DIRECTORY FILE
	  CALL TYPERR		;UNEXPECTED ERROR
	MOVEM T1,DIRJFN		;SAVE DIRECTORY JFN
	RET			;RETURN TO WHENCE WE CAME ...
;GTFILE - GET FILE NAME FOR THIS DIRECTORY AND GET A JFN ON IT
;
;ACCEPTS IN T1/	POINTER TO DIRECTORY SPEC
;	    T2/	DIRECTORY DESIGNATOR
;	CALL GTFILE
;RETURNS: +1	 FAILED
;	  +2	SUCCESS, WITH DIRJFN CONTAINING JFN OF DIRECTORY FILE

GTFILE:	TDZA T4,T4		;NOTE JFN WANTED
GTSTR:	SETOM T4		;NOTE STRING WANTED
	STKVAR <GTFPTR,GTFDIR,DOTPTR,BRKPTR,GTFFLG>
	MOVEM T1,GTFPTR		;SAVE POINTER TO DIRECTORY SPEC
	MOVEM T2,GTFDIR		;SAVE DIRECTORY DESIGNATOR
	MOVEM T4,GTFFLG		;SAVE FLAG

	SETZM DOTPTR		;INDICATE DOT NOT FOUND YET
	SETZM BRKPTR		;INDICATE BRACKET NOT FOUND YET
GTFIL1:	ILDB T2,T1		;GET NEXT CHARACTER IN STRING
	CAIN T2,"<"		;LEFT BRACKET?
	JRST [	MOVEM T1,BRKPTR	;YES. SAVE ITS POINTER
		JRST GTFIL1]	;GO GET NEXT CHARACTER
	CAIN T2,"."		;IS IT A DOT?
	JRST [	MOVEM T1,DOTPTR	;YES. SAVE ITS POINTER
		JRST GTFIL1]	;GO GET NEXT CHARACTER
	CAIE T2,">"		;IS IT A RIGHT BRACKET?
	JRST GTFIL1		;NO. GO GET NEXT CHARACTER
	SKIPN DOTPTR		;FOUND RIGHT BRACKET. HAVE WE SEEN A DOT?
	JRST GTFIL2		;NO. MUST BE IN <ROOT-DIRECTORY>

;HERE WHEN THIS IS A SUBDIRECTORY.  ;WE HAVE STR:<DIRECTORY.SUBDIRECTORY>.
;CONVERT TO STR:<DIRECTORY>SUBDIRECTORY.DIRECTORY

	DPB T2,DOTPTR		;REPLACE DOT WITH RIGHT BRACKET
	MOVEI T2,"."		;GET A DOT
	DPB T2,T1		;REPLACE RIGHT BRACKET WITH DOT
	HRROI T2,[ASCIZ/DIRECTORY/] ;T2/ SOURCE IS THIS STRING
	SETZ T3,		;T3/ STOP ON NULL
	SOUT			;FORM STR:<DIR>SUBDIR.DIRECTORY
	MOVE T2,GTFPTR		;GET POINTER TO DIRECTORY SPEC
	JRST GTFIL3		;GO GET JFN

;HERE WHEN DIRECTORY IS IN ROOT-DIRECTORY. FORM STR:<ROOT-DIRECTORY>DIR.DIRECTORY

GTFIL2:	HRROI T1,TMPSTR		;GET POINTER TO TEMPORARY STRING AREA
	HLRZ T2,GTFDIR		;GET STRUCTURE UNIQUE CODE
	HRLI T2,.DVDES		;FORM DEVICE DESIGNATOR
	DEVST			;GET STRING FOR STR
	 RET			;FAILED, RETURN FAILURE
	MOVX T2,":"		;GET STR PUNCTUATION
	IDPB T2,T1		;ADD STR PUNCTUATION
	HRROI T2,[ASCIZ/<ROOT-DIRECTORY>/]
	SETZM T3		;TERMINATE ON NULL
	SOUT			;ADD DIRECTORY TO STR STRING
	MOVE T2,BRKPTR		;POINT TO LEFT BRACKET
	MOVEI T3,^D40		;DIRECTORY NAME <=39 CHARACTERS
	MOVEI T4,">"		;STOP ON RIGHT BRACKET
	SOUT			;COPY DIRECTORY NAME
	SETOM T3		;BACK UP POINTER OVER THE BRACKET
	IBP T3,T1
	MOVEM T3,T1		;T1/ DESTINATION IS END OF DIRECTORY NAME
	HRROI T2,[ASCIZ/.DIRECTORY/] ;T2/ POINTER TO SOURCE
	SETZ T3,		;T3/ STOP ON NULL
	SOUT			;COPY ".DIRECTORY" TO END OF STRING
	HRROI T2,TMPSTR		;POINT TO START OF THIS STRING
	JRST GTFIL3		;GO GET JFN

;T2 POINTS TO FILE SPEC. GET A JFN ON THIS DIRECTORY FILE

GTFIL3:	SKIPE GTFFLG		;STRING WANTED ?
	RETSKP			;YES, RETURN STRING
	MOVX T1,GJ%PHY!GJ%SHT!GJ%OLD	;PHYSICAL ONLY, SHORT BLOCK
	GTJFN			;GET A JFN
	RET			;FAILED, RETURN ERROR
	HRRZM T1,DIRJFN		;SAVE JFN
	RETSKP			;DONE, RETURN
SUBTTL		MAPPING SUBROUTINES

; MAPDP0 - ROUTINE TO MAP DIRECTORY PAGE 0 INTO THE
;	   ADDRESS SPACE OF THIS PROCESS.
;
; CALL:		[JFN FOR DIRECTORY FILE IS IN DIRJFN]
;		CALL MAPDP0
;		RETURN

MAPDP0:	HRLZ T1,DIRJFN		;GET DIRECTORY JFN,, FILE PAGE 0
	MOVSI T2,.FHSLF		;GET OUR FORK HANDLE
	MOVEI A1,DIRPG0		;GET CORE ADDRESS OF DIR PAGE 0
	LSH A1,-^D9		;CONVERT ADDRESS TO PAGE #
	HRR T2,A1		;COPY ADDRESS TO ARG AC FOR PMAP
	MOVX T3,PM%RD		;READ ACCESS ONLY
	PMAP			;MAP THE PAGES
	RET			;RETURN TO WHENCE WE CAME ...
; MAPSTB - ROUTINE TO MAP THE SYMBOL TABLE INTO THE ADDRESS
;	   SPACE OF THIS PROCESS.
;
; CALL:		[PAGE 0 OF DIRECTORY MUST BE MAPPED]
;		CALL MAPSTB
;		RETURN


MAPSTB:	HRLZ T1,DIRJFN		;GET JFN OF DIRECTORY FILE
	LOAD A1,DRBOT		;GET START ADDRESS OF TABLE
	LSH A1,-^D9		;CONVERT ADDRESS TO PAGE #
	HRR T1,A1		;COPY PAGE # TO ARG AC FOR PMAP
	MOVSI T2,.FHSLF		;GET OUR FORK HANDLE
	MOVEI A1,SYMTAB		;GET ADDRESS TO MAP TABLE INTO
	LSH A1,-^D9		;CONVERT ADDRESS TO A PAGE #
	HRR T2,A1		;COPY PAGE # TO ARG AC FOR PMAP
	MOVX T3,<PM%CNT!PM%RD>	;MULTIPLE PAGES, READ
	LOAD A1,DRBOT		;GET BOTTOM ADDRESS OF TABLE
	LOAD A2,DRTOP		;GET TOP ADDRESS OF SYMBOL TABLE
	SUB A2,A1		;COMPUTE SIZE OF TABLE
	LSH A2,-^D9		;CONVERT # OF WORDS TO PAGES
	HRRI T3,1(A2)		;COPY # OF PAGES TO MAP
	PMAP			;MAP THE PAGES
	MOVEI A1,SYMTAB		;GET CORE ADR OF SYMBOL TABLE
	HRRZ A2,T1		;GET PAGE NUMBER IN FILE
	LSH A2,^D9		;COMPUTE ADDRESS IN FILE
	SUB A1,A2		;COMPUTE OFFSET REQUIRED
	MOVEM A1,STBOFS		;SAVE OFFSET TO SYMBOL TABLE
	RET			;RETURN TO WHENCE WE CAME ...
; MAPDIR - ROUTINE TO MAP PAGES FROM THE DIRECTORY FILE INTO THE
;	   ADDRESS SPACE OF THIS PROCESS.
;
; CALL:		[JFN FOR DIRECTORY FILE IS IN DIRJFN]
;		MOVE MA,REQUIRED ADDRESS
;		CALL MAPDIR
;		RETURN

MAPDIR:	CALL SAVACS		;GO SAVE ALL AC'S
	HRLZ T1,DIRJFN		;GET DIRECTORY JFN
	MOVE A1,MA		;COPY ADDRESS REQUIRED
	LSH A1,-^D9		;CONVERT ADDRESS TO PAGE #
	HRR T1,A1		;GET PAGE # IN FILE
	MOVSI T2,.FHSLF		;GET OUR FORK HANDLE
	MOVEI A1,MAPPGS		;GET CORE ADDRESS OF DIR PAGE
	LSH A1,-^D9		;CONVERT ADDRESS TO PAGE #
	HRR T2,A1		;COPY ADDRESS TO ARG AC FOR PMAP
	MOVX T3,PM%RD!PM%CNT	;READ ACCESS ONLY, ITERATION CNT
	HRRI T3,FDBPGS		;GET # OF PAGES TO MAP
	LOAD A1,DRFRE		;GET HIGHEST ADDRESS+1 FOR FDB'S
	SUBI A1,1		;COMPUTE HIGHEST ADR FOR FDB'S
	LSH A1,-^D9		;CONVERT ADDRESS TO PAGE #
	MOVE A2,MA		;GET DESIRED ADDRESS
	LSH A2,-^D9		;CONVERT ADDRESS TO A PAGE #
	SUB A1,A2		;COMPUTE # OF PAGES TO MAP-1
	ADDI A1,1		;COMPUTE # OF PAGES TO MAP
	CAIG A1,FDBPGS		;LESS THAN # OF MAPPING PAGES ?
	HRR T3,A1		;YES, USE LESSER # OF PAGES
	HRREI T4,-1(T3)		;SAVE # OF PAGES TO MAP-1
	PMAP			;MAP THE PAGES
	MOVE A1,MA		;GET REQUIRED ADDRESS
	TRZ A1,777		;COMPUTE LOWEST ADDRESS MAPPED
	MOVEM A1,MAPBOT		;SAVE LOWEST ADDRESS MAPPED
	LSH A1,-^D9		;CONVERT LOWEST ADR TO PAGE #
	ADD A1,T4		;COMPUTE HIGHEST PAGE MAPPED
	LSH A1,^D9		;CONVERT PAGE # TO ADDRESS
	TRO A1,777		;COMPUTE HIGHEST ADR MAPPED
	MOVEM A1,MAPTOP		;SAVE HIGHEST ADR MAPPED
	MOVEI A1,MAPPGS		;GET ADDRESS OF MAPPED AREA
	HRRZ A2,T1		;GET PAGE # IN FILE
	LSH A2,^D9		;COMPUTE ADDRESS IN FILE
	SUB A1,A2		;COMPUTE MAPPED ADDRESS OFFSET
	MOVEM A1,FDBOFS		;SAVE OFFSET TO MAPPED ADDRESSES
	CALL RESACS		;GO RESTORE ALL THE AC'S
	RET			;RETURN TO WHENCE WE CAME ...
; ECHOFF - ROUTINE TO TURN OFF ECHOING FOR ESCAPES
;
; CALL:		CALL ECHOFF
;		RETURN


ECHOFF:	MOVEI T1,.PRIOU		;GET PRIMARY OUTPUT JFN
	RFCOC			;READ ECHOING BITS
	TRZ T3,3B19		;TURN OFF ESCAPE ECHOING
	SFCOC			;TELL MONITOR
	RET			;RETURN TO WHENCE WE CAME ...



; SAVACS - ROUTINE TO SAVE ALL 16 ACCUMULATORS.
;
; CALL:		CALL SAVACS
;		RETURN


SAVACS:	MOVEM 0,SAVE0		;SAVE ACCUMULATOR 0
	MOVE 0,[T1,,SAVET1]	;SET UP FOR BLT
	BLT 0,SAVET1+16		;SAVE NEXT 15 ACCUMULATORS
	RET			;RETURN TO WHENCE WE CAME ...



; RESACS - ROUTINE TO RESTORE ALL 16 ACCUMULATORS
;
; CALL:		CALL RESACS
;		RETURN


RESACS:	MOVE 0,[SAVET1,,T1]	;SET UP FOR BLT
	BLT 0,17		;RESTORE AC'S 1-17
	MOVE 0,SAVE0		;RESTORE AC 0
	RET			;RETURN TO WHENCE WE CAME ...
; INDENT - ROUTINE TO OUTPUT LEADING TABS. THE NUMBER OF
;	   TABS OUTPUT IS CONTROLLED BY THE NUMBER
;	   STORED AT LOCATION "INDVAL".
;
; CALL:		PUSHJ P,INDENT
;		RETURN

INDENT:	MOVE T1,OUTJFN		;GET OUTPUT JFN
	MOVE A1,INDVAL		;GET # OF TABS TO OUTPUT
	MOVEI T2,.CHTAB		;GET A TAB CHARACTER
RETTST:	SOJL A1,R##		;RETURN  IF ALL DONE
	BOUT			;OUTPUT ONE TAB
	JRST RETTST		;GO SEE IF DONE YET



; PUTSIX - ROUTINE TO PRINT A SINGLE WORD AS SIXBIT TEXT.
;	   OUTPUT GOES TO "OUTJFN"
;
; CALL:		MOVE T2,SIXBIT TEXT(ONE WORD MAX)
;		CALL PUTSIX
;		RETURN

PUTSIX:	TDZA T4,T4		;NOTE OUTPUT TO OUTJFN
ASMSIX:	SETOM T4		;NOTE OUTPUT TO TEXT ASSEMBLY AREA
	STKVAR <SIXTXT,SAVA1>	;ALLOCATE TEMPORARY STORAGE
	MOVEM A1,SAVA1		;SAVE AN AC FOR LATER USE
	MOVEM T2,SIXTXT		;SAVE THE TEXT
	MOVE T1,OUTJFN		;GET JFN FOR OUTPUT
	SKIPE T4		;OUTPUT TO TEXT ASSEMBLY AREA?
	MOVE T1,TXTPTR		;YES, GET POINTER
	MOVEI T2,"'"		;INDICATE TYPING SIXBIT
	BOUT
	MOVE T3,[POINT 6,SIXTXT] ;POINT AT SIXBIT TEXT
	MOVEI A1,6		;SIX CHARACTERS IN A WORD
SXLOOP:	ILDB T2,T3		;GET A SIXBIT CHARACTER
	ADDI T2,40		;MAKE IT ASCII
	BOUT			;OUTPUT A CHARACTER
	 ERJMP PUTERR
	SOJG A1,SXLOOP		;OUTPUT THE WHOLE WORD ALWAYS
	MOVEI T2,"'"		;INDICATE END OF SIXBIT OUTPUT
	BOUT
	MOVE A1,SAVA1		;RESTORE DESTROYED AC
	RET			;GO BACK

; PUTHLF - ROUTINE TO PRINT A 36-BIT QUANTITY AS TWO HALFWORDS.
;	   OUTPUT GOES TO JFN "OUTJFN"
;
; CALL:		MOVE T2,36-BIT QUANTITY
;		MOVE T3,RADIX AND CONTROL BITS
;		CALL PUTHLF
;		RETURN

PUTHLF:	TDZA T4,T4		;NOTE OUTPUT TO OUTJFN
ASMHLF:	SETOM T4		;NOTE OUTPUT TO TEXT ASSEMBLY AREA
	STKVAR <VALUE,RAIDIX,DCFL> ;ALLOCATE TEMPORARY STORAGE
	MOVEM T2,VALUE		;SAVE THE VALUE TO OUTPUT
	HRRZ T2,T3		;GET RADIX MINUS FLAGS
	SETZM DCFL		;ASSUME NOT DECIMAL
	CAIN T2,^D10		;DECIMAL REQUESTED?
	SETOM DCFL		;YES
	MOVE T1,OUTJFN		;GET JFN FOR OUTPUT
	SKIPE T4		;OUTPUT TO TEXT ASSEMBLY AREA ?
	MOVE T1,TXTPTR		;YES, GET POINTER
	HLRZ T2,VALUE		;GET LEFT HALFWORD TO OUTPUT
	NOUT			;OUTPUT THE LEFT HALFWORD
	  CALL PUTERR		;UNEXPECTED ERROR
	MOVEM T3,RAIDIX		;SAVE THE RAIDIX
	MOVEI T2,"."		;READY TO DO DECIMAL POINT
	SKIPE DCFL		;WANT ONE?
	BOUT			;YES
	HRROI T2,[ASCIZ / ,, /]	;GET PUNCTUATION
	SETZM T3		;TERMINATE ON NULL
	SOUT			;OUTPUT PUNCTUATION
	MOVE T3,RAIDIX		;RESTORE THE RAIDIX
	HRRZ T2,VALUE		;GET RIGHT HALF WORD OF ORIGINAL
	NOUT			;OUTPUT RIGHT HALFWORD
	  CALL PUTERR		;UNEXPECTED ERROR
	MOVEI T2,"."		;READY FOR DECIMAL POINT
	SKIPE DCFL		;DECIMAL?
	BOUT			;YES
	RET			;RETURN TO WHENCE WE CAME ...
;CHKCAP - ROUTINE TO CHECK CAPABILITIES


CHKCAP:	MOVEI T1,.FHSLF		;GET OUR PROCESS HANDLE
	RPCAP			;READ OUR ENABLED CAPABILITIES
	 ERJMP R		;IF FAILED, JUST CONTINUE
	TXNE T3,SC%WHL!SC%OPR	;WHEEL OR OPER ENABLED ?
	RET			;YES, ALL IS KOSHER
	CALL TSTCOL		;NO, ISSUE NEW LINE IF NEEDED
	TMSG <? DIRPNT: Required capabilities not enabled
>
	HALTF			;STOP SO USER CAN ENABLE
	JRST CHKCAP		;GO CHECK CAPABILITIES NOW

;LINEUP - ROUTINE TO OUTPUT A STRING WITH TRAILING PADDING SO NEXT STRING
;	  OUTPUT WILL LINE UP.
;
;ACCEPTS IN T1/	COLUMN NUMBER
;		CALL LINEUP
;RETURNS: +1 ALWAYS, STRING OUTPUT FOLLOWED BY REQUIRED NUMBER OF BLANKS

LINEUP:	ASUBR <LNUCNT,LNUPTR>

	SETZM T3		;TERMINATE ON NULL
	MOVE T2,[POINT 7,TEXT]	;GET POINTER TO ASSEMBLED TEXT
	MOVE T1,OUTJFN		;GET OUTPUT JFN
	SOUT			;OUTPUT INITIAL STRING

; DETERMINE NUMBER OF PADDING CHARACTERS NEEDED

	MOVE T4,[POINT 7,TEXT]	;GET POINTER TO START OF TEXT AGAIN
	MOVEM T4,LNUPTR		;SAVE POINTER
	SETZM T2		;INITIALIZE PADDING COUNT
LNU010:	ILDB T4,LNUPTR		;GET A CHARACTER FROM THE STRING
	CAIE T4,.CHNUL		;END OF STRING  ?
	AOJA T2,LNU010		;NO, INCREMENT PADDING COUNT AND GET NEXT CHAR

; OUTPUT REQUIRED NUMBER OF PAD CHARACTERS

	CAMLE T2,LNUCNT		;NEED TO DO ANY OUTPUT ?
	RET			;NO, JUST RETURN
	MOVE T3,LNUCNT		;YES, GET COLUMN NUMBER
	SUB T3,T2		;COMPUTE NUMBER OF PAD CHARACTERS NEEDED
	MOVEI T2," "		;GET THE PADDING CHARACTER
	MOVE T1,OUTJFN		;GET OUTPUT JFN

LNU020:	BOUT			;OUTPUT A PAD CHARACTER
	SOJG T3,LNU020		;LOOP UNTIL ALL PAD CHARACTERS OUTPUT
	RET			;DONE, RETURN
; TYPERR  - SUBROUTINE TO TYPE AN ERROR MESSAGE ON THE TERMINAL
;	   WHEN A JSYS GIVES AN ERROR RETURN.
;
; CALL:		CALL TYPERR
;		HALT THE PROCESS
;
; OR:		CALL PUTERR
;		RETURN
;
; PRESERVES ACCUMULATOR T1 - USES T2 AND T3


PUTERR:	SKIPA A1,[0]		;GET "RETURN TO CALLER" FLAG
TYPERR:	SETOM A1		;GET "STOP DEAD" FLAG
	MOVE A2,T1		;SAVE REGISTER T1
	MOVEI T1,.PRIOU		;USE PRIMARY OUTPUT
	HRLOI T2,.FHSLF		;CURRENT FORK, LAST ERROR
	SETZM T3		;NO FLAGS
	ERSTR			;OUTPUT THE ERROR MESSAGE
	  JRST	TYPER1		;UNDEFINED ERROR NUMBER
	  JRST	TYPER2		;ERSTR ERROR
	CRLF
	MOVE T1,A2		;RESTORE REGISTER T1
	JUMPN A1,STOP		;GO STOP IF CALLED BY PUTERR
	RET			;  OR RETURN IF CALLED BY TYPERR

TYPER1:	HRROI T1,[ASCIZ/
?DIRPNT: An unkown error has occurred
/]
	PSOUT			;TYPE THE MESSAGE
	MOVE T1,A2		;RESTORE REGISTER T1
	JUMPN A1,STOP		;GO STOP IF CALLED BY TYPERR
.POPJ:	RET			;  OR RETURN IF CALLED BY PUTERR
; HERE IF AN ERROR OCCURRED WHILE TYPING AN ERROR MESSAGE

TYPER2:	HRROI T1,[ASCIZ/
?DIRPNT: Error occurred while typing an error message
/]
	PSOUT			;OUTPUT THE ERROR MESSAGE
	MOVE T1,A2		;RESTORE REGISTER T1
	JUMPE A1,.POPJ		;IF CALLED VIA PUTERR, RETURN
STOP:	HALTF			;HALT THIS PROCESS
	JRST STOP		;IN CASE OF CONTINUE



; BADPTR - ROUTINE TO TYPE AN ERROR MESSAGE WHEN A BAD POINTER
;	   IS FOUND, AND THEN TO RETURN.
;
; 	CALLED BY THE CHEK MACRO ONLY !


BADPTR:	O.STR <
? Bad pointer found, attempting to continue...
>
	RET			;RETURN TO WHENCE WE CAME ...
SUBTTL CONSTANT DATA

; ENTRY VECTOR

ENTVEC:	JRST START		;MAIN ENTRY POINT
	JRST START		;REEENTER ADDRESS
	VDIRPT			;VERSION DEFINITION

PROMPT:	ASCIZ /DIRPNT>/		;PROMPT STRING
PDP:	IOWD PDLSIZ, PDL	;PUSH DOWN POINTER
HLPMSG:	ASCIZ /FUNCTION

        DIRPNT outputs the contents of the blocks in a  disk
        directory in a readable format.

COMMANDS

        DIRECTORY (FILE) DIRECTORY-FILE
        EXIT (TO MONITOR)
        HELP (WITH DIRPNT)
        TYPE (ON TERMINAL)
        LIST (ON PRINTER)
        OUTPUT (TO FILE) FILE-SPEC
        DUMP ARGUMENT

        ARGUMENT is one of:
                        CHAINED-FDBS
                        ENTIRE-DIRECTORY
                        FDB (AT) ADDRESS
                        SYMBOL-TABLE

DEFAULTS

        DIRECTORY (FILE) Connected-directory
        TYPE (ON TERMINAL)
        DUMP ENTIRE-DIRECTORY

EXAMPLES

	To dump just the header of the connected directory
	on the terminal, enter:

	DIRPNT>DUMP DIRECTORY-HEADER

	To dump the symbol table of directory PS:<ABCDE>
	on the terminal, enter:

	DIRPNT>DIRECTORY PS:<ROOT-DIRECTORY>ABCDE.DIRECTORY
	DIRPNT>DUMP SYMBOL-TABLE

	To dump the entire directory STR:<XYZ.ABC> to the
	printer, enter:

	DIRPNT>DIRECTORY (FILE) STR:<XYZ>ABC
	DIRPNT>LIST (ON PRINTER)
	DIRPNT>DUMP ENTIRE-DIRECTORY

RESTRICTIONS

        It  is  neccessary  to  have   WHEEL   or   OPERATOR
        capability enabled in order to read directory files.
/

; COMMAND TABLE

DEFINE TB(RTN,TXT)
<	[ASCIZ/TXT/] ,, RTN
>

CMDTAB:	CMDSIZ-1 ,, CMDSIZ
	TB (.DIREC,DIRECTORY)
	TB (.DUMP,DUMP)
	TB (.EXIT,EXIT)
	TB (.HELP,HELP)
	TB (.LIST,LIST)
	TB (.OUTPT,OUTPUT)
	TB (.TYPE,TYPE)

	CMDSIZ== .-CMDTAB

; TABLE OF ARGUMENTS FOR THE DUMP COMMAND

LSTTAB:	LSTSIZ-1 ,, LSTSIZ
	TB (CHNLST,CHAINED-FDBS)
	TB (HDRLST,DIRECTORY-HEADER)
	TB (DIRLST,ENTIRE-DIRECTORY)
	TB (FDBLST,FDB)
	TB (SYMLST,SYMBOL-TABLE)

	LSTSIZ==.-LSTTAB


; TABLE OF BLOCK TYPES AND THE ROUTINES TO OUTPUT THEM

TYPTAB:	.TYNAM ,, NAMPRT
	.TYUNS ,, UNSPRT
	.TYEXT ,, EXTPRT
	.TYFDB ,, FDBPRT
	.TYACT ,, ACTPRT
	.TYFRE ,, FREPNT
	.TYDIR ,, DPGPNT
	.TYGDB ,, GDBPNT
	.TYLAC ,, BLKPNT
	.TYFBT ,, FBTPNT

	TYPSIZ== .-TYPTAB
SUBTTL	VARIABLE DATA STORAGE

DIRFDB:	FLD(.CMIFI,CM%FNC)+CM%DPP
	EXP 0
	EXP 0
	EXP .-.			;DEFAULT POINTER, DIRECTORY COMMAND FILLS IN


PDL:	BLOCK PDLSIZ		;STACK
SAVE0:	BLOCK 1			;ACCUMULATOR 0 SAVED HERE
SAVET1:	BLOCK 17		;ACCUMULATORS 1-17 SAVED HERE
REPLY:	BLOCK REPSIZ		;BUFFER FOR USER REPLIES
LASTQ:	BLOCK 1			;POINTER TO LAST OUTPUT FOR ^R
OUTJFN:	BLOCK 1			;JFN FOR OUTPUT FILE
DIRJFN:	BLOCK 1			;JFN FOR DIRECTORY FILE
CURDIR:	BLOCK 1			;# OF DIRECTORY CURRENTLY MAPPED
STBOFS:	BLOCK 1			;ADDRESS OFFSET FOR SYMBOL TABLE
FDBOFS:	BLOCK 1			;ADDRESS OFFSET FOR FDB STORAGE
MAPBOT:	BLOCK 1			;LOWEST ADR MAPPED IN FDB AREA
MAPTOP:	BLOCK 1			;HIGHEST ADR MAPPED IN FDB AREA
JFNBLK:	BLOCK GJFSIZ		;GTJFN TABLE OF STRING POINTERS
INDVAL:	BLOCK 1			;CURRENT # OF TABS TO INDENT
CMDBLK:	BLOCK .CMGJB+5		;COMMAND STATE BLOCK FOR COMND JSYS
ATMBFR:	BLOCK ATMSIZ		;ATOM BUFFER
BUFFER:	BLOCK BUFSIZ		;INPUT TEXT GOES HERE
GJFBLK:	BLOCK GJFSIZ		;GTJFN BLOCK FOR COMND JSYS
HDRLST:	BLOCK 1			;0 IF DIRECTORY HEADER LISTING DESIRED
ONELST:	BLOCK 1			;SINGLE LISTING WANTED
FDBLST:	BLOCK 1			;IF NON-0, ADDRESS OF FDB TO LIST
CHNLST:	BLOCK 1			;0 IF CHAINED LISTING WANTED
DIRLST:	BLOCK 1			;0 IF LINEAR DIRECTORY LISTING WANTED
SYMLST:	BLOCK 1			;0 IF SYMBOL TABLE LISTING REQUESTED
LSTFLG:	BLOCK 1			;-1 IF NO LIST COMMAND WAS SEEN
TXTPTR:	BLOCK 1			;POINTER INTO TEXT ASSEMBLY AREA
TEXT:	BLOCK 50		;PLACE FOR TEXT BEING ASSEMBLED FOR OUTPUT
DEFDIR:	BLOCK 20		;DEFAULT DIRECTORY STRING
TMPSTR:	BLOCK 50		;TEMPORARY STRING AREA


; AREAS INTO WHICH PORTIONS OF THE DIRECTORY ARE MAPPED

	LOC DIRADR		;CHOOSE SOME HIGH ADDRESS,
				; OUT OF THE WAY OF THE PROGRAM


DIRPG0:	BLOCK PAGSIZ		;PAGE 0 OF THE DIRECTORY

MAPPGS:	BLOCK FDBPGS*PAGSIZ	;PAGES FOR MAPPING FDB'S

SYMTAB:	BLOCK STBPGS*PAGSIZ	;ENTIRE SYMBOL TABLE

	RELOC

	END <3,,ENTVEC>