home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
ZSYS
/
SIMTEL20
/
SYSLIB
/
SLIB1.LBR
/
SDIR06.Z80
< prev
next >
Wrap
Text File
|
2000-06-30
|
10KB
|
421 lines
;
; SYSLIB Module Name: SDIR06
; Author: Richard Conn
; Part of SYSLIB3 SDIR Series
; SYSLIB Version Number: 3.6
; Module Version Number: 1.5
public diralpha
MACLIB SDIRHDR.LIB
EXT SDMOVE,PRINT
;
; DIRALPHA -- ALPHABETIZES DIRECTORY PTED TO BY HL; BC CONTAINS
; THE NUMBER OF FILES IN THE DIRECTORY AND A = SORT FLAG
; (0=SORT BY FILE NAME/TYPE, <>0 = SORT BY FILE TYPE/NAME)
;
DIRALPHA:
LD (CMP$FLAG),A ; SET FLAG
LD A,B ; ANY FILES?
OR C
RET Z
PUSH HL ; SAVE REGS
PUSH DE
PUSH BC
LD (DIRBUF),HL ; SAVE PTR TO DIRECTORY
PUSH HL ; SAVE HL
LD H,B ; HL=BC=FILE COUNT
LD L,C
LD (N),HL ; SET "N"
POP HL
;
; SHELL SORT --
; THIS SORT ROUTINE IS ADAPTED FROM "SOFTWARE TOOLS"
; BY KERNIGAN AND PLAUGHER, PAGE 106. COPYRIGHT, 1976, ADDISON-WESLEY.
; ON ENTRY, BC=NUMBER OF ENTRIES
;
SORT:
EX DE,HL ; POINTER TO DIRECTORY IN DE
LD HL,(ORDER) ; PT TO ORDER TABLE
;
; SET UP ORDER TABLE; HL PTS TO NEXT ENTRY IN ORDER TABLE, DE PTS TO NEXT
; ENTRY IN DIRECTORY, BC = NUMBER OF ELEMENTS REMAINING
;
SORT1:
LD (HL),E ; STORE LOW-ORDER ADDRESS
INC HL ; PT TO NEXT ORDER BYTE
LD (HL),D ; STORE HIGH-ORDER ADDRESS
INC HL ; PT TO NEXT ORDER ENTRY
PUSH HL ; SAVE PTR
LD HL,ESIZE ; HL=NUMBER OF BYTES/ENTRY
ADD HL,DE ; PT TO NEXT DIR1 ENTRY
EX DE,HL ; DE PTS TO NEXT ENTRY
POP HL ; GET PTR TO ORDER TABLE
DEC BC ; COUNT DOWN
LD A,B ; DONE?
OR C
JP NZ,SORT1
;
; THIS IS THE MAIN SORT LOOP FOR THE SHELL SORT IN "SOFTWARE TOOLS" BY K&P
;
;
; SHELL SORT FROM "SOFTWARE TOOLS" BY KERNINGHAN AND PLAUGER
;
LD HL,(N) ; NUMBER OF ITEMS TO SORT
LD (GAP),HL ; SET INITIAL GAP TO N FOR FIRST DIVISION BY 2
; FOR (GAP = N/2; GAP > 0; GAP = GAP/2)
SRTL0:
OR A ; CLEAR CARRY
LD HL,(GAP) ; GET PREVIOUS GAP
LD A,H ; ROTATE RIGHT TO DIVIDE BY 2
RRA
LD H,A
LD A,L
RRA
LD L,A
; TEST FOR ZERO
OR H
JP Z,SDONE ; DONE WITH SORT IF GAP = 0
LD (GAP),HL ; SET VALUE OF GAP
LD (IVAL),HL ; SET I=GAP FOR FOLLOWING LOOP
; FOR (I = GAP + 1; I <= N; I = I + 1)
SRTL1:
LD HL,(IVAL) ; ADD 1 TO I
INC HL
LD (IVAL),HL
; TEST FOR I <= N
EX DE,HL ; I IS IN DE
LD HL,(N) ; GET N
LD A,L ; COMPARE BY SUBTRACTION
SUB E
LD A,H
SBC A,D ; CARRY SET MEANS I > N
JP C,SRTL0 ; DON'T DO FOR LOOP IF I > N
LD HL,(IVAL) ; SET J = I FOR FIRST SUBTRACTION OF GAP
LD (J),HL
; FOR (J = I - GAP; J > 0; J = J - GAP)
SRTL2:
LD HL,(GAP) ; GET GAP
EX DE,HL ; ... IN DE
LD HL,(J) ; GET J
LD A,L ; COMPUTE J - GAP
SUB E
LD L,A
LD A,H
SBC A,D
LD H,A
LD (J),HL ; J = J - GAP
JP C,SRTL1 ; IF CARRY FROM SUBTRACTIONS, J < 0 AND ABORT
LD A,H ; J=0?
OR L
JP Z,SRTL1 ; IF ZERO, J=0 AND ABORT
; SET JG = J + GAP
EX DE,HL ; J IN DE
LD HL,(GAP) ; GET GAP
ADD HL,DE ; J + GAP
LD (JG),HL ; JG = J + GAP
; IF (V(J) <= V(JG))
CALL ICOMPARE ; J IN DE, JG IN HL
; ... THEN BREAK
JP C,SRTL1
; ... ELSE EXCHANGE
LD HL,(J) ; SWAP J, JG
EX DE,HL
LD HL,(JG)
CALL ISWAP ; J IN DE, JG IN HL
; END OF INNER-MOST FOR LOOP
JP SRTL2
;
; SORT IS DONE -- RESTRUCTURE DIR1 IN SORTED ORDER IN PLACE
;
SDONE:
LD HL,(N) ; NUMBER OF ENTRIES
LD B,H ; ... IN BC
LD C,L
LD HL,(ORDER) ; PTR TO ORDERED POINTER TABLE
LD (PTPTR),HL ; SET PTR PTR
LD HL,(DIRBUF) ; PTR TO UNORDERED DIRECTORY
LD (PTDIR),HL ; SET PTR DIR BUFFER
; FIND PTR TO NEXT DIR1 ENTRY
SRTDN:
LD HL,(PTPTR) ; PT TO REMAINING POINTERS
EX DE,HL ; ... IN DE
LD HL,(PTDIR) ; HL PTS TO NEXT DIR ENTRY
PUSH BC ; SAVE COUNT OF REMAINING ENTRIES
; FIND PTR TABLE ENTRY
SRTDN1:
LD A,(DE) ; GET CURRENT POINTER TABLE ENTRY VALUE
INC DE ; PT TO HIGH-ORDER POINTER BYTE
CP L ; COMPARE AGAINST DIR1 ADDRESS LOW
JP NZ,SRTDN2 ; NOT FOUND YET
LD A,(DE) ; LOW-ORDER BYTES MATCH -- GET HIGH-ORDER POINTER BYTE
CP H ; COMPARE AGAINST DIR1 ADDRESS HIGH
JP Z,SRTDN3 ; MATCH FOUND
SRTDN2:
INC DE ; PT TO NEXT PTR TABLE ENTRY
DEC BC ; COUNT DOWN
LD A,C ; END OF TABLE?
OR B
JP NZ,SRTDN1 ; CONTINUE IF NOT
; FATAL ERROR -- INTERNAL ERROR; POINTER TABLE NOT CONSISTENT
FERR$PTR:
CALL PRINT
DB 0DH,0AH,'DIRALPHA Error',0
JP CPM
; FOUND THE POINTER TABLE ENTRY WHICH POINTS TO THE NEXT UNORDERED DIR1 ENTRY
; MAKE BOTH POINTERS (PTR TO NEXT, PTR TO CURRENT UNORDERED DIR1 ENTRY)
; POINT TO SAME LOCATION (PTR TO NEXT DIR1 ENTRY TO BE ORDERED)
SRTDN3:
LD HL,(PTPTR) ; GET PTR TO NEXT ORDERED ENTRY
DEC DE ; DE PTS TO LOW-ORDER POINTER ADDRESS
LD A,(HL) ; MAKE PTR TO NEXT UNORDERED DIR1 PT TO BUFFER FOR
LD (DE),A ; DIR1 ENTRY TO BE MOVED TO NEXT UNORDERED DIR1 POS
INC HL ; PT TO NEXT PTR ADDRESS
INC DE
LD A,(HL) ; MAKE HIGH POINT SIMILARLY
LD (DE),A
; COPY NEXT UNORDERED DIR1 ENTRY TO HOLD BUFFER
LD B,ESIZE ; B=NUMBER OF BYTES/ENTRY
LD HL,(PTDIR) ; PT TO ENTRY
LD DE,HOLD ; PT TO HOLD BUFFER
PUSH BC ; SAVE B=NUMBER OF BYTES/ENTRY
CALL SDMOVE
POP BC
; COPY TO-BE-ORDERED DIR1 ENTRY TO NEXT ORDERED DIR1 POSITION
LD HL,(PTPTR) ; POINT TO ITS POINTER
LD E,(HL) ; GET LOW-ADDRESS POINTER
INC HL
LD D,(HL) ; GET HIGH-ADDRESS POINTER
LD HL,(PTDIR) ; DESTINATION ADDRESS FOR NEXT ORDERED ENTRY
EX DE,HL ; HL PTS TO ENTRY TO BE MOVED, DE PTS TO DEST
PUSH BC ; SAVE B=NUMBER OF BYTES/ENTRY
CALL SDMOVE
POP BC
EX DE,HL ; HL PTS TO NEXT UNORDERED DIR1 ENTRY
LD (PTDIR),HL ; SET POINTER FOR NEXT LOOP
; COPY ENTRY IN HOLD BUFFER TO LOC PREVIOUSLY HELD BY LATEST ORDERED ENTRY
LD HL,(PTPTR) ; GET PTR TO PTR TO THE DESTINATION
LD E,(HL) ; GET LOW-ADDRESS POINTER
INC HL
LD D,(HL) ; HIGH-ADDRESS POINTER
LD HL,HOLD ; HL PTS TO HOLD BUFFER, DE PTS TO ENTRY DEST
CALL SDMOVE ; B=NUMBER OF BYTES/ENTRY
; POINT TO NEXT ENTRY IN POINTER TABLE
LD HL,(PTPTR) ; POINTER TO CURRENT ENTRY
INC HL ; SKIP OVER IT
INC HL
LD (PTPTR),HL
; COUNT DOWN
POP BC ; GET COUNTER
DEC BC ; COUNT DOWN
LD A,C ; DONE?
OR B
JP NZ,SRTDN
POP BC ; RESTORE REGS
POP DE
POP HL
RET ; DONE
;
; SWAP (Exchange) the pointers in the ORDER table whose indexes are in
; HL and DE
;
ISWAP:
PUSH HL ; SAVE HL
LD HL,(ORDER) ; ADDRESS OF ORDER TABLE - 2
LD B,H ; ... IN BC
LD C,L
POP HL
DEC HL ; ADJUST INDEX TO 0...N-1 FROM 1...N
ADD HL,HL ; HL PTS TO OFFSET ADDRESS INDICATED BY INDEX
; OF ORIGINAL HL (1, 2, ...)
ADD HL,BC ; HL NOW PTS TO POINTER INVOLVED
EX DE,HL ; DE NOW PTS TO POINTER INDEXED BY HL
DEC HL ; ADJUST INDEX TO 0...N-1 FROM 1...N
ADD HL,HL ; HL PTS TO OFFSET ADDRESS INDICATED BY INDEX
; OF ORIGINAL DE (1, 2, ...)
ADD HL,BC ; HL NOW PTS TO POINTER INVOLVED
LD C,(HL) ; EXCHANGE POINTERS -- GET OLD (DE)
LD A,(DE) ; -- GET OLD (HL)
EX DE,HL ; SWITCH
LD (HL),C ; PUT NEW (HL)
LD (DE),A ; PUT NEW (DE)
INC HL ; PT TO NEXT BYTE OF POINTER
INC DE
LD C,(HL) ; GET OLD (HL)
LD A,(DE) ; GET OLD (DE)
EX DE,HL ; SWITCH
LD (HL),C ; PUT NEW (DE)
LD (DE),A ; PUT NEW (HL)
RET
;
; ICOMPARE compares the entry pointed to by the pointer pointed to by HL
; with that pointed to by DE (1st level indirect addressing); on entry,
; HL and DE contain the numbers of the elements to compare (1, 2, ...);
; on exit, Carry Set means ((DE)) < ((HL)), Zero Set means ((HL)) = ((DE)),
; and Non-Zero and No-Carry means ((DE)) > ((HL))
;
ICOMPARE:
PUSH HL ; SAVE HL
LD HL,(ORDER) ; ADDRESS OF ORDER - 2
LD B,H ; ... IN BC
LD C,L
POP HL
DEC HL ; ADJUST INDEX TO 0...N-1 FROM 1...N
ADD HL,HL ; DOUBLE THE ELEMENT NUMBER TO POINT TO THE PTR
ADD HL,BC ; ADD TO THIS THE BASE ADDRESS OF THE PTR TABLE
EX DE,HL ; RESULT IN DE
DEC HL ; ADJUST INDEX TO 0...N-1 FROM 1...N
ADD HL,HL ; DO THE SAME WITH THE ORIGINAL DE
ADD HL,BC
EX DE,HL
;
; HL NOW POINTS TO THE POINTER WHOSE INDEX WAS IN HL TO BEGIN WITH
; DE NOW POINTS TO THE POINTER WHOSE INDEX WAS IN DE TO BEGIN WITH
; FOR EXAMPLE, IF DE=5 AND HL=4, DE NOW POINTS TO THE 5TH PTR AND HL
; TO THE 4TH POINTER
;
LD C,(HL) ; BC IS MADE TO POINT TO THE OBJECT INDEXED TO
INC HL ; ... BY THE ORIGINAL HL
LD B,(HL)
EX DE,HL
LD E,(HL) ; DE IS MADE TO POINT TO THE OBJECT INDEXED TO
INC HL ; ... BY THE ORIGINAL DE
LD D,(HL)
LD H,B ; SET HL = OBJECT PTED TO INDIRECTLY BY BC
LD L,C
;
; COMPARE DIR ENTRY PTED TO BY HL WITH THAT PTED TO BY DE;
; NO NET EFFECT ON HL, DE; RET W/CARRY SET MEANS DE<HL
; RET W/ZERO SET MEANS DE=HL
;
CMP$ENTRY:
LD A,(CMP$FLAG) ; GROUP BY FILE TYPE?
OR A
JP Z,CMP$FN$FT
;
; COMPARE BY FILE TYPE, FILE NAME, EXTENSION, AND USER (IN THAT ORDER)
;
CMP$FCB1:
PUSH HL
PUSH DE
LD BC,9 ; PT TO FT (8 BYTES + 1 BYTE FOR USER NUMBER)
ADD HL,BC
EX DE,HL
ADD HL,BC
EX DE,HL ; DE, HL NOW PT TO THEIR FT'S
LD B,3 ; 3 BYTES
CALL COMP ; COMPARE FT'S
POP DE
POP HL
RET NZ ; CONTINUE IF COMPLETE MATCH
PUSH HL
PUSH DE
INC HL ; PT TO FILE NAME
INC DE
LD B,8 ; 8 BYTES
CALL COMP ; COMPARE FN'S
POP DE
POP HL
RET NZ ; CONTINUE IF COMPLETE MATCH
PUSH HL
PUSH DE
LD BC,12 ; PT TO EXT (11 BYTES FOR FN/FT AND 1 BYTE FOR USER)
ADD HL,BC
EX DE,HL
ADD HL,BC
EX DE,HL ; DE, HL NOW PT TO THEIR EXT'S
LD A,(DE) ; COMPARE
CP (HL)
POP DE
POP HL
RET NZ
LD A,(DE) ; COMPARE USER NUMBERS
CP (HL)
RET
;
; COMPARE BY FILE NAME, FILE TYPE, EXTENSION, AND USER NUM (IN THAT ORDER)
;
CMP$FN$FT:
PUSH HL
PUSH DE
INC HL ; PT TO FN
INC DE
LD B,12 ; COMPARE FN, FT, EX
CALL COMP
POP DE
POP HL
RET NZ
LD A,(DE) ; COMPARE USER NUMBER
CP (HL)
RET
;
; COMP COMPARES DE W/HL FOR B BYTES; RET W/CARRY IF DE<HL
; MSB IS DISREGARDED
;
COMP:
LD A,(HL) ; GET (HL)
AND 7FH ; MASK MSB
LD C,A ; ... IN C
LD A,(DE) ; COMPARE
AND 7FH ; MASK MSB
CP C
RET NZ
INC HL ; PT TO NEXT
INC DE
DEC B ; COUNT DOWN
JP NZ,COMP
RET
;*************************************************************************
;
; BUFFERS
;
CMP$FLAG: ; 0=SORT BY FILE NAME/TYPE, ELSE BY TYPE/NAME
DS 1
HOLD:
DS 35 ; EXCHANGE HOLD BUFFER FOR FCB'S
PTPTR:
DS 2 ; POINTER POINTER
PTDIR:
DS 2 ; DIRECTORY POINTER
IVAL:
DS 2 ; INDEXES FOR SORT
J:
DS 2
JG:
DS 2
N:
DS 2 ; NUMBER OF ELEMENTS TO SORT
GAP:
DS 2 ; BINARY GAP SIZE
END