.Z80 ASEG ; PASTE - copy two input files into an output file joined side by side ; for syntax enter >PASTE ; Douglas L. Anderton 1/16/86 ; EQUATES MAX$ENT EQU 3 ; max and min arguments in command line parse BDOS EQU 05H BEL EQU 07H TBUF EQU 80H CR EQU 0DH LF EQU 0AH NDSK EQU 0FFH ; ; DECLARE LIBRARY REFERENCES EXT F$EXIST EXT FO0$OPEN,FO0$CLOSE,F0$PUT EXT FI0$OPEN,FI0$CLOSE,F0$GET EXT FI1$OPEN,FI1$CLOSE,F1$GET EXT CLINE,ARGV,FNAME,LOGUD,RETUD EXT PSTR,CRLF,CAPINE ; ; START of program code ORG 100H LD (SPSAVE),SP LD SP,STAK ; Set up user stack CALL RETUD ; Get and Save current drive/user LD (CURUD),BC ; ; get and parse command line LD HL,TBUF ; Parse of Transient Buffer CALL CLINE JP Z,USAGE LD DE,IOARGV ; Address of ARGV argument table LD A,0FFH ; End each arg with null 0 CALL ARGV JP NZ,USAGE ; Error, too many args LD A,(IOARGV+1) CP MAX$ENT ; too few JP M,USAGE ; ; move file names into IOFCBn blocks and open them LD HL,IOARGV+2 ; now address of arg in HL LD E,(HL) INC HL LD D,(HL) EX DE,HL LD DE,IOFCBO ; fill output fcb CALL FNAME JP Z,ERRO8 CALL DTST ; Check for drive user or default LD (DRUSO),BC ; save for close CALL LOGUD ; log in there for open LD DE,IOFCBO CALL F$EXIST ; check to see if it is already there JP Z,OKOPEN LD HL,EXISTS CALL PSTR CALL CAPINE CALL CRLF CP 'Y' JP Z,OKOPEN LD HL,USEAGE JP EXIT OKOPEN: CALL FO0$OPEN ; open output file JP NZ,ERRO2 ; No Dir Space Error LD HL,IOARGV+4 ; go for the first input fcb LD E,(HL) INC HL LD D,(HL) EX DE,HL LD DE,IOFCB0 ; fill first input fcb CALL FNAME JP Z,ERRO8 CALL DTST ; Check for drive user or default CALL LOGUD ; log in there for open LD DE,IOFCB0 CALL FI0$OPEN ; open output file JP NZ,ERRO3 ; File not found error LD HL,IOARGV+6 ; second input file LD E,(HL) INC HL LD D,(HL) EX DE,HL LD DE,IOFCB1 CALL FNAME JP Z,ERRO8 CALL DTST CALL LOGUD LD DE,IOFCB1 CALL FI1$OPEN JP NZ,ERRO3 ; ; do the read and paste LOOP: ; test to see if all input files eofed LD A,(EOFLG) CP 1 JP NZ,READ0 LD A,(EOFLG+1) CP 1 JP Z,CLOSEF ; else check each file and read from current one READ0: LD A,(CURFL) CP 0 JP NZ,READ1 LD A,(EOFLG) ; test to see if eof detected CP 1 JP Z,EOF0 RED0: CALL F0$GET ; Get Next Input Byte in A JP NZ,ERRO1 CP 1AH JP Z,EOF0 ; eof, else CP CR ; each line assumed terminated by CRLF pair JP NZ,WRITEO ; not end of line go write CALL F0$GET ; Get line feed JP NZ,ERRO1 CP LF JP NZ,LFERR ; else give error LD A,1 ; change current file to read LD (CURFL),A LD A,(SEPART) JP WRITEO EOF0: LD A,1 ; else store eof flag LD (EOFLG),A LD (CURFL),A ; change current file to read READ1: LD A,(EOFLG+1) ; test to see if eof detected CP 1 JP Z,EOF1 RED1: CALL F1$GET ; Get Next Input Byte in A JP NZ,ERRO1 CP 1AH JP Z,EOF1 ; eof, else CP CR ; each line assumed terminated by CRLF pair JP NZ,WRITEO ; not end of line go write CALL F1$GET ; Get line feed JP NZ,ERRO1 CP LF JP NZ,LFERR ; else give error LD A,0 ; Change back current file LD (CURFL),A CALL EOLLF JP LOOP ; go back in loop EOF1: LD A,(EOFLG) ; has other file ended? CP 1 CALL NZ,EOLLF ; if not write crlf LD A,1 ; else store eof flag LD (EOFLG+1),A LD A,0 ; change current file to read LD (CURFL),A JP LOOP ; line feed on end of last file if eofed EOLLF: LD A,CR CALL F0$PUT ; Put Byte in A to Output File JP NZ,ERRO2 ; Process Write Error LD A,LF CALL F0$PUT ; Put Byte in A to Output File JP NZ,ERRO2 ; Process Write Error RET ; ; write char and continue loop WRITEO: CALL F0$PUT ; Put Byte in A to Output File JP NZ,ERRO2 ; Process Write Error JP LOOP ; ; close files CLOSEF: ; ; close input file needed only if fcb to be reused ; so only output closed LD BC,(DRUSO) ; Retrieve and log into drive/user CALL LOGUD LD DE,IOFCBO CALL FO0$CLOSE ; Close Output File JP NZ,ERRO6 LD HL,DONE JP EXIT ; ; error routine for syslib ARGV USAGE: LD HL,USEAGE JP EXIT ; ; no carriage line feed pair error LFERR: LD HL,LFPAIR JP EXIT ; ; error routine for syslib I/0 ERRO1: CP 1 JP Z,ERRO2 LD HL,ERR1 JP EXIT ERRO2: CP 2 JP Z,ERRO3 LD HL,ERR2 JP EXIT ERRO3: CP 3 JP Z,ERRO4 LD HL,ERR3 JP EXIT ERRO4: CP 4 JP Z,ERRO5 LD HL,ERR4 JP EXIT ERRO5: CP 5 JP Z,ERRO6 LD HL,ERR5 JP EXIT ERRO6: CP 6 JP Z,ERRO7 LD HL,ERR6 JP EXIT ERRO7: CP 7 JP Z,ERRO8 LD HL,ERR7 JP EXIT ERRO8: LD HL,ERR8 ; ; print terminator and back to ccp EXIT: CALL PSTR CALL CRLF LD SP,(SPSAVE) RET ; ; Subroutine to check disk and user in bc filling with current ; if missing DTST: PUSH AF PUSH HL LD HL,(CURUD) LD A,B CP NDSK JP NZ,DTST1 LD B,H JP DTST2 DTST1: AND A SBC A,1 LD B,A DTST2: LD A,C CP NDSK JP NZ,DTST3 LD C,L DTST3: POP HL POP AF RET ; ; ARGV control block and command line buffer IOARGV: DEFB MAX$ENT DEFS 1 ; ARGV filled number of args DEFS 2*MAX$ENT ; ARGV filled pointers to arg 1,2,.. ds 2 ; Separator to write between merged lines SEPART: DEFB " " ; EOF flags for input files and sum of closed out EOFLG: DEFB 0 DEFB 0 ; Current file reading from CURFL: DEFB 0 ; DU's for files CURUD: DEFS 2 DRUSO: DEFS 2 ; fcb's for files IOFCBO: DEFS 1 DEFB ' ' ; File Name DEFB ' ' ; File Type DEFS 24 IOFCB0: DEFS 1 DEFB ' ' ; File Name DEFB ' ' ; File Type DEFS 24 IOFCB1: DEFS 1 DEFB ' ' ; File Name DEFB ' ' ; File Type DEFS 24 ; ; messages LFPAIR: DEFB BEL,'Carriage Return without following Line Feed.',0 EXISTS: DEFB BEL,'Output File Already Exists - ERASE (Y/N)? ',0 USEAGE: DEFB 'USAGE: PASTE du:outfile.typ du:infile1.typ du:infile2.type' DEFB CR,LF,' joins two infiles side by side into outfile.',0 ERR1: DEFB BEL,'GET or PUT attempt on unopened file.',0 ERR2: DEFB BEL,'Disk Full.',0 ERR3: DEFB BEL,'File Not Found.',0 ERR4: DEFB BEL,'Read Past EOF.',0 ERR5: DEFB BEL,'Directory Full.',0 ERR6: DEFB BEL,'Error Closing File.',0 ERR7: DEFB BEL,'Attempt to Open File already Opened.',0 ERR8: DEFB BEL,'Error of Undefined Code.',0 DONE: DEFB 'Done.',0 ; ; user stack SPSAVE: DEFW 0 DEFS 64 STAK: DEFB 0 ; Top of stack END