Google
 

Trailing-Edge - PDP-10 Archives - bb-d868b-bm_tops20_v3a_2020_dist - 3a-sources/lnkov1.mac
There are 48 other files named lnkov1.mac in the archive. Click here to see a list.
TITLE LNKOV1 - PHASE 1 OVERLAY MODULE FOR LINK
SUBTTL	D.M.NIXON/DMN/JLd/RKH/JBC/JNG/MCHC	27-Feb-78


;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, MAYNARD, MASS.

ENTRY	LNKOV1
SEARCH	LNKPAR,LNKLOW,MACTEN,UUOSYM,SCNMAC
EXTERN	LNKLOD,LNKWLD,LNKOV2

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



VERSION


;LOCAL ACC DEFINITIONS

R=:R1		;CURRENT RELOCATION COUNTER

SALL
SEGMENT
SUBTTL	REVISION HISTORY

;START OF VERSION 2
;135	ADD OVERLAY FACILITY
;136	FIX VARIOUS BUGS
;170	MAKE PLOT SWITCH WORK
;174	FIX RELOCATABLE OVERLAY BUGS
;175	REPLACE /RESET WITH /NODE
;200	LOAD REENTRANT OVERLAY HANDLER
;207	REDUCE SIZE OF OVERHEAD TABLES
;216	(13559) ADD ZSV ERROR CHECKS

;START OF VERSION 2B
;237	(13931) CHANGE RPR ERROR TO NBR
;245	MAKE OVERLAY FILE STAY ON SAME STRUCTURE ON SUPERSEDE
;	MODIFY OC.OPN ROUTINE TO CHECK THIS CASE
;262	Force a /LINK on encountering /NODE, if needed
;300	Fix copy of permanent excludes on /OVERLAY
;331	Set size of segment correctly so don't loose
;	EXTTAB and ENTTAB'S.
;352	LABEL EDIT 237
;404	Put edit 316 back in to LINK.
;407	Correct problem with /NODE:-1
;413	Fix some small bugs with ELN message.
;414	Make sure FUNCT. is loaded in the root link.
;416	Update GS.FR instead of GS.PT when creating bound globals.
;425	Improve FSN error detect to not bomb users unnecessarily.

;START OF VERSION 2C
;466	Avoid loop on /NODE when loading relocatable overlays.
;504	Get output IOWD right when putting symbols in overlay file.
;505	Fix absolute addresses after call to LNKCOR via SY.CHR.
;511	Overlap by 1 page when copying LS to overlay file for fixups.
;521	Zap MNSEEN and MNTYPE on /LINK.
;530	Get triplet flag definitions right.
;534	Make multiple /LINK switches work on one line.
;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
;605	Use OUTSTR in LNKRER message.
;623	Handle multiple /PLOT switches (delete data block)
;625	Print blank line after LNKELN message
;631	Print correct file spec with LNKEOV message.
;632	Implement $FIXUP.
;635	Add code to handle /ARSIZE switch, and count any
;	ambiguous request table space in previous link.
;650	Use VM on TOPS-10 if available.
;651	Put the overlay file where the user wants it.
;660	Clear .LINK storage at the end of an overlay.
;664	Don't destroy last word of BG area on /NODE:0.
;665	Fix core management problem broken by edit 650.
;666	Fix edits 650 and 665, this time for sure.
;671	Don't leave junk in PH.ORL.
;677	Don't default to /SYMSEG:LOW if loading overlays.
;730	Check for /DEBUG, do it before /LINK.
;731	SEARCH MACTEN,UUOSYM
;765	Release on both TOPS-10 and TOPS-20 as LINK version 4(765)
SUBTTL	ENTRY POINT

LNKOV1:	JFCL	.+1		;NORMAL ENTRY
	JRST	LNKLOD		;

;IOWD FOR PREAMBLE SECTION

IFE FTKIONLY,<
PHIOWD:	IOWD	PH.ZZ,PH.HDR
	0
>
IFN FTKIONLY,<EXTERN	PHIOWD>		;BUG IN DMOVE MACRO
SUBTTL	OVERLAY SWITCHES

.OVERLAY::
	HRLZ	T1,(P2)		;GET NEXT SWITCH
	HLLM	T1,1(P1)	;FIX LIST OF SWITCHES TO DO
	JRST	OVRLAY

%OVERLAY::
	HRRZ	T1,(P2)		;GET NEXT SWITCH
	HRRM	T1,1(P1)	;FIX LIST OF SWITCHES TO DO
;	JRST	OVRLAY

OVRLAY:	MOVE	T1,OVLTBL-1(T2)	;GET BIT
	IORM	T1,OVERLW	;SET IN MEMORY
	SKIPE	IO.PTR+%OC	;ALREADY SET ONCE?
	JRST	OVRLA1		;YES, JUST RETURN
	MOVSI	T1,'OVL'	;FORCE EXTENSION
	MOVEM	T1,F.EXT(P1)
	PUSHJ	P,DVOUT.##	;SETUP DATA BLOCK
	  %OC,,.IODPR
	HRLZI	T1,2(P1)	;CLEAR ALL BUT LINK AND SWITCH
	HRRI	T1,3(P1)
	SETZM	2(P1)
	BLT	T1,F.LEN-1(P1)
	PUSHJ	P,OVRTST	;PUT REQUEST IN SYMBOL TABLE
	HLLZ	T1,INCPTR	;SEE IF ANY VERY PERM INCLUDES
	JUMPE	T1,OVRLA0	;NO INCLUDES, TRY EXCLUDES
	MOVEI	T2,.EXC		;YES, GET SPACE
	PUSHJ	P,DY.GET##
	HRLZM	T1,OVINEX	;SAVE START OF LIST
	HLLZ	T2,INCPTR	;START OF LIST
	HRR	T2,T1		;WHERE TO PUT IT
	BLT	T2,.EXC-1(T1)	;DO MOVE
	HRRZ	T2,(T1)		;SEE IF MORE
	JUMPE	T2,OVRLA0	;NO
	PUSHJ	P,OVRINX	;YES, COPY REST
;HERE TO SAVE SUPER-GLOBAL EXCLUDES, IF ANY EXIST.

OVRLA0:	HLLZ	T1,EXCPTR	;ANY EXCLUDES
	JUMPE	T1,OVRLA1	;NO
	MOVEI	T2,.EXC		;YES, GET SPACE
	PUSHJ	P,DY.GET##
	HRRM	T1,OVINEX	;SAVE START OF LIST
	HLLZ	T2,EXCPTR	;START OF LIST
	HRR	T2,T1		;WHERE TO PUT IT
	BLT	T2,.EXC-1(T1)	;DO MOVE
	HRRZ	T2,(T1)		;SEE IF MORE
	JUMPE	T2,OVRLA1	;NO
	PUSHJ	P,OVRINX	;YES, COPY REST
OVRLA1:	HRLS	ARSIZE		;[635] STORE STICKY /ARSIZE
	SUB	P,[2,,2]	;ADJUST STACK
	MOVE	T1,P2		;ADDRESS OF SWITCH BLOCK
	HLRZ	T2,(P2)		;SIZE
	PUSHJ	P,DY.RET##	;GIVE IT BACK
	HLLZ	T1,FL		;GET PERMANENT FLAGS TO DATE
	IORM	T1,FLAGS	;SAVE SO AS TO AFFECT ALL LINKS
	JRST	LNKWLD		;RETURN & TRY AGAIN

OVRTST:	PUSHJ	P,.SAVE4##	;SAVE THE P'S
	MOVX	W1,PT.SGN!PT.SYM	;
	MOVE	W2,['.OVRLA']	;ENTRY POINT
	SETZ	W3,
	PUSHJ	P,TRYSYM##	;SEE IF DEFINED
	  PJRST	SY.RQ##		;UNDEF, ENTER REQUEST
	  POPJ	P,		;ALREADY UNDEFINED
	POPJ	P,		;ALREADY DEFINED

OVRINX:	SPUSH	<T2,T1>		;SAVE THE POINTERS
	MOVEI	T2,.EXC		;GET ANOTHER BLOCK
	PUSHJ	P,DY.GET##
	POP	P,T2		;GET LAST NEW BLOCK
	HRRM	T1,(T2)		;LINK THIS TO IT
	POP	P,T2		;NEXT BLOCK IN ORIGINAL LIST
	HRLZ	T3,T2		;FROM
	HRR	T3,T1		;TO
	BLT	T3,.EXC-1(T1)
	HRRZ	T2,(T1)		;GET NEXT
	JUMPN	T2,OVRINX	;YES THERE IS
	POPJ	P,		;RETURN

DEFINE KEYMAC (A,B)<
 IFIDN <A><OVL>,<
  A'TBL:
  IRP B,<
   EXP $OV'B
>>>
XALL
KEYWORDS
SALL
%LINK::
	SKIPN	T1,S.DEBG	;[730] HAVE WE SEEN A /DEBUG?
	JRST 	%LINK1		;[730] NO, JUMP
	SETZM	S.DEBG		;[730] YES, CLEAR FLAG
	MOVEI	T2,0(P2)	;[730] GET CURRENT /LINK SWITCH PTR
	HRRM	T2,1(T1)	;[730] CHAIN INTO /DEBUG FILE SPEC AS LOCAL SW
	HRRZ	T2,(P2)		;[730] MOVE PTR OF NEXT SWITCH INTO AN AC
	HLLZS	0(P2)		;[730] BEFORE IT GET CLEARED
	MOVE	P2,T2		;[730] UPDATE CURRENT SWTICH PTR WITH IT
	POPJ	P,		;[730] RETURN
%LINK1:				;[730] 
	JUMPN	T2,.+3		;NAME ALREADY SET?
	SKIPGE	LNKMAX		;NO, SO IS IT FIRST TIME?
	MOVE	T2,['ROOT  ']	;YES, PREEMPT NAME "ROOT"
	MOVEM	T2,LNKNAM	;STORE NAME OR ZERO
	MOVEI	T1,LINKTO	;HERE ON TERMINATION
	MOVEM	T1,GOTO
	SETOM	S.INZR		;FLAG RETFSP TO END LINE IN LNKWLD
	JUMPE	T2,CPOPJ	;NO NAME
	PUSHJ	P,.SAVE2##	;NEED TWO SAFE ACCS
	MOVE	P1,T2		;SAVE NAME
	MOVS	P2,LNMPTR	;GET START OF NAME CHAIN
	JUMPE	P2,LINKB	;NOT SETUP YET
LINKA:	CAMN	P1,(P2)		;SAME NAME
	JRST	LNKLNA		;YES, ERROR
	HRRZ	T1,1(P2)	;SEE IF ANY MORE
	JUMPE	T1,LINKB	;NO
	MOVE	P2,T1
	JRST	LINKA		;YES

LINKB:	MOVEI	T2,2		;USE 2 WORDS
	PUSHJ	P,DY.GET##
	JUMPE	P2,[HRLZM T1,LNMPTR
		JRST	.+2]
	HRRM	T1,1(P2)	;LINK TO NEW BLOCK
	MOVE	P2,LNKMAX	;LINK NUMBER OF PREVIOUS
	HRLZI	P2,1(P2)	;ONE MORE IS # OF THIS ONE
	DMOVEM	P1,(T1)		;STORE
	AOS	LNMPTR		;COUNT ONE MORE
	POPJ	P,

LNKLNA:	HLRZ	P2,1(P2)	;GET LINK#
	.ERR.	(MS,.EC,V%L,L%W,S%W,LNA,<Link name >)
	.ETC.	(SBX,.EC!.EP,,,,P1)
	.ETC.	(STR,.EC,,,,,< already assigned to link number >)
	.ETC.	(DEC,.EP,,,,P2)
	POPJ	P,

%ARSIZE::
	HRRM	T2,ARSIZE	;[635] STORE VALUE FOR THIS LINK
	POPJ	P,		;[635] RETURN TO LNKWLD
%NOENTRY::
	PUSHJ	P,STRLSW##	;WAIT 'TIL FILE IS LOADED
.NOENTRY::
	PUSHJ	P,.SAVE4##	;SAVE P1-P4
	MOVX	W1,PT.SGN!PT.SYM	;FLAGS
	SKIPN	W2,T2		;SYMBOL
	JRST	ZSVERR##	;ZERO IS ILLEGAL
	SETZ	W3,		;VALUE
	PUSHJ	P,TRYSYM##	;SEE IF DEFINED
	  POPJ	P,		;IGNORE
	  JFCL			;UNDEFINED
	MOVX	W1,PS.NOE	;NOT AN ENTRY FLAG
	IORM	W1,0(P1)	;SET IN SYMBOL TRIPLET
	POPJ	P,

%NOREQUEST::
	PUSHJ	P,STRLSW##	;WAIT 'TIL FILE IS LOADED
.NOREQUEST::
	PUSHJ	P,.SAVE4##	;SAVE P1-P4
	MOVX	W1,PT.SGN!PT.SYM	;FLAGS
	SKIPN	W2,T2		;SYMBOL
	JRST	ZSVERR##	;ZERO IS ILLEGAL
	SETZ	W3,		;VALUE
	PUSHJ	P,TRYSYM##	;SEE IF DEFINED
	  POPJ	P,		;IGNORE
	  JFCL			;UNDEFINED
	MOVX	W1,PS.NRQ	;NOT A REQUEST FLAG
	IORM	W1,0(P1)	;SET IN SYMBOL TRIPLET
	POPJ	P,

%PLOT::
	SETOM	PLOTSW		;MAKE SURE WE DO IT
	SKIPE	T1,3(P2)	;GET SWITCH VALUE
	MOVEM	T1,PLTTAB-1(T2)	;STORE FOR LNKPLT
	SKIPE	NULSPC		;[623] FIRST CALL THIS FILE SPEC?
	POPJ	P,		;NO
	PUSHJ	P,COPYP1##	;MAKE A NEW DATA BLOCK
	PUSHJ	P,DVOUT.##	;SETUP OUTPUT BLOCK
	  %PC,,-1		;WILL BE EITHER ASCII LINE OR IMAGE AT RUN TIME
	PJRST	RESTP1##	;DELETE DATA BLOCK

%REGION::
	JUMPE	T2,CPOPJ	;ALLOW /REGION:0
	.ERR.	(MS,0,V%L,L%I,S%I,MRN,<Multiple regions not yet implemented>)
	POPJ	P,


%SPACE::
	MOVEM	T2,SPACE	;SAVE VALUE
	POPJ	P,
%REQUEST::
	PUSHJ	P,STRLSW	;WAIT TIL AFTER FILE LOADED
.REQUEST::
	PUSHJ	P,.SAVE4##	;SAVE P1-P4
	MOVE	P2,HT.PRM	;GET INDEX INTO HASH TABLE
	HRRZ	T1,LOWSUB	;[605] TTY TYPEOUT ROUTINE
	PUSHJ	P,.TYOCH##	;TYPE-OUT ON TTY ONLY
	PUSH	P,T1		;SAVE IT
	PUSH	P,[-1]		;MARKER FOR NO REQUESTS
