Google
 

Trailing-Edge - PDP-10 Archives - BB-5255D-BM - language-sources/lnkmap.mac
There are 38 other files named lnkmap.mac in the archive. Click here to see a list.
TITLE	LNKMAP - MAP MODULE FOR LINK
SUBTTL	D.M.NIXON/DMN/SRM/JBC/RKH/JNG/DZN	24-Aug-79


;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1973, 1978 BY DIGITAL EQUIPMENT CORPORATION


SEARCH	LNKPAR,LNKLOW,MACTEN,UUOSYM,SCNMAC
SALL

ENTRY	LNKMAP
EXTERN	LNKFIO,LNKXIT,LNKLOD,LNKLOG,LNKCOR,.TYOCH


CUSTVR==0		;CUSTOMER VERSION
DECVER==4		;DEC VERSION
DECMVR==1		;DEC MINOR VERSION
DECEVR==1220		;DEC EDIT VERSION


VERSION


SEGMENT
SUBTTL	REVISION HISTORY


;START OF VERSION 1A
;47	INTEGRATE WITH SCAN %4, ADD DATE75 HACK
;54	ADD KIONLY D.P. INST.
;55	PUT VERSION# IN .RBVER OF MAP FILE
;63	PUT MULTIPLY-DEFINED SYMBOLS IN MAP
;104	PUT FAIL BLOCKS OUT ON MAP

;START OF VERSION 2
;135	ADD OVERLAY FACILITY
;144	(12772) FIX LOOP IF MORE THAN 1 SFD
;160	(12736) ADD WORDS FREE IN EACH SEGMENT TO MAP OUTPUT
;205	ADD NO. OF GLOBALS AND MIN. HASH SIZE TO MAP OUTPUT

;START OF VERSION 2A
;225	ADD SUPPORT FOR PSECT (MACRO VERSION 51 ONLY)

;START OF VERSION 2B
;304	FIX LOOP IN MAP OUTPUT
;344	INCLUDE EDIT 304 IN MAINTENANCE SOURCES
;353	REMOVE EDIT 225
;363	UPDATE MINOR VERSION #
;372	Don't print an overlay path on /MAP:NOW

;START OF VERSION 2C
;452	Don't print the module name as the only line on a new page
;453	Don't repeat module names if map index is longer than one page.
;463	Fix ?ILL UUO and lost symbols on /MAP:NOW
;475	Replace calls to .TYVER with calls to .TVERW
;503	Make pages LN.LPP lines long, not LN.LPP+1.
;507	Avoid informational messages in map when using /ERR:0.
;530	Get triplet flag bit definitions right.
;532	Fix problems with title when paging heavily.
;540	Detect all cases of zero length modules correctly.
;557	Clean up the listing for release.

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

;START OF VERSION 4
;601	Print the correct version if from /VERSION
;604	Support device NUL: correctly
;611	Support COBOL-74
;640	Avoid additional disk overflow if possible.
;711	Fix bug in MAP when only 1 psect in a module.
;731	SEARCH MACTEN,UUOSYM instead of C.
;765	Release on both TOPS-10 and TOPS-20 as LINK version 4(765)
;START OF VERSION 4A
;1100	Don't free up a different size title buffer than we allocated.
;1112	Get words free and segment lengths in K/P right in the map.
;1120	Pring correct CPU specifications in the map for module and program.
;1161	Clean up printout of PSECT lengths.
;1164	Don't overwrite FX area in SHFSYM if no extra room.
;1174	Label and clean up all error messages.
;1203	Add support for extended FORTRAN.
;1217	Clean up the listings for release.
;1220	Release on both TOPS-10 and TOPS-20 as version 4A(1220).
SUBTTL	HEADER LINES


LNKMAP:	JFCL	.+1		;INCASE CCL
E$$MPS::.ERR.	(MS,0,V%L,L%I,S%I,MPS,<MAP segment>) ;[1174]
	ZAPTMP			;CLEAR DATA AREA
	SETOM	LS.PP		;PROHIBIT DEFAULT PAGING OF SYMBOL TABLE
	AOS	SYMPTR		;SKIP INITIAL ZERO
	PUSHJ	P,RDVER		;SET UP VERSION # IN MAPVER
	MOVEI	T1,MC		;SET IO.CHN
	MOVEM	T1,IO.CHN	;TO MAP CHAN#
	MOVE	T1,IO.PTR+MC	;GET DATA BLOCK
	SKIPN	T2,VERNUM	;GET VERSION FROM SWITCH
	SKIPA	T2,MAPVER	;[601] NO SWITCH, GET VERSION FROM CORE
	MOVEM	T2,MAPVER	;[601] STORE /VERSION FOR MAP TITLE
	SKIPN	I.VER(T1)	;BUT NOT IF SET IN FILE
	MOVEM	T2,I.VER(T1)	;PUT IN .RBVER
	SKIPN	T2,I.NAM(T1)	;GET USER OR DEFAULT NAME
	PUSHJ	P,DVNAM.##	;SET DEFAULT
	MOVEM	T2,MAPNAM	;FOR HEADER INFO
	PUSHJ	P,DVCHK.##	;GET DEVCHR AGAIN
	MOVE	T2,IO.CHR	;GET DEVCHR WORD
	TLC	T2,-1-<(DV.TTA)>	;[604] NUL: ISN'T A TTY
	TLCE	T2,-1-<(DV.TTA)>	;[604]
	TXNN	T2,DV.TTY	;[604] IF TTY
	  CAIA			;[604] IT ISN'T
	JRST	.+3		;IGNORE INIT & ENTER
	PUSHJ	P,DVOPN.##	;OPEN MAP DEVICE
	PUSHJ	P,DVENT.##	;AND ENTER FILE NAME
	HRRZ	T1,LOWSUB	;[604] ASSUME TTY IS MAP DEVICE
	MOVE	T2,IO.PTR+MC	;[604] GET POINTER BACK
	SKIPE	I.RNG(T2)	;[604] ARE THERE SOME BUFFERS
	MOVEI	T1,MAPIT	;[604] YES, POINT TO SOSGE ROUTINE
	PUSHJ	P,.TYOCH##	;INIT OUTPUT
	MOVEM	T1,OLDDEV	;SAVE OLD .TYOCH RETURN INCASE ERROR
	MOVEI	T1,LN.LPP	;NO OF LINES PER PAGE
	MOVEM	T1,CNTLPP
;HERE WITH MAP FILE OPEN. PRINT HEADER LINES.

LNKMP1:	MOVEI	T1,HEAD1	;NORMAL HEADER
	MOVEM	T1,PAGHDR	;FOR PAGES
	PUSHJ	P,.TYHDR	;TYPE HEADER LINE
	MOVEI	T1,HEAD2
	PUSHJ	P,.TSTRG##
	MOVE	T2,HIORGN	;[650] GET HISEG ORIGIN
	MOVSI	T1,.		;FIND OUT WHERE WE ARE
	SKIPL	T1		;SHOULD BE IN HIGH SEG
	SKIPA	T1,.JBVER	;NO, GET LOW VERSION
	MOVE	T1,.JBHVR(T2)	;[650] HIGH SEG VER
	PUSHJ	P,.TVERW##	;TYPED IN VERSION FORMAT
	MOVEI	T1,[ASCIZ	\ on \]
	PUSHJ	P,.TSTRG##
	PUSHJ	P,.TDATN##	;DAY
	MOVEI	T1,[ASCIZ	\ at \]
	PUSHJ	P,.TSTRG##
	PUSHJ	P,.TTIMN##	;TIME
	PUSHJ	P,.TYLPP	;END LINE
	PUSHJ	P,.TYLPP	;BLANK LINE
	SETZ	R1,		;NOW FOR PER-SEGMENT STUFF
IFN FTOVERLAY,<
	AOS	FSTPGN		;INCASE NO OVERLAYS, START ON PAGE 1
	SKIPGE	T2,LNKMAX	;ANY OVERLAYS?
	JRST	SEGSTF		;NO
	LSH	T2,-1
	ADDI	T2,1		;TAKE CARE OF ODD#
	PUSHJ	P,LOGBCK	;PUT MOVING LOWSEG MSGS IN LOG
	PUSHJ	P,DY.GET##	;GET SPACE FOR NO. INDEX
	HRLI	T1,T1		;PUT T1 IN INDEX FIELD
	MOVEM	T1,OVMIDX
	PUSHJ	P,LOGBCK	;REST OF INFO IN MAP
	SETZM	LNKNO.		;START AT LINK# 0
	JRST	OVMAP1
OVMAP0:	SETZM	CNTLPP		;START ON NEW PAGE
	MOVEI	T1,HEAD1	;RESET HEADER LINE
	MOVEM	T1,PAGHDR
	PUSHJ	P,.TYLPP	;NEW PAGE & HEADER LINE
	MOVEI	T1,1
	MOVEM	T1,SYMPTR	;RESET SYMBOL PTR
OVMAP1:	MOVE	P1,LNKNO.
	PUSHJ	P,LOGBCK	;MAKE SURE ERRORS GET TO TTY
	PUSHJ	P,RDCST##	;READ THE PREAMBLE & CS FOR THIS LINK
	  JFCL			;NEITHER EXTTAB NOR INTTAB
	PUSHJ	P,LOGBCK	;PUT LOG INFO OUT TO LOG
	MOVE	T1,OV.S1	;LENGTH
	HRRM	T1,HL.S1	;SO BOUNDS COME OUT RIGHT
	MOVEI	T1,[ASCIZ	\	Overlay no.	\]
	PUSHJ	P,.TSTRG##
	MOVE	T1,LNKNO.	;GET THIS ONE
	PUSHJ	P,.TDECW##	;LIST IN DECIMAL
	SKIPN	PH.NAM		;SEE IF NAME
	JRST	OVMAP2		;NO
	MOVEI	T1,[ASCIZ	\	name	\]
	PUSHJ	P,.TSTRG##
	MOVE	T1,PH.NAM	;GET NAME
	PUSHJ	P,.TSIXN##	;IN SIXBIT
OVMAP2:	PUSHJ	P,.TYLPP
;SEGMENT LENGTHS
	SETZ	R1,		;MAKE SURE R IS CORRECT
SGSTF0:	PUSHJ	P,.TTABC##
	MOVEI	T1,SEG0(R1)
	PUSHJ	P,.TSTRG##
	MOVEI	T1,SEG1
	PUSHJ	P,.TSTRG##
	HRRZ	T1,PV.S1(R1)	;STARTS AT
	PUSHJ	P,.T6OCT##
	MOVEI	T1,SEG2
	PUSHJ	P,.TSTRG##
	HRRZ	T1,OV.S1(R1)	;ENDS AT
	SKIPE	T1
	SUBI	T1,1		;ONE LESS THAN PROG BREAK
;	ADD	T1,LL.S1(R1)	;DON'T FORGET OFFSET
	PUSHJ	P,.T6OCT##
	MOVEI	T1,SEG3
	PUSHJ	P,.TSTRG##
	HRRZ	T1,OV.S1(R1)
	HRRZ	T2,PV.S1(R1)	;PREVIOUS
	SUB	T1,T2		;DIFFERENCE
	PUSH	P,T1		;SAVE IT
	PUSHJ	P,.T6OCT##	;LENGTH IN OCTAL
	MOVEI	T1,[ASCIZ	\ = \]
	PUSHJ	P,.TSTRG##
	POP	P,T1		;LENGTH BACK
	ADD.	T1,.PGSIZ	;[1112] ROUND UP TO NEXT PAGE BOUND
	ANDCM.	T1,.PGSIZ	;[1112] ..
IFE TOPS20,<
	MOVE	T2,.PGSIZ	;[1112] GET THIS SYSTEM'S PAGE SIZE
	CAIE	T2,777		;PAGES?
	JRST	[LSH	T1,-^D10	;K
		PUSHJ	P,.TDEC3	;IN DECIMAL
		MOVEI	T1,"K"
		JRST	SGSTF1]	
>;END OF IFE TOPS20
	LSH	T1,-^D9		;P
	PUSHJ	P,.TDEC3	;IN DECIMAL
	MOVEI	T1,"P"
SGSTF1:	PUSHJ	P,.TCHAR##
	PUSHJ	P,.TYLPP
	JUMPN	R1,OVMP2A	;DONE HIGH SEG ALREADY?
	HRRZ	T1,OV.S2	;NO, BUT IS THERE ANY HIGH SEGMENT?
	HRRZ	T2,PV.S2
	SUB	T1,T2
	SKIPE	T1		;NO
	AOJA	R1,SGSTF0	;NOW FOR HIGH SEG
OVMP2A:	MOVEI	T1,[ASCIZ	\	Control Block address is \]
	PUSHJ	P,.TSTRG##
	HRRZ	T1,PH.CST
	PUSHJ	P,.T6OCT##
	MOVEI	T1,[ASCIZ	\, length \]
	PUSHJ	P,.TSTRG##
	HLRE	T1,CS.INT	;LENGTH OF INTTAB
	JUMPE	T1,[HLRE T1,CS.EXT
		JUMPE	T1,OVMAP4	;NEITHER
		IMUL	T1,[-ET.ZZ]	;GET LENGTH
		ADD	T1,CS.EXT	;PLUS START
		JRST	OVMAP3]
	IMUL	T1,[-2]		;2 WORDS PER INTTAB
	ADD	T1,CS.INT
OVMAP3:	SUB	T1,PH.CST	;- START
	TLZA	T1,-1		;RIGHT HALF ONLY
