Google
 

Trailing-Edge - PDP-10 Archives - BB-H311D-RM - swskit-tools/dirpnt.mac
There are 6 other files named dirpnt.mac in the archive. Click here to see a list.
;[114] More small tidying ups. (JGZ)
;[113] Change output format for .FBAUT. (JGZ)
;[112] Revise symbol table output format for better appearance, fit. (JGZ)
;[111] Build general ODTIM macro, A.DATE/O.DATE. (JGZ)
;[110] Add TOPS-10 PPN directory page zero variables for v6. (JGZ)
;[109] Add password encryption page zero variables for v6. (JGZ)
;[108] Decimal also for subdirectory counts, file expiration interval. (JGZ)
;[107] Print directory quotas, allocation in decimal. (JGZ)
;[106] Print Header/Next on free block typeout. (JGZ)
;[105] Pretty up listing a bit: pages, XLIST/LIST, MACROs... (JGZ)
;[104] Standardize to "Header:" (JGZ)
;[103] Change FDB typeout back to using the correct .FBxxx names. (JGZ)
;[102] Merge various edits, decimal version number. (JGZ)
;101	JBS	2-Feb-84
;	Add % after all JSYSes, change ambiguous messages, fix bug that
;	gave error "file is already open" all the time with DUMP command,
;	don't save/restore P in SAVACS/RESACS, remove LIST and TYPE commands
;	since they are redundant with OUTPUT, update help text and file.
;
;<V-SOURCES>DIRPNT.MAC.5, 27-SEP-82 14:55:00, EDIT BY MCINTEE
;HANDLE REMOTE ALIAS BLOCKS
;<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/WET/JBS/JGZ		28-AUG-84

	SEARCH MACSYM, MONSYM
	.REQUIRE REL:MACREL
	SALL
	.DIRECT FLBLST


; VERSION NUMBERS

	VMAJOR==^D14		;MAJOR VERSION
	VMINOR==0		;MINOR VERSION
	VWHO==0			;WHO LAST EDITED (0=DEC DEVELOPMENT)
	VEDIT==^D114		;EDIT NUMBER

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


;	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
; MISCELLANEOUS SYMBOL DEFINITIONS

GENDEL=="."		;GENERATION DELIMITER
SDIRCH=="."		;SUBDIRECTORY DELIMITER CHARACTER
NCHPW==5		;NUMBER OF ASCII CHARACTERS PER WORD
BUFSIZ==^D128		;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==^D50		;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==^D27		;COLUMN NUMBER FOR DESCRIPTIVE HEADER TEXTS
OLDV1==31		;LENGTH OF OLD V1 FDBS
	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
.TYRNA==401000		;REMOTE ALIAS 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
DEFSTR (DRRNA,DIRPG0+32,35,36)	;POINTER TO REMOTE ALIAS BLOCKS
DEFSTR (DRPEV,DIRPG0+33,35,18)	;PASSWORD ENCRYPTION VERSION NUMBER
DEFSTR (DRPDT,DIRPG0+34,35,36)	;CREATION DATE/TIME OF PASSWORD
DEFSTR (DRPED,DIRPG0+35,35,36)	;EXPIRATION DATE/TIME OF PASSWORD
DEFSTR (DRPUD,DIRPG0+36,35,36)	;PASSWORD USE DATA:  USE COUNT,,MAX USE
DEFSTR (DRPPN,DIRPG0+37,35,36)	;TOPS-10 PPN FOR DIRECTORY
; 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


;OFFSETS TO VALUES IN REMOTE ALIAS BLOCKS

.RNTYP==0		;TYPE & LENGTH
.RNNXT==1		;NEXT BLOCK IN LIST
.RNNOD==2		;NODE NAME BLOCK
.RNUSR==3		;USERID NAME BLOCK
.RNPAS==4		;PASSWORD NAME BLOCK
.RNACT==5		;ACCOUNT NAME BLOCK


; 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 TXT(TEXT) <POINT 7,[ASCIZ\TEXT\]>

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

	DEFINE ALIGN (COUNT)
<	XLIST
	MOVX T1,COUNT
	CALL LINEUP
	LIST
>

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

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

	DEFINE O.OCT(NUM)
<	XLIST
	MOVE T1,OUTJFN
	MOVE T2,NUM
	MOVEI T3,10
	NOUT%
	  CALL PUTERR
	LIST
>

	DEFINE 	A.OCTM (NUM)
