;SORT PROGRAM FOR CP/M RANDOM FILES ;USES FXED FIELD LENGTH OF 5 ;WRITES CP/M FILE OF RECORD NUMBERS, WHICH ;CAN BE READ BY CP/M AS A SEQUENTIAL FILE ;OR FROM BASIC AS A RANDOM FILE WITH RECORD ;LENGTH OF 5 ; ;COMMAND FORMAT: SORT INPUT.NAME OUTPUT.NAME N ; ;INPUT.NAME IS THE NAME OF A RANDOM BASIC E ;FILE; OUTPUT.NAME IS THE NAME OF THE INDEX FILE ;TO BE WRITTEN. N IS THE FIELD NUMBER TO BE ;SORTED UPON ;8/14/77 DEBUG EQU 0 ORG 100H IF DEBUG LXI SP,4000H ;FOR DDT LXI H,0 SHLD 4000H ENDIF CALL START DB 'SORT VERSION 1.2',13,10,'$' START POP D ;GET ID MESSAGE CALL MSGPRT ;INIT LOCAL STACK LXI H,0 DAD SP SHLD STACK LXI SP,STACK ;THIS PROGRAM IS PROGRAMMED (PERHAPS NOT WELL) ;USING TOP DOWN STRUCTURED PROGRAMMING TECHNIQUES CALL INIT CALL READ$TABLE IF DEBUG ! RST 7 ! ENDIF CALL SORT$TABLE IF DEBUG ! RST 7 ! ENDIF CALL WRITE$SORTED$FILE IF DEBUG ! RST 7 ! ENDIF CALL ERXIT DB '++END OF SORT$' ; ;INIT ROUTINE INIT CALL GET$FLDNO CALL SAVE$FCB CALL OPEN$INPUT RET GET$FLDNO: LDA 80H ;GET PARM LENGTH ORI 80H ;POINT TO LAST BYTE MOV L,A MVI H,0 MOV A,M ;GET FIELD NUMBER ANI 0FH ;MAKE BINARY STA FLDNO RET ;MOVE THE OUTPUT FCB NAME SAVE$FCB: LXI H,FCB+16 LXI D,FCB2 MVI B,12 MOVE MOV A,M STAX D INX H INX D DCR B JNZ MOVE RET ;OPEN INPUT FILE OPEN$INPUT: LXI D,FCB MVI C,OPEN CALL BDOS INR A ;OPEN OK? RNZ CALL ERXIT DB '++CAN''T OPEN INPUT FILE$' OPEN$OUTPUT: LXI D,FCB2 MVI C,DELT CALL BDOS LXI D,FCB2 MVI C,MAKE CALL BDOS INR A RNZ CALL ERXIT DB '++CAN''T OPEN OUTPUT FILE$' ERXIT POP D ;GET MESSAGE CALL MSGPRT EXIT: IF DEBUG ! RST 7 ! ENDIF LHLD STACK SPHL RET READ$TABLE: POP H ;RET ADDR SHLD EOFRET+1 ;SAVE IN JMP RET RTLOOP CALL SKIP$TO$FIELD CALL MOVE$FIELD CALL INCR$NON$MT CALL STORE$RECNO JMP RTLOOP ;COME HERE AT END OF FILE, EXITING RTLOOP EOF LHLD NON$MT ;GET ACTUAL REC COUNT SHLD HOW$MANY$TO$WRITE EOFRET JMP $-$ ;ADDR MODIFIED ;SKIP TO C/R IN RECORD SKIP$TO$CR: CALL RDCHR CPI 0AH ;L/F AFTER C/R? JNZ SKIP$TO$CR RET EMPTY$REC: CALL SKIP$TO$CR SKIP$TO$FIELD: CALL INCR$RECNO CALL RDCHR ;GET FIRST CHAR IN REC CPI '0' ;EMPTY RECORD? JZ EMPTY$REC CALL RDCHR ;',' AFTER FLAG LDA FLDNO MOV B,A SKIPLP DCR B RZ ;AT FIELD NOW SKIPCH CALL RDCHR CPI ',' JNZ SKIPCH JMP SKIPLP MOVE$FIELD: LHLD TABLE$POINTER MVI B,5 ;ALL SORT FIELDS 5 LONG CALL RDCHR ;READ FIRST CHAR (MAY BE ") CPI '"' JNZ MFNQ ;SKIP IF NOT '"' MOVFLP CALL RDCHR MFNQ CPI ',' JZ ENDMV CPI '"' JZ ENDMV MOV M,A ;STORE CHAR CALL TYPE INX H DCR B JNZ MOVFLP JMP ENDPAD ;PAD TO 5 LONG WITH BLANKS PADBL MVI A,' ' MOV M,A CALL TYPE DCR B INX H ENDMV INR B DCR B JNZ PADBL ENDPAD SHLD TABLE$POINTER MVI A,' ' CALL TYPE LDA WIDTH DCR A STA WIDTH CZ CRLF JMP SKIP$TO$CR ;SKIP TO END OF RECORD INCR$RECNO: ;INCREMENT DECIMAL RECORD NUMBER LHLD RECNO ORA A ;CLR CARRY MOV A,L ;GET LO INR A DAA MOV L,A MOV A,H ACI 0 DAA MOV H,A SHLD RECNO RET INCR$NON$MT: LHLD NON$MT INX H SHLD NON$MT RET STORE$RECNO: LHLD RECNO XCHG LHLD TABLE$POINTER MOV M,D INX H MOV M,E INX H SHLD TABLE$POINTER RET SORT$TABLE: XRA A ;GET A ZERO STA CHANGE ;SHOW NO SWAP LHLD NON$MT DCX H SHLD NON$MT SHLD TEMP ;TEMP = HOW MANY TO COMPARE LXI H,TABLE SHLD CURR SORTLP CALL COMPR CNC SWAP CALL NEXT$ENTRY JNZ SORTLP LDA CHANGE ORA A ;ANY SWAPS? JNZ SORT$TABLE RET COMPR LHLD CURR XCHG LXI H,7 DAD D ;DE=CURRENT, HL = NEXT PUSH D PUSH H ;SAVE FOR SWAP COMPLP LDAX D CMP M JNZ DIFF INX H INX D DCR B JNZ COMPLP DIFF POP H POP D RET SWAP RZ ;RETURN IF = ENTRIES MVI B,7 SWAPL MOV C,M LDAX D MOV M,A MOV A,C STAX D INX H INX D DCR B JNZ SWAPL MVI A,1 ;SHOW.. STA CHANGE ;..SWAP RET NEXT$ENTRY: LHLD CURR ;GET CURRENT ENTRY LXI D,7 ;DISPL TO NEXT DAD D SHLD CURR LHLD TEMP DCX H SHLD TEMP MOV A,H ORA L ;ZERO SET IF DONE RET WRITE$SORTED$FILE: CALL OPEN$OUTPUT LHLD HOW$MANY$TO$WRITE SHLD TEMP LXI H,TABLE+5 ;FIRST REC # SHLD CURR WSLOOP LHLD CURR MOV A,M ;GET HI REC NO CALL WRITE$NIBBL ;IGNORE HI DIGIT INX H MOV A,M ;GET LO 2 DIGITS CALL WRITE$HEX CALL WRITE$CRLF CALL NEXT$ENTRY JNZ WSLOOP CALL CLOSE$OUTPUT RET CRLF MVI A,13 CALL TYPE MVI A,10 STA WIDTH TYPE PUSH PSW PUSH B PUSH D PUSH H MOV E,A MVI C,WRCON CALL BDOS POP H POP D POP B POP PSW RET MSGPRT MVI C,PRINT JMP BDOS ;READ CHAR FROM INPUT FILE RDCHR PUSH H LHLD INPTR MOV A,H ;TIME TO READ? DCR A JNZ NOREAD ;READ INPUT RECORD PUSH D PUSH B LXI D,FCB MVI C,READ CALL BDOS ORA A JZ RDOK DCR A JZ EOF CALL ERXIT DB '++INPUT FILE READ ERROR$' RDOK LXI H,80H POP B POP D NOREAD MOV A,M ;GET CHAR INX H SHLD INPTR POP H RET ;WRITE CRLF INTO OUTPUT FILE WRITE$CRLF: MVI A,13 CALL WRITE$CHAR MVI A,10 ;FALL INTO WRITE$CHAR ;WRITE OUTPUT FILE CHAR WRITE$CHAR: PUSH H LHLD OUTPTR MOV M,A INR L ;FULL? SHLD OUTPTR POP H RNZ ;..NO WRITE$RECORD: PUSH B PUSH D PUSH H LXI D,FCB2 MVI C,WRITE CALL BDOS ORA A JZ WROK CALL ERXIT DB '++WRITE ERROR$' WROK LXI H,80H SHLD OUTPTR POP H POP D POP B RET WRITE$HEX: PUSH PSW ;SAVE CHAR RAR!RAR!RAR!RAR CALL WRITE$NIBBL ;WRITE LEFT DIGIT POP PSW WRITE$NIBBL: ANI 0FH CPI 10 JC ISNUM ADI 7 ISNUM ADI '0' JMP WRITE$CHAR CLOSE$OUTPUT: MVI A,'Z'-40H ;EOF CHAR CALL WRITE$CHAR CALL WRITE$RECORD LXI D,FCB2 MVI C,CLOSE CALL BDOS INR A RNZ CALL ERXIT DB '++OUTPUT FILE CLOSE ERROR$' TABLE$POINTER DW TABLE NON$MT DW 0 ;COUNT OF NON-EMPTY REC'S READ HOW$MANY$TO$WRITE DW 0 RECNO DW 0 ;DECIMAL RECORD # READ TEMP DS 2 WIDTH DB 10 ;PRINT ENTRIES/LINE CURR DS 2 CHANGE DS 1 FCB2 DB 0,'XXXXXXXXYYY',0 DS 19 DB 0 FLDNO DS 1 ;FIELD # TO SORT DS 40 ;STACK STACK DS 2 ;CPM'S STACK INPTR DW 100H ;INPUT FILE CHAR POINTER OUTPTR DW 80H ;OUTPUT FILE CHAR POINTER TABLE EQU $ ;SORT TABLE ; ; BDOS EQUATES (VERSION 3) ; RDCON EQU 1 WRCON EQU 2 PRINT EQU 9 OPEN EQU 15 ;0FFH=NOT FOUND CLOSE EQU 16 ; " " SRCHF EQU 17 ; " " SRCHN EQU 18 ; " " DELT EQU 19 ;NO RET CODE READ EQU 20 ;0=OK, 1=EOF WRITE EQU 21 ;0=OK, 1=ERR, 2=?, 0FFH=NO DIR SPC MAKE EQU 22 ;0FFH=BAD REN EQU 23 ;0FFH=BAD STDMA EQU 26 BDOS EQU 5 FCB EQU 5CH