home *** CD-ROM | disk | FTP | other *** search
- ; SORTV.ASM ver 1.2
- ; by Ward Christensen
- ; (revised 1/3/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.
- ;
- ;--->NEEDS MAC TO ASSEMBLE<---
- ;
- ;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.
- ;
- ;EX: 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
- ;
- ;(FROM EQU10.LIB...)
- ;
- MF SET 0 ;SHOW MOVE NOT REQUESTED
- CF SET 0 ;SHOW COMP NOT REQUESTED
- ;
- ;DEFINE SOME MACROS TO MAKE THINGS EASIER
- ;
- ;DEFINE DATA MOVE MACRO: MOVE from,to,length
- ; from may be addr, or quoted string
- ;
- MOVE MACRO ?F,?T,?L
- MCSUB ?F,?T,?L ;;HANDLE ARGS
- CALL MOVER
- MF SET -1 ;;SHOW EXPANSION
- ENDM
- ;
- ;COMPARE MACRO
- COMP MACRO ?F,?T,?L
- MCSUB ?F,?T,?L ;;HANDLE ARGS
- CALL COMPR
- CF SET -1 ;;SHOW EXPANSION
- ENDM
- ;
- ;MCSUB - HANDLES MOVE, COMPARE ARGUMENTS
- MCSUB MACRO ?F,?T,?L
- IF NOT NUL ?F
- IRPC ?C,?F
- ?Q SET '&?C&?C' ;;TEST FOR QUOTE
- EXITM
- ENDM
- IF ?Q EQ ''''
- LOCAL ?B,?Z
- CALL ?Z
- ?B DB ?F
- ?Z POP H ;GET FROM
- LXI B,?Z-?B ;GET LEN
- ELSE
- LXI H,?F
- ENDIF
- ENDIF
- IF NOT NUL ?T
- LXI D,?T
- ENDIF
- IF NOT NUL ?L
- LXI B,?L
- ENDIF
- ENDM
- ;
- ;DEFINE CP/M MACRO - CPM FNC,PARM [,NOSAVE]
- ;
- CPM MACRO ?F,?P,?N
- IF NUL ?N
- PUSH B
- PUSH D
- PUSH H
- ENDIF
- IF NOT NUL ?F
- MVI C,?F
- ENDIF
- IF NOT NUL ?P
- LXI D,?P
- ENDIF
- CALL BDOS
- IF NUL ?N
- POP H
- POP D
- POP B
- ENDIF
- ENDM
- ;
- RDB MACRO ?F
- PUSH D
- PUSH H
- LXI H,?F
- CALL RDBYTE
- POP H
- POP D
- ENDM
- ;
- WRB MACRO ?F
- PUSH H
- LXI H,?F
- CALL WRBYTE
- POP H
- ENDM
- ;
- EFCB MACRO ?B,?P,?F
- DW ?B
- DW 0
- DB ?P
- DW ?F
- ENDM
- ;
- ORG 100H
- ;
- ;INIT LOCAL STACK
- ;
- LXI SP,STACK
- ;
- CALL START
- DB 'SORTV rev 1.2'
- 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
- ;
- 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
- MOVE FCB2,OUTNAME,12
- RET
- ;
- ;OUTPUT NAME = INPUT NAME
- ;
- SAMENAM MOVE FCB,OUTNAME,12
- 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 CPM OPEN,FCB
- INR A
- RNZ ;SUCCESSFUL? RETURN
- CALL ERXIT
- DB '++Input file not found$'
- ;
- ;====> READ IN THE NAMES
- ;
- READN LXI H,BUFF ;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?
- RDB EXTFCB ;READ A BYTE
- 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.
- RDB EXTFCB ;GOBBLE UP LF
- 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
- CPM WRCON
- 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 NECESS
- ;
- 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 ENTRY, 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
- MOVE OUTNAME,FCB,12 ;RESTORE NAME
- CPM ERASE,FCB
- CPM MAKE,FCB
- 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
- WRB EXTFCB ; CHAR
- LXI H,EXTFCB ;FLUSH
- CALL FLUSH ; BUFFERS
- CPM STDMA,80H ;RESET DMA
- CPM CLOSE,FCB ;CLOSE,
- CALL ERXIT ; AND EXIT
- DB '++DONE++$'
- ;
- WRITEL PUSH H ;SAVE POINTER
- INX H
- ;
- WRLP INX H ;TO NEXT CHAR
- MOV A,M ;GET CHAR
- WRB EXTFCB ;WRITE IT
- MOV A,M ;SEE IF END
- CPI CR ; OF LINE
- JNZ WRLP ;NO, LOOP
- MVI A,LF ;OTHERWISE
- WRB EXTFCB ; WRITE LF
- 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
- ;
- IF MF ;MACRO EXPANSION FLAG SET?
- MOVER MOV A,M
- STAX D
- INX H
- INX D
- DCX B
- MOV A,B
- ORA C
- JNZ MOVER
- RET
- ENDIF
- ;
- IF CF ;MACRO EXPANSION FLAG SET?
- COMPR LDAX D
- CMP M
- RNZ
- INX D
- INX H
- DCX B
- MOV A,B
- ORA C
- JNZ COMPR
- RET
- ENDIF
- ;
- ; 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 ;..FCB..
- 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
- CPM STDMA ;SET DMA ADDR
- POP D ;GET FCB
- CPM READ
- 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 ;BACK TO "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 TO WRITE)
- ; 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
- CPM STDMA ;SET DMA ADDR
- POP D ;GET FCB
- CPM WRITE
- 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
- CPM STDMA,80H
- 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 CPM STDMA
- XCHG
- CPM WRITE
- XCHG
- ORA A
- JNZ WRBERR
- PUSH H
- LXI H,80H
- DAD D
- XCHG
- POP H
- DCR B
- JNZ FLUSHL
- XCHG
- CPM CLOSE
- 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
- ;
- ;====> START OF WORK AREA
- ;
- EXTFCB EFCB DKBUF,4,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
- BUFF EQU $ ;NAMES READ IN HERE
- ;
- ;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
- FCB EQU 5CH
- FCB2 EQU 6CH
- FCBEXT EQU FCB+12
- FCBRNO EQU FCB+32
- ;
- END
-