OVMAP4:	MOVEI	T1,CS.ZZ	;USE LENGTH OF CS ONLY
	PUSH	P,T1		;SAVE IT
	PUSHJ	P,.T6OCT##	;LIST IN OCTAL
	MOVEI	T1,[ASCIZ	\ (octal), \]
	PUSHJ	P,.TSTRG##
	POP	P,T1
	PUSHJ	P,.TDECW##	;AND IN DECIMAL
	MOVEI	T1,[ASCIZ	\. (decimal)\]
	PUSHJ	P,.TSTRG##
	PUSHJ	P,.TYLPP
	HLRE	P2,PH.SYM	;LENGTH WE NEED
	MOVM	P2,P2
	SUB	P2,LS.AB	;SEE IF ENOUGH
	ADD	P2,LS.LB
	JUMPLE	P2,OVMAP5	;YES
	PUSHJ	P,LOGBCK	;PUT INFO MESSAGES TO LOG FILE
	MOVEI	P1,LS.IX
	PUSHJ	P,LNKCOR##
	  PUSHJ	P,E$$MEF##	;[1174]
	PUSHJ	P,LOGBCK	;BUT ALL OTHERS IN MAP
OVMAP5:	MOVEI	T1,$MAPNOW	;GET /MAP:NOW
	CAME	T1,MAPSW	;SKIP PATH IF SO (NOT SET UP)
	SKIPN	LNKNO.		;LIST PATH FOR ALL BUT ROOT
	JRST	OVMAP6
	MOVEI	T1,[ASCIZ	\	Path is	\]
	PUSHJ	P,.TSTRG##
	MOVE	T1,PH.FPT	;GET PATH POINTER
	USETI	OC,(T1)		;SET ON BLOCK
	HLRZ	P1,T1		;GET WORD NUMBER
	ADD	P1,LS.LB	;WHERE IN CORE
	HRLI	P1,(POINT 18)	;1/2 WORDS