<	XLIST
	MOVE T1,TXTPTR
	MOVE T2,NUM
	MOVX T3,NO%MAG+10	;MAGNITUDE, AND OCTAL RADIX
	NOUT%
	 CALL PUTERR
	MOVEM T1,TXTPTR
	LIST
>

	DEFINE O.OCTM (NUM)
<	XLIST
	MOVE T1,OUTJFN
	MOVE T2,NUM
	MOVX T3,NO%MAG+10	;MAGNITUDE, AND OCTAL RADIX
	NOUT%
	  CALL PUTERR
	LIST
>

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

	DEFINE A.DATE (ARG,TEXT)
<	XLIST
	MOVE T2,ARG
	MOVE T1,TXTPTR
	SETZM T3
	SKIPE T2
	ODTIM%
   IFB <TEXT>,<	JUMPE T2,[A.STR Never >
   IFNB <TEXT>,<JUMPE T2,[A.STR TEXT  >
		JRST .+1]
	MOVEM T1,TXTPTR
	LIST
>

	DEFINE O.DATE (ARG,TEXT)
<	XLIST
	MOVE T2,ARG
	MOVE T1,OUTJFN
	SETZM T3
	SKIPE T2
	ODTIM%
   IFB <TEXT>,<	JUMPE T2,[O.STR Never >
   IFNB <TEXT>,<JUMPE T2,[O.STR TEXT  >
		JRST .+1]
	LIST
>

	DEFINE O.CRLF
<	XLIST
	MOVE T1,OUTJFN
	MOVEI T2,.CHCRT
	BOUT
	MOVEI T2,.CHLFD
	BOUT
	LIST
>

	DEFINE MAPTST (ADR)
<	XLIST
	MOVE MA,ADR
	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)
<	XLIST
	HRRZ AC,LOC
	ADD AC,STBOFS
	MOVE AC,(AC)
	LIST
>

	DEFINE PUTSYM (AC,LOC)
<	XLIST
	HRRZ AC,LOC
	ADD AC,STBOFS
	MOVEM AC,(AC)
	LIST
>

	DEFINE TLOAD (AC,LOC,ADR)
<	XLIST
	MOVE MA,LOC
	CAML MA,MAPBOT
	CAMLE MA,MAPTOP
	CALL MAPDIR
	LOAD AC,LOC,ADR
	LIST
>

	DEFINE CRLF
<	XLIST
	HRROI	T2,[ASCIZ/
/]
	PSOUT%
	LIST
>

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

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


	DEFINE PUTOCT (ADR)
<	XLIST
	MOVE T2,ADR
	MOVEI T1,.PRIOU
	MOVX T3,1B0+^D8
	NOUT%
	 CALL PUTERR
	LIST
>


	DEFINE CHEK (AC,ADR,LOC)
<	XLIST
	SKIPGE ADR
IFB <LOC>,<RET>
IFNB <LOC>,<JRST LOC>
	LOAD AC,DRTOP
	CAMGE AC,ADR
IFB <LOC>,<RET>
IFNB <LOC>,<JRST LOC>
	LIST
>
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 <%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,[FLDDB. (.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,[FLDDB. (.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 <?No such 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,[FLDDB. (.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 <
?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
	HRRZ T1,(T2)		;GET FLAG ADDRESS
	CAIE T1,FDBLST		;LISTING OF AN FDB DESIRED?
	 JRST	DUMP50		;NO, SKIP AHEAD
	MOVEI T1,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI T2,[FLDDB. (.CMNOI,,<TXT(AT)>)] ;GET DESCRIPTOR BLOCK
	COMND%			;PARSE NOISE WORD
	TXNN T1,CM%NOP		;PARSE OK?
	 JRST DUMP25		;YES
	CALL TSTCOL		;NO, ISSUE NEW LINE IF NEEDED
	TMSG <?Invalid guide phrase
>
	RET

DUMP25:	MOVEI T2,[FLDDB. (.CMNUM,,^D8)] ;GET DESCRIPTOR BLOCK
	COMND%			;PARSE ADDRESS
	TXNN T1,CM%NOP		;VALID ADDRESS ENTERED?
	 JRST DUMP40		;YES, GO ON
	CALL TSTCOL		;NO, ISSUE CRLF IF NEEDED
	TMSG <?Invalid FDB address
>				;OUTPUT REMAINDER OF MESSAGE
	RET			;RETURN

DUMP40:	MOVEM T2,FDBLST		;SAVE ADDRESS OF FDB TO LIST
DUMP50:	MOVEI T1,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI T2,[FLDDB. (.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
	MOVX T2,FLD(7,OF%BSZ)+OF%WR ;ASCII TEXT, OUTPUT ACCESS
	OPENF%			;OPEN THE OUTPUT FILE
	 JRST [	CALL TSTCOL	;UNEXPECTED ERROR, ISSUE NEW LINE IF NEEDED
		TMSG <?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
DUMP20:	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
	O.DATE (<[-1]>)		;USE CURRENT 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
	SUBTTL	OUTPUT ROUTINES

; DP0PNT - ROUTINE TO OUTPUT DIRECTORY PAGE 0 HEADER INFO.
;
; CALL:		CALL DP0PNT
;		RETURN


DP0PNT:	O.CRLF			;NEW LINE
	MOVE I1,DIRPG0		;GET BASE ADR OF PAGE 0
	A.STR <DRTYP:  >	;FIRST WORD DESCRIPTION
	MOVE T2,DIRPG0		;GET FIRST WORD OF HEADER
	MOVX T3,NO%MAG+10	;MAGNITUDE, AND OCTAL RADIX
	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
	MOVX T3,NO%MAG+10	;MAGNITUDE, AND OCTAL RADIX
	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 <Beginning 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 <End 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 A1,DRDPW		;GET DEFAULT PROTECTION
	A.OCTM A1		;OUTPUT DEFAULT PROTECTION
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Default file protection
>
	A.STR <DRPRT:  >	;DIRECTORY PROTECTION
	LOAD A1,DRPRT		;GET PROTECTION
	A.OCTM A1		;OUTPUT PROTECTION
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Default directory protection
>
	A.STR <DRDBK:  >	;BACKUP SPEC
	LOAD A1,DRDBK		;GET BACKUP SPEC
	A.OCTM A1		;OUTPUT SPEC
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Retention count
>
	A.STR <DRLIQ:  >	;LOGGED IN QUOTA
	LOAD A1,DRLIQ		;GET LOGGED-IN QUOTA
	A.DEC A1		;OUTPUT QUOTA
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Working quota
>
	A.STR <DRLOQ:  >	;LOGGED OUT QUOTA
	LOAD A1,DRLOQ		;GET LOGGED-OUT QUOTA
	A.DEC A1		;OUTPUT QUOTA
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Permanent quota
>
	A.STR <DRDCA:  >	;CURRENT ALLOCATION
	LOAD A1,DRCUR		;GET ALLOCATION
	A.DEC 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 directory name
>
	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 A1,DRMOD		;GET MODE WORD
	A.OCTM A1		;OUTPUT WORD
	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.DATE A1		;OUTPUT DATE AND TIME
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Time and date of last login
>
	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.DATE A1		;OUTPUT DATE AND TIME
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Last update time
>
	A.STR <DRSDC:  >
	LOAD A1,DRSDC		;GET SUBDIRECTORY COUNT
	A.DEC 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.DEC 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 [ A.DATE A1	;DATE!
		JRST DRDNE1]	;CONTINUE
	A.DEC A1
DRDNE1:	ALIGN HDRCOL
	O.STR <Default online expiration date/interval
>
	A.STR <DRDFE:  >
	LOAD A1,DRDFE
	TLNE A1,-1		;DATE OR INTERVAL?
	 JRST [ A.DATE A1	;DATE!
		JRST DRDFE1]	;CONTINUE
	A.DEC A1
DRDFE1:	ALIGN HDRCOL
	O.STR <Default offline expiration date/interval
>
	A.STR <DRRNA:  >
	LOAD A1,DRRNA		;GET REMOTE ALIAS LIST POINTER
	A.OCTM A1		;OUTPUT POINTER TO REMOTE ALIAS LIST
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Pointer to remote alias list
>
	A.STR <DRPEV:  >
	LOAD A1,DRPEV		;GET PASSWORD ENCRYPTION VERSION
	A.DEC A1		;OUTPUT PASSWORD ENCRYPTION VERSION
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Password encryption version number
>
	A.STR <DRPDT:  >
	LOAD A1,DRPDT		;GET PASSWORD CREATION DATE/TIME
	A.DATE A1		;OUTPUT PASSWORD CREATION DATE/TIME
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Password creation date/time
>
	A.STR <DRPED:  >
	LOAD A1,DRPED		;GET PASSWORD EXPIRATION DATE/TIME
	A.DATE A1		;OUTPUT PASSWORD EXPIRATION DATE/TIME
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Password expiration date/time
>
	A.STR <DRPUD:  >
	LOAD A1,DRPUD		;GET PASSWORD USE DATA
	MOVX T3,^D10		;DECIMAL
	CALL ASMHLF		;OUTPUT USE COUNTS AS HALFWORDS
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <Password use count ,, maximum use count
>
	A.STR <DRPPN:  >
	LOAD A1,DRPPN		;GET TOPS-10 PPN
	MOVX T3,^D8		;OCTAL
	CALL ASMHLF		;OUTPUT PPN AS HALFWORDS
	ALIGN HDRCOL		;LINE UP DESCRIPTIVE TEXT
	O.STR <TOPS-10 Project-programmer number
>
	O.CRLF			;BLANK LINE
	RET			;RETURN FROM 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 <

?Unknown 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 FROM 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?OA
	 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 >
	PUTOCT I1	;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
	MOVX T3,NO%MAG+10	;MAGNITUDE, AND OCTAL RADIX
	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

	O.STR <	Entry Type  Offset	Value	Resolution
>				;HEADER
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.STR <	>		;OUTPUT A TAB
	O.OCTM A3		;OUTPUT TYPE OF ENTRY
	CAIN A3,.STNAM		;FILE?
	 JRST [	O.STR < (File)     >
		JRST .+1]	;YES
	CAIN A3,.STUNS		;USER?
	 JRST [	O.STR < (User)     >
		JRST .+1]	;YES
	CAIN A3,.STACT		;ACCOUNT?
	 JRST [	O.STR < (Account)  >
		JRST .+1]	;YES
	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
	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.STR <	>		;ANOTHER 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

	O.CRLF			;OUTPUT A CRLF

	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:	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
	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 FROM 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:	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 FROM 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 FROM 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 FROM 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 FROM 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 FROM 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
	MOVX T3,NO%MAG+10	;MAGNITUDE, AND OCTAL RADIX
	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 FROM WHENCE WE CAME
; RNAPRT - ROUTINE TO OUTPUT THE CONTENTS OF A REMOTE ALIAS BLOCK
;
; CALL:		MOVE P1,ADDRESS OF NAME BLOCK
;		RETURN
;USES P1,T1,T2,T3

RNAPRT:	O.STR <Remote alias 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
	MOVX T3,1B0+10		;PRINT MAGNITUDE, USE OCTAL
	CALL PUTHLF		;GO OUTPUT TWO HALFWORDS
	O.STR <
	Next:		>	;output next pointer
	ADDI P1,1
	GETMPW T2,P1
	O.OCT T2
	O.STR <
	Node:		>	;output node pointer
	ADDI P1,1
	GETMPW T2,P1
	O.OCT T2
	O.STR <
	Userid:		>	;output userid pointer
	ADDI P1,1
	GETMPW T2,P1
	O.OCT T2
	O.STR <
	Password: 	>	;output password pointer
	ADDI P1,1
	GETMPW T2,P1
	O.OCT T2
	O.STR <
	Account: 	>	;output account pointer
	ADDI P1,1
	GETMPW T2,P1
	O.OCT T2
	O.CRLF
	RET
; 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
	MOVX T3,NO%MAG+10	;MAGNITUDE, AND OCTAL RADIX
	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 FROM 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
	MOVX 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
	O.DEC T2		;OUTPUT THE SHARE COUNT
	O.CRLF
	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 FROM 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
	MOVX T3,NO%MAG+10	;MAGNITUDE, AND OCTAL RADIX
	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
	O.DEC T2		;OUTPUT THE SHARE COUNT
	O.CRLF
	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 FROM 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 O.CRLF
	MOVE P1,FB		;GET THE ADDRESS OF THE BLOCK
	CALLRET BLKPNT		;GO OUTPUT THE FUNNY BLOCK

FDBP00:	O.CRLF			;START WITH A FREE O.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
	MOVX T3,NO%MAG+10	;MAGNITUDE, AND 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
	MOVX T3,NO%MAG+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:	>
	O.OCTM .FBPRT(FB)	;OUTPUT PROTECTION WORD
	O.CRLF			;OUTPUT A CRLF
	CALL INDENT		;GO INDENT
	O.STR <.FBCRE:	>
	MOVE T2,.FBCRE(FB)	;GET CREATION DATE AND TIME
	MOVX T3,NO%MAG+FLD(6,NO%COL)+10 ;MAGNITUDE, OCTAL RADIX
	CALL PUTHLF		;GO OUTPUT TWO HALFWORDS
	O.STR <	[>
	O.DATE .FBCRE(FB)	;OUTPUT CREATION DATE AND TIME
	O.STR <]
>
	CALL INDENT		;GO INDENT
	LOAD T1,BT%VER,(FB)	;GET VERSION # OF THIS FDB
	CAIN T1,0		;VERSION 0 FDB?
	 JRST FDBP10		;YES, GO OUTPUT OLD HEADING
	O.STR <.FBAUT:	>	;NO, OUTPUT VERSION 1 HEADING
	JRST FDBP20		;AND GO OUTPUT THE FIELD
FDBP10:	O.STR <.FBUSE:	>
FDBP20:	O.OCTM .FBAUT(FB)	;DO AUTHOR POINTER
	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 <.FBBYV:	>
	MOVE T2,.FBBYV(FB)	;GET GENERATIONS, BYTE SIZE, PAGES
	MOVX 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
	MOVX T3,1B0+6B17+10	;MAGNITUDE, OCTAL RADIX
	CALL PUTHLF		;GO OUTPUT DATE,,TIME
	O.STR <	[>
	O.DATE .FBCRV(FB)	;GET DATE AND TIME
	O.STR <]
>
	CALL INDENT		;GO INDENT
	O.STR <.FBWRT:	>
	MOVE T2,.FBWRT(FB)	;GET DATE AND TIME OF LAST WRITE
	MOVX T3,NO%MAG+FLD(6,NO%COL)+10 ;MAGNITUDE, OCTAL RADIX
	CALL PUTHLF		;GO OUTPUT DATE,, TIME
	O.STR <	[>
	O.DATE .FBWRT(FB)	;OUTPUT WRITE DATE AND TIME
	O.STR <]
>
	CALL INDENT		;GO INDENT
	O.STR <.FBREF:	>
	MOVE T2,.FBREF(FB)	;GET LAST TIME REFERENCED
	MOVX T3,NO%MAG+FLD(6,NO%COL)+10 ;MAGNITUDE, OCTAL RADIX
	CALL PUTHLF		;GO OUTPUT DATE,, TIME
	O.STR <	[>
	O.DATE .FBREF(FB)	;OUTPUT REFERENCE DATE AND TIME
	O.STR <]
>
	CALL INDENT		;GO INDENT
	O.STR <.FBCNT:	>
	MOVE T2,.FBCNT(FB)	;GET FDBCNT WORD
	MOVX T3,NO%MAG+^D10	;USE DECIMAL
	CALL PUTHLF		;GO OUTPUT HALFWORDS
	O.CRLF
	CALL INDENT		;GO INDENT
	O.STR <.FBBK0:	>
	MOVE T2, .FBBK0(FB)	;OUTPUT BACKUP WORDS IN HALFWORDS
	MOVE T3,[1B0+^D8]	;IN OCTAL
	CALL PUTHLF
	O.CRLF			;OUTPUT A CRLF
	CALL INDENT		;GO 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 [	O.DATE .FBNET(FB) ;OUTPUT THE DATE AND TIME
		JRST USWST]	;GO TO NEXT WORD
	O.DEC <.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
	LOAD T1,BT%VER,(FB)	;GET VERSION # OF THIS FDB
	CAIN T1,0		;IS THIS A VERSION 0 FDB?
	 RET			;YES, RETURN
	CALL INDENT		;GO INDENT
	O.STR <.FBLWR:	>	;NO, 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 <	[>
	O.DATE .FBTDT(FB),<Not archived> ;OUTPUT ARCHIVE DATE AND TIME
	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 [	O.DATE .FBFET(FB) ;OUTPUT THE DATE AND TIME
		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 FROM 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
	MOVX T3,NO%MAG+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:
	Header:	>
	GETMPW T2,P1		;GET FIRST WORD OF BLOCK
	MOVX T3,NO%MAG+10	;PRINT MAGNITUDE, OCTAL
	CALL PUTHLF		;GO OUTPUT HALFWORDS
	O.STR <
	Next:	>
	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 FROM 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
	MOVX T3,NO%MAG+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
	MOVX T3,NO%MAG+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 FROM 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 FROM 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,[FLDDB. (.CMNOI,,<TXT(TO FILE)>)]
	COMND%			;PARSE NOISE WORD
	TXNN T1,CM%NOP		;PARSE OK?
	 JRST OUT01		;YES
	CALL TSTCOL		;NO, ISSUE NEW LINE IF NEEDED
	TMSG <?Invalid guide phrase
>
	RET			;DONE

OUT01:	MOVEI T2,[FLDDB. (.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 <?Invalid file specification
>
	RET			;RETURN

OUTPA2:	MOVEM T2,OUTPTJ		;SAVE OUTPUT JFN
	MOVEI T2,[FLDDB. (.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	DIRECTORY COMMAND

.DIREC:	STKVAR <DIRECN>		;DIRECTORY NUMBER
	MOVEI T1,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI T2,[FLDDB. (.CMNOI,,<TXT(TO USE IS)>)] ;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 <?Invalid guide phrase
>
	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 <?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,[FLDDB. (.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,[FLDDB. (.CMNOI,,<TXT(WITH DIRPNT)>)]
	COMND%			;PARSE NOISE WORD
	TXNN T1,CM%NOP		;PARSE OK?
	 JRST HELP01		;YES
	CALL TSTCOL		;NO, ISSUE NEW LINE IF NEEDED
	TMSG <?Invalid guide phrase
>
	RET

HELP01:	MOVEI T1,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI T2,[FLDDB. (.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,[FLDDB. (.CMNOI,,<TXT(TO EXEC)>)]
	COMND%			;PARSE NOISE WORD
	TXNN T1,CM%NOP		;PARSE OK?
	 JRST EXIT01		;YES
	CALL TSTCOL		;NO, ISSUE NEW LINE IF NEEDED
	TMSG <?Invalid guide phrase
>
	RET

EXIT01:	MOVEI T2,[FLDDB. (.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 <?Garbage at end-of-command
>				;OUTPUT ERROR MESSAGE
	RET			;RETURN FROM 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 <
>				;ELSE OUTPUT A CRLF
	RET			;RETURN FROM 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 FROM 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 DIR 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 FROM 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 FROM 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
	JRST	RESACS		;RESTORE AC'S AND RETURN
; SAVACS - ROUTINE TO SAVE ALL ACCUMULATORS EXCEPT P
;
; CALL:		CALL SAVACS
;		RETURN

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

; RESACS - ROUTINE TO RESTORE ALL ACCUMULATORS EXCEPT P
;
; CALL:		CALL RESACS
;		RETURN

RESACS:	MOVE 0,[SAVET1,,T1]	;SET UP FOR BLT
	BLT 0,16		;RESTORE AC'S 1-16
	MOVE 0,SAVE0		;RESTORE AC 0
	RET			;RETURN FROM 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
	SKIPE T4		;RESTORE PTR?
	 MOVEM T1,TXTPTR	;YES
	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
	SKIPE T4		;RESTORE PTR?
	 MOVEM T1,TXTPTR	;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 <?WHEEL or OPERATOR capabilities required
>
	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
	IDPB T3,TXTPTR		;END BUFFER WITH NULL
	MOVE T2,[POINT 7,TEXT]	;GET POINTER TO ASSEMBLED TEXT
	MOVEM T2,TXTPTR		;RESET THE ASSEMBLED TEXT POINTER
	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/
?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

TYPER2:	HRROI T1,[ASCIZ/
?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 FROM 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 (TO USE IS) directory filespec
        EXIT (TO EXEC)
        HELP (WITH DIRPNT)
        OUTPUT (TO FILE) filespec
        DUMP argument

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

Defaults:

        DIRECTORY (FILE) connected directory
        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>OUTPUT (TO FILE) LPT:
	DIRPNT>DUMP ENTIRE-DIRECTORY

Restrictions:

        It  is  neccessary  to  have   WHEEL   or   OPERATOR
        capability 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 (.OUTPT,OUTPUT)

	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
	.TYRNA,,RNAPRT

	TYPSIZ==.-TYPTAB
SUBTTL	VARIABLE DATA STORAGE

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


PDL:	BLOCK PDLSIZ		;STACK
SAVE0:	BLOCK 1			;ACCUMULATOR 0 SAVED HERE
SAVET1:	BLOCK <P-1>-T1		;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>