REQST1:	SKIPN	P3,@HT.PTR	;GET POINTER TO SYMBOL
	JRST	REQST3		;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.ENT	;SEE IF AN ENTRY
	JRST	REQST3		;NO
	TXNN	T1,PS.NRQ	;NOT WANTED?
	SKIPN	2(P3)		;OR ZERO VALUE (I.E. NOT A CALL FOO)
	JRST	REQST3		;DO NOT LIST
	AOSE	(P)		;FIRST TIME?
	JRST	REQST2		;NO
	MOVEI	T1,REQHDR
	PUSHJ	P,.TSTRG##		;YES. OUTPUT HEADER LINE
	MOVEI	T1,REQMES
	PUSHJ	P,.TSTRG##
REQST2:	PUSHJ	P,.TTABC##
	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,.TCRLF##	;NEW LINE
REQST3:	SOJGE	P2,REQST1	;LOOP IF MORE SYMBOLS TO LOOK AT
	SKIPL	(P)		;-1 IF NONE SEEN
	JRST	REQST4
	MOVEI	T1,REQHDR
	PUSHJ	P,.TSTRG##
	MOVEI	T1,[ASCIZ	\No \]
	PUSHJ	P,.TSTRG##	;FAILED TO FIND ANY
	MOVEI	T1,REQMES	;REST OF MESSAGE
	PUSHJ	P,.TSTRG##
REQST4:	POP	P,T1		;CLEAR STACK
	POP	P,T1		;RESTORE OLD TYPE-OUT ROUTINE
	PJRST	.TYOCH##	;AND RETURN
REQHDR:	ASCIZ	\[LNKRER \
REQMES:	ASCIZ	\Request External References (Inter-Link Entry points)]
\
SUBTTL	HERE TO TERMINATE LINK

LINKGO::SKIPN	PRGNO		;LOAD ANYTHING?
	JRST	LNKOV2		;NO, DO PASS2
	PUSHJ	P,LIBRARY##	;LOAD DEFAULT LIBS
	PUSH	P,.+1		;LOAD RETURN ADDRESS
	CAI	LNKOV2
	JRST	LINKGT		;COMMON CODE

LINKTO::PUSHJ	P,LIBRARY##	;LOAD DEFAULT LIBS
	PUSH	P,.+1		;LOAD RETURN ADDRESS
	CAI	LNKOV1

LINKGT:	SETOM	LINKSEEN	;END OF SEGMENT SPECIFIED
	AOS	T1,LNKMAX	;INCREMENT NUMBER SEEN
	MOVEM	T1,CS.NUM	;STORE CURRENT IN HEADER
	MOVE	W2,STADDR	;IS START ADDRESS STILL SYMBOLIC?
	TLNN	W2,-1		;NON-ZERO LEFT HALF IF SO
	JRST	LNKT0		;NO
	MOVX	W1,PT.SGN!PT.SYM	;
	SETZ	W3,
	PUSHJ	P,TRYSYM##	;SEE IF DEFINED BY NOW
	  JRST	LKSTER		;CANNOT HAPPEN
	  JRST	LKSTER		;UNDEFINED
	MOVE	W3,2(P1)	;GET VALUE
	HRRZM	W3,STADDR	;STORE 18 BITS
LNKT0:	SKIPE	CS.NUM		;LINK 0?
	JRST	LNKT1		;NO
	MOVX	W1,PT.SGN!PT.SYM ;FLAG BITS FOR A SYMBOL
	MOVE	W2,['FUNCT.']	;THE SYMBOL'S NAME
	SETZ	W3,		;
	PUSHJ	P,TRYSYM	;IT MUST BE THERE OR OVRLAY
				;WILL RECURSE HORRIBLY
	  SKIPA			;NOT NEEDED IS OK
	  JRST	LNKFSN		;OVRLAY NEEDS IT, MUST BE THERE
	MOVX	W1,PT.SGN!PT.SYM	;
	MOVE	W2,['.OVRLA']	;NEED TO KNOW WHERE IT IS
	SETZ	W3,
	PUSHJ	P,TRYSYM##
	  JRST	LNKOHN		;MUST BE THERE
	  JRST	LNKOHN		;BUT WARN USER
	MOVE	T1,2(P1)	;GET ADDRESS
	HRLI	T1,(JSP	1,)	;COMPLETE INST
	MOVEM	T1,EXTTRP	;AND STORE IN PROTOTYPE EXTTAB
	HRRI	W2,'RLU'	;WHERE UNDEFINED REQUESTS GO
	PUSHJ	P,TRYSYM##
	  JRST	LNKOHN
	  JRST	LNKOHN
;HERE TO SET UP FRONT OF OVERLAY FILE.

	MOVE	T1,2(P1)	;GET ADDRESS
	MOVEM	T1,ADDOVU	;SO WE CAN DO FIXUPS
	PUSHJ	P,OC.OPN	;SETUP OVERLAY FILE
	MOVEI	T2,^D128	;START TABLE WITH 256 LINKS
	MOVEM	T2,L.MAX	;STORE NUMBER FOR CHECKS
	PUSHJ	P,DY.GET##	;GET SOME SPACE
	HRLI	T1,P1		;PUT INDEX IN P1 FOR @
	MOVEM	T1,LNKTBL	;FOR DISC BLOCKS
	MOVEI	T1,LN.OVL/<.DBS*2>	;[650]
	MOVEM	T1,OVLBLK	;FIRST FREE BLOCK FOR LINKS
	SKIPN	LW.S1		;SEE IF PAGING AND BASE NOT IN CORE
	JRST	LNKT0A		;OK IT IS
	MOVEI	P2,.JBVER	;HIGHEST ADDRESS WE NEED
	SETZ	P3,		;LOWER
	PUSHJ	P,PG.LSG##	;MAKE SURE WINDOW IS IN CORE
LNKT0A:	MOVE	T1,LC.LB	;BASE OF LOW SEG
	MOVE	T2,SYMSEG	;GET SYMSEG VALUE
	CAIE	T2,$SEGNONE	;USER SAYS NO?
	SKIPE	NOSYMS		;HOWEVER IF USER SAID NO
	JRST	[SETZM	SYMSEG	;MAKE SURE NONE
		JRST LNKT0B]	;CONTINUE
	JUMPN	T2,LNKT0B	;OK IF USER ALREADY SAID /SYMSEG
	SKIPN	.JBDDT(T1)	;IS DDT LOADED
	JRST	LNKT0B		;NO, CONTINUE
	MOVEI	T2,$SEGLOW	;SYMBOLS IN LOW SEG INDEX
	MOVEM	T2,SYMSEG	;SET VALUE SO WE CAN SAVE SYMBOLS
	MOVE	T2,['.LOW. ']	;NAME OF SYMSEG PSECT
	MOVEM	T2,SSGNAM	;STORE FOR LNKXIT

LNKT0B:	MOVE	T2,.JBVER(T1)	;GET VERSION N0.
	SKIPN	VERNUM
	MOVEM	T2,VERNUM	;SET FOR OVERLAY FILE
	MOVX	W1,PT.SGN!PT.SYM	;
	MOVE	W2,['.OVRLO']
	SETO	W3,
	MOVE	T1,OVERLW	;GET FLAGS
	TXNE	T1,$OVLOG	;WANT A LOG FILE?
	PUSHJ	P,SETVAL	;YES
	SETZ	W3,
	TXNE	T1,$OVNOLOG	;SPECIFICALLY NOT?
	PUSHJ	P,SETVAL
	HRRI	W2,'RWA'	;NOW FOR WARNINGS
	TXNE	T1,$OVWARN
	PUSHJ	P,SETVAL
	SETO	W3,
	TXNE	T1,$OVNOWARN
	PUSHJ	P,SETVAL
	JRST	LNKT1B

SETVAL:	PUSHJ	P,TRYSYM##
	  JRST	LNKOHN
	  JRST	LNKOHN
	HRRZ	P2,2(P1)	;GET ADDRESS
	MOVE	P3,P2		;FOR ADDRESS CHECK
	SKIPE	PAG.S1		;ON DSK
	PUSHJ	P,PG.LSG##	;YES
	ADD	P3,LC.LB
	MOVEM	W3,(P3)		;STORE BACK
	MOVE	T1,OVERLW	;RESET SWITCH
	POPJ	P,
