Trailing-Edge
-
PDP-10 Archives
-
decuslib10-08
-
43,50501/lnklst.mac
There are no other files named lnklst.mac in the archive.
TITLE LNKLST NODE POINTER MANIPULATION IN DOUBLY LINKED LISTS
SUBTTL ERNIE PETRIDES, WESLEYAN UNIVERSITY, JANUARY, 1979
;IMPORTANT INFORMATION FOR THE USER:
; UNLIKE MOST LINKED LIST IMPLEMENTATIONS WHERE ONE HALF
; IS THE LINK AND THE OTHER IS THE DATA OR POINTER TO IT, THESE
; ROUTINES OPERATE ON DOUBLE-LINK FORWARD/BACKWARD LINKED LISTS
; WHERE THE NODES ARE ASSUMED TO BE MULTI-WORD BLOCKS. THE 1ST
; (OR LINK) WORD CONTAINS A POINTER TO THE PREVIOUS NODE IN THE
; LEFT HALF AND A POINTER TO THE NEXT NODE OF THE LIST IN THE
; RIGHT HALF. THIS ALLOWS FORWARD OR BACKWARD SCANNING OF THE
; STRUCTURE AND COMPLETE SINGLE NODE REMOVAL. AT ALL TIMES, A
; ZERO POINTER SPECIFIES NO LINK (WHOSE POINTERS ARE ALSO DEFINED
; TO BE ZERO) AND THEREFORE AC 0 CAN NEVER BE LINKED (OR ACCIDENTALLY
; MODIFIED). ALL POINTERS ARE MEMORY ADDRESSES AND ONLY LINKAGE
; WORDS ARE MODIFIED. A WORKING STACK DEPTH OF TWO IS EXPECTED
; BY EACH LINKED LIST ROUTINE. FOLLOWING IS A DESCRIPTION OF THE
; ARGUMENTS PASSED IN AC 16:
;
; ROUTINE SENT RETURNED
; LNK LEFT NODE ADR,,RIGHT NODE ADR (SAME AS SENT)
; REM (IGNORED),,NODE ADDRESS NODE'S PREVIOUS LINKAGE
; INR NEW NODE ADR,,LINKED NODE ADR NEW NODE'S LINKAGE
; INL NEW NODE ADR,,LINKED NODE ADR NEW NODE'S LINKAGE
; APR NEW NODE ADR,,ANY NODE ADR NEW NODE'S LINKAGE
; APL NEW NODE ADR,,ANY NODE ADR NEW NODE'S LINKAGE
SUBTTL DEFINITIONS AND PARAMETERS
SALL ;MAKE CLEAN LISTINGS
TWOSEG ;AND A TWO-SEGMENT PROGRAM
ENTRY LL$LNK,LL$REM,LL$INR,LL$INL,LL$APR,LL$APL
RELOC 400000 ;BUT PUT EVERTHING IN THE HISEG
A==16 ;ARGUMENT PASSER
P==17 ;PUSH DOWN STACK POINTER
ALL==777777 ;HALF WORD MASK FOR TESTING FOR ZERO LINKS
LNKMAX==^D1000 ;MAXIMUM NUMBER OF END SEARCHES ON APPEND
;(TO AVOID INFINITE LOOP ON CIRCULAR LIST)
SUBTTL LINKED LIST ROUTINES --- LNK,REM,INX
;LINKED LIST ROUTINE TO LINK LEFT NODE TO RIGHT NODE
LL$LNK: PUSH P,A ;SAVE LEFT-NODE-ADR,,RIGHT-NODE-ADR
TRNE A,ALL ;AS LONG AS RIGHT NODE ADR IS GIVEN,
HLR A,(A) ; LOAD RIGHT NODE'S LEFT LINK
TRNE A,ALL ;AS LONG AS THERE REALLY IS ONE,
HLLZS (A) ; ZERO ITS RIGHT NODE POINTER
HLRZS A ;PUT LEFT NODE ADR IN RIGHT
TRNE A,ALL ;AS LONG AS LEFT NODE ADR IS GIVEN,
HRR A,(A) ; LOAD LEFT NODE'S RIGHT LINK
TRNE A,ALL ;AS LONG AS THERE REALLY IS ONE,
HRRZS (A) ; ZERO ITS LEFT NODE POINTER
POP P,A ;RESTORE ORIGINAL LEFT,,RIGHT ARGS
TRNE A,ALL ;AS LONG AS THERE IS A RIGHT PNTR,
HLLM A,(A) ; RE-LINK ITS LEFT SUCCESSOR
MOVSS A ;SWAP LINKAGE POINTERS
TRNE A,ALL ;AS LONG AS THERE IS A LEFT PNTR,
HLRM A,(A) ; RE-LINK ITS RIGHT SUCCESSOR
MOVSS A ;RE-SWAP LINKAGE POINTERS
POPJ P, ;AND RETURN TO CALLER
;LINKED LIST ROUTINE TO REMOVE NODE FROM LIST
LL$REM: MOVEI A,(A) ;CLEAR LEFT HALF OF ARG
TRNN A,ALL ;MAKE SURE WE'VE GOT AN ADR
POPJ P, ;OTHERWISE, JUST RETURN A ZERO
PUSH P,A ;SAVE ADR OF NODE TO BE REMOVED
MOVE A,(A) ;LOAD THE NODE'S LINKAGE
TRNE A,ALL ;IF THERE IS A RIGHT SUCCESSOR,
HLLM A,(A) ; REPLACE ITS LEFT WITH OURS
MOVSS A ;SWAP LINKAGE POINTERS
TRNE A,ALL ;IF THERE IS A LEFT SUCCESSOR,
HLRM A,(A) ; REPLACE ITS RIGHT WITH OURS
MOVSS A ;RE-SWAP LINKAGE POINTERS
EXCH A,(P) ;SAVE THEM AND RECOVER NODE ADR
SETZM (A) ;CLEAR THE NODE'S LINKAGE
POP P,A ;BUT PROVIDE IT FOR CALLER
POPJ P, ;RETURN
;HERE FOR EXIT OF BOTH INSERT AND APPEND ROUTINES
LL$INX: HLRZS A ;PUT NEW NODE ADR IN RIGHT HALF
JUMPE A,.+4 ;CHECK TO SEE IF IT'S REALLY THERE
POP P,(A) ;ENTER ITS LINKAGE IF IT REALLY IS
MOVE A,(A) ;AND PROVIDE IT TO CALLER
POPJ P, ;AND RETURN
POP P,A ;OTHERWISE, JUST PROVIDE IT TO CALLER
POPJ P, ;AND RETURN
SUBTTL LINKED LIST ROUTINES --- INS,APP (BOTH R AND L)
;THE FOLLOWING MACRO GENERATES CODE FOR BOTH RIGHT AND LEFT ROUTINES
;
DEFINE RLGEN (DIR)<
IFG DIR,<
LL$APR:>;LINKED LIST ROUTINE TO APPEND NODE TO THE RIGHT END OF LIST
IFL DIR,<
LL$APL:>;LINKED LIST ROUTINE TO APPEND NODE TO THE LEFT END OF LIST
TRNN A,ALL ;MAKE SURE WE HAVE A LEGIT NODE
IFG DIR,< JRST LL$INR> ;OTHERWISE, DO DUMMY INSERT
IFL DIR,< JRST LL$INL> ;OTHERWISE, DO DUMMY INSERT
PUSH P,A ;FIRST SAVE THE ARGS ON STACK
MOVEI A,LNKMAX ;LOAD MAX NUMBER OF END SEARCHES
EXCH A,(P) ;PUT IT ON STACK AND RECOVER ARGS
PUSH P,A ;HEAD OF LOOP--SAVE THIS POSITION
IFG DIR,<HRR A,(A)> ;LOAD NEXT RIGHT LINK
IFL DIR,<HLR A,(A)> ;LOAD NEXT LEFT LINK
TRNE A,ALL ;REACHED END OF LIST?
SOSG -1(P) ;NO--BUT RUN OUT OF TIME?
JRST .+3 ;YES FOR EITHER--EXIT FROM LOOP
MOVEM A,(P) ;OTHERWISE, SAVE THIS POSITION
JRST .-5 ;AND LOOP TO LOAD NEXT LINK
POP P,A ;HERE WHEN DONE--RELOAD LAST LINK
POP P,(P) ;ADJUST STACK POINTER (RID COUNTER)
;FALL THROUGH TO INSERT
IFG DIR,<
LL$INR:>;LINKED LIST ROUTINE TO INSERT NODE TO THE RIGHT OF GIVEN NODE
IFL DIR,<
LL$INL:>;LINKED LIST ROUTINE TO INSERT NODE TO THE LEFT OF GIVEN NODE
PUSH P,A ;SAVE NEW-NODE-ADR,,OLD-NODE-ADR
TRNN A,ALL ;SEE IF OLD NODE ADR IS GIVEN
TLZA A,ALL ;USE ZERO LINK IF NOT
IFG DIR,< HRL A,(A) ;ELSE LOAD ITS RIGHT LINK
MOVSS A> ;SWAP POINTERS TO CORRECT POSITION
IFL DIR,< HLL A,(A)> ;ELSE LOAD ITS LEFT LINK
EXCH A,(P) ;SAVE LINKAGE AND RECOVER ARGS
TRNE A,ALL ;CHECK OLD NODE ADR AGAIN
IFG DIR,< HLRM A,(A) ;LINK NODE TO US IF GIVEN
HRR A,(P) ;LOAD OUR RIGHT NODE POINTER
TRNE A,ALL ;CHECK ON OUR RIGHT SUCCESSOR
HLLM A,(A)> ;LINK IT TO US IF WE'VE GOT ONE
IFL DIR,< HLLM A,(A) ;LINK NODE TO US IF GIVEN
HLR A,(P) ;LOAD OUR LEFT NODE POINTER
TRNE A,ALL ;CHECK ON OUR LEFT SUCCESSOR
HLRM A,(A)> ;LINK IT TO US IF WE'VE GOT ONE
JRST LL$INX ;DO IDENTICAL EXIT ROUTINE
>;END OF RLGEN MACRO
PAGE ;FOR NICE LISTING FORMAT
RLGEN +1 ;GENERATE RIGHT INSERT AND APPEND ROUTINES
RLGEN -1 ;GENERATE LEFT INSERT AND APPEND ROUTINES
END