home *** CD-ROM | disk | FTP | other *** search
- ; SORTV.ASM ver 1.4
- ; by Ward Christensen
- ; (revised 6/29/81)
- ;
- ;Simple sort program for sorting lists of names,
- ;or any other variable length file, with CR/LF
- ;delimited records.
- ;
- ;This is a "simple" program: FILE MUST FIT IN MEMORY.
- ;
- ;06/29/81 Cleaned up file and re-tabified it. (KBP)
- ;
- ;06/22/81 Changed so MAC is not needed. Changed so alternate or
- ; standard CP/M may be selected. By Ted Shapin.
- ;
- ;01/03/81 Change stack init. By Keith Petersen, W8SDZ
- ;
- ;11/15/80 Add @ command (WLC)
- ;
- ;10/24/80 Originally written by Ward Christensen
- ;
- ;FORMAT:
- ; SORTV input-name output-name
- ; OR SORTV name
- ;
- ;If the second format is used, the file is read into
- ;memory, sorted, erased, created, and written back.
- ;
- ; The sort will be based on the first characters
- ; in the file, unless the command is followed by
- ; an "@" sign, then a string (1 or more characters)
- ; to skip. If these are present, the line will be
- ; sorted starting after one of these characters.
- ;
- ;Example: SORTV NAMES.SUB @.
- ;
- ;Will sort NAMES.SUB by filetype, since it skips past
- ;the "." before doing the compare.
- ;
- EOF EQU 1AH
- CR EQU 0DH
- LF EQU 0AH
- ;
- BIAS EQU 0 ;0 FOR STANDARD CP/M, 4200H FOR ALTERNATE CP/M
- ;
- ;BDOS/CBIOS EQUATES (VERSION 10)
- ;
- RDCON EQU 1
- WRCON EQU 2
- PRINT EQU 9
- RDCONBF EQU 10
- CONST EQU 11
- OPEN EQU 15
- CLOSE EQU 16
- SRCHF EQU 17
- SRCHN EQU 18
- ERASE EQU 19
- READ EQU 20
- WRITE EQU 21
- MAKE EQU 22
- REN EQU 23
- STDMA EQU 26
- BDOS EQU 5+BIAS
- FCB EQU 5CH+BIAS
- FCB2 EQU 6CH+BIAS
- FCBEXT EQU FCB+12
- FCBRNO EQU FCB+32
- ;
- ORG 100H+BIAS
- ;
- ;INIT LOCAL STACK
- ;
- LXI SP,STACK
- ;
- CALL START
- DB 'SORTV rev 1.3'
- DB CR,LF,'$'
- ;
- START POP D ;GET ID
- MVI C,PRINT
- CALL BDOS ;PRINT ID
- ;
- ;START OF PROGRAM EXECUTION
- ;
- CALL SVSKIP ;SAVE SKIP INFO
- CALL CKNAMES ;SEE THAT 2 NAMES ARE THERE
- CALL OPENIN ;OPEN INPUT FILE
- CALL READN ;READ THE NAMES
- CALL SORTN ;SORT THE NAMES
- CALL WRITEN ;WRITE THE NAMES
- CALL ERXIT
- DB '++DONE++$'
- ;
- ;====> SUBROUTINES
- ; ----------------
- ;
- ;====> SAVE "SKIP TO" INFORMATION
- ;
- SVSKIP LXI H,81H+BIAS
- ;
- SVSKL MOV A,M
- ORA A
- RZ ;NO 'SKIP TO'
- CPI '@' ;SKIP DELIMITER?
- INX H
- JNZ SVSKL
- LXI D,SKIPC ;CHARS TO SKIP
- ;
- SVSKL2 MOV A,M
- STAX D
- INX H
- INX D
- ORA A
- JNZ SVSKL2
- RET
- ;
- ;====> CHECK THAT 2 NAMES WERE SUPPLIED
- ;
- CKNAMES LDA FCB+1
- CPI ' '
- JZ NONAME
- LDA FCB2+1
- CPI ' '
- JZ SAMENAM
- CPI '@' ;SKIP PARM?
- JZ SAMENAM
- LXI H,FCB2
- LXI D,OUTNAME
- LXI B,12
- CALL MOVER
- RET
- ;
- ;OUTPUT NAME = INPUT NAME
- ;
- SAMENAM LXI H,FCB
- LXI D,OUTNAME
- LXI B,12
- CALL MOVER
- RET
- ;
- NONAME CALL ERXIT
- DB '++Error - ',CR,LF
- DB 'Command format requires an '
- DB 'input name, and an output name.$'
- ;
- ;====> OPEN THE INPUT FILE
- ;
- OPENIN PUSH B
- PUSH D
- PUSH H
- MVI C,OPEN
- LXI D,FCB
- CALL BDOS
- POP H
- POP D
- POP B
- INR A
- RNZ ;SUCCESSFUL? RETURN
- CALL ERXIT
- DB '++Input file not found$'
- ;
- ;====> READ IN THE NAMES
- ;
- READN LXI H,SBUFF ;TO FIRST NAME
- ;
- READNL CALL READL ;READ ONE LINE
- RC ;GOT EOF, RETURN
- CALL CHAIN ;CHAIN THINGS TOGETHER
- JMP READNL
- ;
- ;====> READ ONE LINE
- ;
- READL SHLD CURR ;SAVE CURR LINE PTR
- XRA A ;GET 0
- MOV M,A ;INIT FORWARD
- INX H ; POINTER
- MOV M,A ; TO
- INX H ; 0
- LXI D,SKIPC ;TO CK SKIP CHARS PRESENT
- ;
- READLLP LDA BDOS+2 ;ARE WE
- DCR A ; OVER-
- CMP H ; FLOW-
- JZ OFLO ; ING?
- PUSH D
- PUSH H
- LXI H,EXTFCB
- CALL RDBYTE ;READ A BYTE
- POP H
- POP D
- CPI EOF ;SET CARRY
- STC ; AND RETURN
- RZ ; IF EOF
- MOV M,A ;STORE CHAR
- ;TEST FOR SKIP CHAR FOUND
- MOV B,A ;SAVE FOR COMPARE
- LDAX D
- ORA A ;NO MORE SKIP CHARS?
- JZ READLNS ;NO MORE
- CMP B ;A SKIP CHAR?
- JNZ READLNS ;NO, KEEP TRYIN.
- INX D ;TO NEXT SKIP CHAR
- ;
- READLNS INX H ;POINT TO NEXT
- MOV A,B ;GET CHAR
- CPI CR ;END OF LINE?
- JNZ READLLP ; NO, LOOP.
- PUSH D
- PUSH H
- LXI H,EXTFCB
- CALL RDBYTE ;GOBBLE UP LF
- POP H
- POP D
- LDAX D ;GET SKIP CHAR END
- ORA A ;TEST IT AND SET "NO EOF"
- RZ
- ;ERROR - NO SKIP CHAR
- LHLD CURR
- INX H ;SKIP
- INX H ; POINTER
- ;
- ERPLP MOV E,M
- PUSH B
- PUSH D
- PUSH H
- MVI C,WRCON
- CALL BDOS
- POP H
- POP D
- POP B
- MOV A,M
- INX H
- CPI CR
- JNZ ERPLP
- CALL ERXIT
- DB LF,'++NO SKIP CHAR FOUND++$'
- ;
- OFLO CALL ERXIT
- DB '++File won''t fit in memory$'
- ;
- ;====> CHAIN RECORDS TOGETHER
- ;
- CHAIN PUSH H ;SAVE POINTER
- LHLD CURR ;GET CURRENT
- XCHG ; TO DE
- LHLD PREV ;PREV TO HL
- MOV M,E ;MOVE CURR
- INX H ; TO
- MOV M,D ; PREV
- XCHG ;THEN MOVE
- SHLD PREV ; PREV TO CURR
- POP H
- RET
- ;
- ;====> SORT THE NAMES
- ;
- SORTN XRA A ;SHOW NO
- STA SWAPS ; SWAPS
- LXI H,PTR ;POINT PREV
- SHLD PREV ; TO PTR
- LHLD PTR ;POINT TO FIRST
- ;
- ;HANDLE WIERD CASE OF ONLY ONE NAME
- ;
- MOV A,M ;GET POINTER
- INX H ;POINT TO NEXT
- ORA M ;OR TOGETHER
- DCX H ;BACK UP
- RZ ;RETURN IF ONLY ONE
- ;
- SORTL CALL CMPR ;COMPARE ENTRIES
- CC SWAP ;SWAP IF WRONG ORDER
- CALL NEXT ;POINT TO NEXT
- JNC SORTL ;LOOP IF MORE
- LDA SWAPS ;ANY
- ORA A ; SWAPS?
- JNZ SORTN ;YES, LOOP
- RET ;NO, RETURN
- ;
- ;----> COMPARE TWO NAMES
- ;
- CMPR PUSH H ;SAVE POINTER
- MOV E,M ;GET NEXT
- INX H ; POINTER
- MOV D,M ; TO DE
- INX D ;ALIGN POINTERS
- ;
- ;SKIP IF NECESSARY
- ;
- LXI B,SKIPC
- ;
- TSTSKIP LDAX B
- ORA A
- JZ COMPL ;NO SKIP
- INX B
- ;
- SKIP1 INX H
- CMP M
- JNZ SKIP1
- XCHG ;SWAP
- ;
- SKIP2 INX H
- CMP M
- JNZ SKIP2
- XCHG ;PUT THINGS BACK
- JMP TSTSKIP
- ;
- COMPL INX D ;TO NEXT
- INX H ;TO NEXT
- LDAX D ;GET ONE
- CMP M ;COMPARE
- JNZ COMPNE ;NO COMPARE
- CPI CR ;END?
- JNZ COMPL ; NO, LOOP
- ;
- COMPH POP H ;RESTORE POINTER
- RET ;THEY ARE EQUAL
- ;
- ;COMPARE NOT EQUAL - SEE IF END OF ELEMENT,
- ;AND IF SO, CALL THEM EQUAL
- ;
- COMPNE MOV A,M
- CPI CR
- JZ COMPH
- LDAX D
- CMP M
- JMP COMPH ;CARRY SET AS APPROP
- ;
- ;----> SWAP ENTRIES
- ;
- ;LOGIC: PTR POINTS TO SOME ENTRY, WHICH POINTS
- ;TO ANOTHER ENTRY. THEY ARE NOT IN ORDER. THUS:
- ;POINT PTR TO THE SECOND, POINT THE SECOND TO
- ;THE FIRST, AND POINT THE FIRST TO WHAT THE
- ;SECOND USED TO POINT TO.
- ;
- SWAP MVI A,1
- STA SWAPS ;SHOW WE SWAPPED
- ;BC=NEXT
- MOV C,M
- INX H
- MOV B,M
- DCX H
- ;CHAIN CURRENT TO NEXT ONES CHAIN
- LDAX B
- MOV M,A
- INX B
- INX H
- LDAX B
- MOV M,A
- DCX B
- DCX H
- ;SAVE CURRENT POINTER IN DE
- XCHG
- ;GET POINTER TO PREV
- LHLD PREV
- ;POINT PREV TO NEXT
- MOV M,C
- INX H
- MOV M,B
- ;STORE CURR IN NEXT
- MOV A,E
- STAX B
- INX B
- MOV A,D
- STAX B
- DCX B
- ;RESTORE CURRENT POINTER
- XCHG
- RET ;CURRENT POINTER IN DE
- ;
- ;----> GET NEXT ETRY, CARRY IF NOT 2 MORE
- ;
- NEXT SHLD PREV ;SAVE POINTER
- MOV E,M
- INX H
- MOV D,M
- XCHG ;HL= NEXT
- MOV A,H ;CARRY ON
- ORA L ; IF HL
- STC ; =
- RZ ; 0
- MOV A,M ;GET
- INX H ;SEE IF THERE
- ORA M ; IS
- DCX H ; ANOTHER
- RNZ ;THERE IS ANOTHER
- STC ;SHOW NOT 2 TO SWAP
- RET
- ;
- ;====> WRITE THE NAMES
- ;
- WRITEN LXI H,0 ;INIT
- SHLD EXTFCB+2 ; EFCB
- XRA A ;INIT
- STA FCBEXT ; THE
- STA FCBRNO ; FCB
- ;RESTORE NAME
- LXI H,OUTNAME
- LXI D,FCB
- LXI B,12
- CALL MOVER
- PUSH B
- PUSH D
- PUSH H
- MVI C,ERASE
- LXI D,FCB
- CALL BDOS
- POP H
- POP D
- POP B
- PUSH B
- PUSH D
- PUSH H
- MVI C,MAKE
- LXI D,FCB
- CALL BDOS
- POP H
- POP D
- POP B
- INR A ;MAKE OK?
- JZ BADOUT ; NO, ERROR
- LHLD PTR ;GET FIRST
- ;
- WNLP CALL WRITEL ;WRITE ONE LINE
- JNC WNLP ;LOOP IF MORE
- MVI A,EOF ;WRITE EOF CHAR
- PUSH H
- LXI H,EXTFCB
- CALL WRBYTE
- POP H
- LXI H,EXTFCB ;FLUSH
- CALL FLUSH ; BUFFERS
- PUSH B
- PUSH D
- PUSH H
- MVI C,STDMA ;RESET DMA
- LXI D,80H+BIAS
- CALL BDOS
- POP H
- POP D
- POP B
- PUSH B
- PUSH D
- PUSH H
- MVI C,CLOSE
- LXI D,FCB
- CALL BDOS
- POP H
- POP D
- POP B
- CALL ERXIT ; AND EXIT
- DB '++DONE++$'
- ;
- WRITEL PUSH H ;SAVE POINTER
- INX H
- ;
- WRLP INX H ;TO NEXT CHAR
- MOV A,M ;GET CHAR
- PUSH H
- LXI H,EXTFCB
- CALL WRBYTE ;WRITE IT
- POP H
- MOV A,M ;SEE IF END
- CPI CR ; OF LINE
- JNZ WRLP ;NO, LOOP
- MVI A,LF ;OTHERWISE
- PUSH H
- LXI H,EXTFCB
- CALL WRBYTE ;WRITE LF
- POP H
- POP H ;GET POINTER
- MOV E,M ;GET
- INX H ; FORWARD
- MOV D,M ; POINTER
- XCHG ;PUT IT IN HL
- MOV A,H ;IS POINTER
- ORA L ; ZERO?
- RNZ ;NO, RETURN
- STC ;CARRY SHOWS END
- RET
- ;
- BADOUT CALL ERXIT
- DB '++Can''t make output file$'
- ;
- ;FOLLOWING FROM 'EQU10.LIB'---->
- ;
- ;MOVE, COMPARE SUBROUTINES
- ;
- MOVER MOV A,M
- STAX D
- INX H
- INX D
- DCX B
- MOV A,B
- ORA C
- JNZ MOVER
- RET
- ;
- ; FROM EQU10.LIB: AS OF 07/19/80
- ;
- ;RDBYTE, HL POINTS TO EXTENDED FCB:
- ;
- ; 2 BYTE BUFFER ADDR
- ; 2 BYTE "BYTES LEFT" (INIT TO 0)
- ; 1 BYTE BUFFER SIZE (IN PAGES)
- ; 2 BYTE FCB ADDRESS
- ;
- RDBYTE MOV E,M
- INX H
- MOV D,M ;GET BUFFER ADDR
- INX H
- MOV C,M
- INX H
- MOV B,M ;BC = BYTES LEFT
- MOV A,B ;GET COUNT
- ORA C
- JNZ RDBNORD ;NO READ
- ;
- INX H ;TO BUFFER SIZE
- MOV A,M ;GET COUNT
- ADD A ;MULTIPLY BY 2
- MOV B,A ;SECTOR COUNT IN B
- INX H ;TO FCB
- PUSH H ;SAVE FCB POINTER
- MOV A,M ;GET..
- INX H
- MOV H,M ;..ADDR..
- MOV L,A ;..TO HL
- ;
- RDBLP MVI A,1AH ;GET EOF CHAR
- STAX D ;SAVE IN CASE EOF
- PUSH D ;SAVE DMA ADDR
- PUSH H ;SAVE FCB ADDR
- PUSH B
- PUSH D
- PUSH H
- MVI C,STDMA
- CALL BDOS ;SET DMA ADDR
- POP H
- POP D
- POP B
- POP D ;GET FCB
- PUSH B
- PUSH D
- PUSH H
- MVI C,READ
- CALL BDOS
- POP H
- POP D
- POP B
- ORA A
- POP H ;HL=DMA, DE=FCB
- JNZ RDBRET ;GOT EOF
- MOV A,L
- ADI 80H ;TO NEXT BUFF
- MOV L,A
- MOV A,H
- ACI 0
- MOV H,A
- XCHG ;DMA TO DE, FCB TO HL
- DCR B ;MORE SECTORS?
- JNZ RDBLP ;YES, MORE
- ;
- RDBRET POP H ;GET FCB POINTER
- DCX H ;TO LENGTH
- MOV A,M ;GET LENGTH
- DCX H ;TO COUNT
- MOV M,A ;SET PAGE COUNT
- DCX H ;TO LO COUNT
- DCX H ;TO HI FCB
- DCX H ;TO EFCB START
- JMP RDBYTE ;LOOP THRU AGAIN
- ;
- RDBNORD INX H ;TO LENGTH
- MOV A,M ;GET LENGTH (PAGES)
- XCHG ;BUFF TO HL
- ADD H
- MOV H,A ;HL = END OF BUFF
- MOV A,L
- SUB C
- MOV L,A
- MOV A,H
- SBB B
- MOV H,A ;HL = DATA POINTER
- MOV A,M ;GET BYTE
- XCHG ;EFCB BACK TO HL
- CPI 1AH ;EOF?
- RZ ;YES, LEAVE POINTERS
- DCX B ;DECR COUNT
- DCX H ;"BYTES LEFT"
- MOV M,B
- DCX H
- MOV M,C ;STORE BACK COUNT
- RET
- ;
- ;SAMPLE EFCB:
- ;
- ;EFCB DW BUFF ;BUFFER ADDR
- ; DW 0 ;BYTES LEFT (OR TITE)
- ; DB 20 ;BUFFER SIZE (IN PAGES)
- ; DW FCB ;FCB ADDRESS
- ;
- ;
- ;WRBYTE, HL POINTS TO EXTENDED FCB:
- ;
- ; 2 BYTE BUFFER ADDR
- ; 2 BYTE "BYTES LEFT" (INIT TO 0)
- ; 1 BYTE BUFFER SIZE (IN PAGES)
- ; 2 BYTE FCB ADDRESS
- ;
- WRBYTE MOV E,M
- INX H
- MOV D,M ;DE=BUF ADDR
- INX H
- MOV C,M
- INX H
- MOV B,M ;BC=BYTES IN BUFF
- PUSH D ;SAVE FCB
- XCHG
- DAD B ;TO NEXT BYTE
- MOV M,A ;STORE IT
- INX B ;ONE MORE
- XCHG
- POP D
- ;
- ;SEE IF BUFFER IS FULL
- ;
- INX H ;GET
- MOV A,M ; SIZE
- CMP B ;FULL?
- JNZ WRBNOWR ;NO WRITE
- ;
- ADD A ;MULTIPLY BY 2
- MOV B,A ;SECTOR COUNT IN B
- INX H ;TO FCB
- PUSH H ;SAVE FCB POINTER
- MOV A,M ;GET..
- INX H ;..FCB..
- MOV H,M ;..ADDR..
- MOV L,A ;..TO HL
- ;
- WRBLP PUSH D ;SAVE DMA ADDR
- PUSH H ;SAVE FCB ADDR
- PUSH B
- PUSH D
- PUSH H
- MVI C,STDMA
- CALL BDOS ;SET DMA ADDR
- POP H
- POP D
- POP B
- POP D ;GET FCB
- PUSH B
- PUSH D
- PUSH H
- MVI C,WRITE
- CALL BDOS
- POP H
- POP D
- POP B
- ORA A
- POP H ;HL=DMA, DE=FCB
- JNZ WRBERR ;GOT ERR
- MOV A,L
- ADI 80H ;TO NEXT BUFF
- MOV L,A
- MOV A,H
- ACI 0
- MOV H,A
- XCHG ;DMA TO DE, FCB TO HL
- DCR B ;MORE SECTORS?
- JNZ WRBLP ;YES, MORE
- ;
- WRBRET POP H ;GET FCB POINTER
- DCX H ;TO LENGTH
- DCX H ;TO COUNT
- MVI M,0 ;SET 0 TO WRITE
- DCX H ;TO LO COUNT
- MVI M,0
- PUSH B
- PUSH D
- PUSH H
- MVI C,STDMA
- LXI D,80H+BIAS
- CALL BDOS
- POP H
- POP D
- POP B
- RET
- ;
- WRBNOWR DCX H ;TO LENGTH
- MOV M,B ;SET NEW LENGTH
- DCX H
- MOV M,C
- RET
- ;
- ;FLUSH THE EFCB BUFFERS
- ;
- FLUSH MOV E,M
- INX H
- MOV D,M ;DE=BUF ADDR
- INX H
- MOV C,M
- INX H
- MOV B,M ;BC=BYTES IN BUFF
- INX H ;TO COUNT
- MOV A,B
- ORA C
- RZ ;NOTHING TO WRITE
- MOV A,C ;GET LOW COUNT
- ADD A ;SHIFT HIGH TO CARRY
- MOV A,B ;GET LOW COUNTAL
- RAL ;MULT BY 2, + CARRY
- INR A ;FUDGE FOR PARTIAL SECT
- MOV B,A ;SAVE SECTOR COUNT
- INX H ;TO FCB
- MOV A,M
- INX H
- MOV H,M
- MOV L,A ;HL=FCB
- ;
- FLUSHL PUSH B
- PUSH D
- PUSH H
- MVI C,STDMA
- CALL BDOS
- POP H
- POP D
- POP B
- XCHG
- PUSH B
- PUSH D
- PUSH H
- MVI C,WRITE
- CALL BDOS
- POP H
- POP D
- POP B
- XCHG
- ORA A
- JNZ WRBERR
- PUSH H
- LXI H,80H
- DAD D
- XCHG
- POP H
- DCR B
- JNZ FLUSHL
- XCHG
- PUSH B
- PUSH D
- PUSH H
- MVI C,CLOSE
- CALL BDOS
- POP H
- POP D
- POP B
- INR A
- RNZ
- CALL ERXIT
- DB '++OUTPUT FILE CLOSE ERROR ++$'
- ;
- WRBERR CALL ERXIT
- DB '++OUTPUT FILE WRITE ERROR++$'
- ;
- ;EXIT WITH ERROR MESSAGE
- ;
- MSGEXIT EQU $ ;EXIT W/"INFORMATIONAL" MSG
- ;
- ERXIT POP D ;GET MSG
- MVI C,PRINT
- CALL BDOS
- ;
- ;EXIT, RESTORING STACK AND RETURN
- ;
- EXIT JMP 0+BIAS
- ;
- ;====> START OF WORK AREA
- ;
- EXTFCB DW DKBUF
- DW 0
- DB 4
- DW FCB
- PREV DW PTR ;POINTER TO PREV POINTER
- SKIPC DB 0 ;SKIP CHARS END
- DS 8 ;VARIABLE SKIP CHARS
- ;
- DS 100 ;STACK AREA
- STACK EQU $
- ;
- OUTNAME DS 12 ;OUTPUT FILENAME
- SWAPS DS 1
- CURR DS 2
- PTR DS 2 ;POINTER TO FIRST NAME
- ;
- ORG ($+255) AND 0FF00H ;TO PAGE
- ;
- DKBUF DS 256*4 ;4 PAGES OF BUFFER
- SBUFF DS 0 ;NAMES READ IN HERE
- ;
- END