Google
 

Trailing-Edge - PDP-10 Archives - AP-4178E-RM - swskit-sources/dirpnt.mac
There are 6 other files named dirpnt.mac in the archive. Click here to see a list.
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==77		;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== 400		;PAGE WHERE DIRECTORY IS MAPPED
DIRADR== DIRORG*1000	;ADDRESS WHERE DIRECTORY IS MAPPED
PAGSIZ== 1000		;SIZE OF A PAGE
FDBPGS== 17		;# OF PAGES TO MAP FDB'S INTO
STBPGS== ^D13		;# 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==^D25		;COLUMN NUMBER FOR DESCRIPTIVE HEADER TEXTS
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
; 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
	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 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 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
	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
	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 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.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 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.OCTM 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.OCTM 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.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
>
	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 PROTECTIO