title 'COMBINE.ASM 12/20/79' page 0 ;12/10/78 BY Ward Christensen ;Modified by Bob Van Valzah & Steve Ness on 1/9/78 to allow ;source files on any drive and remove comments preceded by blanks. ; ;Modified by Steve Ness on 12/20/79 to allow filetypes on source files. ; ;Used to combine multiple small programs into one large assembly file. ; ;command format: ; ; COMBINE output=input1,input2.... ; ;The input files may have a: or b: specified. ;The output file may have A: or B: specified. TEST EQU 0 K EQU 1024 ;1K BLKSIZE EQU 12*K ;OUTPUT FILE BLOCKSIZE ; ;(FROM EQU7.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 MACRO ?F,?T,?L,?I IF NOT NUL ?F LXI H,?F ENDIF IF NOT NUL ?T LXI D,?T ENDIF IF NOT NUL ?L LXI B,?L ENDIF IF NOT NUL ?I LOCAL ?B,?Z CALL ?Z ?B DB ?I ?Z POP H ;GET TO LXI B,?Z-?B ENDIF CALL MOVER MF SET -1 ;;SHOW EXPANSION ENDM ;COMPARE MACRO COMP MACRO ?F,?T,?L,?I IF NOT NUL ?F LXI H,?F ENDIF IF NOT NUL ?T LXI D,?T ENDIF IF NOT NUL ?L LXI B,?L ENDIF IF NOT NUL ?I LOCAL ?B,?Z CALL ?Z ?B DB ?I ?Z POP D ;GET TO LXI B,?Z-?B ENDIF CALL COMPR CF SET -1 ;;SHOW EXPANSION ENDM ; ;DEFINE CP/M MACRO - CPM FNC,PARM ; CPM MACRO ?F,?P PUSH B PUSH D PUSH H IF NOT NUL ?F MVI C,?F ENDIF IF NOT NUL ?P LXI D,?P ENDIF CALL BDOS POP H POP D POP B ENDM ; ORG 100H ;INIT LOCAL STACK ; LXI H,0 DAD SP SHLD STACK LXI SP,STACK ; ;START OF PROGRAM EXECUTION ; ;MOVE THE COMMAND BUFFER MOVE 80H,HOLD,80H ;FROM,TO,LENGTH ;ERASE THE OUTPUT FILE IF NOT TEST CPM ERASE,FCB CPM MAKE,FCB INR A JZ NOROOM ENDIF ;POSITION TO FIRST NAME TO COPY (FOLLOWS =) LXI H,HOLD SKIPEQ INX H MOV A,M CPI '=' JNZ SKIPEQ SHLD NAMEADD ;SAVE POINTER CALL NEXTFL ;PRIME THINGS LOOP CALL WRBYTE CALL RDBYTE JNC LOOP ;DONE - MVI A,1AH CALL WRBYTE LHLD WRCOUNT LXI D,128 DAD D ;FORCE LAST SECTOR SHLD WRCOUNT ;..WRITE CALL WRBUFS ;WRITE THE BUFFER CPM CLOSE,FCB INR A JNZ EXIT CALL ERXIT DB '++CLOSE ERROR++$' ; ;WRITE BYTE TO OUTPUT FILE ; WRBYTE LHLD WRBUFAD MOV M,A INX H SHLD WRBUFAD ;BUMP COUNT LHLD WRCOUNT INX H SHLD WRCOUNT ;SEE IF TIME TO WRITE BUFFER DAD H ;H=# SECTORS MOV A,H CPI BLKSIZE/128 RNZ ;TIME TO WRITE THE OUTPUT BUFFER ; WRBUFS LXI H,WRBUFF SHLD WRBUFAD XCHG LHLD WRCOUNT DAD H ;H=# SECTORS MOV B,H ;SAVE SECTOR COUNT MOV A,B ORA A ;0 SECTORS? (POSS AT EOF) JNZ WRBFLP INR B ;FUDGE IN PARTIAL SECTOR WRBFLP CPM SETDMA CPM WRITE,FCB ORA A JNZ WRERR LXI H,80H DAD D XCHG DCR B JNZ WRBFLP LXI H,0 SHLD WRCOUNT RET ; WRERR CALL ERXIT DB '++WRITE ERROR++$' ; ;READ BYTE FROM INPUT FILE ; RDBYTE LHLD RDBUFAD LDA RDCOUNT ;GET CHAR COUNT ORA A ;TIME TO READ? JP NOREAD ;HAVE TO READ CPM SETDMA,RDBUFF CPM READ,RDFCB ORA A JNZ RDERR CPM SETDMA,80H LXI H,RDBUFF MVI A,0 NOREAD INR A STA RDCOUNT ;SAVE CHAR COUNT ;CHECK FOR NEW LINE OR TAB, TO DELETE COMMENTS LDA PREV CPI 9 JZ TESTCOM CPI ' ' JZ TESTCOM CPI 0AH ;LF? JZ TESTCM1 NOCOM MOV A,M ;GET CHAR INX H SHLD RDBUFAD CPI 'Z'-40H ;EOF? JZ NEXTFL STA PREV ;SAVE FOR COMMENTS TEST ORA A ;CARRY OFF SHOWN NOT EOF RET ; ;TEST FOR COMMENT TESTCOM MOV A,M CPI ';' JNZ NOCOM ;GOT COMMENT, SKIP IT STA PREV INX H SHLD RDBUFAD SKIPCOM CALL RDBYTE CPI 0DH JNZ SKIPCOM STA PREV RET TESTCM1 MOV A,M CPI ';' JNZ NOCOM STA PREV INX H SHLD RDBUFAD ;DELETE ENTIRE LINE DELINE CALL RDBYTE CPI 0AH JNZ DELINE JMP RDBYTE ;GET, RET NEXT CHAR ;GOT EOF - GET NEXT FILE RDERR CALL ERXIT DB '++READ ERROR++$' NEXTFL LHLD NAMEADD ;GET NAME POINTER MOV A,M ;GET DELIMITER ORA A STC RZ ;RET IF ALL DONE INX H ;SKIP DELIMITER LXI D,RDFCB ;POINT TO NAME xra a ;prepare to use default drive stax d inx d PUSH D ;BLANK THE FCB MVI A,' ' MVI B,11 BLANK STAX D INX D DCR B JNZ BLANK POP D inx h ;look ahead for colon, indicating drive mov a,m dcx h ;backup j.i.c. not there cpi ':' ;was a drive specified? jnz moven ;nope - just scan off file name mov a,m ;yup - insert drive name into fcb sui 'A'-1 sta rdfcb inx h ;move source pointer over drive spec. inx h MOVEN MOV A,M CPI ',' JZ MOVED cpi '.' jz movft ORA A ;ZERO @ END? JZ MOVED STAX D INX H INX D JMP MOVEN movft inx h lxi d,rdfcb+9 ;address filetype of read block jmp moven ;ALL DONE MOVING MOVED SHLD NAMEADD ;SAVE NAME LIST ADDR XRA A STA RDEXT ;ZERO EXTENT STA RDRNO ;ZERO RECORD # CPM SETDMA,RDBUFF CPM OPEN,RDFCB INR A JZ OPENERR MVI A,80H ;SHOW TIME TO READ STA RDCOUNT CPM SETDMA,80H JMP RDBYTE OPENERR LXI H,RDFCB+1 MVI B,11 NAMELP MOV A,M CALL TYPE INX H DCR B JNZ NAMELP CALL ERXIT DB ': ++OPEN FAILED++$' NOROOM CALL ERXIT DB '++NO ROOM ON OUTPUT DISK$' ; TYPE MOV E,A CPM WRCON RET ; ;FOLLOWING FROM 'EQU7.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 ;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 LHLD STACK SPHL RET ;TO CCP PREV DB 0AH ;PREV CHAR FOR COMMENTS TEST WRBUFAD DW WRBUFF ;OUTPUT BUFFER ADDR WRCOUNT DW 0 ;BYTE COUNTER RDBUFAD DW RDBUFF RDDRV DB 0 ;DRIVE NAME TO READ FROM RDFCB DB 0,' ' RDEXT DB 0 DS 19 RDRNO DB 0 RDCOUNT DB 80H ;CHARACTER COUNT IN BUFF DS 40H ;STACK AREA STACK DS 2 ;POINTER TO LIST OF FILENAMES NAMEADD DS 2 ;COPY OF INPUT COMMAND BUFFER (FROM 80H) HOLD DS 128 ;OUTPUT DISK BUFFER ORG ($+255) AND 0FF00H ;TO PAGE RDBUFF DS 128 WRBUFF DS BLKSIZE ;BDOS/CBIOS EQUATES (VERSION 7) RDCON EQU 1 WRCON EQU 2 PRINT EQU 9 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 SETDMA EQU 26 BDOS EQU 5 FCB EQU 5CH FCB2 EQU 6CH FCBEXT EQU FCB+12 FCBRNO EQU FCB+32