LNKT1:	SKIPN	P1,LSTPTR	;FIRST TIME (LINK# 1)?
	JRST	[MOVEI	T2,4		;NEED 4 WORDS
		PUSHJ	P,DY.GET##
		MOVEM	T1,FSTPTR	;STORE START OF TREE
		MOVSI	T2,-4		;-4 ,, 0
		JRST	LNKT1A]
	SKIPN	(P1)		;JUST DONE A RESET (0 WORD)
	JRST	[MOVS	T2,CS.NUM
		MOVEM	T2,(P1)
		JRST	LNKT1B]	;REPLACE WITH LINK#
	MOVEI	T2,4		;ASSUME AT LEAST 2 FORWARD PATHS FROM THIS LINK
	PUSHJ	P,DY.GET##
	HRRM	T1,(P1)		;LINK BACK TO PREVIOUS
	HLRZ	T2,P1		;PTR TO START OF BLOCK
	HRL	T2,(T2)		;GET ITS LINK#
	MOVEM	T2,1(T1)	;STORE BACK POINTER
	MOVSI	T2,-4
	HLR	T2,(P1)		;THIS LINK#
LNKT1A:	MOVEM	T2,(T1)
	MOVS	T2,CS.NUM
	MOVEM	T2,2(T1)	;STORE LINK # WITH ZERO PTR
	HRLI	T1,2(T1)	;POINT TO NULL PTR
	MOVSM	T1,LSTPTR
LNKT1B:	SKIPE	CS.NUM		;ROOT IS SPECIAL
	SMOVE	T1,.OVPSP	;PATCH SPACE IF NOT ROOT
	MOVEI	T1,PATSP.	;PATCH SPACE IF ROOT
	SKIPN	PATSPC
	MOVEM	T1,PATSPC	;SETUP IF NOT ALREADY
	SKIPN	T1,HL.S1	;GET CURRENT HIGHEST LOC
	JRST	[SKIPN	T1,PH.ADD	;NEVER SETUP, SO NO LOW SEG
		MOVEI	T1,.JBDA	;NOT POSSIBLE, BUT !!1
		MOVEM	T1,HL.S1	;JUST STORE TABLES, ETC.
		JRST	.+1]
	MOVEM	T1,PH.CST	;WILL BE START OF HEADER SECTION
	SKIPN	CS.NUM		;IF ROOT
	HRLM	T1,ADDOVU	;STORE FOR UNDEF SYMBOL
	HRL	T1,CS.NUM	;PUT NUMBER IN LH
	MOVEM	T1,EXTCST	;ALSO IN EXTTAB
	MOVE	T1,PH.ADD	;GET THIS LINK'S ORIGIN
	MOVEM	T1,CS.COR	;SAVE AS START OF LINK
	MOVEI	T1,CS.ZZ	;ALLOCATE SPACE FOR HEADER
	ADDB	T1,HL.S1	;AND ACCOUNT FOR IT
	MOVE	T1,[CS.HDR,,PH.HDR]
	BLT	T1,PH.NAM	;COPY COMMON INFO
	MOVE	T1,STADDR	;COPY START ADDRESS
	HRRZM	T1,CS.STA
	SETZM	CS.EXT		;INCASE NO UNDEFS
	SKIPN	P2,USYM		;NO. OF UNDEFS
	JRST	LNKT3		;NONE
	MOVN	T1,P2		;- NUMBER
	HRL	T1,HL.S1	;,,ADDRESS
	MOVSM	T1,CS.EXT	;POINT TO TABLE
	IMULI	P2,ET.ZZ	;4 WORDS EACH
	MOVE	P3,HL.S1	;LOWER BOUND
	ADD	P2,HL.S1	;ACCOUNT FOR THEM
	PUSHJ	P,LNKTCK	;MAKE SURE IT'S IN CORE
;HERE TO SET EXTTAB

LNKT2:	HRLI	P3,EXTHDR	;FORM BLT PTR IN P3
	MOVE	P4,USYM		;GET UNDEFINED SYMBOL COUNT AGAIN
	MOVE	P2,HT.PRM	;GET INDEX INTO HASH TABLE
LNKT2A:	SKIPN	P1,@HT.PTR	;GET POINTER TO SYMBOL
	JRST	LNKT2B		;NO POINTER, NO SYMBOL
	ADD	P1,GS.LB	;ADD IN BASE
	MOVE	T1,0(P1)	;GET FLAGS
	TXNE	T1,PT.SYM	;WE ONLY WANT SYMBOLS
	TXNN	T1,PS.UDF!PS.REQ	;SEE IF UNDEFINED STILL
	JRST	LNKT2B		;NO
	AOS	EXTCNT		;COUNT ONE MORE
	DMOVE	T1,1(P1)	;GET SYMBOL AND VALUE (POINTER)
	MOVEM	T1,EXTNAM	;STORE NAME
	MOVE	T1,P3		;GET BYTE PTR
	ADDI	P3,ET.ZZ	;INCR P3
	BLT	T1,-1(P3)	;MOVE PROTOTYPE BLOCK
	MOVEI	W3,ET.ZZ
	ADD	W3,HL.S1	;NEW TOP
	EXCH	W3,HL.S1	;OLD BASE
	HRLI	R,(1B1)		;RELOCATE RHS
	SETZ	P1,		;NOT SYMBOLIC THOUGH
	SUB	P3,LC.LB	;MAKE RELATIVE IN CASE CORE MOVES
	PUSHJ	P,SY.CHR##	;LINK ALL REQUESTS TO EXTTAB
	ADD	P3,LC.LB	;CAN HAPPEN IF PAGING LC AREA
	SOJLE	P4,LNKT3	;DONE IF NO MORE UNDEFS
LNKT2B:	SOJGE	P2,LNKT2A	;LOOP IF MORE SYMBOLS TO LOOK AT
;HERE TO SET INTTAB

LNKT3:	SETZM	CS.INT		;INCASE 0 ENTRIES
	SKIPN	CS.NUM		;NOT REQUIRED IF LINK 0
	JRST	LNKT4		
	MOVEI	T1,100		;MAKE SURE ENOUGH SPACE FOR 100 ENTRIES
	MOVEM	T1,INTCNT
	MOVE	P3,HL.S1	;LOWER BOUND
	MOVEI	P2,2*100(P3)	;ALLOCATE SPACE FOR WORD PAIRS
	PUSHJ	P,LNKTCK	;MAKE SURE IN CORE
	MOVE	P2,HT.PRM	;GET INDEX INTO HASH TABLE
LNKT3A:	SKIPN	T4,@HT.PTR	;GET POINTER TO SYMBOL
	JRST	LNKT3B		;NO POINTER, NO SYMBOL
	ADD	T4,GS.LB	;ADD IN BASE
	MOVE	T1,0(T4)	;GET FLAGS
	TXNE	T1,PT.SYM	;WE ONLY WANT SYMBOLS
	TXNN	T1,PS.ENT	;SEE IF AN ENTRY
	JRST	LNKT3B		;NOT AN ENTRY
	TXNE	T1,PS.BGS!PS.NOE	;BUT ONLY IF NOT BOUND AND USER DIDN'T SAY NO
	JRST	LNKT3B		;NO
	SOSGE	INTCNT		;ENOUGH SPACE
	JRST	[MOVEI	T1,100		;GET ANOTHER 100 WORDS WORTH
		MOVEM	T1,INTCNT
		ADDB	T1,CS.INT	;ACCOUNT FOR THEM
		LSH	T1,1		;WORD PAIRS
		PUSH	P,P2		;SAVE INDEX INTO HASH TABLE
		MOVE	P3,HL.S1	;BASE AGAIN
		MOVEI	P2,2*100(P3)
		ADD	P2,T1		;ADDRESS BOUNDS
		PUSHJ	P,LNKTCK	;ADDRESS CHECK IT
		ADD	P3,CS.INT	;ACCOUNT FOR PREVIOUS
		ADD	P3,CS.INT	; IN PAIRS
		POP	P,P2
		JRST	LNKT3A]		;KEEP ON TRYING
	DMOVE	T1,1(T4)	;GET NAME + VALUE
	HRL	T2,HL.S1	;BASE OF TABLE
	DMOVEM	T1,(P3)		;STORE IN CORE
	ADDI	P3,2		;INCREMENT
LNKT3B:	SOJGE	P2,LNKT3A	;LOOP IF MORE SYMBOLS TO LOOK AT
	MOVEI	T1,100
	SUB	T1,INTCNT	;SEE HOW MANY ENTRY POINTS
	ADD	T1,CS.INT	;INCASE MORE THAN 100
	MOVN	T2,T1		;-NUMBER
	HRL	T2,HL.S1	;,, ADDRESS
	MOVSM	T2,CS.INT	;POINTER TO TABLE
	LSH	T1,1		;2 WORDS EACH
	ADDM	T1,HL.S1	;ACCOUNT FOR THEM
;	JRST	LNKT4
LNKT4:	DMOVE	T1,OV.S1	;SAVE CURRENT
	HRR	T1,PH.ADD	;HOWEVER LOW REALLY STARTS AFTER SPACE
	DMOVEM	T1,PV.S1	;AS PREVIOUS SO MAP CAN COMPUTE LENGTHS
	HRRZ	T1,ARSIZE	;[635] RESERVE SPACE AFTER INTTAB FOR
	ADDB	T1,HL.S1	;[635]   ARL'S, PICK UP NEW HL.S1
	MOVE	T2,HL.S2	;[635] NEED HI SEG HIGHEST ALSO
	HRL	T1,T1		;MAKE THE HIGEST CODE THE
	HRL	T2,T2		;  HIGHEST SEEN TO HERE
	DMOVEM	T1,OV.S1	;SAVE FOR MAP AND EXIT
	MOVE	T1,HL.S1	;HIGHEST USED
	MOVE	T2,T1
	SUB	T2,PH.ADD	;REMOVE BASE
	HRLM	T2,CS.COR	;SAVE LENGTH REQUIRED
	HRRZM	T2,PH.LEN
	MOVE	P1,CS.NUM	;GET THIS LINK #
	ROT	P1,-1		;CUT IN HALF AND MAKE REM SIGN BIT
	HRLS	T2,OVLBLK	;THIS TRICK PUTS RH(OVLBLK) INTO LH(OVLBLK)
				;AND BOTH HALVES IN T2
	JUMPL	P1,[HRRM T2,@LNKTBL
		JRST	.+2]
	HRLZM	T2,@LNKTBL	;DISC BLOCK # OF PREAMBLE
	AOS	T1,OVLBLK	;ACCOUNT FOR PREAMBLE (OUTPUT IT LATER)
	HRRZM	T1,PH.OVL	;USE THIS BLOCK FOR CODE
LNKT4A:	MOVE	P3,PH.CST	;ADDRESS OF CONTROL SECTION
	MOVEI	P2,CS.ZZ-1(P3)	;UPPER BOUND
	PUSHJ	P,LNKTCK	;MAKE SURE ITS IN CORE
	HRLI	P3,CS.HDR	;FORM BLT PTR
	MOVEI	P2,CS.ZZ-1(P3)	;RESET UPPER BOUND
	BLT	P3,(P2)		;PUT HEADER IN CORE IMAGE
	MOVE	T1,HL.S1	;TOP OF CORE
	ADD	T1,SPACE	;PLUS BUFFER SPACE
	MOVEM	T1,PH.NFL	;FOR NEXT LINK
	MOVN	T2,PH.LEN	;TOTAL NO. OF WORDS
	HRLM	T2,PH.OVL	;IN IOWD FORM
	PUSHJ	P,LODFIX##	;DO ALL CORE FIXCUPS ETC.
	SKIPN	PAG.S1		;PAGING?
	JRST	LNKT4B		;NO
	HRLZ	T1,LW.S1
	HRR	T1,UW.S1
	PUSHJ	P,LC.OUT##	;MAKE SURE FILE IS CORRECT
	SETZM	LW.S1		;NOW START AT FRONT
	MOVE	T1,LC.UB	;GET TOP
	MOVEM	T1,LC.AB	;USE ALL SPAE WE CAN
	SUB	T1,LC.LB
	MOVEM	T1,UW.S1	;MAKE IT UPPER BOUND
	PUSHJ	P,LC.IN##	;READ BACK
;HERE TO SETUP .JBOVL AND UPDATE OVERLAY FILE

LNKT4B:	HRRZ	T1,OVLBLK	;[666] BLOCK TO START STASHING CODE
	USETO	OC,(T1)		;SET ON IT
	SKIPE	CS.NUM		;IF LINK# 0
	JRST	LNKT4C		;NO
	MOVE	T1,LC.LB	;BASE
	MOVE	T2,PH.CST	;START OF CONTROL BLOCK
	MOVEM	T2,.JBOVL(T1)	;STORE INITIAL PTR


;HERE TO DUMP LC AREA IF NOT PAGING OR ON EACH BUFFER IF PAGING.

LNKT4C:	MOVE	T1,LC.AB	;[666] USUALLY WILL WANT TO DUMP
	SUB	T1,LC.LB	;[666]   ENTIRE LC AREA, SO CALCULATE
	ADDI	T1,1		;[666]   SIZE TO DUMP
	MOVE	T3,PH.LEN	;[666] NUMBER OF WORDS TO DUMP TOTAL
	SKIPN	PAG.S1		;[666] HAS LC AREA OVERFLOWED TO DISK?
	SKIPA	T1,T3		;[666] NO, DUMP ALL WORDS AT ONCE
	CAML	T3,UW.S1	;[666] YES, IF NOT LAST BUF DUMP ALL LC
	JRST	LNKT4G		;[666] T1 HAS CORRECT # WORDS TO DUMP
	SUB	T1,UW.S1	;[666] LAST BUF WHEN PAGING, ONLY DUMP
	SUBI	T1,1		;[666]   LAST PARTIAL BUFFER
	ADD	T1,PH.LEN	;[666]   GET LENGTH EXACT
LNKT4G:	HRLZ	T1,T1		;[666] GENERATE IOWD TO DUMP LC AREA
	SETCA	T1,		;[666] ..
	ADD	T1,LC.LB	;[666] ..
	SETZ	T2,		;TERMINATOR
	OUT	OC,T1		;OUTPUT WHOLE AREA
	  JRST	LNKT4D		;OK
	PUSHJ	P,ER.OOV##	;OUTPUT ERROR
LNKT4D:	SKIPE	PAG.S1		;[666] PAGING?
	CAMG	T3,UW.S1	;[666] YES, FINISHED LAST BUFFER?
	JRST	LNKT4F		;[666] DON'T NEED TO DUMP ANOTHER BUF
	MOVE	T1,LC.AB	;GET TOP OF WHATS IN USE
	SUB	T1,LC.LB	;GET DIFF	
	MOVEI	T1,1(T1)	;SO WE CAN ADD NO.
	ADDM	T1,LW.S1	;ADJUST WINDOWS
	ADDB	T1,UW.S1
	IORI	T3,.IPM		;[666] MAKE SUB COME OUT EVEN .IPS'S
	SUB	T3,T1		;[666] DO WE STILL NEED IT ALL?
	JUMPGE	T3,LNKT4E	;[666] YES, USE ALL OF SPACE AVAILABLE
	ADDM	T3,UW.S1	;[666]
	ADDB	T3,LC.AB	;[666] REDUCE WINDOW NOW
	HRLI	T3,1(T3)	;[666] FORM BLT PTR
	HRRI	T3,2(T3)	;[666]
	SETZM	-1(T3)		;[666] CLEAR FROM (LC.AB)+1
	BLT	T3,@LC.UB	;[666] THROUGH ALL OF FREE SPACE
LNKT4E:	HRLZ	T1,LW.S1
	HRR	T1,UW.S1	;SETUP NEW WINDOW
	PUSHJ	P,LC.IN##	;INPUT NEW AREA
	JRST	LNKT4C		;[666] AND OUTPUT IT

LNKT4F:	MOVE	T1,PH.LEN	;GET LENGTH WE NEED
	ADDI	T1,.DBM		;[650] FILL OUT BLOCK
	LSH	T1,-.DBS2W	;[650] INTO BLOCKS
	ADDM	T1,OVLBLK	;ACCOUNT FOR THEM
;	JRST	LNKT5
;HERE FOR LOCAL SYMBOLS

LNKT5:	MOVN	T1,LSYM		;[666] NEGATED # SYMBOLS FOR IOWD
	HRL	T1,OVLBLK	;GET FREE BLOCK
	MOVS	T1,T1
	MOVEM	T1,PH.SYM	;HOLD LOCAL IN THIS AREA
	MOVE	T1,LSYM		;CALCULATE # OF BLOCKS LS WILL USE
	ADDI	T1,.DBM		;[650] ROUND WORDS UP TO NEXT BLOCK
	LSH	T1,-.DBS2W	;[650] WORDS ---> BLOCKS
	ADDM	T1,OVLBLK	;UPDATE OVLBLK TO END OF SYMBOLS
	SKIPN	T1,PAG.LS	;PAGING?
	JRST	LNKT5B		;NO
	JUMPG	T1,LNKT5A	;IS UPPER WINDOW SET?
	MOVE	T1,LSYM		;NO
	IORI	T1,.DBM		;[666]
LNKT5A:	HRL	T1,LW.LS	;IOWD
	PUSHJ	P,LS.OUT##	;WRITE OUT SYMBOLS
	MOVEI	P1,LS.IX	;EXPAND LS AREA AS MUCH AS WE CAN
	MOVE	P2,LSYM		;HOW MUCH WE NEED
	ADD	P2,LS.LB	;MINUS HOW MUCH WE ALREADY HAVE
	SUB	P2,LS.AB	;GIVES HOW MUCH WE NEED
	JUMPLE	P2,LNKT5E	;SKIP LNKCOR CALL IF ALREADY ENUF
	PUSHJ	P,FR.CNT##	;SEE HOW MUCH IS FREE
	CAMLE	P2,T1		;AS MUCH AS WE NEED?
	MOVE	P2,T1		;NO, USE WHAT WE CAN
	PUSHJ	P,LNKCOR##	;NEED MORE - TRY FOR IT
	  PUSHJ	P,NO.COR##	;TOO BAD
LNKT5E:	SETZM	LW.LS		;START BACK AT FRONT OF FILE
	MOVE	T1,LS.AB	;CALCULATE THE
	SUB	T1,LS.LB	;LENGTH
IFL .IPS-2*.DBS,<
	CAIGE	T1,2*.DBS	;[650] MUST HAVE THIS MUCH FOR FIXUPS
	  PUSHJ	P,NO.COR##	;TOO BAD
> ;END IFL .IPS-2*.DBS
	MOVEM	T1,UW.LS	;OF WINDOW
	PUSHJ	P,LS.IN##	;INPUT IT
;HERE IF NOT PAGING OR ON EACH BUFFER OF SYMBOLS IF PAGING

LNKT5B:	MOVE	T1,LS.AB	;SAME AS FOR LC
	SUB	T1,LS.LB
	ADDI	T1,1		;[666] WILL USUALLY WANT TO DUMP ALL LS
	MOVE	T3,LSYM		;[666] GET # WORDS TO DUMP TOTAL
	SKIPE	PAG.LS		;[666] IS LS AREA ON DISK?
	JRST	LNKT5F		;[666] YES, T1 MAY BE OK
	MOVE	T1,T3		;[666] DO ONE DUMP, EXACT RIGHT # WORDS
	JRST	LNKT5H		;[666] GO DUMP THE LS AREA

LNKT5F:	CAMG	T3,UW.LS	;[666] IS THIS THE LAST BUF OF SYMBOLS?
	JRST	LNKT5G		;[666] YES, SPECIAL STUFF
	SUBI	T1,.DBS		;[666] NO, DON'T DUMP LAST WORDS TILL
	JRST	LNKT5H		;[666]   NEXT TIME SO FIXUPS CAN BE DONE

LNKT5G:	SUB	T1,UW.LS	;[666] LAST BUF IF PAGING, REDUCE COUNT
	SUBI	T1,1		;[666] DON'T BE OFF BY ONE
	ADD	T1,LSYM		;[666] WE DON'T WANT TO DUMP TOO MUCH

LNKT5H:	HRLZ	T1,T1		;[666] GENERATE IOWD TO DUMP LS AREA
	SETCA	T1,		;[666] ..
	ADD	T1,LS.LB	;[666] ..
	SETZ	T2,
	OUT	OC,T1
	  JRST	LNKT5C
	PUSHJ	P,ER.OOV##	;OUTPUT ERROR
LNKT5C:	SKIPE	PAG.LS		;PAGING?
	CAMG	T3,UW.LS	;YES, SEE IF MORE TO DO
	JRST	LNKT6		;NO, ALL DONE
	MOVE	T1,LS.AB	;[666] WINDOW MOVES UP BY SIZE OF
	SUB	T1,LS.LB	;[666]   LS AREA MINUS .DBM
	ANDCMI	T1,.DBM		;[666] FIGURE WINDOW OFFSET INTO T1
	ADDM	T1,LW.LS	;[666] MOVE THE WINDOW UP
	ADDB	T1,UW.LS	;[666] ..
	IORI	T3,.IPM		;[666] MAKE SUB BELOW COME OUT .IPS'S
	SUB	T3,T1		;[666] ARE WE DUMPING FINAL PART WINDOW?
	JUMPGE	T3,LNKT5D	;[666] NO, PROCEED AS USUAL
	SUBI	T3,.DBS		;[666] YES, FIX ANDCMI .DBM ABOVE
	ADDM	T3,UW.LS	;[666] GET RID OF EXTRA LS SPACE
	ADDB	T3,LS.AB	;[666] ADJUST POINTERS, THEN BLT IT ZERO
	HRLI	T3,1(T3)	;
	HRRI	T3,2(T3)	;FORM BLT PTR
	SETZM	-1(T3)		;
	BLT	T3,@LS.UB	;TO CLEAR ALL EXCESS CORE
LNKT5D:	HRLZ	T1,LW.LS	;[666] LOWER WINDOW ADDR TO FILL
	HRR	T1,UW.LS	;[666] UPPER WINDOW ADDR
	PUSHJ	P,LS.IN##	;GET WINDOW
	JRST	LNKT5B		;AND OUTPUT IT
;HERE FOR RELOCATION TABLES
LNKT6:	SETZM	PH.REL		;[671] ASSUME NO RELOCATION
	SETZM	PH.ORL		;[671] AND NO "OTHER" RELOCATION
	SKIPN	RT.LB		;SETUP YET?
	JRST	LNKT7		;NO
	HRRZ	P3,HL.S1	;GET HIGHEST LOC USED
	PUSHJ	P,RT.P3##	;SETUP RT.PT TO IT
	MOVE	T1,RT.LB
	HRRZ	T2,RT.PT
	SUBI	T1,1(T2)	;- LENGTH ACTUALLY USED
	HRL	T1,OVLBLK
	MOVSM	T1,PH.REL	;-LENGTH ,, BLOCK NUMBER
	MOVE	T1,RT.AB
	SUB	T1,RT.LB	;LENGTH
	AOS	T2,T1		;ACTUALLY ONE LARGER
	LSH	T2,-.DBS2W	;[650] NO. OF BLOCKS
	ADDM	T2,OVLBLK
	MOVN	T1,T1
	HRLZ	T1,T1
	HRR	T1,RT.LB
	HRRI	T1,-1(T1)	;IOWD AT LAST
	SETZ	T2,
	OUT	OC,T1
	  CAIA
	PUSHJ	P,ER.OOV##

	SKIPN	RBGPTR		;ANY OTHER RELOCATION
	JRST	LNKT7		;NO
	MOVE	T1,RT.LB	;YES, GET AREA TO HOLD IT IN
	MOVEM	T1,RT.PT	;POINT TO FIRST FREE
	HRL	T1,T1
	ADDI	T1,1		;BLT PTR
	SETZM	-1(T1)		;CLEAR FIRST WORD
	BLT	T1,@RT.AB	;AND  REST
	MOVE	T1,RT.LB
	IORI	T1,.IPM
	MOVEM	T1,RT.AB	;ALLOCATE ONE BLOCK
	SUB	T1,RT.LB	;FREE SPACE
	MOVEM	T1,RT.FR	;IN THIS BLOCK
;USES ACCS AS FOLLOWS
;P1 = TO HOLD RBGPTR TO WHATS LEFT
;P2 = CURRENT LINK #
;P3 = TO HOLD LIST FOR THIS LINK
LNKT6A:	MOVE	P1,RBGPTR	;GET START OF LIST
	HRRZ	P3,P1		;SET INITIAL PTR
	SETZM	RBGPTR		;WILL PUT BACK THOSE NOT REQUIRED
	MOVE	T1,P1		;GET FIRST ITEM IN LIST
	ADD	T1,FX.LB	;FIX IN CORE
	HLRZ	P2,(T1)		;GET LINK#
	HRRZ	P1,(T1)		;GET NEXT ITEM PTR
	HLLZS	(T1)		;CLEAR THIS PTR
LNKT6B:	SKIPN	T1,P1		;GET NEXT ITEM
	JRST	LNKT6L		;LIST EMPTY
	ADD	T1,FX.LB	;FIX IN CORE
	HRRZ	P1,(T1)		;GET PTR TO NEXT
	HLLZS	(T1)		;CLEAR PTR
	HLRZ	T2,(T1)		;GET LINK#
	CAMN	T2,P2		;THIS THE ONE WE WANT?
	JRST	LNKT6C		;YES
	MOVE	T2,T1
	SUB	T2,FX.LB	;REMOVE BASE
	EXCH	T2,RBGPTR
	HRRM	T2,(T1)		;PUT BACK IN LIST
	JUMPN	P1,LNKT6B	;IF NOT END
	JRST	LNKT6L		;END OF THIS CHAIN

LNKT6C:	HRRZ	T2,1(T1)	;GET ADDRESS WE WANT TO ADD
	MOVE	T3,P3		;START OF CHAIN
LNKT6M:	ADD	T3,FX.LB	;MAKE ABS
	HRRZ	T4,1(T3)	;ADDRESS IN CHAIN
	CAML	T2,T4		;FOUND OUR PLACE YET?
	JRST	LNKT6G		;NO
	HLRZ	T3,T3		;PUT LAST ADDRESS BACK
	JUMPE	T3,[HRRM P3,0(T1)	;PUT IN FRONT OF LIST
		SUB	T1,FX.LB
		MOVE	P3,T1		;RESET BASE PTR
		JRST	LNKT6B]		;GET NEXT
	MOVE	T4,0(T3)	;GET FORWARD PTR
	HRRM	T4,0(T1)	;PUT INTO NEW BLOCK
LNKT6D:	SUB	T1,FX.LB	;MAKE REL
	HRRM	T1,0(T3)	;AND MAKE LAST POINT TO IT
	JRST	LNKT6B		;GET NEXT

LNKT6G:	HRL	T3,T3		;SAVE LAST PTR
	HRR	T3,0(T3)	;GET NEXT
	TRNE	T3,-1		;0 IS END OF LIST
	JRST	LNKT6M		;NO, MORE TO COME
	MOVS	T3,T3		;SWAP BACK
	JRST	LNKT6D		;PUT LAST IN LIST
LNKT6L:	MOVE	T1,RT.PT	;GET PTR
	SUB	T1,RT.LB	;MAKE RELATIVE
	PUSH	P,T1		;SAVE PTR SO WE CAN ADD COUNT LATER
	AOS	RT.PT
	SOS	RT.FR		;ACCOUNT FOR WORD
	MOVE	T1,BRNADD	;GET START OF ADDRESS TABLE
	HRLI	T1,-^D128	;MAX SIZE?
	MOVS	T2,(T1)		;GET LINK#
	CAIN	P2,(T2)		;ONE WE WANT?
	JRST	.+3		;YES
	AOBJN	T1,.-3		;NO
	HALT
	MOVS	P1,T2		;LINK# ,, ADDRESS
	SETZ	T1,		;NO PREVIOUS
	PUSHJ	P,RT.DPB	;STORE IT
LNKT6K:	SKIPN	T1,P3		;COPY OF PTR
	JRST	LNKT6R		;END OF LIST
	ADD	T1,FX.LB
	HRRZ	P3,0(T1)	;GET NEXT
	JUMPE	P1,[MOVE P1,1(T1)	;NO PREVIOUS
		JRST	LNKT6K]		;GET NEXT
	HRRZ	T2,1(T1)	;ADDRESS OF THIS RELOC WORD
	SUBI	T2,(P1)		;- PREVIOUS
	CAIL	T2,^D9		;WITHIN RANGE?
	JRST	[PUSH	P,1(T1)		;GET THIS VALUE
		PUSHJ	P,RT.DPB	;DUMP CURRENT
		POP	P,P1		;RESET THIS ONE
		JRST	LNKT6K]		;GET NEXT
	HLLZ	T3,1(T1)	;GET RELOC BITS
	IMULI	T2,-2		;2 BITS PER WORD
	LSH	T3,(T2)		;SHIFT INTO POSSITION
	IOR	P1,T3
	JUMPN	P3,LNKT6K	;TRY NEXT WORD
;HERE TO CHECK TO SEE IF MORE TO DO AND OUTPUT RT AREA IF NOT.

LNKT6R:	SKIPE	P1		;PREVIOUS TO STORE STILL?
	PUSHJ	P,RT.DPB	;YES
	POP	P,P1		;GET PTR TO START OF TABLE
	ADD	P1,RT.LB	;MAKE ABS
	MOVE	T1,RT.PT	;PTR TO END
	SUBI	T1,1(P1)	;LENGTH
	MOVEM	T1,(P1)		;PUT IT IN
	SKIPE	P1,RBGPTR	;MORE TO DO?
	JRST	LNKT6A		;YES
LNKT6Z:	MOVE	T1,RT.LB
	HRRZ	T2,RT.PT
	SUBI	T1,1(T2)	;- LENGTH ACTUALLY USED
	HRL	T1,OVLBLK
	MOVSM	T1,PH.ORL	;-LENGTH ,, BLOCK NUMBER
	MOVE	T1,RT.AB
	SUB	T1,RT.LB	;LENGTH
	AOS	T2,T1		;ACTUALLY ONE LARGER
	LSH	T2,-.DBS2W	;[650] NO. OF BLOCKS
	ADDM	T2,OVLBLK
	MOVN	T1,T1
	HRLZ	T1,T1
	HRR	T1,RT.LB
	HRRI	T1,-1(T1)	;IOWD AT LAST
	SETZ	T2,
	OUT	OC,T1
	  JRST	LNKT7
	PUSHJ	P,ER.OOV##
RT.DPB:	SOSL	RT.FR		;ANY ROOM
	JRST	RTDPB1		;YES
	SPUSH	<T1,P1,P2>
	MOVEI	P1,RT.IX	;NEED MORE ROOM
	MOVEI	P2,.IPS
	PUSHJ	P,LNKCOR##
	  PUSHJ	P,NO.COR##
	SPOP	<P2,P1,T1>
RTDPB1:	MOVEM	P1,@RT.PT
	AOS	RT.PT
	MOVE	P1,T1		;STORE NEW AS PREVIOUS
	POPJ	P,
;HERE FOR GLOBAL SYMBOLS
LNKT7:	MOVE	T1,HT.PTR	;ABS ADDRESS OF HASH TABLE
	SUB	T1,GS.LB	;RELATIVE
	HRL	T1,HT.PRM	;NEED TO SAVE THE HASH NUMBER
	MOVEM	T1,@GS.LB	;IN A SAFE PLACE
	MOVE	T1,OVLBLK
	HRRZM	T1,PH.GLB	;POINT TO BLOCK
	MOVE	T1,GS.AB	;SAME AS FOR LC
	SUB	T1,GS.LB
	MOVEI	T2,.IPS(T1)
	LSH	T2,-.DBS2W	;[650]
	ADDM	T2,OVLBLK
	MOVN	T1,T1
	HRLZ	T1,T1
	HRR	T1,GS.LB
	HRRI	T1,-1(T1)
	HLLM	T1,PH.GLB
	SETZ	T2,
	OUT	OC,T1
	  JRST	LNKT8
	PUSHJ	P,ER.OOV##	;OUTPUT ERROR

;HERE TO OUTPUT PREAMBLE - MUST BE LAST
LNKT8:	HLRZ	T1,OVLBLK	;GET BLOCK RESERVED FOR PREAMBLE
	USETO	OC,(T1)		;SET ON IT
	DMOVE	T1,PHIOWD	;SINCE IOWD CAN NOT BE IN HIGH SEG YET
	OUT	OC,T1
	  JRST	LNKT9
	PUSHJ	P,ER.OOV##	;OUTPUT ERROR

LNKT9:	MOVE	T1,CS.NUM	;GET THIS LINK
	MOVEM	T1,PH.BPT	;AS BACK POINTER FOR NEXT LINK
;HERE TO ZERO VARIOUS AREAS

;HERE TO ZERO LOW CODE AREA
LNKZLC:	MOVE	T1,LC.LB	;BASE
	HRL	T1,T1
	ADDI	T1,1		;BLT PTR
	SETZM	-1(T1)		;CLEAR FIRST WORD
	BLT	T1,@LC.AB	;AND  REST
	MOVE	T1,LC.LB
	IORI	T1,.IPM		;PRE-ALLOCATE ONE BLOCK ONLY
	MOVEM	T1,LC.AB
	SKIPN	PAG.S1		;PAGING?
	JRST	LNKZRT		;NO
	MOVEI	T1,LC		;CHAN# IF ON DSK
	MOVEM	T1,IO.CHN
	PUSHJ	P,DVDEL.##	;DELETE FILE
	  JFCL			;INCASE OF ERRORS
	PUSHJ	P,DVZAP.##	;GET RID OF DATA BLOCK
	SETZM	LW.S1		;ZERO ALL PAGING INFO
	SETZM	UW.S1
	SETZM	HB.S1

;HERE TO ZERO THE RELOCATION TABLE
LNKZRT:	SKIPN	T1,RT.LB	;DO WE HAVE SPACE ALLOCATED?
	JRST	LNKZLS		;NO
	HRL	T1,T1
	ADDI	T1,1		;BLT PTR
	SETZM	-1(T1)		;CLEAR FIRST WORD
	BLT	T1,@RT.AB	;AND  REST
	MOVE	T1,RT.LB
	IORI	T1,.IPM		;PRE-ALLOCATE ONE BLOCK ONLY
	MOVEM	T1,RT.AB
	SKIPN	PAG.RT		;PAGING
	JRST	LNKZLS		;NO
	HALT
;HERE TO ZERO LOCAL SYMBOL AREA
LNKZLS:	MOVE	T1,LS.LB	;BASE
	HRL	T1,T1
	ADDI	T1,1		;BLT PTR
	SETZM	-1(T1)		;CLEAR FIRST WORD
	BLT	T1,@LS.AB	;AND  REST
	MOVE	T1,LS.LB
	ADDI	T1,1		;PRE-ALLOCATE FIRST WORD
	MOVEM	T1,LS.PT	;SO USER CAN NOT GET IT
	IORI	T1,.IPM		;PRE-ALLOCATE ONE BLOCK ONLY
	MOVEM	T1,LS.AB
	MOVEI	T1,.IPM		;NO. OF WORDS FREE
	MOVEM	T1,LS.FR	;IN THIS BLOCK
	SKIPN	PAG.LS		;PAGING?
	JRST	LNKZFX		;NO
	MOVEI	T1,SC		;CHAN# IF ON DSK
	MOVEM	T1,IO.CHN
	PUSHJ	P,DVDEL.##	;DELETE FILE
	  JFCL			;INCASE OF ERRORS
	PUSHJ	P,DVZAP.##	;GET RID OF DATA BLOCK
	SETZM	LW.LS		;ZERO ALL PAGING INFO
	SETZM	UW.LS
	SETZM	HB.LS

;HERE TO ZERO AND REMOVE THE FIXUP AREA
LNKZFX:	MOVEI	T1,FX.IX	;AREA#
	SKIPE	TAB.LB(T1)	;SET UP?
	PUSHJ	P,XX.ZAP##	;YES, DELETE WHOLE AREA
	MOVE	T1,[FX.S1,,FX.S2]
	SETZM	FX.S1
	BLT	T1,FXC.SS	;CLEAR ALL POINTERS
;HERE TO ADD GS TO BG AND ZERO GS
LNKZBG:	SKIPE	BG.LB		;BOUND GLOBAL TABLE SET UP
	JRST	LNKZGS		;YES
	SETOM	BG.SCH		;WILL BE ALLOWED TO SEARCH THEM
	MOVEI	T2,^D128	;SETUP BRANCH TABLES
	PUSHJ	P,DY.GET##
	HRLI	T1,P1		;PUT INDEX IN P1 FOR @
	MOVEM	T1,BRNTBL	;LINK # ,, REL ADDRESS
	MOVEI	T2,^D128
	PUSHJ	P,DY.GET##
	HRLI	T1,P1		;PUT INDEX IN P1 FOR @
	MOVEM	T1,BRNADD	;LINK# ,, LOWEST ADDRESS
	MOVEI	T2,^D128
	PUSHJ	P,DY.GET##
	HRLI	T1,P1		;PUT INDEX IN P1 FOR @
	MOVEM	T1,BRNDSK	;LENGTH ,, DSK BLOCK #
	MOVE	T2,GS.PT	;LAST LOC USED
	SUB	T2,GS.LB	;- FIRST = LENGTH
	MOVSM	T2,(T1)		;STORE LENGTH
	MOVSI	T1,-^D127	;AOBJN WORD FOR NUMBER LEFT
	MOVEM	T1,BRNLEN
	MOVE	T1,GS.AB	;TOP IN ACTUAL USE
	CAML	T1,GS.UB	;ANY FREE?
	JRST	[MOVEI	P1,GS.IX	;EASIEST WAY IS TO EXPAND
		MOVEI	P2,.IPS		;BY ONE BLOCK
		PUSHJ	P,LNKCOR##
		  PUSHJ	P,NO.COR##
		MOVNI	T1,.IPS		;NOW TAKE BACK EXTRA
		ADDM	T1,GS.FR	;NO MORE FREE THAN BEFORE
		ADDB	T1,GS.AB
		JRST	.+1]		;AND CONTINUE
	MOVEM	T1,BG.AB	;MOVE AREA
	MOVEM	T1,BG.UB	; BY MOVING THE POINTERS
	MOVE	T2,GS.LB
	MOVEM	T2,BG.LB
	MOVE	T2,GS.PT
	MOVEM	T2,BG.PT	;POINT TO NEXT FREE
	MOVE	T2,GS.FR
	MOVEM	T2,BG.FR	;AND FREE SPACE IN IT
	ADDI	T1,1		;NEXT FREE WILL BE START OF NEW GS
	MOVEM	T1,GS.LB
	JRST	LNKZHT		;NOW SET UP HASH TABLES ETC.
LNKZGS:	MOVE	T1,BG.UB	;SEE IF ENOUGH CORE
	SUB	T1,BG.PT
	ADD	T1,GS.UB	;IN GS +BG
	SUB	T1,GS.PT
	CAIL	T1,.IPS		;SO WE CAN MOVE AND ALLOCATE 1 BLOCK
	JRST	LNKZG1		;OK, NO PROBLEM
	MOVEI	P1,BG.IX
	MOVEI	P2,.IPS
	PUSHJ	P,LNKCOR##	;EXPAND
	  PUSHJ	P,NO.COR##	;TOO BAD
	MOVNI	T1,.IPS
	ADDM	T1,BG.AB	;DON'T REALLY WANT IT
LNKZG1:	MOVE	P1,BRNLEN	;GET NO. OF LINKS IN BRANCH
	AOBJP	P1,[HALT]
	MOVEM	P1,BRNLEN	;ALL OK
	HRRZ	P1,P1		;INDEX ONLY
	CAMLE	P1,BRNMAX	;DEEPEST YET?
	MOVEM	P1,BRNMAX	;YES, STORE FOR LATER
	MOVE	T2,BG.PT	;NEXT FREE LOC
	SUB	T2,BG.LB	;REMOVE BASE
	HRL	T2,CS.NUM	;LINK # IN LEFT 
	MOVEM	T2,@BRNTBL
	HLLZ	T3,T2		;LINK#
	HRR	T3,PH.ADD	;STARTING ADDRESS
	MOVEM	T3,@BRNADD	;IN CASE RELOCATABLE
	MOVE	T3,GS.PT	;NOW FOR LENGTH OF NEW GLOBAL
	SUB	T3,GS.LB
	ADDM	T3,BG.PT	;ACCOUNT FOR IT
	MOVSM	T3,@BRNDSK
	ADD	T2,BG.LB	;PUT BACK BASE
	HRL	T2,GS.LB	;FORM BLT PTR
	BLT	T2,@BG.PT	;MOVE ALL WORDS
	HRRZ	T1,BG.PT	;NOW CLEAN UP
	SETZM	(T1)
	HRL	T1,T1
	ADDI	T1,1
	BLT	T1,@GS.AB	;ALL OF GS AREA
	MOVE	T1,BG.PT
	MOVE	T2,T1
	IORI	T1,.IPM		;THIS IS TOP
	MOVEM	T1,BG.AB
	MOVEM	T1,BG.UB	;NO WASTED SPACE
	SUB	T2,T1		;SEE WHATS LEFT
	MOVMM	T2,BG.FR
	ADDI	T1,1		;START OF GS
	MOVEM	T1,GS.LB
;HERE TO SET UP HASH TABLE
LNKZHT:	IORI	T1,.IPM		;MUST ALLOCATE 1 BLOCK
	MOVEM	T1,GS.AB	;TO KEEP LNKCOR HAPPY
	ANDCMI	T1,.IPM-1	;PRE-ALLOCATE FIRST WORD
	HRLI	T1,P2		;USES P2 AS INDEX
	MOVEM	T1,HT.PTR	;START OF NEW HASH TABLE
	MOVEI	T2,I.PRM	;INITIAL HASH TABLE
	MOVEM	T2,HT.PRM	; PRIME NUMBER
	HRRZI	T1,I.PRM(T1)	;SEE IF ENOUGH SPACE FOR WHAT WE NEED
	CAMG	T1,GS.UB	;WELL?
	JRST	LNKZB1
	SUB	T1,GS.UB	;EXTRA WE NEED
	MOVEI	P1,GS.IX
	MOVE	P2,T1
	PUSHJ	P,LNKCOR##
	  PUSHJ	P,NO.COR##	;FAILED
LNKZB1:	MOVE	T1,GS.LB	;GET BASE
	SETOM	(T1)		;MAKE NON-ZERO SO WE DON'T LOAD JOBDAT AGAIN
	ADDI	T1,1+<I.PRM+.L-1>/.L*.L	;SPACE RESERVED FOR HASH TABLE
	MOVEM	T1,GS.PT	;MAKE SURE CORRECT
	MOVE	T2,T1
	IORI	T2,.IPM		;NOW RESET TO WHAT IT SHOULD BE
	MOVEM	T2,GS.AB	;INCASE MORE THAN ONE BLOCK LONG
	SUB	T1,T2		;- WHATS FREE
	MOVNM	T1,GS.FR	;IN GS BLOCK
	MOVEI	T1,I.PRM*.HS%/^D100	;INITIAL AMOUNT FREE
	MOVEM	T1,HSPACE	;BEFORE WE REHASH
	MOVSI	T1,(POINT 18,0)
	MOVEM	T1,PRMPTR	;START HASH POINTER AT REL 0
	SETZM	GS.LNK		;NO FREE SPACE IN LINKED LISTS
	SETZM	GS.FSP
;HERE TO INITIALIZE THE REST OF LOW CORE
	SKIPN	CS.LNM		;DOES THIS LINK HAVE A NAME?
	JRST	LNKZNN		;NO
	.ERR.	(MS,.EC!.EB,V%L,L%I6,S%I,ELN,<End of link number >)	;
	.ETC.	(DEC,.EC!.EP,,,,CS.NUM)	;
	.ETC.	(STR,.EC,,,,,<, name >)	;
	.ETC.	(SBX,.EP,,,,CS.LNM)	;
	JRST	LNKZA		;JOIN COMMON CODE
LNKZNN:	.ERR.	(MS,.EC!.EB,V%L,L%I6,S%I,ELN)	;
	.ETC.	(DEC,.EP,,,,CS.NUM)	;
LNKZA:	MOVEI	R,1		;POINT TO RELOC TABLE 1
	MOVE	R,@RC.TB
	MOVE	T1,PH.NFL	;NEXT FREE LOC
	MOVEM	T1,PH.ADD	;SET ORIGIN OF NEXT LINK
	MOVEM	T1,RC.CV(R)	;SET AS NEW CURRENT VALUE
	SETZM	RC.HL(R)	;CLEAR
	PUSHJ	P,Z.INEX##	;CLEAR INCLUDE/EXCLUDE STORAGE
	MOVSS	INCPTR		;BOTH HALVES
	MOVSS	EXCPTR
	PUSHJ	P,Z.INEX##
	MOVE	T1,[OV1.Z0,,OV1.Z0+1]
	SETZM	OV1.Z0		;CLEAR PASS1 DATA
	BLT	T1,OV1.ZE
	MOVE	T1,[CS.NUM,,CS.NUM+1]
	SETZM	CS.NUM
	BLT	T1,CS.HDR+CS.ZZ-1
	SKIPN	T1,LINKTB	;[660] .LINK TABLE SET UP?
	JRST	LNKZA0		;[660] NO
	SETZM	LINKTB		;[660] YES, DELETE IT
	HRRZ	T1,T1		;[660] ADDRESS TO GIVE BACK ONLY
	MOVEI	T2,LN.12	;[660] LENGTH
	PUSHJ	P,DY.RET##	;[660] RETURN THE BLOCK
LNKZA0:	SETZM	%OWN		;[660] CANNOT LINK ALGOL OWN YET
	SETZM	HL.S1
	SETZM	MNSEEN		;NO MAIN PROGRAMS SEEN YET
	SETZM	MNTYPE		;SO DON'T KNOW LIBRARIES, CPU ETC.
	SETZM	NOLIBS
	SETZM	NAMPTR
	SETZM	PRGNAM
	SETZM	LSTSYM

;CONTINUED ON NEXT PAGE
;FALL IN FROM PREVIOUS PAGE

	SETZM	GOTO		;SO WE DON'T LOOP
	HLRS	ARSIZE		;[635] RESET STICKY SIZE FOR ARL TABLE
	MOVEI	T1,.SPL		;SET DEFAULT SPACE
	MOVEM	T1,SPACE	;[635] FOR NON-ROOT LINKS
	AOS	LSYM		;ALLOCATE FIRST WORD
	HLLZ	T1,OVINEX	;SEE IF ANY INCLUDES TO SETUP
	JUMPE	T1,LNKZA1	;NO
	MOVEI	T2,.EXC		;GET SPACE
	PUSHJ	P,DY.GET##
	HRLZM	T1,INCPTR	;SET IT UP
	HLLZ	T2,OVINEX	;FROM
	HRR	T2,T1		;TO
	BLT	T2,.EXC-1(T1)	;MOVE
	HRRZ	T2,(T1)		;SEE IF MORE
	SKIPE	T2		;NO
	PUSHJ	P,OVRINX	;YES
LNKZA1:	HRRZ	T1,OVINEX	;SEE IF EXCLUDES
	JUMPE	T1,LNKZA2	;NO
	MOVEI	T2,.EXC		;GET SPACE
	PUSHJ	P,DY.GET##
	HRLZM	T1,EXCPTR	;SET IT UP
	HRLZ	T2,OVINEX	;FROM
	HRR	T2,T1		;TO
	BLT	T2,.EXC-1(T1)	;MOVE
	HRRZ	T2,(T1)		;GET NEXT
	SKIPE	T2		;IF NONE
	PUSHJ	P,OVRINX	;OTHERWISE MOVE REST
LNKZA2:	MOVE	T1,OVERLW	;GET OVERLAY SWITCHES
	SKIPN	RT.LB		;ALREADY SETUP?
	TXNN	T1,$OVRELOC	;NO, BUT DO WE NEED IT
	POPJ	P,		;NO, RETURN TO EITHER LNKOV1 OR LNKOV2
	MOVEI	P1,RT.IX	;AREA WE WANT
	PJRST	XX.INI##	;SET IT UP
LNKTCK:	SKIPE	RT.LB		;RELOCATABLE?
	PUSHJ	P,RT.P2##	;YES, SETUP BYTE PTR
	SUB	P2,PH.ADD	;REMOVE BASE ADDRESS INCASE ABS
	SUB	P3,PH.ADD	;...
	SKIPE	PAG.S1		;PAGING?
	JRST	LNKTC2		;YES
	ADD	P2,LC.LB	;RELOCATE
	CAMG	P2,LC.AB	;FIT IN WHAT WE HAVE?
	JRST	LNKTC1		;YES
	SUB	P2,LC.AB	;GET EXTRA REQUIRED
	MOVEI	P1,LC.IX
	PUSHJ	P,LNKCOR##
	  JRST	LNKTC2		;MUST BE ON DSK NOW
	SUB	P3,LW.S1	;INCASE WE DUMPED CORE
LNKTC1:	ADD	P3,LC.LB	;RELOCATE
	POPJ	P,

LNKTC2:	PUSHJ	P,PG.LSG##	;MAKE SURE IN CORE
	JRST	LNKTC1		;IS BY NOW


LKSTER:	PUSHJ	P,STARTU##	;UNDEFINED MESSAGE
	SETZM	STADDR		;CLEAR ADDRESS
	POPJ	P,
SUBTTL	DO OPEN & ENTER FOR OV FILE

OC.OPN::MOVEI	T2,LN.IO	;GET SPACE FOR LOOKUP/ENTER BLOCK
	PUSHJ	P,DY.GET##
	MOVEM	T1,IO.PTR+OC	;STORE POINTER
	MOVE	T3,IO.PTR+%OC	;GET PTR TO REAL BLOCK
	MOVEI	T2,.IODPR	;MODE 16
	MOVEM	T2,I.MOD(T1)
	SKIPN	T2,I.DEV(T3)	;USE WHAT USER SPECIFIED
	MOVSI	T2,'DSK'
	MOVEM	T2,I.DEV(T1)
	MOVEI	T2,LN.RIB-1	;SIZE OF EXTENDED  RIB
	MOVEM	T2,I.RIB(T1)
	MOVE	T2,I.EXT(T3)	;GET USER EXT OR DEFAULT
	MOVEM	T2,I.EXT(T1)	;USE IT FOR LOOKUP
	MOVE	T2,I.PPN(T3)	;[651] COPY PPN SPECIFIED
	MOVEM	T2,I.PPN(T1)	;[651] TO TMP FILE DATA BLOCK
	HRLZI	T2,I.PTH(T3)	;[651] COPY ALL SFD'S ALSO
	HRRI	T2,I.PTH(T1)	;[651] VIA STANDARD BLT
	BLT	T2,I.PTH+LN.SFD-1(T1)	;[651] BUT NOT TOO FAR
	MOVEI	T1,OC		;SET CURRENT CHAN #
	MOVEM	T1,IO.CHN	;
	PUSHJ	P,DVNAM.##	;SET UP OUTPUT NAME
	PUSHJ	P,DVSUP.##	;DETERMINE STRUCTURE
	  PJRST	ODVERR##	;DEV IS NOT A DSK, DIE
	MOVE	T1,IO.PTR+OC	;RESTORE THE I/O DATA
	MOVE	T3,IO.PTR+%OC	;  BLOCK POINTERS
	MOVE	T2,JOBNUM	;SIXBIT JOB NUMBER
	HRRI	T2,'OVL'
	MOVEM	T2,I.NAM(T1)	;AS FILE NAME
	MOVSI	T2,'TMP'	;EXT
	MOVEM	T2,I.EXT(T1)
	MOVSI	T2,077000	;PROTECTION
	MOVEM	T2,I.PRV(T1)
	SKIPN	T2,I.EST(T3)	;SEE IF USER SUPPLIED
	MOVEI	T2,1000		;REAL JOBS  ARE  BIG
	MOVEM	T2,I.EST(T1)
	MOVEI	T1,OC		;CHAN#
	PUSHJ	P,DVUPD.##	;OPEN IN UPDATE MODE
	  JRST	ER.EOV		;FAILED
	POPJ	P,

ER.EOV:	PUSH	P,IO.CHN	;[631] TELL ERROR ROUTINE CHANNEL NUMBER
	.ERR.	(LRE,.EC,V%L,L%F,S%F,EOV,<Error creating overlay file >)
	.ETC.	(FSP,,,,,OC)
SUBTTL	RESET SWITCH

%NODE::
%RESET::
	PUSHJ	P,.SAVE4##
	SKIPN	LINKSEEN	;PREVIOUS SEGMENT COMPLETED?
	PUSHJ	P,[PUSHJ P,.SAVE4##	;WILL NEED P2
		MOVE	P2,LNKMAX	;OVERLAY COUNT
		ADDI	P2,1		;OVERLAY NUMBER
		.ERR.	(MS,.EC,V%L,L%W,S%W,LSM,</LINK switch missing while loading link number >) ;
		.ETC.	(DEC,.EC!.EP,,,,P2) ;LINK NUM
		.ETC.	(STR,,,,,,< -- assumed>) ;
		PUSHJ	P,SYSLB1##	;SEARCH LIBRARIES
		SETZM	LNKNAM		;/LINK:<LNKNAM>
		PJRST	LINKGT]		;FORCE /LINK
	SETZM	LINKSEEN	;STARTING NEW SEGMENT
	MOVE	T2,2(P2)	;RESTORE /NODE VALUE
	TLNN	T2,-1		;TEST FOR NAME
	JRST	RSTA		;CERTAINLY NOT
	TLC	T2,-1		;BUT MIGHT BE NEGATIVE NO.
	TLCE	T2,-1
	JRST	RSTL		;NO, ITS A NAME
RSTA:	CAMN	T2,LNKMAX	;TEST FOR TRIVIAL CASE
	POPJ	P,		;IT WAS, LEAVE AS IS
	CAMLE	T2,LNKMAX	;IS IT IN RANGE?
	JRST	RSTNE		;NO
	MOVEM	T2,CS.NUM	;NO, STORE SO WE KNOW WHO TO LINK TO
	MOVE	P2,T2		;SAFER PLACE FOR LINK#
	JUMPE	P2,RESET0	;RESET TO ROOT IS SPECIAL
	JUMPL	P2,RSTN		;STILL A NEGATIVE NO.?
	MOVS	T1,LSTPTR	;SEE IF SPECIAL CASE
	MOVE	T2,(T1)		;OF WANTING PENULTIMATE LINK
	CAIE	P2,(T2)
	JRST	RST2		;NO, GENERAL CASE
;HERE ON A /NODE TO THE ROOT LINK.

RSTB:	HLL	T1,(T1)		;FORM AOBJN PTR
	ADD	T1,[2,,2]	;BYPASS LINK# AND BACK PTR
	SKIPN	(T1)		;BLANK?
	JRST	RST1		;YES
	AOBJN	T1,.-2
	HLRZ	T1,LSTPTR	;GET NODE BLOCK
	HLRE	T2,(T1)		;GET LENGTH
	MOVM	T2,T2
	ADDI	T2,1		;MAKE ONE MORE
	PUSHJ	P,DY.GET##
	HLLZ	T3,LSTPTR	;FROM
	HRR	T3,T1		;TO, BLT PTR
	MOVN	T4,T2		;- LENGTH
	HLL	T2,LSTPTR	;SAVE START OF OLD BLOCK
	HRLM	T1,LSTPTR
	ADDI	T1,-2(T2)	;END OF BLT
	BLT	T3,(T1)		;MOVE DATA
	HRRM	T1,LSTPTR	;RESET LAST POINTER
	SUBI	T1,-2(T2)	;BACKUP
	HRLM	T4,(T1)		;SET NEW COUNT
	HLRZ	T1,T2		;OLD ORIGIN
	HRRZI	T2,-1(T2)	;OLD BLOCK SIZE
	PUSHJ	P,DY.RET##
	HLRZ	T1,LSTPTR	;GET NEW BLOCK AGAIN
	HRRZ	T2,(T1)		;THIS LINK#
	SKIPN	T3,1(T1)	;BACK POINTER
	JRST	[MOVEM	T1,FSTPTR	;MUST BE LINK# 0
		JRST	RSTBB]
	MOVS	T4,2(T3)	;GET LINK#
	CAIE	T2,(T4)		;ONE WE WANT
	AOJA	T3,.-2		;MUST BE THERE
	HRRM	T1,2(T3)	;MAKE IT POINT TO NEW BLOCK
RSTBB:	MOVEI	T3,2(T1)	;NOW LOOK AT POSSIBLE FORWARD PTRS
RSTC:	SKIPN	T2,(T3)		;GET POINTER
	JRST	RST1		;ALL DONE
	TRNE	T2,-1		;FORWARD PTR?
	HRRM	T1,1(T2)	;YES
	AOJA	T3,RSTC
;THIS CASE IS SPECIAL IN THAT ALL THAT HAS TO BE DONE IS TO DELETE
;THE LAST LINK STORED AND ADJUST THE POINTERS ACCORDINGLY
RST1:	AOS	LSTPTR		;MAKE ROOM IN CURRENT BLOCK
RST1A:	HRRZ	P1,BRNLEN	;GET POINTER TO LAST LINK STORED
	PUSHJ	P,CHKBRN	;SEE IF LINK AS AT TOP OF TABLE
	  JRST	RST1C		;ON DSK SO NOTHING TO DO

RST1B:	SETZM	(T1)		;ZERO FIRST WORD
	HRLZ	T2,T1
	HRRI	T2,1(T1)	;BLT PTR
	BLT	T2,@BG.AB	;DELETE ALL AREA
	MOVEM	T1,BG.PT	;NEW TOP OF AREA USED
	IORI	T1,.IPM		;PUT ON BLOCK BOUND
	MOVEM	T1,BG.AB	;MAKE NEW TOP
	MOVEM	T1,BG.UB
	ADDI	T1,1		;NEW START OF GS AREA
	HRLZ	T2,GS.LB
	HRR	T2,T1		;BLT PTR
	SUB	T1,GS.LB	;- DIFF
	JUMPE	T1,RST1C	;SHOULD NOT HAPPEN
	ADDM	T1,GS.LB	;FIXUP PTR
	ADDM	T1,GS.AB
	ADDM	T1,GS.PT
	ADDM	T1,HT.PTR
	BLT	T2,@GS.AB	;MOVE AREA DOWN
	MOVM	T1,T1		;+ DIFF
	ADD	T1,GS.AB	;GET OLD END AGAIN
	HRRZ	T2,GS.AB
	HRLI	T2,1(T2)
	HRRI	T2,2(T2)	;BLT PTR
	SETZM	-1(T2)
	BLT	T2,(T1)		;CLEAR ALL OF AREA LEFT
RST1C:	MOVE	T1,BRNLEN	;GET OLD LENGTH
	HRRZ	P1,T1		;INDEX INTO BRANCH TABLES
	SETZM	@BRNTBL		;AVIODS CONFUSION
	SETZM	@BRNDSK
	SETZM	@BRNADD
	SUB	T1,[1,,1]	;BACKUP
	MOVEM	T1,BRNLEN	;AND RESET IT
	MOVE	P1,CS.NUM	;GET NUMBER WE WANT
	JRST	RST06		;AND READ IN THE PREAMBLE
;HERE TO RESET TO SOME LINK ON THE CURRENT PATH
;THE LINKS ABOVE THE REQUIRED ONE MUST BE DELETED
;AND ALL POINTERS ADJUSTED

RST2:	PUSHJ	P,DLTDSK	;DELETE POSSIBLE DSK FILE
	PUSHJ	P,MRKLNK	;MARK IT AS REQUIRED
	  JRST	RST3		;NOT IN BRANCH
	PUSHJ	P,.SAVE2##	;NEED P2
	MOVS	P1,LSTPTR	;WALK BACKWARDS THROUGH TREE
	HRRZ	T1,(P1)		;GET LINK#
	MOVE	P1,1(P1)	;AND NEXT PTR
	CAME	P2,T1		;BACK TO ONE WE WANT?
	JRST	.-3		;NOT YET
RST2A:	HRRZ	P2,(P1)		;LINK#
	PUSHJ	P,MRKLNK	;WE NEED THIS ONE
	  PUSHJ	P,ER.LNC##	;MUST BE INCORE
	MOVE	P1,1(P1)	;GET PREVIOUS
	JUMPN	P2,RST2A	;END AT 0
	PUSHJ	P,ADJBRN	;NOW REMOVE WHATS NOT NEEDED
RST2B:	PUSHJ	P,BKPBRN	;DELETE AREA AND BACKUP BRNTBL
	SUBI	P1,1
	CAME	P1,P2		;DONE THEM ALL YET?
	JRST	RST2B		;NO, LOOP
	HLRZ	P2,@BRNTBL	;GET LINK# WE REALLY WANTED
	MOVS	T1,LSTPTR	;GET NODE PTR
	HRRZ	T2,(T1)		;GET NUMBER
	CAMN	T2,P2		;WHAT WE WANTED?
	JRST	RST2D		;YES
	HLL	T1,(T1)		;AOBJN
	ADD	T1,[2,,2]	;BYPASS HEADER & BACK PTR
	MOVS	T2,(T1)		;GET LINK#
	CAIN	P2,(T2)		;ONE WE WANTED?
	JRST	.+3
	AOBJN	T1,.-3		;NOT YET
	PUSHJ	P,ER.LNC##	;MUST BE INCORE
	TLNN	T2,-1		;FORWARD PTR?
	JRST	RST2D		;NO?
	MOVS	T2,T2		;GET PTR
	HRLM	T2,LSTPTR	;POINT TO NEW
	HLL	T2,(T2)		;AOBJN PTR
	ADD	T2,[2,,2]	;BYPASS LINK# AND BACK PTR
	SKIPE	(T2)		;LOOK FOR BLANK
	AOBJN	T2,.-1		;OR END OF LIST
	SUBI	T2,1		;BACKUP 1 TO POINT TO LAST USED
	HRRM	T2,LSTPTR
RST2D:	MOVE	T1,[1,,1]	;FAKE OUT BRNLEN
	ADDM	T1,BRNLEN	;SO WE CAN REMOVE NON-EXISTENT TOP
	MOVS	T1,LSTPTR
	JRST	RSTB		;YES, NOW MOVE GS DOWN
;HERE TO RESET TO SOME LINK NOT ON THE CURRENT PATH
;ALL THE LINKS NOT REQUIRED MUST BE DELETED
;THEN ALL OTHER LINKS ON THE PATH READ IN

RST3:	MOVE	P1,P2		;WE WANTED THIS LINK
	PUSHJ	P,TR.WLK##	;FIND NODE
	HLRZ	T1,P1		;GET ADDRESS OF START OF NODE
	HRRZ	T2,(T1)		;GET LINK#
	CAIN	T2,(P1)		;ONE WE WANTED?
	JRST	RST3A		;YES, AS EXPECTED
	MOVEI	T2,4		;NO, MUST BE A NEW NODE
	PUSHJ	P,DY.GET##	;SO GET SPACE FOR IT
	HRRZ	T2,P1		;LINK #
	HRLI	T2,-4		;LENGTH
	MOVEM	T2,(T1)		;HEADER WORD
	HLRZM	P1,1(T1)	;BACK POINTER
	HRLI	T1,1(T1)	;MAKE LSTPTR
	MOVSM	T1,LSTPTR
	HLRZ	T2,P1		;NOW LOOK BACK TO FIND FATHER
	HLRZ	T3,2(T2)
	CAIE	T3,(P1)		;MATCHING ONE WE WANT?
	AOJA	T2,.-2		;MUST BE THERE
	HRRM	T1,2(T2)	;POINT TO IT
	JRST	RST3B		;NOW CONTINUE

RST3A:	HRLM	T1,LSTPTR	;START OF NODE
	ADD	T1,[2,,2]	;BYPASS LINK# AND BACK PTR
	HLL	T1,(T1)		;FORM AOBJN PTR
	SKIPN	(T1)		;LOOK FOR BLANK
	JRST	.+3
	AOBJN	T1,.-2		;OR END OF LIST
	SUBI	T1,1		;END SO BACKUP TO LAST
	HRRM	T1,LSTPTR	;LSTPTR IS NOW POINTING TO NODE WE WANT
RST3B:	MOVS	P1,LSTPTR
	PUSH	P,P2		;DEPTH WE FINALLY WANT
	CAIA
RST3C:	MOVE	P1,1(P1)	;GET BACK PTR
	HRRZ	P2,(P1)		;GET LINK #
	PUSHJ	P,MRKLNK	;MARK AS REQUIRED
	  JFCL			;TOO BAD, WILL HAVE TO READ IT IN LATER
	JUMPN	P2,RST3C	;FINISH ON 0
	PUSHJ	P,ADJBRN	;REMOVE WHATS NOT NEEDED
RST3D:	CAMN	P1,P2		;NOTHING TO REMOVE?
	JRST	RST3E
	PUSHJ	P,DLTBRN	;REMOVE SYMBOL TABLE
	SOJA	P1,RST3D	;SEE IF DONE
;HERE WHEN ALL OLD SYMBOL TABLES DELETED. READ IN NEW ONES.

RST3E:	POP	P,P2		;RECOVER DEPTH
	MOVE	T1,BRNLEN	;DEPTH WE NOW HAVE
	SUBI	P2,(T1)		;DIFFERENCE
	HRL	P2,P2		;IN BOTH HALVES
	ADDB	P2,BRNLEN	;MAKE IT WHAT WE WANT
	HRRZS	P1,P2
	HLRZ	T1,LSTPTR	;START OF BACK PATH
RST3F:	HRRZ	T2,(T1)		;GET LINK#
	SKIPE	@BRNDSK		;IF 0 THEN ITS NOT YET SETUP
	JRST	RST3G		;ALL DONE
	HRLZM	T2,@BRNTBL	;STORE # WE NEED
	MOVE	T1,1(T1)	;GET NEXT PTR
	SOJG	P1,RST3F	;LINK# IS ALWAYS IN CORE

;HERE TO READ IN ALL REQUIRED SYMBOL TABLES
RST3G:	MOVNI	P2,1(P2)
	HRLZ	P2,P2		;FORM AOBJN WORD
RST3H:	HRRZ	P1,P2		;INDEX FOR TABLE LOOKUPS
	SKIPE	@BRNDSK		;SEE IF ALREADY SET
	AOBJN	P2,.-2		;WILL EVENTUALLY SKIP
	HLRZ	P1,@BRNTBL	;GET LINK#
	ROT	P1,-1		;USUAL METHOD TO PICK CORRECT HALF
	JUMPL	P1,[HRRZ T1,@LNKTBL
		JRST	.+2]
	HLRZ	T1,@LNKTBL	;FOR USETI TO GET PREAMBLE
	USETI	OC,(T1)		;SET ON BLOCK
	DMOVE	T1,PHIOWD
	IN	OC,T1		;READ IT IN
	  CAIA			;OK
	PUSHJ	P,ER.IOV##	;INPUT ERROR
	HRRZ	P1,P2		;INDEX INTO BRANCH TABLES
	HRRZ	T1,PH.ADD	;LOWER ADDRESS
	HLL	T1,@BRNTBL	;LINK #
	MOVEM	T1,@BRNADD	;INCASE RELOCATED

RST3I:	MOVE	T1,PH.GLB	;POINTER TO GLOBAL SYMBOLS
	HLRE	T2,T1		;WORD COUNT (FROM IOWD)
	MOVM	T2,T2
	ADD	T2,BG.PT	;TOP WE NEED
	CAMG	T2,BG.AB	;IS THERE ENOUGH?
	JRST	RST3J		;YES
	SUB	T2,BG.AB	;EXCESS
	PUSH	P,P2		;SAVE AOBJN COUNTER
	MOVEI	P1,BG.IX
	MOVE	P2,T2		;WHAT WE NEED
	PUSHJ	P,LNKCOR##
	  PUSHJ	P,NO.COR##
	POP	P,P2
	JRST	RST3I		;TRY AGAIN
;HERE WHEN ENOUGH ROOM. READ IN REQUIRED GLOBAL TABLE.

RST3J:	USETI	OC,(T1)		;SET ON BLOCK
	HRR	T1,BG.PT	;IOWD (ALMOST)
	HRRI	T1,-1(T1)
	SETZ	T2,
	IN	OC,T1		;READ IN GLOBAL TABLE
	  CAIA
	PUSHJ	P,ER.IOV##	;INPUT ERROR
	HRRZ	P1,P2		;TO HOLD BRN DEPTH
	HRRZI	T2,1(T1)	;GET LOWER ADDRESS BACK
	SUB	T2,BG.LB	;MAKE RELATIVE
	HRRM	T2,@BRNTBL	;START OF SYMBOL AREA
	HLRE	T2,T1		;- LENGTH
	MOVM	T2,T2
	HRLM	T2,@BRNDSK	;STORE LENGTH
	ADDM	T2,BG.PT	;ACCOUNT FOR AREA
	AOBJN	P2,RST3H	;GET NEXT
	JRST	RST2D		;NOW CORRECT PTRS
RSTN0:	PUSHJ	P,BKPBRN	;BACKUP ONE LINK
	AOS	P2,CS.NUM	;GET ITS FATHER
;	JRST	RSTN		;AND SEE IF ALL DONE

RSTN:	MOVN	T1,LNKMAX	;CHECK FOR INRANGE LINK
	CAMGE	P2,T1		;NODE REQUESTED BEFORE ROOT?
	JRST	RSTRPR		;YES - ERROR
	MOVS	T1,LSTPTR	;MUST BACKUP BY ONE LEVEL
	CAME	P2,[-1]		;BACK TO LAST YET?
	JRST	RSTN0		;NO, KEEP TRYING
	HRRZ	P2,(T1)		;GET LINK#	
	MOVEM	P2,CS.NUM	;SET IT
	JUMPE	P2,RESET0	;ROOT IS SPECIAL
	JRST	RST2		;DO IT


RSTL:	MOVS	T1,LNMPTR	;GET POINTER
	JUMPE	T1,RSTLE	;ERROR
RSTLA:	CAMN	T2,(T1)		;IS THIS IT
	JRST	RSTLF		;YES
	HRRZ	T1,1(T1)	;GET FORWARD PTR
	JUMPN	T1,RSTLA	;TRY AGAIN
RSTLE:	.ERR.	(MS,.EC,V%L,L%W,S%W,LNN,<Link name >)
	.ETC.	(SBX,.EC!.EP,,,,T2)
	.ETC.	(STR,,,,,,< not assigned>)
	POPJ	P,

RSTNE:	.ERR.	(MS,.EC,V%L,L%W,S%W,LNL,<Link number >)
	.ETC.	(DEC,.EC!.EP,,,,T2)
	.ETC.	(STR,,,,,,< not loaded>)
	POPJ	P,

RSTLF:	HLRZ	T2,1(T1)	;GET NUMBER
	JRST	RSTA		;AND RETURN

RSTRPR:	.ERR.	(MS,,V%L,L%F,S%F,NBR,<Attempt to position to node before ROOT>)	;
;HERE IF RESET IS ALL THE WAY BACK TO THE ROOT
RESET0:	MOVE	T1,FSTPTR
	HLL	T1,(T1)		;FORM AOBJN
	ADD	T1,[2,,2]	;BYPASS LINK# AND BACK PTR
	SKIPN	(T1)		;LOOK FOR NULL IN CURRENT BLOCK
	JRST	RST0A		;FOUND IT
	AOBJN	T1,.-2
	HLRE	T2,@FSTPTR	;GET LENGTH
	MOVM	T2,T2
	ADDI	T2,1		;MAKE ONE MORE
	PUSHJ	P,DY.GET##
	HRLZ	T3,FSTPTR	;FROM
	HRR	T3,T1		;TO, BLT PTR
	MOVN	T4,T2		;- LENGTH
	ADDI	T1,-2(T2)	;END OF BLT
	BLT	T3,(T1)		;MOVE DATA
	SUBI	T1,-2(T2)	;BACKUP
	HRLM	T4,(T1)		;SET NEW COUNT
	EXCH	T1,FSTPTR	;EXCH OLD WITH NEW
	HRRZI	T2,-1(T2)	;OLD BLOCK SIZE
	PUSHJ	P,DY.RET##
	HRRZ	T3,FSTPTR	;GET NEW BLOCK AGAIN
	MOVEI	T1,2(T3)	;NOW LOOK AT POSSIBLE FORWARD PTRS
RST0C:	SKIPN	T2,(T1)		;GET POINTER
	JRST	RST0A		;ALL DONE
	TRNE	T2,-1		;FORWARD PTR?
	HRRM	T3,1(T2)	;YES
	AOJA	T1,RST0C

RST0A:	HRL	T1,FSTPTR
	MOVEM	T1,LSTPTR	;RESET TREE PTR
	PUSHJ	P,DLTDSK	;DELETE DSK FILE, MARK LINKS NOT IN CORE
	HRRZ	P1,BRNLEN	;NO. OF LINKS TO SCAN
RST01:	HLRZ	T2,@BRNTBL	;GET LINK #
	JUMPE	T2,RST02	;FOUND IT
	SETZM	@BRNTBL		;ZERO THE TABLE SLOTS
	SETZM	@BRNDSK
	SETZM	@BRNADD
	SOJGE	P1,RST01	;LOOP
	  PUSHJ	P,ER.LNC##	;MUST BE INCORE

RST02:	HRRZ	T1,@BRNTBL	;GET ORIGIN OF TABLE
	JUMPE	T1,RST03	;ALREADY AT BOTTOM
	HRLZ	T2,T1
	HRR	T2,BG.LB	;BLT PTR
	HLRZ	T3,@BRNDSK	;GET LENGTH OF THIS TABLE
	ADDB	T1,T3		;NEXT FREE WORD
	MOVEM	T1,BG.PT	;RESET NEXT FREE PTR
	BLT	T2,-1(T2)	;MOVE DOWN
	JRST	RST04		;NOW ZERO THE REST AND GIVE IT AWAY
RST03:	HLRZ	T3,@BRNDSK	;GET LENGTH
	ADD	T3,BG.LB	;+ BASE
	MOVEM	T3,BG.PT	;NEW PTR TO NEXT FREE
RST04:	HRLZ	T1,T3
	HRRI	T1,1(T3)	;BLT PTR
	SETZM	-1(T1)		;[664] CLEAR CORE
	BLT	T1,@BG.AB	;BEFORE WE GIVE IT AWAY
	MOVE	T1,T3
	IORI	T1,.IPM
	MOVEM	T1,BG.AB	;HIGHEST IN ACTUAL USE
	SUBM	T1,T3		;GET FREE SPACE
	MOVEM	T3,BG.FR	;NO. OF WORDS FREE IN LAST BLOCK
	CAML	T1,BG.UB	;JUST INCASE NOTHING TO GIVE AWAY
	JRST	RST05		;NOT VERY LIKELY!
	MOVEM	T1,BG.UB
	AOS	T3,T1		;WHERE IT WILL GO
	HRL	T1,GS.LB	;FROM
	SUB	T3,GS.LB	;- NEGATIVE DIFF
	ADDM	T3,GS.LB	;FIXUP ALL GS PTR
	ADDM	T3,GS.PT
	ADDM	T3,HT.PTR
	MOVE	T2,GS.PT	;NEXT FREE
	HRLI	T2,1(T2)	;BLT PTR (SWAPPED)
	BLT	T1,-1(T2)	;MOVE DOWN
	SETZM	(T2)		;CLEAR REST
	MOVS	T2,T2		;PUT BLT PTR RIGHT WAY ROUND
	BLT	T2,@GS.AB	;CLEAR CORE
	ADDM	T3,GS.AB	;SET LOWER
RST05:	MOVE	T1,BRNLEN	;GET AOBJN POINTER
	HRLS	T2,BRNLEN	;PUTINDEX IN BOTH SIDES
	SUB	T1,T2		;GET ORIGINAL PTR
	HLLZM	T1,BRNLEN	;ONLY LINK 0 IN TABLE
	SETZ	P1,		;INDEX FOR LINK # 0
RST06:	ROT	P1,-1		;CUT IN HALF
	JUMPL	P1,[HRRZ T1,@LNKTBL
		JRST	.+2]
	HLRZ	T1,@LNKTBL	;GET BLOCK
	USETI	OC,(T1)		;OF PREAMBLE
	DMOVE	T1,PHIOWD
	IN	OC,T1
	  PJRST	LNKZA		;NOW ZERO WHAT WE DON'T NEED
	PUSHJ	P,ER.IOV##	;INPUT ERROR
SUBTTL	COMMON SUBROUTINES

;CHKBRN - CHECKS TO SEE IF LINK IS AT TOP OF BG AREA
;IF NOT IT MOVES ALL LINKS ABOVE DOWN AND PUTS ADDRESS OF
;THIS LINK AT TOP. NOTE ACTUAL LINK IS NOT MOVED UP.
;IF LINK IS ON DSK NOTHING IS DONE
;ENTERS WITH
;	P1 CONTAINS DEPTH IN BRANCH OF REQUIRED LINK #
;RETURNS
;+1	LINK IS ON DSK
;+2	LINK IS NOW AT TOP OF BG

CHKBRN:	HRRZ	T1,@BRNTBL	;GET ITS ADDRESS
	ADD	T1,BG.LB	;FIX IT
	MOVS	T2,@BRNDSK	;GET LENGTH
	SKIPE	T2		;DOES NOT REALLY EXIST IF 0
	TLNE	T2,-1		;IS CURRENTLY ON DSK
	POPJ	P,		;JUST BACKUP PTR
	ADD	T2,T1		;GET END
	CAMN	T2,BG.PT	;MAKE SURE ITS THE LAST ITEM
	JRST	CPOPJ1		;YES, SIMPLE CASE
	HRL	T1,T2
	MOVS	T1,T1		;FORM BLT PTR
	HRRZ	T3,T2		;ALL AT OR ABOVE THIS ADDRESS MUST BE ADJUSTED
	SUB	T2,BG.LB
	MOVN	T2,T2		;- NO. OF WORDS TO REMOVE
	ADD	T2,BG.PT	;TOP OF SYMBOLS LEFT
	HRRM	T2,@BRNTBL	;SO POINT TO WHERE IT WOULD BE MOVED TO
	BLT	T1,(T2)		;MOVE REQUIRED SYMBOLS DOWN
	SUB	T2,BG.PT	;GET - COUNT BACK
	PUSH	P,P1
	SUBI	P1,1		;NOW FIXUP POINTERS
	HRRZ	T1,@BRNTBL	;GET POINTER
	CAIL	T3,(T1)		;NEED TO ADJUST?
	ADDM	T2,@BRNTBL	;YES
	SOJGE	P1,.-3
	POP	P,P1
	JRST	CHKBRN		;NOW TRY
MRKLNK:	PUSHJ	P,.SAVE1##
	HRRZ	P1,BRNLEN	;NO. OF LINKS TO SCAN
MRKLN1:	HLRZ	T1,@BRNTBL	;GET LINK#
	CAMN	T1,P2		;ONE WE WANT
	JRST	MRKLN2		;FOUND IT
	SOJGE	P1,MRKLN1	;NO
	POPJ	P,		;NOT IN BRANCH

MRKLN2:	HLLOS	@BRNDSK		;MARK BY -1 IN RIGHT HALF
	JRST	CPOPJ1		;FOUND IT

DLTDSK:	PUSHJ	P,.SAVE1##	;NEED P1
	HRRZ	P1,BRNLEN	;NO. OF LINKS IN BRANCH
	HLLZS	@BRNDSK		;ZERO RH MEANS NOT NEEDED YET
	SOJGE	P1,.-1
	POPJ	P,

ADJBRN:	HRRZ	T4,BRNLEN	;MAX NO. WE HAVE
	SETZ	P1,		;START AT ZERO
	SETO	P2,		;SAFE SINCE LINK# 0 IS ALWAYS WANTED
ADJBR1:	MOVE	T1,@BRNDSK
	TRNN	T1,-1		;DO WE NEED IT?
	JRST	ADJBR2		;NO, SEE IF ALL DONE
	ADDI	P2,1		;INCRENENT SINCE WE NEED TO STORE THIS ONE
	MOVE	T2,@BRNTBL	;GET ADDRESS AND NUMBER
	MOVE	T3,@BRNADD	;LINK # AND LOWER BOUND
	EXCH	P1,P2		;SWAP PTRS
	HLLZM	T1,@BRNDSK
	MOVEM	T2,@BRNTBL	;MOVE BACK
	MOVEM	T3,@BRNADD
	EXCH	P1,P2
ADJBR2:	CAMGE	P1,T4		;DONE THEM ALL?
	AOJA	P1,ADJBR1	;NOT YET
	POPJ	P,
BKPBRN:	MOVS	T1,LSTPTR
	HRRZ	T2,(T1)		;GET FATHER LINK
	SKIPN	T1,1(T1)	;BACK POINTER
	JRST	RSTRPR		;ERROR
	HRLM	T1,LSTPTR	;BACK UP
	HLL	T1,(T1)		;FORM AOBJN POINTER
	ADD	T1,[2,,2]	;BYPASS LINK# AND BACK PTR
	SKIPN	(T1)		;BLANK YET?
	JRST	BKPB1		;YES
	AOBJN	T1,.-2		;
	SUBI	T1,1		;NO SPACE, SO BACKUP
BKPB1:	HRRM	T1,LSTPTR	;RESET NOW
;	JRST	DLTBRN

DLTBRN:	HRRZ	P1,BRNLEN	;GET DEPTH IN BRANCH
	PUSHJ	P,CHKBRN	;MAKE SURE ITS AT TOP
	  JFCL			;OK IF ON DSK
	HLRZ	T1,@BRNDSK	;GET LENGTH
	MOVN	T1,T1
	ADDM	T1,BG.PT	;AND BACK UP
	MOVE	T1,BRNLEN	;ONE LESS BRANCH IN CORE
	SUB	T1,[1,,1]	;SO BACKUP
	MOVEM	T1,BRNLEN
	SETZM	@BRNTBL		;AVOIDS CONFUSION
	SETZM	@BRNDSK
	SETZM	@BRNADD
	JUMPL	T1,CPOPJ	;STILL VALID POINTER
	PUSHJ	P,ER.LNC##	;MUST BE INCORE
SUBTTL	SEARCH BOUND GLOBALS

TRY.BG::SPUSH	<P1,P2,P3>	;SAVE HASH ACCS
	SPUSH	<NAMLOC,HSPACE,HT.PRM,HT.PTR>	;GS PARAMETERS
	.JDDT	LNKOV1,TRY.BG,<<CAMN	W2,$SYMBOL##>>
	SETZM	HSPACE		;PREVENT REHASHING
	HRRZ	T1,BRNLEN	; NO. OF BOUND GLOBAL TABLES
	MOVEM	T1,BG.SCH	;SAFE PLACE TO PUT IT
TRYBG1:				;START AT LINK 0 AND READ IN ASCENDING ORDER
				; SINCE MOST GLOBALS WILL BE IN ROOT
	HRRZ	T1,BRNLEN	;TOTAL
	SUB	T1,BG.SCH	;MINUS WHATS LEFT GIVES INDEX
	ADD	T1,BRNTBL	;INDEX   INTO TABLE
	SKIPN	T2,(T1)		;GET LINK #,,ADDRESS
	JRST	.+3		;LINK 0 IS ALWAYS IN CORE
	TRNN	T2,-1		;ON DSK?
	  PUSHJ	P,ER.LNC##	;MUST BE INCORE
	ADD	T2,BG.LB	;ADD IN BASE
	HRRZM	T2,NAMLOC	;WHERE IT IS
	MOVE	T1,(T2)		;FIRST WORD IS SPECIAL
	HLRZM	T1,HT.PRM	;CONTAINS HASH SIZE
	ADDI	T2,(T1)		;ADD OFFSET FOR HASH TABLE
	HRRM	T2,HT.PTR
	PUSHJ	P,TRYSYM##	;TRY AGAIN
	  JRST	TRYBG3		;FAILED
	  JRST	TRYBG3		;ALSO FAILED
	SPOP	<HT.PTR,HT.PRM,HSPACE,NAMLOC>
	MOVE	P4,P1		;SAVE POINTER TO THIS SYMBOL
	MOVE	W1,0(P1)	;GET FLAGS
	TXO	W1,PS.BGS	;TURN ON BOUND BIT
	TXZ	W1,PS.ENT	;MAKE SURE ENTRY FLAG OFF IN COPY 
				; ALSO NOT RELOC WRT THIS LINK
	SPOP	<P3,P2,P1>	;PREV VALUES
	PUSH	P,W3		;SAVE CURRENT VALUE (REQUEST CHAIN)
	MOVE	W3,2(P4)	;GET BOUND VALUE
	HRRZ	T1,BRNLEN	;NO. OF POSSIBLE LINKS
	SUB	T1,BG.SCH	;CURRENT INDEX
	TXZN	W1,PS.REL	;IS THE SYMBOL RELOCATABLE
	JRST	.+3		;NO, SO NO RELOC PROBLEM
	SKIPE	RT.LB		;LINK RELOCATABLE?
	JUMPN	T1,TRYBG4	;YES, UNLESS LINK 0
	TXNN	W1,PT.EXT	;IS IT EXTENDED?
	JRST	TRYBG2		;NO
	EXCH	P1,P4		;PTR BACK IN P1
	PUSHJ	P,SY.CHK##	;SEE HOW LONG
	SUB	P1,BG.LB	;IN CASE CORE MOVES
	PUSHJ	P,GS.GET##	;GET SPACE
	ADDI	T2,-1(T1)	;END OF BLT
	ADD	P1,BG.LB
	MOVE	W3,T1		;SYMBOL LOCATION
	HRL	T1,P1		;BLT PTR
	BLT	T1,(T2)		;COPY SYMBOL
	MOVEM	W1,0(W3)	;RESET POSSIBLE CHANGED VALUE OF FLAGS
	SUB	W3,GS.LB	;RELATIVE
	EXCH	P1,P4		;RESTORE P1
TRYBG2:	PUSHJ	P,INSRT##	;PUT IN CURRENT TABLE
	SOS	GSYM		;NOT REALLY A NEW GLOBAL SO REDUCE COUNT
	AOS	BSYM		;INCREASE COUNT FROM BOUND TABLES
	POP	P,W3		;GET REQUEST CHAIN BACK
	HRRZ	P1,@HT.PTR	;GET REL ADDRESS OF SYMBOL
	ADD	P1,NAMLOC	;MAKE ABS
	SETOM	BG.SCH		;PUT BACK NORMAL VALUE
	HRRZ	R,R		;NOT RELOCATABLE WITH RESPECT TO THIS LINK
CPOPJ2:	AOS	(P)
CPOPJ1:	AOS	(P)
CPOPJ:	POPJ	P,

TRYBG3:	SOSL	T1,BG.SCH	;MORE TO LOOK AT?
	JRST	TRYBG1		;YES
	SPOP	<HT.PTR,HT.PRM,HSPACE,NAMLOC>	;PUT THINGS BACK
	SPOP	<P3,P2,P1>
	SETOM	BG.SCH		;AS IT WAS
	POPJ	P,		;NOT FOUND RETURN
TRYBG4:	TXO	W1,PS.RBG	;TURN ON REL BOUND GLOBAL
	EXCH	P1,P4		;GET POINTER BACK
	PUSHJ	P,SY.CHK##	;SEE HOW LONG
	SUB	P1,BG.LB	;IN CASE CORE MOVES
	ADDI	T2,.L		;NEED EXTRA BLOCK
	PUSHJ	P,GS.GET##	;GET SPACE FOR COPY
	ADDI	T2,-<1+.L>(T1)	;END OF BLT
	ADD	P1,BG.LB
	MOVE	W3,T1		;SYMBOL LOCATION
	HRL	T1,P1		;FORM BLT PTR
	BLT	T1,(T2)		;MOVE IT
	MOVEM	W1,0(W3)	;SET NEW FLAGS
	MOVX	T1,PT.EXT	;MUST BE EXTENDED BY NOW
	IORM	T1,(W3)		;SET BIT
	SUB	W3,GS.LB	;RELATIVE
	MOVX	T1,S.LST	;CLEAR LAST TRIPLET BIT IF SET
	TXOE	W1,PT.EXT	;SET AS EXTENDED
	ANDCAM	T1,-.L+1(T2)	;IT WAS
	MOVX	T1,S.SYM!S.LST!S.RBG	;
	MOVEM	T1,1(T2)	;STORE  NEW TRIPLET
	MOVEM	W2,2(T2)	;STORE NAME FOR NOW
	HRRZ	T1,BRNLEN	;GET POSSIBLE MAX INDEX
	SUB	T1,BG.SCH	;GET INDEX INTO TABLE
	ADD	T1,BRNTBL	;PLUS BASE
	HLRZ	T1,(T1)		;LINK#
	MOVEM	T1,3(T2)	;CRUCIAL ITEM IN THIS TRIPLET
	JRST	TRYBG2		;PUT IN TABLE
SUBTTL	STORE INTO USER CORE IMAGE

;HERE TO STORE BLOCK TYPE 1 (AND 21)
;ENTER WITH DATA IN W1 (RESULT FROM RB.1)
;STORE ADDRESS IN P3
;THIS BLOCK IS NOT GENERALIZED BECAUSE OF SPEED CONSIDERATIONS
;CALLED BY
;	MOVE	W1,DATA WORD
;	CSTORE
;WHICH IS
;	JSP	T1,CS.RHS##
;
CS.LHS==:(JSP T1,)		;BUILD THE INSTRUCTION UP
CS.RHS::MOVEM	W1,(P3)		;STORE IN CORE
	SKIPN	RT.LB		;LOADING RELOCATABLE OVERLAYS?
	JRSTF	(T1)		;NO
	ROT	R,2		;PUT RELOC BITS IN 34-35
	IDPB	R,RT.PT		;STORE
	ROT	R,-2		;PUT BACK
	JRSTF	(T1)		;RETURN
SUBTTL	RELOCATABLE OVERLAY ROUTINES

;RT.FX - ROUTINE TO STORE RELOCATION FOR BOUND GLOBAL IN A RELOCATABLE LINK
;ENTER WITH
;P1 = POINTER TO SYMBOL
;W1 = FIXUP FLAGS (WHICH HALF)
;W3 = FIXUP VALUE
;USES T1-T4

RT.FX::	MOVEI	T2,2		;USES 2 WORDS
	SUB	P1,GS.LB	;IN CASE CORE MOVES
	PUSHJ	P,FX.GET##	;IN FIXUP AREA
	ADD	P1,GS.LB
	MOVE	T2,P1		;COPY PTR TO SYMBOL
	MOVE	T3,0(T2)	;GET PRIMARY FLAGS
	TXNN	T3,PT.EXT	;IT BETTER BE EXTENDED
	HALT
RT.FX1:	ADDI	T2,.L		;GET NEXT TRIPLET
	MOVE	T3,0(T2)	;GET SECONDARY FLAGS
	TXNE	T3,S.RBG	;BOUND GLOBAL?
	JRST	RT.FX2		;YES
	TXNN	T3,S.LST	;LAST TRIPLET?
	JRST	RT.FX1		;NOT YET
	HALT

RT.FX2:	MOVS	T2,2(T2)	;GET LINK#
	HRR	T2,RBGPTR	;LAST ONE TO LINK IN
	SETZ	T3,		;START WITH NO RELOCATION
	TXNE	W1,FS.FXR	;RIGHT ONLY?
	TXO	T3,1B1		;YES
	TXNE	W1,FS.FXL	;OR LEFT ONLY?
	TXO	T3,1B0		;YES
	TXNE	W1,FS.FXF	;OR BOTH?
	TXO	T3,3B1		;YES
	TXNE	W1,FS.FXS	;SYMBOL TABLE?
	HALT			;NOT YET
	HRR	T3,W3		;VALUE
	DMOVEM	T2,(T1)		;STORE
	SUB	T1,FX.LB	;REMOVE BASE
	.JDDT	LNKOV1,RT.FX2,<<CAMN T1,$FIXUP##>>	;[632]
	MOVEM	T1,RBGPTR	;POINT TO IT
	POPJ	P,
;RT.FXC - ROUTINE SAME AS RT.FX BUT USES PREVIOUS RELOCATION
;I.E. FOR CHAINED REFERENCES
;ENTER WITH
;P1 = POINTER TO SYMBOL
;W1 = FIXUP FLAGS (WHICH HALF)
;W3 = FIXUP VALUE
;USES T1-T4

RT.FXC::MOVEI	T2,2		;SAME 2 WORDS AS ABOVE
	PUSHJ	P,FX.GET##
	MOVE	T2,RBGPTR	;GET ADDRESS OF LAST
	ADD	T2,FX.LB	;FIX IN CORE
	DMOVE	T3,(T2)		;GET LAST
	HRR	T3,RBGPTR	;LINK TO LAST ADDRESS
	HRR	T4,W3		;CHANGE VALUE
	DMOVEM	T3,(T1)		;STORE IN NEW BLOCK
	SUB	T1,FX.LB	;REMOVE BASE
	.JDDT	LNKOV1,RT.FXC,<<CAMN T1,$FIXUP##>>	;[632]
	MOVEM	T1,RBGPTR	;STORE POINTER TO LIST
	POPJ	P,
;RT.T2R - ROUTINE TO SET RELOC BITS CORRECT FOR RIGHT HALF CHAINED REFERENCES
;ENTER WITH
;T2 = ADDRESS
;R  = RELOC BITS (BITS 0 & 1)
;P1 = PTR TO SYMBOL
;W1 = FLAGS OF PRIMARY SYMBOL

RT.T2R::PUSHJ	P,RT.T2H	;CHECK NOT IN HISEG
	POPJ	P,		;IN HIGH
	PUSH	P,P3		;NEED P3 FOR ADDRESS CHECK
	MOVE	P3,T2
	PUSHJ	P,RT.P3##	;SETUP RT.PT
	TXNN	R,1B1		;IS IT RELOCATED?
	TDZA	T2,T2		;NO
	MOVEI	T2,1		;YES
	MOVE	T1,RT.PT	;GET BYTE PTR
	TLC	T1,(<POINT 3,>-<POINT 0,>)
	IBP	T1		;BYPASS LHS
	IDPB	T2,T1		;NEW BYTE
	JUMPE	P1,POPP3	;NOT SYMBOLIC
	PUSH	P,W1		;SAVE FLAGS
	MOVX	W1,FS.FXR	;RH IN CASE BOUND
RT.T2Z:	MOVE	T2,0(P1)	;GET FLAGS
	TXNN	T2,PS.RBG	;BOUND?
	JRST	.+4		;NO
	EXCH	W3,P3		;PUT ADDRESS IN W3
	PUSHJ	P,RT.FX		;STORE FIXUP
	EXCH	W3,P3
	POP	P,W1		;RESTORE FLAGS
POPP3:	MOVE	T2,P3		;RESET T2
	POP	P,P3
	POPJ	P,

;RT.T2H - ROUTINE TO CHECK ADDRESS NOT IN HISEG
;ENTER WITH
;T2 = ADDRESS
;RETURNS
;+1 IN HISEG
;+2 IN LOW SEG

RT.T2H:	SKIPE	HC.LB		;NO HIGH SEG
	CAMGE	T2,LL.S2	;IS IT IN HIGH?
	AOS	(P)		;NO
	POPJ	P,
;RT.T2L - ROUTINE TO SET RELOC BITS CORRECT FOR LEFT HALF CHAINED REFERENCES
;ENTER WITH
;T2 = ADDRESS
;R  = RELOC BITS (BITS 0 & 1)

RT.T2L::PUSHJ	P,RT.T2H	;CHECK NOT IN HISEG
	POPJ	P,		;IN HIGH
	PUSH	P,P3		;NEED P3 FOR ADDRESS CHECK
	MOVE	P3,T2
	PUSHJ	P,RT.P3##	;SETUP RT.PT
	TXNN	R,1B0		;IS IT RELOCATED?
	TDZA	T2,T2		;NO
	MOVEI	T2,1		;YES
	MOVE	T1,RT.PT	;GET BYTE PTR
	TLC	T1,(<POINT 3,>-<POINT 0,>)
	IDPB	T2,T1		;NEW BYTE
	JUMPE	P1,POPP3	;NOT SYMBOLIC
	PUSH	P,W1		;SAVE FLAGS
	MOVX	W1,FS.FXL	;LH IN CASE BOUND
	JRST	RT.T2Z		;RESET T2,P3, AND RETURN

;RT.T2F - ROUTINE TO SET RELOC BITS CORRECT FOR FULL WORD CHAINED REFERENCES
;ENTER WITH
;T2 = ADDRESS
;R  = RELOC BITS (BITS 0 & 1)

RT.T2F::PUSHJ	P,RT.T2H	;CHECK NOT IN HISEG
	POPJ	P,		;IN HIGH
	PUSH	P,P3		;NEED P3 FOR ADDRESS CHECK
	MOVE	P3,T2
	PUSHJ	P,RT.P3##	;SETUP RT.PT
	TXNN	R,3B1		;IS IT RELOCATED?
	TDZA	T2,T2		;NO
	MOVEI	T2,1		;YES
	MOVE	T1,RT.PT	;GET BYTE PTR
	IDPB	T2,T1		;NEW BYTE
	JUMPE	P1,POPP3	;NOT SYMBOLIC
	PUSH	P,W1		;SAVE FLAGS
	MOVX	W1,FS.FXF	;FULL WORD IN CASE BOUND
	JRST	RT.T2Z		;RESET T2,P3, AND RETURN
LNKOHN:	.ERR.	(MS,,V%L,L%F,S%F,OHN,<Overlay handler not loaded>)
LNKFSN:	.ERR.	(MS,,V%L,L%F,S%F,FSN,<FUNCT. subroutine not loaded>)

OV1LIT:

END	LNKOV1