.Z80 ASEG ; SPLIT - cut large data file into subsets of n lines ; ; EQUATES MAX$ENT EQU 3 ; max (and min) arguments in command line parse NOBLX equ 80h ;No of blocks in copy buffer --> 16K buffers BLKSZ equ 80h BDOS EQU 05H BEL EQU 07H TBUF EQU 80H BLANK EQU 20H CR EQU 0DH LF EQU 0AH NDSK EQU 0FFH PSTRNG EQU 09H ; ; DECLARE LIBRARY REFERENCES EXT FXI$OPEN,FXO$OPEN,FXI$CLOSE,FXO$CLOSE,FX$GET,FX$PUT EXT CLINE,ARGV,FNAME,LOGUD,RETUD,CODEND ; ; START of program code ORG 100H LD (SPSAVE),SP ; save old stack pointer LD SP,STAK ; Set up user stack ; ; Establish Locations for File Buffers ; call codend ld (WORK1),hl ld de,NOBLX*BLKSZ add hl,de ld (WORK2),hl ; ; get and parse command line LD HL,TBUF ; Address of Transient Buffer CALL CLINE ; get it to internal buffer JP Z,USAGE LD DE,IOARGV ; Address of ARGV argument table LD A,0FFH ; End each arg with null 0 CALL ARGV ; Parse command line into ARGV table JP NZ,USAGE ; Error, too many args LD A,(IOARGV+1) CP MAX$ENT ; too few JP M,USAGE ; ; move file names into IOCTLn blocks LD HL,IOARGV+2 ; address of address of arg in HL LD E,(HL) ; load address of arg in DE INC HL LD D,(HL) EX DE,HL ; shift back to HL LD DE,IOCFC1 ; address of fcb in I/O control block CALL FNAME ; put name into fcb JP Z,ERRO8 CALL DTST ; check drive and user set to current if no LD (DRUS1),BC ; save drive/user ; LD HL,IOARGV+4 ; same for next arg LD E,(HL) INC HL LD D,(HL) EX DE,HL LD DE,IOCFC2 CALL FNAME JP Z,ERRO8 LD A,'0' LD (IOFCT2),A LD (IOFCT2+1),A LD A,'A'-1 LD (IOFCT2+2),A CALL DTST LD (DRUS2),BC ; ; Get lines to write to subfiles LD HL,IOARGV+6 ; lines are third arg LD E,(HL) INC HL LD D,(HL) EX DE,HL CALL DEVAL ; evaluate numeric response at (HL) into HL LD (LINES),HL ; store lines to write ; ; Init IOCTL1 and IOCTL2, where 1 is input, 2 is output LD BC,(DRUS1) ; Retrieve and log into drive/user 1 CALL LOGUD LD DE,IOCTL1 CALL FXI$OPEN ; Open 1 for Input JP Z,ERRO3 ; File Not Found Error OKOPEN: LD BC,(DRUS2) ; Retrieve and log into drive/user 2 CALL LOGUD LD DE,IOCTL2 LD HL,IOFCT2+2 INC (HL) ; increment file number CALL FXO$OPEN ; Open 2 for Output JP Z,ERRO2 ; No Dir Space Error LD HL,0000H LD (LINECT),HL ; init line count on begin new file XOR A ; set no newfile LD (NEWF),A ; read records counting lines LOOP: LD DE,IOCTL1 CALL FX$GET ; Get Next Input Byte in A JP Z,CLOSEF ; Process EOF LD (CHARST),A ; save character to check for new line below LD DE,IOCTL2 CALL FX$PUT ; Put Byte in A to Output File JP Z,ERRO2 ; Process Write Error ; if cr or lf reset start of line toggle to 1 LD A,(CHARST) ; here is the saved character CP LF JP NZ,LOOP ; on lf check to see if end due LD HL,(LINECT) ; get address of line count in hl INC HL ; increment current line count (HL) LD (LINECT),HL EX DE,HL LD HL,(LINES) AND A SBC HL,DE JP NZ,LOOP ; if not end continue LD A,1 ; if end of lines close, reopen, etc. LD (NEWF),A JP CLOSEF ; ; close files CLOSEF: ; ; close input file needed only if ioctl1 to be reused LD BC,(DRUS2) ; Retrieve and log into drive/user 2 CALL LOGUD LD DE,IOCTL2 CALL FXO$CLOSE ; Close Output File JP Z,ERRO1 LD A,(NEWF) CP 1 JP Z,OKOPEN ; if closing subfile return LD DE,DONE ; else finished message JP EXIT ; ; error routine for syslib ARGV USAGE: LD DE,USEAGE JP EXIT ; ; error routine for syslib file I/0 ERRO1: CP 1 JP Z,ERRO2 LD DE,ERR1 JP EXIT ERRO2: CP 2 JP Z,ERRO3 LD DE,ERR2 JP EXIT ERRO3: CP 3 JP Z,ERRO4 LD DE,ERR3 JP EXIT ERRO4: CP 4 JP Z,ERRO5 LD DE,ERR4 JP EXIT ERRO5: CP 5 JP Z,ERRO6 LD DE,ERR5 JP EXIT ERRO6: CP 6 JP Z,ERRO7 LD DE,ERR6 JP EXIT ERRO7: CP 7 JP Z,ERRO8 LD DE,ERR7 JP EXIT ERRO8: LD DE,ERR8 ; ; print terminator and back to ccp EXIT: LD C,PSTRNG CALL BDOS LD SP,(SPSAVE) ; restore stack RET ; so return back to cpm without boot ; ; Subroutine to check disk and user in bc filling with current ; if missing DTST: PUSH AF PUSH HL LD H,B LD L,C CALL RETUD LD A,H CP NDSK JP NZ,DTST1 LD H,B JP DTST2 DTST1: AND A SBC A,1 LD H,A DTST2: LD A,L CP NDSK JP NZ,DTST3 LD L,C DTST3: LD B,H LD C,L POP HL POP AF RET ; ; subroutine to evaluate numeric string at (HL) into HL DEVAL: PUSH DE PUSH AF LD DE,0 ; SET DE=0 INITIALLY ; Get next digit and check for '0' - '9' AE10L: LD A,(HL) ; GET BYTE CP '0' ; CHECK FOR RANGE JP C,ATOID SUB '0' ; CONVERT TO BINARY CP 10 ; CHECK FOR RANGE JP NC,ATOID PUSH AF ; SAVE LATEST DIGIT ; Multiply DE by 10 PUSH HL ; SAVE HL LD H,D ; HL=DE LD L,E ADD HL,HL ; *2 ADD HL,HL ; *4 ADD HL,DE ; *5 ADD HL,HL ; *10 EX DE,HL POP HL ; RESTORE HL ; Add in A POP AF ; GET LATEST DIGIT ADD A,E ; A=A+E LD E,A LD A,D ; ADD TO D IF NECESSARY ADC A,0 LD D,A ; STORE RESULT INC HL ; PT TO NEXT CHARACTER JP AE10L ; Done -- Result already in DE ATOID: EX DE,HL ; INT IN HL POP AF POP DE 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 ; DU & IO control block for input file DRUS1: DEFS 2 IOCTL1: DEFB NOBLX ; Use NOBLX Pages DEFS 5 ; Filled in by FXIO WORK1: DEFS 2 ; Address of Working Buffer IOCFC1: DEFS 1 ; Filled in by FXIO to 0 DEFB ' ' ; File Name DEFB ' ' ; File Type DEFS 24 ; Filled in by FXIO ; DU & IO control block for output file DRUS2: DEFS 2 IOCTL2: DEFB NOBLX ; Use NOBLX Pages DEFS 5 ; Filled in by FXIO WORK2: DEFS 2 ; Address of Working Buffer IOCFC2: DEFS 1 ; Filled in by FXIO to 0 DEFB ' ' ; File Name IOFCT2: DEFB ' ' ; File Type DEFS 24 ; Filled in by FXIO ; ; Misc Storage NEWF: DEFB 0 ; Toggle for start of file LINES: DEFW 2 ; Number of lines to write in file CHARST: DEFS 1 ; Save character LINECT: DEFS 2 ; Current line count ; ; messages USEAGE: DEFB 'USAGE: SPLIT du:infile.typ du:outfile nnnn',CR,LF DEFB ' break infile into outfiles.00a of nnnn lines.',CR,LF,'$' ERR1: DEFB BEL,'GET or PUT on Unopen File.',CR,LF,'$' ERR2: DEFB BEL,'Disk Full.',CR,LF,'$' ERR3: DEFB BEL,'File Not Found.',CR,LF,'$' ERR4: DEFB BEL,'Read Past EOF.',CR,LF,'$' ERR5: DEFB BEL,'Directory Full.',CR,LF,'$' ERR6: DEFB BEL,'Error Closing File.',CR,LF,'$' ERR7: DEFB BEL,'Open of File already Opened.',CR,LF,'$' ERR8: DEFB BEL,'Undefined Error.',CR,LF,'$' DONE: DEFB 'Done.',CR,LF,'$' PRMT: DEFB 'Number of lines to write in subset files: ',CR,LF,'$' ; ; user stack SPSAVE: DEFW 0 DEFS 64 STAK: DEFB 0 ; Top of stack END