;FORM IOWD AND READ IN PATH INFO FOR PRINTING

	MOVE	T1,LS.LB
	SUBI	T1,1
	HRLI	T1,-.DBS	;[650] FORM IOWD
	SETZ	T2,
	IN	OC,T1
	  CAIA
	PUSHJ	P,[PUSHJ P,LOGBCK	;ERRORS TO TTY
		   PJRST E$$IOV##]	;[1174] GO REPORT INPUT ERROR
	ILDB	T1,P1		;GET FIRST #
	PUSHJ	P,.TDECW##	;AUGHT TO BE 0 BUTB MUST PRINT IT
OVMP5A:	ILDB	T1,P1		;GET NEXT
	JUMPE	T1,OVMP5B	;DONE
	MOVEI	T1,[ASCIZ \, \]
	PUSHJ	P,.TSTRG##	;SEPARATOR
	LDB	T1,P1		;GET # BACK
	PUSHJ	P,.TDECW##
	JRST	OVMP5A		;GET NEXT

OVMP5B:	PUSHJ	P,.TYLPP	;END LINE
OVMAP6:	MOVE	T1,PH.SYM	;GET BLOCK# OF SYMBOLS
	USETI	OC,(T1)		;SET ON IT
	MOVE	T1,LS.LB	;FORM IOWD TO READ IN SYMBOLS
	SUBI	T1,1
	HLL	T1,PH.SYM	;EVENTUALLY
	SETZB	T2,USYM
	IN	OC,T1
	  SKIPA	T1,LNKNO.	;OK
	PUSHJ	P,[PUSHJ P,LOGBCK	;ERRORS TO TTY
		   PJRST E$$IOV##]	;[1174] INPUT ERROR
	ROT	T1,-1		;USUAL WAY TO ADDRESS 1/2 WORD
	MOVE	T2,PAGENO	;PAGE # OF FIRST MODULE INCASE NO INDEX
	MOVEM	T2,FSTPGN	;SO WE CAN SEE IF INDEX REQUIRED
	JUMPL	T1,[HRRM T2,@OVMIDX
		JRST	.+2]
	HRLM	T2,@OVMIDX
	MOVE	T1,LS.LB
	ADD	T1,LSYM		;NEXT FREE LOCATION
	SETZM	(T1)		;CLEAR UP TO END OF LS.AB WITH A BLT
	HRLZI	T2,0(T1)
	HRRI	T2,1(T1)
	BLT	T2,@LS.AB
	IORI	T1,.IPM
	MOVEM	T1,LS.AB	;GIVE BACK EXCESS SPACE
	JRST	SEGDN

>;END OF IFN FTOVERLAY
;SEGMENT LENGTHS
SEGSTF:	PUSHJ	P,.TTABC##
	MOVEI	T1,SEG0(R1)
	PUSHJ	P,.TSTRG##
	MOVEI	T1,SEG1
	PUSHJ	P,.TSTRG##
	MOVE	T1,LL.S1(R1)	;STARTS AT
	PUSHJ	P,.T6OCT##
	MOVEI	T1,SEG2
	PUSHJ	P,.TSTRG##
	SKIPE	T1,HL.S1(R1)	;ENDS AT
	SUBI	T1,1		;ONE LESS THAN PROG BREAK
	ADD	T1,LL.S1(R1)	;DON'T FORGET OFFSET
	PUSHJ	P,.T6OCT##
	MOVEI	T1,SEG3
	PUSHJ	P,.TSTRG##
	MOVE	T1,HL.S1(R1)
	PUSH	P,T1
	PUSHJ	P,.T6OCT##	;LENGTH IN OCTAL
	MOVEI	T1,[ASCIZ	\ = \]
	PUSHJ	P,.TSTRG##
	POP	P,T1		;GET BACK LENGTH
	ADD.	T1,.PGSIZ	;[1112] ROUND UP TO NEXT PAGE BOUND
	ANDCM.	T1,.PGSIZ	;[1112] ..
IFE TOPS20,<
	MOVE	T2,.PGSIZ	;[1112] GET THIS SYSTEM'S PAGE SIZE
	CAIE	T2,777		;PAGES?
	JRST	[LSH	T1,-^D10	;K
		PUSHJ	P,.TDECW##	;IN DECIMAL
		MOVEI	T1,"K"
		JRST	SGSTF2]	
>;END OF IFE TOPS20
	LSH	T1,-^D9		;P
	PUSHJ	P,.TDECW##	;IN DECIMAL
	MOVEI	T1,"P"
SGSTF2:	PUSHJ	P,.TCHAR##
	PUSHJ	P,.TYLPP
	SKIPN	R1		;DONE HIGH SEG ALREADY?
	SKIPN	HL.S2		;NO, BUT IS THERE ANY HIGH SEGMENT?
	JRST	SEGDN		;NO
	AOJA	R1,SEGSTF	;NOW FOR HIGH SEG
;HERE TO READ THE VERSION NUMBER IN USER LOC .JBVER

RDVER:
IFN FTOVERLAY,<
	SKIPGE	LNKMAX		;ANY OVERLAYS?
	JRST	RDVER1		;NO
	PUSHJ	P,LOGBCK	;I/O ERRORS TO TTY
	SETZB	P1,LNKNO.	;NEED LINK# 0 IN CORE
	PUSHJ	P,INPH##	;GET PREAMBLE
	MOVE	T1,PH.OVL	;BLOCK# OF JOBDAT
	USETI	OC,(T1)		;SET ON IT
	MOVE	T1,LC.LB
	SUBI	T1,1
	HRLI	T1,-.DBS	;[650] READ FIRST BLOCK
	SETZ	T2,
	IN	OC,T1
	  SKIPA	T1,.JBVER+1(T1)	;GET VERSION#
	PUSHJ	P,E$$IOV##	;[1174] INPUT ERROR
	MOVEM	T1,MAPVER
	PJRST	LOGBCK		;PUT ALL MAP INFO IN MAP
RDVER1:
>;END OF IFN FTOVERLAY
	SKIPE	PAG.S1		;IF PAGING LOW SEG
	SKIPN	LW.S1		;AND JOBDAT NOT IN CORE
	JRST	[MOVE	T1,LC.LB	;GET START OF LOW AREA
		MOVE	T1,.JBVER(T1)	;GET VERSION#
		MOVEM	T1,MAPVER	;SAVE FOR HEADER LINE
		POPJ	P,]		;RETURN
	PUSHJ	P,LOGBCK	;[LNKEXP] MESSAGES TO TTY
	MOVEI	T2,.JBDA		;NEED 140 WORDS
	PUSHJ	P,DY.GET##	;TO HOLD JOBDAT
	SUBI	T1,1		;IOWD STARTS 1 BACK
	HRLI	T1,-140		;NO OF WORDS
	SETZ	T2,		;TERMINATE LIST
	USETI	LC,1		;TO READ BLOCK 1
	IN	LC,T1		;FOR FIRST 140 WORDS
	  JRST	[MOVEI	T1,1(T1)	;INCR T1
		MOVE	T2,.JBVER(T1)	;GET VERSION #
		MOVEM	T2,MAPVER	;SAVED
		MOVEI	T2,.JBDA	;NOW TO RESTORE BLOCK
		PUSHJ	P,DY.RET##	;RETURN THE CORE
		PJRST	LOGBCK]		;AND .TYOCH AND RETURN
	PUSHJ	P,LOGBCK	;MAKE SURE USER GETS MESSAGE
E01ILC::PUSH	P,[LC]		;[1174] CHAN #
	.ERR.	(ST,,V%L,L%F,S%F,ILC)
SEGDN:	PUSHJ	P,.TTABC##
	MOVE	T1,HL.S1	;GET LOW SEG BREAK
	ADD.	T1,.PGSIZ	;[1112] ROUND UP TO NEXT P OR K
	ANDCM.	T1,.PGSIZ	;[1112] ..
	SUB	T1,HL.S1	;FIND WHATS LEFT
	PUSHJ	P,.TDECW##	;PRINT IN DECIMAL
	MOVEI	T1,[ASCIZ	\ words free in Low segment\]
	PUSHJ	P,.TSTRG##
	SKIPN	HL.S2		;ANY HIGH SEGMENT
	JRST	SEGDN1		;NO, CLOSE OUT LINE
	MOVEI	T1,[ASCIZ	\, \]
	PUSHJ	P,.TSTRG##	;SEPARATE
	MOVE	T1,HL.S2	;SAME FOR HIGH SEG
	ADD.	T1,.PGSIZ	;[1112] ROUND UP TO NEXT P OR K
	ANDCM.	T1,.PGSIZ	;[1112] ..
	SUB	T1,HL.S2
	PUSHJ	P,.TDECW##
	MOVEI	T1,[ASCIZ	\ words free in high segment\]
	PUSHJ	P,.TSTRG##
SEGDN1:	PUSHJ	P,.TYLPP
	PUSHJ	P,.TTABC##	;TAB OUT
	MOVE	T1,GSYM		;NO. OF GLOBALS
IFN FTOVERLAY,<
	ADD	T1,BSYM		;PLUS BOUND SYMBOLS
>
	PUSHJ	P,.TDECW##	;PRINT NO.
	MOVEI	T1,[ASCIZ	\ Global symbols loaded, therefore min. hash size is \]
	PUSHJ	P,.TSTRG##
	MOVE	T1,GSYM		;NO. OF SYMBOLS
IFN FTOVERLAY,<
	ADD	T1,BSYM		;PLUS BOUND SYMBOLS
>
	IMULI	T1,^D100
	IDIVI	T1,.HS%		;HOW MUCH SPACE WE WILL NEED TO AVOID REHASH
	ADDI	T1,1		;JUST INCASE A PRIME NO.
	PUSHJ	P,.TDECW##
	PUSHJ	P,.TYLPP	;CLOSE LINE
	SKIPN	STADDR		;IS THERE A STARTING ADDRESS
	JRST	NOSTAD		;NO
	MOVEI	T1,[ASCIZ	\	Start address is \]
	PUSHJ	P,.TSTRG##
	HRRZ	T1,STADDR	;GET IT
	PUSHJ	P,.T6OCT##
	SKIPN	STANAM		;NAME OF PROG CONTAINING ST ADDR.
	JRST	TTLDN		;NONE, OR SET BY SWITCH
	MOVEI	T1,[ASCIZ	\, located in program \]
	PUSHJ	P,.TSTRG##
	MOVE	T1,STANAM	;PROGRAM NAME
	PUSHJ	P,.TSIXN##
	PUSHJ	P,.TYLPP
	JRST	TTLDN
NOSTAD:
IFN FTOVERLAY,<
	SKIPL	LNKMAX		;ANY OVERLAYS
	SKIPN	LNKNO.		;YES, BUT NOT ROOT
	CAIA
	JRST	TTLDN		;DON'T GIVE MESSAGE TO OTHER LINKS
>
	MOVEI	T1,[ASCIZ	\	No start address\]
	PUSHJ	P,.TSTRG##
	PUSHJ	P,.TYLPP
TTLDN:	SKIPL	NOSYMS		;USER SET FOR NO SYMBOLS
	SKIPN	LS.LB		;OR NOTHING YET STORED?
	JRST	NOMAP		;EITHER WAY 
	PUSHJ	P,SYMINI	;GET SYMBOL TABLE RE-INITIALIZED
	SKIPN	T2,PRGNO	;GET NUMBER OF MODULE NAMES
	JRST	TTLSRT		;NO MODULES LOADED YET
	MOVEM	T2,MDLCNT	;HELPS TO TRAP ERRORS
	LSH	T2,1		;2 WORDS PER ENTRY
	PUSHJ	P,LOGBCK	;LNKMOV MESSAGES TO LOG FILE
	PUSHJ	P,DY.GET##	;GET SPACE TO HOLD INDEX
	MOVEM	T1,MDLIDX	;START OF IT
	HRLI	T1,(POINT 36)	;FORM BYTE PTR
	MOVEM	T1,MDLPTR	;TO DEPOSIT NAMES
				;AND ADDRESSES
	PUSHJ	P,LOGBCK	;RESET OUTPUT TO MAP FILE

TTLSRT:	SETZB	R2,R1		;INCASE UNSORTED
	JRST	NXTSYM		;GET NEXT SYMBOL

	SKIPN	T1,NXTTTL	;REL POSITION ON NEXT TITLE
	MOVE	T1,LSYM		;USE END IF LAST
	SUB	T1,SYMPTR	;REMOVE CURRENT POSITION
	SUB	T1,LW.LS	;INCASE ON DSK
	LSH	T1,1		;NEED 2 WORDS
	IDIVI	T1,.L		;FROM TRIPLET ORIGINALLY
	ADD	T2,T1		;ACCOUNT FOR REMAINDER?
	PUSHJ	P,LOGBCK	;ANY MESSAGES TO LOG FILE
	PUSHJ	P,DY.GET##	;GET SPACE
	HRL	T1,T2
	MOVEM	T1,SRTPTR	;STORE START AND SIZE
	PUSHJ	P,LOGBCK	;BACK TO MAP FILE
	HRLZI	T2,(POINT 36)
	HRR	R2,T2		;BYTE POINTER TO STORE NAMES ETC
	MOVE	R1,MAPSRT	;INDEX TO SORT TYPE
;	JRST	NXTSYM		;JUMP TO SYMBOL LOOP
SUBTTL	SYMBOL LOOP


NXTSYM:	PUSHJ	P,GETSYM	;GET FIRST SYMBOL
	  JRST	SYMDN		;ALL OVER
	  JRST	TTLBLK		;A TITLE BLOCK
	PUSHJ	P,SYMCHK	;SEE IF WE WANT THIS SYMBOL?
	  JRST	NXTSYM		;NO
	JUMPN	R2,STRSYM	;JUMP IF SORTING

PNTSYM:	PUSHJ	P,.TTABC##	;TAB
	MOVEM	W1,SYFLAG	;SAVE PRIMARY FLAGS
	MOVE	T1,W2		;FIRST 6 CHARS OF NAME
	MOVEM	W3,VALUE	;VALUE OF SYMBOL
	PUSHJ	P,.TSIXN##
SYMLNG:	MOVX	T1,S.SYM	;SEE IF LONG SYMBOL
	PUSHJ	P,FNDAST
	  JRST	SYMVAL		;NO
	MOVE	T1,W2
	PUSHJ	P,.TSIXN##
	SKIPE	T1,W3
	PUSHJ	P,.TSIXN##
	JRST	SYMLNG		;SEE IF MORE

SYMVAL:	PUSHJ	P,.TTABC##
	MOVE	T1,VALUE
	PUSHJ	P,.TFOCT##	;FULL WORD OCTAL WITH LEADING BLANKS
	PUSHJ	P,.TTABC##
	MOVE	T1,SYFLAG
	TXNE	W1,PS.ENT	;TEST FOR ENTRY POINT
	JRST	ENTSYM		;FOUND ONE
	TXNE	W1,PS.COM	;OR COMMON
	JRST	COMSYM		;BOTH ARE SPECIAL CASES OF GLOBALS
	TXNE	W1,PS.UDF	;UNDEFINED?
	JRST	UDFSYM		;YES
	TXNE	W1,PS.GLB
	JRST	GLBSYM		;NORMAL GLOBAL
	TXNE	W1,PS.LCL	;SHOULD BE LOCAL
	JRST	LCLSYM		;IT WAS
RELTST:	TXNE	W1,PS.MDF	;MULTIPLY-DEFINED?
	JRST	[MOVEI	T1,[ASCIZ	\Multiply-defined\]
		JRST	TSTFIN]
	MOVEI	T1,[ASCIZ	\Relocatable \]
	TXNN	W1,PS.REL	;ASSUME IT WAS RELOCATABLE
	MOVEI	T1,[ASCIZ	\Absolute    \]
	PUSHJ	P,.TSTRG##	;OUTPUT ONE OR OTHER
	MOVEI	T1,[ASCIZ	\Suppressed\]
	TXNN	W1,PS.DDT	;SUPPRESSED?
COMRET:	MOVEI	T1,[ASCIZ	\	\]
TSTFIN:	PUSHJ	P,.TSTRG##	;YES
	SETCMB	T1,ODDNESS	;AT END OF LINE?
	JUMPN	T1,ENDSYM	;NOT THIS TIME
	PUSHJ	P,.TYLPP	;END LINE
ENDSYM:	JUMPE	R2,NXTSYM	;IF NOT SORTING, NOW FOR NEXT
	POPJ	P,		;SORTING
;HERE FOR ENTRY
ENTSYM:	MOVEI	T1,[ASCIZ	\Entry	\]
	PUSHJ	P,.TSTRG##
	JRST	RELTST

;HERE FOR GLOBAL
GLBSYM:	MOVEI	T1,[ASCIZ	\Global	\]
	PUSHJ	P,.TSTRG##
	JRST	RELTST

;HERE FOR LOCAL
LCLSYM:	MOVEI	T1,[ASCIZ	\Local	\]
	PUSHJ	P,.TSTRG##
	JRST	RELTST

;HERE FOR UNDEFINED SYMBOL (LOCAL OR GLOBAL)
UDFSYM:	MOVEI	T1,[ASCIZ	\Undefined	\]
	PUSHJ	P,.TSTRG##
	JRST	RELTST

;HERE FOR COMMON
COMSYM:	MOVEI	T1,[ASCIZ	\Common	length	\]
	PUSHJ	P,.TSTRG##
	MOVX	T1,S.COM	;FIND SECONDARY
	PUSHJ	P,FNDAST
	  JRST	COMRET		;FAILED!
	MOVE	T1,W3		;GET LENGTH
	PUSHJ	P,.TDSPC	;ALLIGN IT
	MOVE	T1,W3		;NO. AGAIN
	PUSHJ	P,.TDECW##	;IN DECIMAL
	MOVEI	T1,"."		;SIGNIFY DECIMAL
	PUSHJ	P,.TCHAR##
	JRST	COMRET		;END LINE
;HERE TO STORE SYMBOL IN SORT BUFFER

STRSYM:	JRST	@STRTBL(R1)	;GO TO RIGHT FUNCTION

DEFINE KEYMAC (A,B)<
 IFIDN <A><MPS>,<
  IRP B,<
   STR'B
>>>
	XALL
STRTBL:	KEYWORDS
	SALL

STRALPHA:
	MOVS	W3,SYMPTR	;RELATIVE ADDRESS NOW
	LSHC	W2,-2		;MAKE SPACE SO SIGNED TEST WILL WORK
	LSH	W3,-1		;SAME FOR 2ND WORD
	TXNN	W2,3B3		;IF NOT ALPHANUMERIC
	TXO	W2,1B1		;MAKE .,%,$ LARGER
	IDPB	W2,R2
	IDPB	W3,R2
	JRST	NXTSYM		;GET NEXT SYMBOL

STRNUMERIC:
STRUNSORTED:
	HALT
SUBTTL	SYMBOL REQUIRED TEST


;HERE TO SEE IF SYMBOL SHOULD BE LISTED
;CALLED BY
;	MOVE	W1,FLAGS
;	PUSHJ	P,SYMCHK
;RETURNS
;+1	IGNORE THIS SYMBOL
;+2	PRINT THIS SYMBOL
;USES T1, T2, T3

SYMCHK:	SKIPGE	T1,MAPCON	;GET CONTENTS SWITCH
	JRST	CPOPJ1		;ALL WAS SET
	MOVE	T2,W1		;GET FLAGS
	ANDX	T2,PS.GLB!PS.ENT!PS.UDF!PS.LCL!PS.COM!PS.REL
	TXZN	T2,PS.REL	;MUST BE ABS IF NOT REL
	JRST	%%.ABS		;SEE IF ALLOWED
%%.REL:	TXNN	T1,C%RELOC	;IS IT ALLOWED?
	POPJ	P,		;NO
;	JRST	SYMTST		;YES, TRY OTHER BITS

SYMTST:	JFFO	T2,.+2		;GET LEADING BIT
	AOSA	(P)		;NO TESTS LEFT
	JRST	@TSTTAB-%%F(T3)	;MUST WAIT TIL T3 SETUP
	POPJ	P,
DEFINE MAKSYM (A)<
 %%L==0
 %%F==^D36
 IRP A,<
  %%==^L<PS.'A>
  IFG %%F-%%,<%%F==%%>
  IFL %%L-%%,<%%L==%%>
  STRSYM \%%,A
>>

DEFINE STRSYM (%%,A)<
 %%.'%%==%%.'A
>

DEFINE SYMGEN <
 IF1,<BLOCK 1>
 IF2,<
  SYMDMP \%%
  %%==%%+1
>>

DEFINE SYMDMP (%%)<
 IFDEF %%.'%%,<%%.'%%>
 IFNDEF %%.'%%,<0>
 PURGE %%.'%%
>



MAKSYM <GLB,ENT,UDL,UDR,LCL,COM,REL>
	%%==%%F

TSTTAB:REPEAT %%L-%%F+1,<SYMGEN>

IF2,<PURGE	%%,%%F,%%L>
;HERE FOR ABSOLUTE
%%.ABS:	TXNE	T2,PS.COM	;HOWEVER COMMON IS NOT REALLY ABS
	JRST	SYMTST		;SO PASS THIS TEST
	TXNN	T1,C%ABSOLUTE
	POPJ	P,
	JRST	SYMTST

;HERE FOR GLOBAL
%%.GLB:	TXZ	T2,PS.GLB	;CLEAR IT
	TXNN	T1,C%GLOBAL
	POPJ	P,
	JRST	SYMTST

;HERE FOR LOCAL
%%.LCL:	TXZ	T2,PS.LCL
	TXNN	T1,C%LOCAL
	POPJ	P,
	JRST	SYMTST

;HERE FOR ENTRY
%%.ENT:	TXZ	T2,PS.ENT!PS.GLB
	TXNN	T1,C%ENTRY
	POPJ	P,
	JRST	SYMTST

;HERE FOR COMMON
%%.COM:	TXZ	T2,PS.COM!PS.GLB
	TXNN	T1,C%COMMON
	POPJ	P,
	JRST	SYMTST


;HERE FOR UNDEFINED (RH OR LH)
%%.UDL:!%%.UDR:!
%%.UDF:	TXZ	T2,PS.UDF
	TXNN	T1,C%UNDEFINED
	POPJ	P,
	JRST	SYMTST
;HERE TO SORT AND PRINT SYMBOL TABLE

SRTSYM:	HRRZ	W2,SRTPTR	;INITIAL VALUE
	SUBI	W2,(R2)		;- NO. OF PAIRS OF WORDS
	LSH	W2,^D17		;CUT IN HALF AND PUT IN LHS
	HRR	W2,SRTPTR	;-N,,ADDRESS
	PUSHJ	P,IDXLP0	;SORT IT
	HRRZ	R2,SRTPTR	;POINT TO TOP OF BUFFER

SRTSY1:	SKIPN	T1,1(R2)	;GET POINTER
	JRST	SRTFIN		;ALL DONE
	LSH	T1,3-^D18	;PUT IN RHS
	ADD	T1,LS.LB	;FIX INCORE
	TMOVE	W1,(T1)		;GET TRIPLET AGAIN
	PUSHJ	P,PNTSYM	;PRINT IT NOW
	JRST	SRTSY1

SRTFIN:	HRRZ	T1,SRTPTR
	HLRZ	T2,SRTPTR
	PUSHJ	P,DY.RET##	;GIVE BACK BUFFER
	SKIPE	ODDNESS		;NEED TO END LINE
	PUSHJ	P,[SETCMM ODDNESS
		PJRST	.TYLPP]		;YES
	MOVE	T1,SYMPTR
	ADD	T1,LS.LB
	TMOVE	W1,(T1)		;GET BACK ORIGINAL TRIPLET
	POPJ	P,
SUBTTL	TITLE ROUTINES


;HERE IF TRIPLET FOUND IS A TITLE
TTLBLK:
	TXNE	W1,PT.PSC	;IS THIS JUST THE PSECTS?
	  JRST	NXTSYM		;YES, ALREADY READ THEM
IFN .NWBLK,<
	TXNE	W1,PT.MSF	;JUST A MULT. SRC. FILE BLOCK?
	  JRST	NXTSYM		;YES, IGNORE IT (ALREADY PRINTED)
> ;END IFN .NWBLK
	SKIPE	ODDNESS		;NEED TO END LINE?
	PUSHJ	P,[SETCMM ODDNESS
		PJRST	.TYLPP]		;YES
	TXNE	W1,PT.BLK	;FAIL BLOCK HEADER?
	JRST	BTITLE		;YES
	MOVEM	W3,NXTTTL	;SAVE POINTER TO NEXT TITLE
	SETZM	CURPRG		;FINISHED WITH THIS PROGRAM
	PUSHJ	P,.TYLPP	;BLANK LINE
	PUSHJ	P,TYSTAR	;PRINT SEPARATORS
	PUSHJ	P,.TSTP5	;SEE IF ENOUGH SPACE ON THIS PAGE
	  JFCL
	PUSHJ	P,.TYLPP	;BLANK LINE
	MOVE	T1,W2		;FIRST 6 CHARS OF NAME
	MOVEM	W2,CURPRG	;SAVE INCASE GOES OVER PAGE
	PUSHJ	P,.TSIXN##
	TXNE	W1,PT.FAK	;ONLY A FAKE TITLE?
	JRST	TTLFAK		;YES, NO ROOM IN INDEX
	MOVE	T1,W2		;NAME
	MOVS	T2,PAGENO	;GET PAGE NUMBER
	LSHC	T1,-2		;SO SIGNED TEST CAN WORK
	LSH	T2,-1		;SAME FOR 2ND WORD OF PAIR
	TXNN	T1,3B3		;IF NOT ALPHANUMERIC
	TXO	T1,1B1		;MAKE .,%,$ LARGER
	IDPB	T1,MDLPTR	;STORE MODIFIED NAME
	IDPB	T2,MDLPTR	;AND PAGE NO
	SOSGE	MDLCNT		;STILL ROOM LEFT?
	JRST	E$$TTF		;[1174] NO, MUST BE ERROR

;CONTINUED ON NEXT PAGE
TTLFAK:	MOVX	T1,S.TTL	;SEE IF ANY MORE TO NAME
	MOVX	T4,S.CMT!S.RLD!S.RLN!S.RLS!S.PRC!S.CRE!S.DEV!S.NAM!S.SFD!S.VER!S.SEG	;STOPPERS
	PUSHJ	P,FNDAST
	  JRST	TTLCMT		;NO, TRY COMMENT
TTLLNM:	MOVE	T1,W2		;GET NEXT SIX CHARS
	PUSHJ	P,.TSIXN##
	SKIPE	T1,W3		;AND NEXT SIX
	PUSHJ	P,.TSIXN##
	MOVX	T1,S.TTL
	MOVX	T4,S.CMT!S.RLD!S.RLN!S.RLS!S.PRC!S.CRE!S.DEV!S.NAM!S.SFD!S.VER!S.SEG	;STOPPERS
	PUSHJ	P,FNDNAS	;SEE IF ANY MORE (NOT INCLUDING THIS ONE)
	  JRST	TTLCMT		;NO
	JRST	TTLLNM		;YES

TTLCMT:
IFN .NWBLK,<
	MOVX	T1,S.TTL!S.CMT	;LOOK FOR THE ASCII COMMENT
	MOVX	T4,S.RLD!S.RLN!S.RLS!S.PRC!S.CRE!S.DEV!S.NAM!S.SFD!S.VER!S.SEG	;STOPPERS
	PUSHJ	P,FNDNAS	;LOOK FOR COMMENTS
	  JRST	TTLRL1		;NONE, GO AFTER NEXT
	PUSHJ	P,.TTABC##	;TYPE A TAB
	JRST	TTLCM2		;AND JUMP INTO MAIN LOOP
TTLCM1:	MOVX	T1,S.TTL!S.CMT	;LOOK FOR NEXT BLOCK OF COMMENT
	MOVX	T4,S.RLD!S.RLN!S.RLS!S.PRC!S.CRE!S.DEV!S.NAM!S.SFD!S.VER!S.SEG	;STOPPERS
	PUSHJ	P,FNDNAS	;GO LOOK
	  JRST	TTLRLD		;DONE, GIVE UP
TTLCM2:	DMOVE	W1,W2		;MOVE ASCII STRING UP
	SETZ	W3,		;MAKE ASCIZ
	MOVEI	T1,W1		;POINT TO THE ASCIZ STRING
	PUSHJ	P,.TSTRG##	;TYPE IT
	JRST	TTLCM1		;LOOK FOR MORE
TTLRLD:	PUSHJ	P,.TYLPP	;END LINE IF COMMENT PRINTED
> ;END IFN .NWBLK


;FALL THROUGH TO PRINT .REL FILE SPEC
TTLRL1:	MOVX	T1,S.TTL!S.RLD	;GET REL FILE DEVICE & FILENAME
	MOVX	T4,S.RLN!S.RLS!S.PRC!S.CRE!S.DEV!S.NAM!S.SFD!S.VER!S.SEG	;STOPPERS
	PUSHJ	P,FNDNAS
	  JRST	TTLPRC		;SKIP REST OF THIS ALSO
	MOVEI	T1,[ASCIZ	\	from \]
	PUSHJ	P,.TSTRG##
	MOVE	T1,W2		;DEVICE
	PUSHJ	P,.TSIXN##
	PUSHJ	P,.TCOLN##
	PUSH	P,W3		;SAVE UFD
	MOVX	T1,S.TTL!S.RLN	;FILE NAME & EXT
	MOVX	T4,S.RLS!S.PRC!S.CRE!S.DEV!S.NAM!S.SFD!S.VER!S.SEG	;STOPPERS
	PUSHJ	P,FNDNAS
	  JRST	TTLRLU
	MOVE	T1,W2		;FILE NAME
	PUSHJ	P,.TSIXN##
	MOVEI	T1,"."
	PUSHJ	P,.TCHAR##
	SKIPE	T1,W3		;EXT
	PUSHJ	P,.TSIXN##
TTLRLU:	POP	P,W3		;RECOVER UFD
	JUMPE	W3,TTLPRC	;NO UFD
	MOVEI	T1,"["
	PUSHJ	P,.TCHAR##
	MOVE	T1,W3		;GET PPN
	PUSHJ	P,.TXWDW##	;PROG,PROJ
	MOVX	T1,S.TTL!S.RLS	;NOW FOR POSSIBLE SFD
	MOVX	T4,S.PRC!S.CRE!S.DEV!S.NAM!S.SFD!S.VER!S.SEG	;STOPPERS
	PUSHJ	P,FNDNAS
	  JRST	TTLRLR		;CLOSE [DIRECTORY]
TTLRLS:	PUSHJ	P,.TCOMA##
	MOVE	T1,W2
	PUSHJ	P,.TSIXN##
	JUMPE	W3,TTLRLR
	PUSHJ	P,.TCOMA##
	MOVE	T1,W3
	PUSHJ	P,.TSIXN##
	MOVX	T1,S.TTL!S.RLS	;NOW FOR NEXT SFD
	MOVX	T4,S.PRC!S.CRE!S.DEV!S.NAM!S.SFD!S.VER!S.SEG	;STOPPERS
	PUSHJ	P,FNDNAS
	  JRST	TTLRLR		;CLOSE [DIRECTORY]
	JRST	TTLRLS

TTLRLR:	MOVEI	T1,"]"
	PUSHJ	P,.TCHAR##
TTLPRC:	MOVX	T1,S.TTL!S.PRC	;FIND PROCESSOR NAME
	MOVX	T4,S.CRE!S.DEV!S.NAM!S.SFD!S.VER!S.SEG	;STOPPERS
	PUSHJ	P,FNDNAS
	  JRST	TTLCRU		;NO LUCK, GO PRINT CREATION STUFF
	PUSH	P,W3		;SAVE CPU BITS ETC
	JUMPE	W2,TTLPRX	;IF NO NAME GIVEN, USE DEFAULT
	MOVEI	T1,[ASCIZ	\	created by \]
	PUSHJ	P,.TSTRG##
	MOVE	T1,W2		;SET UP PROC NAME
TTLPR1:	PUSHJ	P,.TSIXN##	;TYPE 1ST SIX CHARS OF PROCESSOR NAME
	MOVX	T1,S.TTL!S.PRC	;LOOK FOR MORE OF PROCESSOR NAME
	MOVX	T4,S.CRE!S.DEV!S.NAM!S.SFD!S.VER!S.SEG	;STOPPERS
	PUSHJ	P,FNDNAS	;GET NEXT TRIPLET
	  JRST	TTLCPU		;NO MORE, GO PRINT RUNNABLE CPU'S
	MOVE	T1,W2		;NEXT CHARACTERS OF PROCESSOR NAME
	PUSHJ	P,.TSIXN##	;TYPE THEM
	SKIPE	T1,W3		;MORE?
	  JRST	TTLPR1		;YES

TTLCPU:	POP	P,T1		;[1120] RESTORE CPU BITS
TTLCP1:	TLZ	T1,-1		;[1120] ZAP PROCESSOR TYPE BITS
	PUSHJ	P,TYPCPU	;[1120] TYPE CPUS FOR THIS MODULE
	JRST	TTLCRE		;GO PRINT CRE STUFF

TTLPRX:	POP	P,W3		;RESTORE CPU BITS
	JUMPE	W3,TTLCRU	;UNKNOWN PROCESSOR SO SKIP
	MOVEI	T1,[ASCIZ	\	created by \]
	PUSHJ	P,.TSTRG##
	HLRE	T1,W3		;GET PROCESSOR TYPE (-1 IS LINK)
	CAML	T1,[-1]		;TOO LOW?
	CAILE	T1,CT.LEN	;MAKE SURE IN RANGE
	SETZ	T1,		;USE UNKNOWN
TTLCRL:	MOVE	T1,PRCTAB(T1)	;PICKUP NAME
	PUSHJ	P,.TSTRG##
	HRRZI	T1,(W3)		;[1120] GET CPU BITS
	JRST	TTLCP1		;PRINT CPU BITS
TTLCRE:	MOVX	T1,S.TTL!S.CRE		;LOOK FOR CREATION INFO
	MOVX	T4,S.DEV!S.NAM!S.SFD!S.VER!S.SEG	;STOPPERS
	PUSHJ	P,FNDNAS	;FIND THE TRIPLET
	  JRST	TTLSRC		;WHAT CAN YOU DO?
	JUMPE	W3,TTLDAT	;DON'T PRINT A VERSION IF NONE
	MOVEI	T1,[ASCIZ/ version /]
	PUSHJ	P,.TSTRG##	;PROCLAIM THE DATA
	MOVE	T1,W3		;SET IT UP
	PUSHJ	P,.TVERW##	;THEN LET SCAN DO ALL THE WORK
TTLDAT:	JUMPE	W2,TTLSRC	;FORGET IT IF NOT GIVEN
	MOVEI	T1,[ASCIZ/ on /]
	PUSHJ	P,.TSTRG##
	HLRZ	T1,W2		;GET DATE
	PUSHJ	P,.TDATE##	;TYPE IT
	MOVEI	T1,[ASCIZ/ at /]
	PUSHJ	P,.TSTRG##
	HRRZ	T1,W2		;GET TIME (SECS)
	IMULI	T1,^D1000	;SCAN WANTS MILLISECS
	PUSHJ	P,.TTIME##	;TYPE AWAY
	JRST	TTLSRC		;DONE, NOW PRINT SEGMENT STUFF

TTLCRU:	MOVX	T1,S.TTL!S.CRE
	MOVX	T4,S.DEV!S.NAM!S.SFD!S.VER!S.SEG	;STOPPERS
	PUSHJ	P,FNDNAS	;SEE IF CREATION TRIPLET THERE
	  JRST	TTLSRC		;NO, FORGET THE WHOLE IDEA
	JUMPE	W2,TTLSRC	;MUST BE SPECIFIED
	MOVEI	T1,[ASCIZ	\	created\]
	PUSHJ	P,.TSTRG##
	JRST	TTLDAT
TTLSRC:
IFN .NWBLK,<
	MOVX	T1,S.TTL!S.DEV	;LOOK FOR SOURCE FILE INFO
	MOVX	T4,S.NAM!S.SFD!S.VER!S.SEG	;STOPPERS
	PUSHJ	P,FNDNAS	;SEARCH SYMBOL TABLE
	  JRST	TTLSG1		;NOT THERE
	PUSH	P,W3		;SAVE SOURCE UFD
	PUSHJ	P,.TYLPP	;END LINE
	MOVEI	T1,[ASCIZ/	Source file was   /]
TTLSR1:	PUSHJ	P,.TSTRG##	;TYPE HEADER
	MOVE	T1,W2		;DEVICE
	PUSHJ	P,.TSIXN##	;TYPE IT
	PUSHJ	P,.TCOLN##	;A COLON
	MOVX	T1,S.TTL!S.NAM	;FILE NAME AND EXTENSION NEXT
	MOVX	T4,S.SFD!S.VER!S.SEG	;STOPPERS
	PUSHJ	P,FNDNAS	;SEARCH SYMBOL TABLE
	  JRST	TTLUFD		;NON-DIRECTORY DEVICE??
	MOVE	T1,W2		;FILE NAME
	PUSHJ	P,.TSIXN##	;TYPE IT
	MOVEI	T1,"."		;A DOT
	PUSHJ	P,.TCHAR##	;OUT IT GOES
	SKIPE	T1,W3		;IF AN EXTENSION EXISTS
	PUSHJ	P,.TSIXN##	;TYPE IT TOO
TTLUFD:	POP	P,W3		;RESTORE UFD
	JUMPE	W3,TTLVER	;NONE, DON'T TYPE [0,0]
	MOVEI	T1,"["		;OPEN BRACKET
	PUSHJ	P,.TCHAR##	;ZAP
	MOVE	T1,W3		;POSITION PPN
	PUSHJ	P,.TXWDW##	;LET SCAN DO ALL THE WORK
TTLSFD:	MOVX	T1,S.TTL!S.SFD	;SEARCH FOR SFD'S
	MOVX	T4,S.VER!S.SEG	;STOPPERS
	PUSHJ	P,FNDNAS	;SEE IF SPECIFIED
	  JRST	TTLRBK		;NO, GO CLOSE OFF [P,PN]
	PUSHJ	P,.TCOMA##	;A COMMA TO SEPERATE
	MOVE	T1,W2		;SET UP FIRST ONE
	PUSHJ	P,.TSIXN##	;TYPE IT
	JUMPE	W3,TTLRBK	;FINISH UP IF NO MORE
	PUSHJ	P,.TCOMA##	;A SEPARATING COMMA
	MOVE	T1,W3		;THERE IS, SET IT UP
	PUSHJ	P,.TSIXN##	;TYPE IT
	JRST	TTLSFD		;AND CONTINUE
TTLRBK:	PUSHJ	P,.TRBRK##	;CLOSE [PATH]
TTLVER:	MOVX	T1,S.TTL!S.VER	;SOURCE VERSION INFO NEXT
	MOVX	T4,S.SEG	;STOPPERS
	PUSHJ	P,FNDNAS	;LOOK FOR IT
	  JRST	TTLNXT		;CAN'T HAVE EVERYTHING
	JUMPE	W2,TTLCRS	;IF NO VERSION, PRINT CREATION INFO
	MOVEI	T1,[ASCIZ/ version /]
	PUSHJ	P,.TSTRG##	;TYPE INTRODUCTION
	MOVE	T1,W2		;SET UP VERSION
	PUSHJ	P,.TVERW##	;AND LET SCAN WORRY ABOUT IT
TTLCRS:	JUMPE	W3,TTLNXT	;FORGET IT IF NOT SPECIFIED
	MOVEI	T1,[ASCIZ/ created on /]
	PUSHJ	P,.TSTRG##	;USE UP DISK SPACE
	HLRZ	T1,W3		;PICKUP DATE
	PUSHJ	P,.TDATE##	;TYPE IT
	MOVEI	T1,[ASCIZ/ at /]
	PUSHJ	P,.TSTRG##	;TYPE "AT"
	HRRZ	T1,W3		;GET TIME (SECONDS)
	IMULI	T1,^D1000	;SCAN WANTS MILLISECONDS
	PUSHJ	P,.TTIME##	;TYPE THE TIME AS HH:MM:SS
TTLNXT:	SKIPL	T1,NXTTTL	;IS NEXT TITLE BLOCK A MULT. SRC. FILE?
	JRST	TTLSEG		;NO, PRINT IT NEXT TIME
	HRRZ	T1,T1		;YES, CLEAR FLAG IN LH
	SUB	T1,LW.LS	;CONVERT TO PHYSICAL ADDRESS
	ADD	T1,LS.LB	; ...
	ADDI	T1,.L-1		;WANT TO ACCESS LAST WORD OF TRIPLET
	SKIPE	PAG.LS		;IF PAGING
	CAMGE	T1,LS.AB	;AND THIS ADDRESS NOT YET IN CORE
	  SKIPA			;NOT TRUE
	    HALT		;GIVE UP (FOR NOW)
	SUBI	T1,.L-1		;BACK TO FIRST WORD OF TRIPLET
	MOVE	T2,ASTPTR	;IN CASE FIRST TIME THROUGH, GET ASTPTR
	SKIPN	SAVAST		;ANYTHING SAVED YET?
	MOVEM	T2,SAVAST	;NO, JUST SAVE THE FIRST ONE
	MOVE	T2,2(T1)	;SAVE POINTER TO TITLE AFTER THIS ONE
	MOVEM	T2,NXTTTL	;SAVE FOR LATER
	ADDI	T1,.L		;POINT TO 1ST 2NDARY 3RPLET OF NEW BLK
	MOVEM	T1,ASTPTR	;SETUP TO SCAN NEW PT.MSF BLOCK
	MOVX	T1,S.TTL!S.DEV	;LOOK FOR SOURCE DEVICE & UFD
	MOVX	T4,S.NAM!S.SFD!S.VER!S.SEG	;STOPPERS
	PUSHJ	P,FNDNAS	;SEARCH THE SYMBOL TABLE
	  JRST	TTLNXT		;NOT THERE, LOOK FOR MORE
	PUSH	P,W3		;SAVE SOURCE UFD
	PUSHJ	P,.TYLPP	;END OLD LINE
	MOVEI	T1,[ASCIZ/	concatenated with /]
	JRST	TTLSR1		;DUMP THIS BLOCK
> ;END IFN .NWBLK
TTLSEG:
IFN .NWBLK,<
	SKIPN	T1,SAVAST	;IS THERE AN ASTPTR SAVED?
	JRST	TTLSG1		;NO
	MOVEM	T1,ASTPTR	;YES, RESTORE IT
	SETZM	SAVAST		;NOTHING THERE NOW
TTLSG1:> ;END IFN .NWBLK
	PUSHJ	P,.TYLPP	;END LINE
	SETZB	R1,ZERLEN	;ASSUME NOT ZERO LENGTH
	MOVX	T1,S.TTL!S.SEG
	SETZ	T4,		;NO STOPPERS
	PUSHJ	P,FNDNAS	;GET SEGMENT INFO
	  JRST	TTLEND
	HLRZ	T1,W2		;GET LOW SEG ORIGIN
	HLRZ	T2,W3		;AND HIGH SEG
	CAIN	T1,(W2)		;LOW SEG EMPTY?
	CAIE	T2,(W3)		;YES, AND HIGH SEG TOO?
	  CAIA			;SOMETHING LOADED SOMEWHERE
	SETOM	ZERLEN		;NOTHING IN EITHER SEGMENT
TTLHSG:	HLRZ	T1,W2(R1)	;GET LOW SEG INIT REL
	HRRZ	T2,W2(R1)	;AND FINAL
	CAMN	T2,T1		;SAME?
	JRST	[JUMPN	R1,TTLEND	;THIS IS HIGH SEG
		SKIPN	W3
		SETOM	ZERLEN		;BOTH SEGMENTS ZERO
		AOJA	R1,TTLSG1]	;TRY AGAIN
	PUSHJ	P,.TTABC##
	MOVEI	T1,SEG0(R1)
	PUSHJ	P,.TSTRG##
	MOVEI	T1,SEG1
	PUSHJ	P,.TSTRG##
	HLRZ	T1,W2(R1)
	PUSHJ	P,.T6OCT##	;STARTING
	MOVEI	T1,SEG2
	PUSHJ	P,.TSTRG##
	HRRZ	T1,W2(R1)
	SKIPE	T1		;MIGHT NOT BE SETUP (IF 0)
	SUBI	T1,1		;ONE LESS THAN PROG BREAK
	PUSHJ	P,.T6OCT##	;ENDS
	MOVEI	T1,SEG3
	PUSHJ	P,.TSTRG##
	HRRZ	T1,W2(R1)
	HLRZ	T2,W2(R1)
	SUB	T1,T2
	MOVEM	T1,W2(R1)	;SAFE PLACE TO STORE IT
	PUSHJ	P,.T6OCT##	;LENGTH
	MOVEI	T1,[ASCIZ	\ (octal),\]
	PUSHJ	P,.TSTRG##
	MOVE	T1,W2(R1)
	PUSHJ	P,.TDSPC	;ALLIGN WORD
	MOVE	T1,W2(R1)	;GET LENGTH BACK
	PUSHJ	P,.TDECW##
	MOVEI	T1,[ASCIZ	\. (decimal)\]
	PUSHJ	P,.TSTRG##
	PUSHJ	P,.TYLPP	;END LINE
	JUMPN	R1,TTLEND	;DONE
	ADDI	R1,1		;GET NEXT WORD
TTLSG1:	SKIPN	T1,W2(R1)	;SEE WHAT IT IS
	JRST	TTLEND		;NOTHING
	TLNE	T1,-1		;LHS 0?
	JRST	TTLHSG		;NO TRY HIGH
;HERE TO HANDLE PSECTS
TTLPSC:	MOVE R,W3		;GET OFFSET TO BLOCK
	ADD	R,LS.LB		;PLUS BASE
	SUB	R,LW.LS		;MINUS WINDOW
	CAMLE	R,LS.AB		;IN CORE
	HALT			;NO
	MOVEI	T1,[ASCIZ /	Psect /]	;[1161]
	PUSHJ	P,.TSTRG##
	MOVE	T1,1(R)		;NAME
	PUSHJ	P,.TSIXB##	;[1161] TYPE WITH TRAILING BLANKS
	MOVEI	T1,[ASCIZ / starts at   /]
	PUSHJ	P,.TSTRG##
	HLRZ	T1,2(R)		;RC.CV
	PUSHJ	P,.T6OCT##
	MOVEI	T1,SEG2
	PUSHJ	P,.TSTRG##
	HRRZ	T1,2(R)		;PROG BREAK
	SUBI	T1,1
	PUSHJ	P,.T6OCT##
	MOVEI	T1,SEG3		;LENGTH
	PUSHJ	P,.TSTRG##
	HLRZ	T2,2(R)		;RC.CV
	HRRZ	T1,2(R)		;RC.HL
	SUBI	T1,(T2)
	PUSH	P,T1		;SAVE LENGTH
	PUSHJ	P,.T6OCT##
	MOVEI	T1,[ASCIZ / (octal),/]	;[1161]
	PUSHJ	P,.TSTRG##
	MOVE	T1,0(P)		;[1161] GET LENGTH AGAIN
	PUSHJ	P,.TDSPC	;[1161] ALIGN WORD TO COME
	POP	P,T1		;LENGTH
	PUSHJ	P,.TDECW##
	MOVEI	T1,[ASCIZ /. (decimal)/]	;[1161]
	PUSHJ	P,.TSTRG##
	PUSHJ	P,.TYLPP
	ADDI	W3,.L		;POINT TO NEXT
	MOVE	W1,(R)
	JUMPL	W1,[	TXNE	W1,PT.EXT	;[711] IT'S PRIMARY
			JRST	TTLPSC		;[711] MORE TO COME
			JRST	TTLEND]		;[711] NO MORE
	TXNN	W1,S.LST	;[711] NOT PRIMARY, ALL DONE?
	JRST	TTLPSC		;NOT YET
				;YES
TTLEND:	PUSHJ	P,.TYLPP	;BLANK LINE
	MOVE	T1,MAPCON	;GET MASK FOR MAP CONT
	SKIPGE	ZERLEN		;MAKE ZERO LENGTH TEST NOW
	TXNE	T1,C%ZERO	;SKIP IF NOT ALLOWED
	JRST	TTLSRT		;OK, ALLOWED
	MOVEI	T1,[ASCIZ	\	Zero length module\]
	PUSHJ	P,.TSTRG##
	PUSHJ	P,.TYLPP
	PUSHJ	P,GETSYM	;GET FIRST SYMBOL
	  JRST	SYMDN		;ALL OVER
	  JRST	TTLBLK		;A TITLE BLOCK
	JRST	.-3		;LOOP TIL NEXT TITLE OR ELSE END

E$$TTF::.ERR.	(MS,,V%L,L%W,S%W,TTF,<Too many titles found>) ;[1174]
	JRST	NXTSYM		;IGNORE, BUT TRY TO COMPLETE MAP
SUBTTL	FAIL BLOCK HEADER


BTITLE:	MOVX	W1,PS.LCL	;FAKE A LOCAL SYMBOL
	PUSHJ	P,SYMCHK	;SEE IF WE WANT THIS SYMBOL?
	  JRST	NXTSYM		;NO
	PUSHJ	P,.TYLPP	;BLANK LINE
	PUSHJ	P,.TTABC##	;TAB
	MOVEM	W1,SYFLAG	;SAVE PRIMARY FLAGS
	MOVE	T1,W2		;FIRST 6 CHARS OF NAME
	HRRZM	W3,VALUE	;VALUE OF SYMBOL
	PUSHJ	P,.TSIXN##
	MOVEI	T1,[ASCIZ	\	block level	\]
	PUSHJ	P,.TSTRG##
	MOVE	T1,VALUE
	PUSHJ	P,.TDECW##	;LEVEL IN DECIMAL
	PUSHJ	P,.TYLPP	;END LINE
	JRST	NXTSYM
SUBTTL	SYMBOL TABLE ROUTINES


;HERE TO READ BACK SYMBOL TABLE IF ON DSK
;CALLED BY
;	PUSHJ	P,SYMINI

SYMINI:	SKIPN	T1,PAG.LS	;PAGING SYMBOLS?
	POPJ	P,		;NO
	MOVS	T1,LW.LS	;LOWEST INCORE
	HRR	T1,LSYM		;HIGHEST
	IORI	T1,.DBM		;PUT ON DSK BLOCK BOUND (NOT NECESSARY)
	PUSHJ	P,LS.OUT##	;DUMP THEM
	SETZM	LW.LS		;START AGAIN AT 0
	PUSH	P,FRECOR	;SAVE INCASE NOT 0
	SETZM	FRECOR		;DON'T NEED EXTRA SPACE IN MAPS
	PUSHJ	P,FR.CNT##	;COUNT ALL OF FREE CORE
	CAILE	T1,1000		;[640] UNLESS THAT WOULD USE IT ALL
	SUBI	T1,1000		;[640] LEAVE SOME FOR OTHERS (TTLDN ETC)
	MOVEI	P1,LS.IX	;WILL WANT TO EXPAND LS AREA MOST LIKELY
	MOVE	P2,LSYM		;WE WANT THIS MUCH MOST LIKELY
	ADD	P2,LS.LB	;FIND EXTRA WE NEED
	SUB	P2,LS.AB	;REMOVING WHAT WE HAVE
	CAMLE	P2,T1		;MORE THAN WHATS FREE?
	MOVE	P2,T1		;YES, SO JUST GET WHAT WE CAN
	JUMPE	P2,[MOVE T1,LS.AB	;MAKE SURE WE HAVE AT LEAST 2 BLOCKS
		SUB	T1,LS.LB	;IF WE ARE NOT INCREASING
		CAIL	T1,.IPS		;MORE THAN ONE BLOCK
		JRST	SYMIN1		;[640] ENOUGH ALREADY, LEAVE
		MOVEI	P2,.IPS		;NOT ENOUGH, GET ONE MORE
		JRST	.+1]
	PUSHJ	P,LOGBCK	;INCASE LOG FILE OPEN
	PUSHJ	P,LNKCOR	;GET IT ALL
	  PUSHJ	P,E$$MEF##	;[1174] CANNOT HAPPEN
	PUSHJ	P,LOGBCK	;RESTORE MAP DEVICE
SYMIN1:	POP	P,FRECOR	;[640] RESTORE
	MOVE	T1,LS.AB	;RECALCULATE UW.LS
	SUB	T1,LS.LB	;SEE HOW BIG
	MOVEM	T1,UW.LS	;BIGGEST IN CORE
	PJRST	LS.IN##		;INPUT AND RETURN
;HERE TO GET NEXT PRIMARY SYMBOL
;CALLED BY
;	PUSHJ	P,GETSYM
;RETURNS
;+1	END OF SYMBOL TABLE
;+2	TRIPLET IS A TITLE OR OTHER NON-SYMBOL
;+3	NORMAL SYMBOL RETURN
;USES T1
;SETS UP W1, W2, W3 & SYMPTR

GETSYM:	MOVE	T1,SYMPTR	;GET POINTER TO LAST PRIMARY
	ADD	T1,LS.LB	;ADD IN OFFSET
NOTPRM:	ADDI	T1,.L		;GET TO END OF NEXT TRIPLET
	CAMLE	T1,LS.AB	;STILL IN CORE
	JRST	SHFSYM		;NO, GET NEXT BLOCK OR GIVE UP
	SKIPL	W1,-.L(T1)	;GET FLAGS
	JRST	NOTPRM		;NOT A PRIMARY
	DMOVE	W2,-.L+1(T1)	;LOAD REST OF TRIPLET
	SUB	T1,LS.LB	;REMOVE OFFSET
	MOVEM	T1,SYMPTR	;STORE POINTER
	AOS	(P)		;AT LEAST SKIP RET
	TXNE	W1,PT.SYM	;SEE IF SYMBOL TYPE
	AOS	(P)		;YES, RET +3
	POPJ	P,
;HERE TO SHIFT NEW SYMBOL WINDOW INTO CORE
;ALL EXCEPT THE LAST 128 WORDS ARE THROWN AWAY (KEPT INCASE SYMBOL ACROSS A BOUND)
;READ IN NEW PART AND ADJUST POINTERS
;IF THERE IS MORE SPACE THAN WE NEED GIVE BACK THE EXCESS

SHFSYM:	SKIPN	UW.LS		;PAGING?
	POPJ	P,		;NO, ALL DONE
	MOVE	T1,UW.LS	;LAST HIGHEST
	ADDI	T1,1		;NEW LOWEST
	CAMLE	T1,LSYM		;STILL SOME SYMBOLS LEFT?
	POPJ	P,		;NO, ALL DONE
				;KEEP LAST BLOCK IN CORE AGAIN
	HRLI	T1,-.IPS(T1)	;[650] IN BOTH HALVES
	HLRZ	T2,T1
	SUB	T2,LW.LS	;DIFFERENCE = WINDOW SIZE
	ADDM	T2,LW.LS	;FIXUP WINDOW PTRS
	ADDM	T2,UW.LS
	MOVN	T2,T2
	ADDM	T2,SYMPTR	;BACKUP SYMBOL PTR
	MOVM	T2,T2		;BACK POSITIVE
	MOVE	T3,UW.LS	;GET NEXT UPPER BOUND
	ANDCMI	T3,.IPM		;[1164] FORM FIRST FREE IN ALL BUT LAST PAGE
	CAMG	T3,LSYM		;HAVE WE TOO MUCH ROOM NOW?
	SOJA	T2,SHFSY1	;NO, READ ALL WE CAN GET
	MOVE	T2,LSYM		;GET UPPER WE NEED
	SUB	T2,LW.LS	;LENGTH WE REALLY NEED
	IORI	T2,.IPM		;[650] BLOCK BOUND
	MOVE	T3,LSYM		;HIGHEST SYMBOL SEEN
	IORI	T3,.IPM		;PUT ON BOUND
	MOVEM	T3,UW.LS	;STORE AS HIGHEST WINDOW
	MOVE	T3,LS.LB	;ACTUAL LOWER
	ADD	T3,T2		;NEW UPPER
	MOVEM	T3,LS.AB	;ACTUAL BOUND IN USE
	SETZM	1(T3)		;CLEAR IT
	HRLI	T3,1(T3)
	ADDI	T3,2		;FORM BLT PTR
	BLT	T3,@LS.UB	;CLEAR IT ALL
	SUBI	T2,.IPS		;[1164] LAST PAGE HAS ALREADY BEEN COUNTED
SHFSY1:	ADDI	T1,(T2)		;INPUT PTR
	PUSHJ	P,LS.IN##	;READ IN NEW BLOCKS
	JRST	GETSYM		;AND CONTINUE
;HERE TO FIND ASSOCIATED SECONDARY TRIPLET
;CALLED BY
;	MOVE	T1,FLAGS
;	MOVE	T4,"STOPPER" FLAGS (WILL NOT SCAN BEYOND THESE)
;	PUSHJ	P,FNDAST	(FIRST TIME)
;	  -OR-
;	PUSHJ	P,FNDNAS
;RETURNS
;+1	FAILED
;+2	SUCCESS
;USES T1, T2, T3, T4
;SETS UP W1, W2, W3

FNDAST:	SKIPA	T2,SYMPTR	;GET POINTER
FNDNAS:	SKIPA	T2,ASTPTR	;ALREADY RELOCATED
	ADD	T2,LS.LB	;FIX
FNDNAT:	ADDI	T2,.L		;GET NEXT TRIPLET
	CAMLE	T2,LS.AB	;STILL IN CORE?
	PUSHJ	P,FNDNIC	;NOT IN CORE, OR FINISHED
	MOVEI	T3,-.L(T2)	;KEEP ASTPTR UP TO DATE
	MOVEM	T3,ASTPTR	;IN CASE FNDNIC OR ENTERED AT FNDAST
	SKIPGE	T3,-.L(T2)	;GET FLAGS
	POPJ	P,		;FOUND A PRIMARY (FAILED)
	XOR	T3,T1		;IFF ALL BITS MATCH
	TXZ	T3,S.LST	;IGNORE THIS BIT HOWEVER
	TDZ	T4,T1		;GUARD AGAINST REQUESTING A STOPPER
	JUMPN	T3,[TDNE T3,T4	;FOUND A STOPPER?
		POPJ	P,	;YES, QUIT
		JRST	FNDNAT]	;NO, KEEP TRYING
	TMOVE	W1,-.L(T2)	;LOAD TRIPLET
	MOVEM	T2,ASTPTR	;SAVE INCASE CALLED AGAIN
CPOPJ1:	AOS	(P)
CPOPJ:	POPJ	P,
;HERE TO READ IN MORE OF SYMBOL TABLE IF PAGING
;LEAVES THE LAST PAGE IN CORE (IN CASE TRIPLET SPLIT ACROSS BOUND)
;BUT ADJUSTS SYMPTR ETC
;CALLED BY
;	PUSHJ	P,FNDNIC
;
FNDNIC:	SKIPN	PAG.LS
	JRST	TPOPJ		;REMOVE RETURN AND EXIT
	MOVE	T1,UW.LS	;GET CURRENT HIGHEST
	ADDI	T1,1
	CAMLE	T1,LSYM		;ANY MORE TO READ IN?
	JRST	TPOPJ		;NO, GIVE UP
	SUB	T2,LS.LB	;REMOVE OFFSET
	MOVE	T1,SYMPTR	;GET PTR TO CURRENT PRIMARY
	ANDCMI	T1,.IPM		;KEEP THAT BLOCK
	SUB	T2,T1		;ADJUST T2 FOR NEW VALUE
	PUSH	P,T2		;SAVE IT FOR RETURN
	MOVEI	T2,.IPM
	ANDM	T2,SYMPTR	;BACKUP PRIMARY PTR
	ADDM	T1,LW.LS	;GET NEW
	ADDB	T1,UW.LS	;AFTER NEXT INPUT
	CAML	T1,LSYM		;DO WE NEED ALL OF IT?
	PUSHJ	P,REDUSM	;NO, REDUCE SIZE
	HRLZ	T1,LW.LS	;LOWEST ADDRESS
	HRR	T1,UW.LS	;HIGHEST
	PUSHJ	P,LS.IN##	;READ IN AGAIN
	POP	P,T2		;RESTORE T2
	ADD	T2,LS.LB	;RESTORE OFFSET
	POPJ	P,		;RETURN

;HERE TO REDUCE SIZE SO WE DON'T WASTE TIME LOOKING AT ZEROS
;AND SAVES READIN TIME
REDUSM:	SUB	T1,LSYM		;GET EXCESS
	ANDCMI	T1,.IPM		;IN THIS BLOCK
	MOVN	T1,T1		;AS - OFFSET
	ADDM	T1,UW.LS	;BACKUP WINDOW
	ADD	T1,LS.AB	;WILL BE NEW TOP LATER
				;FIRST WE MUST CLEAR JUNK FROM THIS SPACE
	MOVEI	T2,1(T1)	;FIRST FREE LOC
	SETZM	(T2)		;CLEAR IT
	HRL	T2,T2	
	ADDI	T2,1		;BLT PTR
	BLT	T2,@LS.AB	;UP TO OLD LIMIT
	MOVEM	T1,LS.AB	;NOW SET TOP
	POPJ	P,

TPOPJ:	POP	P,T1		;REMOVE RETURN
	POPJ	P,
SUBTTL	OUTPUT ROUTINES


MAPIT:	SOSGE	MCBUF+2		;ANY SPACE EFT
	JRST	MAPDMP		;NO
	IDPB	T1,MCBUF+1	;YES
	POPJ	P,

MAPDMP:	OUT	MC,
	  JRST	MAPIT
	PUSHJ	P,LOGBCK	;RESTORE LOG CHAN
E$$OEM::PUSH	P,[MC]		;ERROR, SAVE CHAN
	.ERR.	(ST,,V%L,L%W,S%W,OEM,<Output error on map file, file closed, load continuing>) ;[1174]
	CLOSE	MC,
	JRST	MAPRET		;AND RETURN

;HERE TO SWAP CURRENT OUTPUT SUBROUTINE WITH PREVIOUS
;CALLEDD BY
;	PUSHJ	P,LOGBCK

LOGBCK:	MOVE	T1,OLDDEV	;RESTORE
	PUSHJ	P,.TYOCH##
	MOVEM	T1,OLDDEV
	POPJ	P,
;HERE TO OUTPUT CR-LF OR CR-FF & HEADER
;CALLED BY
;	PUSHJ	P,.TYLPP

.TYLPP:	SOSLE	CNTLPP		;STILL SPACE ON THIS PAGE?
	PJRST	.TCRLF##	;YES, JUST CRLF
	MOVEI	T1,LN.LPP	;NO, RESET PAGE COUNT
	MOVEM	T1,CNTLPP
	PUSHJ	P,.TCRLF##	;CR-LF
	MOVEI	T1,.CHFFD	;FF
	PUSHJ	P,.TCHAR##
.TYHDR:	MOVE	T1,PAGHDR	;HEADER AGAIN
	PUSHJ	P,.TSTRG##
	MOVE	T1,MAPNAM	;GET MAP FILE NAME
	PUSHJ	P,.TSIXN##	;IN SIXBIT
	MOVE	T1,OKCPUS	;[1120] PRINT CPUS FOR PROGRAM
	PUSHJ	P,TYPCPU	;[1120]   ..
	SKIPN	MAPVER		;ONLY PRINT IF NOT ZERO
	JRST	TYPAGE		;JUST PAGE NUMBER
	MOVEI	T1,[ASCIZ	\	version \]
	PUSHJ	P,.TSTRG##
	MOVE	T1,MAPVER	;VERSION
	PUSHJ	P,.TVERW##
TYPAGE:
IFN FTOVERLAY,<
	SKIPL	LNKMAX		;ANY OVERLAYS?
	SKIPG	LNKNO.		;EXCEPT #0
	JRST	TYPAG1		;NO
	MOVEI	T1,[ASCIZ	\	#\]
	PUSHJ	P,.TSTRG##
	MOVE	T1,LNKNO.
	PUSHJ	P,.TDECW##
	MOVEI	T1,[ASCIZ	\	page \]
	CAIA
TYPAG1:
>;END OF IFN FTOVERLAY
	MOVEI	T1,[ASCIZ	\		page \]
	PUSHJ	P,.TSTRG##
	AOS	T1,PAGENO	;GET PAGE NUMBER
	PUSHJ	P,.TDECW##
	PUSHJ	P,.TYLPP
	MOVE	T1,PAGENO	;GET PAGE NUMBER
	CAIN	T1,1		;BLANK LINE UNLESS PAGE 1
	POPJ	P,
	SKIPE	T1,CURPRG	;GET CURRENT PROG NAME
	PUSHJ	P,.TSIXN##	;OUTPUT IT SO WE KNOW WHERE WE ARE
	PJRST	.TYLPP
;HERE TO TEST FOR 5 FREE LINE ON PAGE
;CALLED BY
;	PUSHJ	P,.TSTP5

.TSTP5:	MOVEI	T1,5
				;FALL INTO .TSTPG

;HERE TO SEE IF WITHIN SO MANY LINES FROM END OF PAGE
;IF SO END PAGE AND RETURN +1
;IF NOT JUST RETURN +2
;CALLED BY
;	MOVEI	T1,NO. OF LINES TO TEST FOR
;	PUSHJ	P,.TSTPG
;RETURNS
;+1	ON A NEW PAGE
;+2	ENOUGH SPACE ON CURRENT PAGE

.TSTPG:	CAMG	T1,CNTLPP	;ENOUGH FREE LINES?
	JRST	CPOPJ1		;YES
	SETZM	CNTLPP		;NO, FORCE END
	PJRST	.TYLPP		;AND WRITE IT OUT

;HERE TO PRINT LINE OF STARS
;CALLED BY
;	PUSHJ	P,TYSTAR

TYSTAR:	MOVEI	T1,STARS	;GET LINE
	PUSHJ	P,.TSTRG##	;OUTPUT
	PJRST	.TYLPP		;AND CLOSE LINE
;.TDSPC - SUBROUTINE TO PRINT ALLIGNMENT SPACES FOR DECIMAL NO.
;CALLED BY
;	MOVE	T1,NUMBER
;	PUSHJ	P,.TDSPC
;OUTPUTS ONE SPACE FOR EVERY DIGIT NOT PRINTED

.TDSPC:	MOVSI	T2,-SPCLEN	;AOBJN WORD
	CAMGE	T1,SPCTBL(T2)	;SEE HOW BIG
	AOBJN	T2,.-1		;NOT YET
	MOVEI	T1," "		;SPACE
	HRRZ	T2,T2		;COUNT OF HOW MANY
	JUMPE	T2,CPOPJ	;NONE
	PUSHJ	P,.TCHAR##
	SOJG	T2,.-1		;LOOP
	POPJ	P,

SPCTBL:	^D100000
	^D10000
	^D1000
	^D100
	^D10
SPCLEN==.-SPCTBL

;.TDEC3 -- TYPE DECIMAL AT LEAST THREE DIGITS
;CALL:	SAME AS .TDECW WITH T2=FILLER CHAR (" " OR "0")

.TDEC3:	CAILE	T1,^D99		;SEE IF TWO DIGITS OR LESS
	PJRST	.TDECW##	;NO--JUST OUTPUT
	MOVEI	T2," "		;SET FILLER
	EXCH	T1,T2		;SWAP
	PUSHJ	P,.TCHAR##	;OUTPUT FILLER
	EXCH	T1,T2		;PUT BACK
	PJRST	.TDEC2##	;OUTPUT OTHER TWO DIGITS
SUBTTL	HEADER MESSAGES ETC


HEAD1:	ASCIZ	\		LINK symbol map of	\
HEAD2:	ASCIZ	\	Produced by LINK version \

SEG0:	ASCIZ	\Low \
	ASCIZ	\High\
SEG1:	ASCIZ	\ segment starts at	\
SEG2:	ASCIZ	\ ends at	\
SEG3:	ASCIZ	\ length	\
STARS:	ASCIZ	\		*************\
END1:	ASCIZ	\	[End of LINK map of	\
DEFINE X (A,B,C)<
	[ASCIZ	\C\]
>

	[ASCIZ	\LINK\]
	XALL
PRCTAB:	PROCESSORS
	SALL
;ROUTINE TO PRINT CPUS ON WHICH A MODULE OR PROGRAM WILL RUN. IF ALL CPUS
;KNOWN TO LINK ARE ALLOWED, PRINT NOTHING.
;ON CALL:
;	T1/	CP.??? BITS

TYPCPU:	CAIN	T1,CP.MSK	;[1120] RUNNABLE ON ALL CPUS?
	POPJ	P,		;[1120] YES--DON'T BOTHER PRINTING
	PUSH	P,P1		;[1120] SAVE SOME VARS
	PUSH	P,P2		;[1120]   ..
	MOVE	P1,T1		;[1120] SAVE CPU BITS IN SAFE AC
	PUSHJ	P,.TSPAC##	;[1120] SEPARATE BY A SPACE
	SETZ	P2,		;[1120] START CHECK AT KA
TYPCPL:	JUMPE	P1,TYPCPE	;[1120] ANY CPUS LEFT TO PRINT?
	MOVE	T1,CPUTAB(P2)	;[1120] YES--GET ADDR OF CPU NAME
	TXNE	P1,1B35		;[1120] PRINT THIS CPU?
	PUSHJ	P,.TSTRG##	;[1120] YES--PRINT IT
	LSH	P1,-1		;[1120] ADVANCE TO NEXT CPU
	AOJA	P2,TYPCPL	;[1120]   AND LOOP UNTIL DONE

TYPCPE:	POP	P,P2		;[1120] RESTORE VARS
	POP	P,P1		;[1120]   ..
	POPJ	P,


DEFINE X(A,B)<
	[ASCIZ	\/A\]
>

	XALL
CPUTAB:	CPUS
	SALL
SUBTTL	END OF MAP


SYMDN:	SETZM	CURPRG		;DON'T WANT LAST PROG ON UNDEF PAGES
	SKIPE	ODDNESS		;NEED TO END LINE?
	PUSHJ	P,[SETCMM ODDNESS
		PJRST	.TYLPP]		;YES
	PUSHJ	P,.TYLPP	;BLANK
	PUSHJ	P,TYSTAR	;SEPARATE THIS AREA
	PUSHJ	P,.TYLPP	;AND BLANK LINE
	SKIPN	USYM		;ANY UNDEFINED SYMBOLS?
	JRST	MULDF0		;NO, TRY FOR MULTIPLY DEFINED

UNRES0:	MOVE	T1,CNTLPP	;GET NUMBER OF LINES ON PAGE
	CAIGE	T1,LN.LPP-3	;UNLESS JUST OUTPUT HEADER
	SETZM	CNTLPP		;START NEW PAGE
	PUSHJ	P,.TYLPP	;START ON A NEW LINE
	MOVE	P1,USYM		;GET NUMBER OF UNDEFS IN A PRESERVED AC
	MOVE	T1,P1		;WHERE SCAN EXPECTS NUMBER
	PUSHJ	P,.TDECW##	;TYPE NO.
	MOVE	T1,P1		;GET UNDEFS AGAIN
	CAILE	T1,2		;LEAVE 0 OR 1 ALONE
	MOVEI	T1,2		;SET INDEX TO 0,1, OR 2
	MOVE	T1,UNRTAB-1(T1)	;GET ADDRESS
	PUSHJ	P,.TSTRG##	;OUTPUT MESSAGE
	PUSHJ	P,.TYLPP	;AND CR-LF
	PUSHJ	P,.TYLPP
	MOVE	P2,HT.PRM	;GET INDEX INTO HASH TABLE
UNRES1:	SKIPN	P3,@HT.PTR	;GET POINTER TO SYMBOL
	JRST	UNRES2		;NO POINTER, NO SYMBOL
	ADD	P3,GS.LB	;ADD IN BASE
	MOVE	T1,0(P3)	;GET FLAGS
	TXNE	T1,PT.SYM	;WE ONLY WANT SYMBOLS
	TXNN	T1,PS.UDF!PS.REQ	;SEE IF UNDEFINED STILL
	JRST	UNRES2		;NO
	MOVE	T1,1(P3)	;GET SYMBOL
	PUSHJ	P,.TSIXN##	;SIXBIT WORD
	PUSHJ	P,.TTABC##	;TAB
	MOVE	T1,2(P3)	;VALUE
	PUSHJ	P,.TOCTW##	;IN OCTAL
	PUSHJ	P,.TYLPP	;NEW LINE
IFE DEBSW,<			;IF DEBUGGING SCAN ALL OF TABLE
	SOJLE	P1,UNRES3	;DONE IF NO MORE UNDFS
				;INCASE COUNT OFF>
UNRES2:	SOJGE	P2,UNRES1	;LOOP IF MORE SYMBOLS TO LOOK AT
UNRES3:	PUSHJ	P,.TYLPP	;BLANK
	PUSHJ	P,TYSTAR	;OUTPUT STARS
;NOW FOR MULTIPLY DEFINED SYMBOLS

MULDF0:	SKIPN	MSYM		;ANY TO OUTPUT?
	JRST	MAPIDX		;NO
	PUSHJ	P,.TSTP5	;SEE IF ENOUGH ROOM
	  JFCL
	MOVE	P1,MSYM		;GET NUMBER OF MULT-DEFS IN A PRESERVED AC
	MOVE	T1,P1		;WHERE SCAN EXPECTS NUMBER
	PUSHJ	P,.TDECW##	;TYPE NO.
	MOVE	T1,P1		;GET MULT-DEFS AGAIN
	CAILE	T1,2		;LEAVE 0 OR 1 ALONE
	MOVEI	T1,2		;SET INDEX TO 0,1, OR 2
	MOVE	T1,MDFTAB-1(T1)	;GET ADDRESS
	PUSHJ	P,.TSTRG##	;OUTPUT MESSAGE
	PUSHJ	P,.TYLPP	;AND CR-LF
	PUSHJ	P,.TYLPP
	MOVE	P2,HT.PRM	;GET INDEX INTO HASH TABLE
MULDF1:	SKIPN	P3,@HT.PTR	;GET POINTER TO SYMBOL
	JRST	MULDF2		;NO POINTER, NO SYMBOL
	ADD	P3,GS.LB	;ADD IN BASE
	MOVE	T1,0(P3)	;GET FLAGS
	TXNE	T1,PT.SYM	;WE ONLY WANT SYMBOLS
	TXNN	T1,PS.MDF	;SEE IF MULT-DEFINED
	JRST	MULDF2		;NO
	MOVE	T1,1(P3)	;GET SYMBOL
	PUSHJ	P,.TSIXN##	;SIXBIT WORD
	PUSHJ	P,.TTABC##	;TAB
	MOVE	T1,2(P3)	;VALUE
	PUSHJ	P,.TOCTW##	;IN OCTAL
	PUSHJ	P,.TYLPP	;NEW LINE
IFE DEBSW,<			;IF DEBUGGING SCAN ALL OF TABLE
	SOJLE	P1,MULDF3	;DONE IF NO MORE UNDFS
				;INCASE COUNT OFF>
MULDF2:	SOJGE	P2,MULDF1	;LOOP IF MORE SYMBOLS TO LOOK AT
MULDF3:	PUSHJ	P,.TYLPP
	PUSHJ	P,TYSTAR
	JRST	MAPIDX

UNRTAB:	[ASCIZ	/ undefined global symbol/]
	[ASCIZ	/ undefined global symbols/]

MDFTAB:	[ASCIZ	/ multiply-defined global symbol/]
	[ASCIZ	/ multiply-defined global symbols/]
SUBTTL	MAP INDEX


IDXHDR:	ASCIZ	\	Index to LINK symbol map of	\

MAPIDX:	MOVE	T1,PRGNO
	SOJLE	T1,MAPEND	;IGNORE INDEX IF ONLY ONE PROGRAM
	MOVE	T1,PAGENO
IFE FTOVERLAY,<
	SOJLE	T1,MAPEND	;OR ONLY ONE PAGE
>
IFN FTOVERLAY,<
	SUB	T1,FSTPGN	;- START OF THIS OVERLAY
	JUMPLE	T1,MAPEND	;OR ONLY ONE PAGE
>
	SETZM	CNTLPP		;WANT NEW PAGE
	MOVEI	T1,IDXHDR	;CHANGE HEADER
	MOVEM	T1,PAGHDR
	PUSHJ	P,.TYLPP	;AND FORCE IT OUT
IFN FTOVERLAY,<
	MOVE	T1,LNKNO.
	ROT	T1,-1		;USUAL WAY TO ADDRESS 1/2 WORD
	MOVE	T2,PAGENO	;PAGE # OF INDEX
	JUMPL	T1,[HRRM T2,@OVMIDX
		JRST	.+2]
	HRLM	T2,@OVMIDX
>;END OF IFN FTOVERLAY
	PUSHJ	P,IDXSRT	;SORT AND LIST
	JRST	MAPEND		;ALL DONE
;NOW TO SORT INDEX

;USES W1, W2, W3 TO HOLD AOBJN POINTERS
;R1, R2 TO HOLD COUNT AND POSITION
;T1 T2 TO HOLD CURRENT NAME AND PAGE
;T3 T4 FOR EXCHANGE

IDXLP0:	MOVE	W1,W2		;GET RUNNING COPY
	DMOVE	T1,0(W1)	;NAME & PAGE

IDXLP1:	CAMLE	T1,2(W1)	;BIGGER THAN ONE FOLLOWING?
	JRST	IDXSWP		;YES, MUST EXCH
	CAML	T1,2(W1)	;HOWEVER IF JUST EQUAL
	JRST	[CAMLE	T2,3(W1)	;TEST 2ND WORD
		JRST	IDXSWP		;SMALLER, SO SWAP
		JRST	.+1]		;REALLY IS BIGGER
	DMOVE	T1,2(W1)	;NO GET BIGGER
	ADDI	W1,1		;ACCOUNT FOR 2ND ENTRY
IDXLP2:	AOBJN	W1,IDXLP1	;AND FOR ALL NAMES IN TABLE

	AOBJP	W2,CPOPJ	;ALL SORTED NOW
	SOJA	W2,IDXLP0	;TRY AGAIN

IDXSWP:	DMOVE	T3,2(W1)	;GET NAME & PAGE
	DMOVEM	T3,0(W1)	;AND STORE
	DMOVEM	T1,2(W1)
	AOJA	W1,IDXLP2	;TRY NEXT

IDXSRT:	MOVN	W2,PRGNO	;NO. OF NAMES
	AOJE	W2,IDXFIN	;DON'T SORT IF SINGLE ITEM
	HRLZ	W2,W2
	HRR	W2,MDLIDX	;-N+1,,INDEX
	PUSHJ	P,IDXLP0	;SORT BUFFER
;	JRST	IDXFIN		;PRINT RESULTS
IDXFIN:	MOVE	R1,PRGNO	;INITIAL NO OF NAMES
	MOVE	R2,MDLIDX	;INITIAL POSSITION
IDXHDI:	MOVE	T1,R1		;NO. OF MODULE NAMES LEFT
	CAILE	T1,4*<LN.LPP-4>	;WILL IT FIT ON PAGE
	MOVEI	T1,4*<LN.LPP-4>	;NO, JUST USE MAX
	SUBI	R1,(T1)		;REDUCE COUNT NOW LEFT
	MOVE	T3,T1		;GET A COPY
	IDIVI	T1,4		;4 ACCROSS
	MOVSI	W1,-4		;AOBJN POINTER
	MOVEM	T1,LCOUNT(W1)	;STORE COUNT
	SOSL	T2		;IF REMAINDER
	AOS	LCOUNT(W1)	;COUNT ONE MORE
	AOBJN	W1,.-3		;LOOP FOR ALL 4
	MOVSI	W1,-4+1		;RESET POINTER
	MOVE	T1,R2		;GET ADDRESS OF FIRST ITEM FOR THIS PAGE
	ADDI	R2,(T3)		;INCREMENT FOR NEXT TIME
	ADDI	R2,(T3)		;REMEMBER 2 WORDS PER ENTRY
	HRLI	T1,(POINT 36)	;FORM BASIC BYTE PTR
	MOVEM	T1,BYTEPT(W1)	;STORE IT
	ADD	T1,LCOUNT(W1)	;GET TO NEXT
	ADD	T1,LCOUNT(W1)	;2 WORDS PER ITEM
	MOVEM	T1,BYTEPT+1(W1)
	AOBJN	W1,.-3		;FOR ALL
IDXHD0:	MOVSI	W1,-4		;BASIC LOOP
	MOVEI	T1,[ASCIZ	\	Name	Page\]
	SKIPE	LCOUNT(W1)	;ANYTHING TO OUTPUT FOR THIS COLUMN
	PUSHJ	P,.TSTRG##
	AOBJN	W1,.-3
	PUSHJ	P,.TYLPP	;END LINE
	PUSHJ	P,.TYLPP	;AND BLANK LINE
	MOVSI	W1,-4		;NOW FOR OUTPUT
IDXHD1:	SOSGE	LCOUNT(W1)	;ANYTHING TO DO
	JRST	IDXHD2		;NOT FOR THIS COLUMN
	PUSHJ	P,.TTABC##	;SPACE ACROSS
	ILDB	T1,BYTEPT(W1)	;GET NAME
	ILDB	T2,BYTEPT(W1)	;AND PAGE
	LSH	T2,1		;NOW PUT BACK
	LSHC	T1,2		;AS SIXBIT AND PAGE NO
	PUSH	P,T2		;SAVE PAGE
	PUSHJ	P,.TSIXN##
	PUSHJ	P,.TTABC##
	POP	P,T1		;PAGE
	MOVS	T1,T1		;RIGHT JUSTIFIED
	MOVEI	T2," "		;FILLER CHAR
	PUSHJ	P,.TDEC2##	;DECIMAL
IDXHD2:	AOBJN	W1,IDXHD1	;LOOP ACCROSS PAGE
	PUSHJ	P,.TYLPP	;END LINE
	MOVSI	W1,-4		;REINIT COUNTER
	SKIPLE	LCOUNT(W1)	;DONE IF NOTHING LEFT ON THIS PAGE
	JRST	IDXHD1		;NO, OUTPUT NEXT LINE
	JUMPG	R1,IDXHDI	;MORE TO COME
	POPJ	P,		;ALL DONE
MAPEND:	SKIPN	T2,PRGNO	;[1100] NOW DELETE INDEX BLOCK
	JRST	MAPND0		;[1100]   BUT NOT IF ZERO
	LSH	T2,1		;[1100] TWO ENTRIES PER MODULE
	HRRZ	T1,MDLIDX	;[1100] GET ADDRESS OF BLOCK
	JUMPE	T1,MAPND0	;[1100]   UNLESS NO SYMBOLS
	PUSHJ	P,DY.RET##	;[1100]   AND FREE IT
MAPND0:
IFN FTOVERLAY,<
	SKIPGE	LNKMAX		;ANY OVERLAYS?
	JRST	MAPND1		;NO
	AOS	T1,LNKNO.
	CAMG	T1,LNKMAX	;ALL DONE?
	JRST	OVMAP0		;NO
	SETZM	CNTLPP		;WANT NEW PAGE
	MOVEI	T1,OVXHDR	;CHANGE HEADER
	MOVEM	T1,PAGHDR
	SETOB	R2,LNKNO.	;START WITH LINK# 0
	PUSHJ	P,.TYLPP	;AND FORCE IT OUT
	MOVE	R1,LNKMAX	;HIGHEST LINK NO.
	ADDI	R1,1		;INITIAL NO. OF LINKS
OVXHDI:	MOVE	T1,R1		;NO. OF MODULE NAMES LEFT
	CAILE	T1,4*<LN.LPP-4>	;WILL IT FIT ON PAGE
	MOVEI	T1,4*<LN.LPP-4>	;NO, JUST USE MAX
	SUBI	R1,(T1)		;REDUCE COUNT NOW LEFT
	MOVE	T3,T1		;GET A COPY
	IDIVI	T1,4		;4 ACROSS
	MOVSI	W1,-4		;AOBJN POINTER
	MOVEM	T1,LCOUNT(W1)	;STORE COUNT
	SOSL	T2		;IF REMAINDER
	AOS	LCOUNT(W1)	;COUNT ONE MORE
	AOBJN	W1,.-3		;LOOP FOR ALL 4
	MOVSI	W1,-4+1		;RESET POINTER
	MOVE	T1,R2		;GET ADDRESS OF FIRST ITEM FOR THIS PAGE
	ADDI	R2,(T3)		;INCREMENT FOR NEXT TIME
	MOVEM	T1,BYTEPT(W1)	;STORE IT
	ADD	T1,LCOUNT(W1)	;GET TO NEXT
	MOVEM	T1,BYTEPT+1(W1)
	AOBJN	W1,.-2		;FOR ALL
OVXHD0:	MOVSI	W1,-4		;BASIC LOOP
	MOVEI	T1,[ASCIZ	\	Overlay	Page\]
	SKIPE	LCOUNT(W1)	;ANYTHING TO OUTPUT FOR THIS COLUMN
	PUSHJ	P,.TSTRG##
	AOBJN	W1,.-3
	PUSHJ	P,.TYLPP	;END LINE
	PUSHJ	P,.TYLPP	;AND BLANK LINE
	MOVSI	W1,-4		;NOW FOR OUTPUT
OVXHD1:	SOSGE	LCOUNT(W1)	;ANYTHING TO DO
	JRST	OVXHD2		;NOT FOR THIS COLUMN
	PUSHJ	P,.TTABC##	;SPACE ACROSS
;PRINT LINK NUMBER, WITH LEADING "#" TO DISTINGUISH FROM NUMERIC NAMES

	MOVEI	T1,"#"		;SAVE CONFUSION, MARK LINKS WITH #
	PUSHJ	P,.TCHAR##
	AOS	T1,BYTEPT(W1)	;GET LINK# OF NEXT LINK
	PUSHJ	P,.TDECW##
	PUSHJ	P,.TTABC##
	MOVE	T1,BYTEPT(W1)	;LINK#
	ROT	T1,-1		;1/2 WORD PICKUP
	JUMPL	T1,[HRRZ T1,@OVMIDX	;GET PAGE #
		JRST	.+2]
	HLRZ	T1,@OVMIDX
	MOVEI	T2," "		;FILLER CHAR
	PUSHJ	P,.TDEC2##	;DECIMAL
OVXHD2:	AOBJN	W1,OVXHD1	;LOOP ACCROSS PAGE
	PUSHJ	P,.TYLPP	;END LINE
	MOVSI	W1,-4		;REINIT COUNTER
	SKIPLE	LCOUNT(W1)	;DONE IF NOTHING LEFT ON THIS PAGE
	JRST	OVXHD1		;NO, OUTPUT NEXT LINE
	JUMPG	R1,OVXHDI	;MORE TO COME

	HRRZ	T2,LNMPTR	;GET NUMBER OF NAMES
	JUMPE	T2,MAPND1	;NONE
	LSH	T2,1		;2 WORDS PER NAME
	PUSHJ	P,LOGBCK	;PUT INFO MESSAGES ON TTY
	PUSHJ	P,DY.GET##	;GET SPACE TO HOLD LIST SO WE CAN SORT
	MOVEM	T1,MDLIDX
	HRLI	T1,(POINT 36)
	MOVEM	T1,MDLPTR
	PUSHJ	P,LOGBCK	;PUT INDEX IN MAP FILE
	PUSHJ	P,.TYLPP	;BLANK LINE
	MOVEI	T1,OVNHDR	;NEW HEADER LINE
	MOVEM	T1,PAGHDR	;INCASE NEEDED
	PUSHJ	P,.TSTRG##	;OUTPUT IT ANYWAY
	MOVE	T1,MAPNAM
	PUSHJ	P,.TSIXN##
	SKIPE	MAPVER		;ANY VERSION
	PUSHJ	P,[MOVEI T1,[ASCIZ	\	version \]
		PUSHJ	P,.TSTRG##
		MOVE	T1,MAPVER
		PJRST	.TVERW##]
	PUSHJ	P,.TYLPP	;END LINE
	PUSHJ	P,.TYLPP	;BLANK LINE SEPARATOR
;NOW SORT INDEX OF LINK NAMES, USING IDXSRT.

	HLRZ	T2,LNMPTR	;GET INITIAL PTR
OVXHD4:	MOVE	T3,0(T2)	;GET NAME
	MOVE	T2,1(T2)	;NUMBER ,, PTR
	HLRZ	T1,T2		;NUMBER
	ROT	T1,-1		;1/2 WORD PICKUP
	JUMPL	T1,[HRLZ T4,@OVMIDX
		JRST	.+2]
	HLLZ	T4,@OVMIDX	;PAGE CORRESPONDING TO LINK#
	LSHC	T3,-2		;SO SIGNED TEST CAN WORK
	LSH	T4,-1		;SAME FOR 2ND WORD OF PAIR
	TXNN	T3,3B3		;IF NOT ALPHANUMERIC
	TXO	T3,1B1		;MAKE .,%,$ LARGER
	IDPB	T3,MDLPTR	;STORE MODIFIED NAME
	IDPB	T4,MDLPTR	;AND PAGE NO
	TRNE	T2,-1		;DONE?
	JRST	OVXHD4		;NOT YET
	PUSH	P,PRGNO		;EASIEST WAY TO FAKE OUT IDXSRT
	HRRZ	T1,LNMPTR
	MOVEM	T1,PRGNO
	PUSHJ	P,IDXSRT	;SORT AND LIST
	POP	P,PRGNO
	HRRZ	T1,MDLIDX	;[1100] FREE INDEX BLOCK FOR LINK NAMES
	HRRZ	T2,LNMPTR	;[1100] LENGTH OF BLOCK
	LSH	T2,1		;[1100]   WITH TWO WORDS PER LINK NAME
	PUSHJ	P,DY.RET##	;[1100] DO THE WORK
	JRST	MAPND1


OVXHDR:	ASCIZ	\	Index to overlay numbers of \
OVNHDR:	ASCIZ	\	Index to overlay names of \
>;END OF IFN FTOVERLAY
MAPND1:	PUSHJ	P,.TYLPP	;BLANK LINE
	MOVEI	T1,END1		;AND FINAL MESSAGE
	PUSHJ	P,.TSTRG##
	MOVE	T1,MAPNAM
	PUSHJ	P,.TSIXN##
	MOVEI	T1,"]"
	PUSHJ	P,.TCHAR##
	PUSHJ	P,.TCRLF##

MAPRET:	PUSHJ	P,LOGBCK	;RESTORE LOG DEVICE
E$$EMS::.ERR.	(MS,0,V%L,L%I,S%I,EMS,<End of MAP segment>) ;[1174]
	MOVE	T1,LS.LB	;NOW TO MAKE SURE LS.PT IS CORRECT
	ADD	T1,LSYM		;BASE + LENGTH
	SUB	T1,LW.LS	; - OFFSET
	MOVEM	T1,LS.PT	;POINTS TO NEXT FREE SYMBOL SLOT
	SUB	T1,LS.AB	;GET NO. OF FREE WORDS
	MOVMM	T1,LS.FR	; IN LAST BLOCK
	SETZM	LS.PP		;OK TO DEFAULT PAGE SYMBOLS AGAIN
	MOVE	T1,MAPSW	;SEE WHAT SORT OF MAP IT WAS
	CAMN	T1,[$MAPEND]	;@ END?
	JRST	MAPXIT		;YES, FINISH OFF
	SKIPN	UW.LS		;PAGING SYMBOLS?
	JRST	MAPRT1		;NO
	MOVE	T1,LS.AB	;TOP
	SUB	T1,LS.LB	;LENGTH
	SUBI	T1,.IPM		;MINUS LAST BLOCK
	ADDM	T1,LW.LS	;ONLY KEEP LAST BLOCK IN CORE
	MOVE	T1,LS.AB
	SUBI	T1,.IPS		;LAST ADDRESS TO KEEP
	PUSHJ	P,GBCK.L##	;GIVE IT AWAY
	SETOM	UW.LS		;INDICATE LS AREA AT END AGAIN
MAPRT1:	MOVE	T1,MAPSW	;RESTORE T1 FROM GBCK.L
	CAMN	T1,[$MAPNOW]	;@ NOW
	JRST	MAPRT2		;YES, CLOSE MAP AND DELETE BUFFERS
	CAME	T1,[$MAPERROR]	;ON ERROR
	POPJ	P,
	PUSHJ	P,DVRLS.##	;CLOSE OUT MAP FILE
	RELEASE	RC,		;AND LOG FILE
	EXIT			;GIVE UP
MAPRT2:	SETZM	MAPSW		;DONE WITH MAP SPEC
	PUSHJ	P,DVRLS.##	;CLOSE FILE
	MOVEI	T1,MC		;NOW DELETE BUFFERS
	MOVEM	T1,IO.CHN
	PUSHJ	P,DVZAP.##	;AND DATA BLOCK
	JRST	LNKLOD		;GET NEXT F/S

;HERE IF SYMBOL AREA EMPTY
NOMAP:	MOVEI	T1,[ASCIZ	\	No symbols to output
\]
	PUSHJ	P,.TSTRG##
	JRST	MAPRET		;AND GIVE UP

IFE FTOVERLAY,<
	MAPXIT=LNKXIT
>

IFN FTOVERLAY,<
MAPXIT:	SKIPL	LNKMAX		;ANY OVERLAYS?
	POPJ	P,		;YES, RETURN TO LNKOV2
	JRST	LNKXIT		;NO
>
SUBTTL	DATA STORAGE


.ZZ==.TEMP
U	(OLDDEV)		;LOG DEVICE WHILE MAP IN USE
U	(CNTLPP)		;LINE PER PAGE
U	(PAGENO)		;PAGE NUMBER (STARTS AT 1)
U	(MAPNAM)		;SIXBIT NAME OF MAP FILE
U	(SYMPTR)		;POINTER TO CURRENT SYMBOL (REL TO LS.LB)
U	(ASTPTR)		;POINTER TO CURRENT ASSOCIATED TRIPLET (ABS)
U	(SAVAST)		;SAVE ASTPTR WHILE DOING MSF
U	(SYFLAG)		;TEMP W1
U	(VALUE)			;TEMP W3
U	(ZERLEN)		;-1 IF ZERO LENGTH PROG
U	(MAPVER)		;VERSION IN LOC 137 (REL TO LC.LB)
U	(CURPRG)		;CURRENT OUTPUT PROG NAME
U	(PAGHDR)		;POINTER TO PAGE HEADER
U	(MDLIDX)		;INDEX TO PROG NAMES
U	(MDLPTR)		;BYTE POINTER TO NAMES
U	(MDLCNT)		;RUNNING COUNT OF PROGRAM NAMES
U	(BYTEPT,4)		;BYTE POINTERS FOR OUTPUT
U	(LCOUNT,4)		;LINE COUNTS FOR OUTPUT
U	(OVMIDX)		;INDEX TO LINK NUMBERS
U	(ODDNESS)		;COLUMN COUNTER (ON/OFF)
U	(NXTTTL)		;REL POSITION OF NEXT TITLE
U	(SRTPTR,2)		;START AND SIZE OF SORT BUFFER
U	(FSTPGN)		;FIRST PAGE# OF THIS LINK
SUBTTL	THE END


MAPLIT:	END	LNKMAP