TITLE 'PRINT version 1.0B utility for CP/M-86' ; DATE 10/06/83 17:39 revised by H.M. Van Tassell to include ; revision 1.0B ; print the date in header and help messages ; changed default of Header & Page ; added fake form feed and always print header ;************************************************ ;* * ;* FILE PRINT UTILITY * ;* * ;************************************************ ; ; By Bill Bolton ; Software Tools ; P.O. Box 80 ; Newport Beach ; NSW, 2016 ; AUSTRALIA ; ; CP/M-86 History (most recent version at top) ; ; Version 1.0 Adapted from PAGE utility ; 4/Mar/82 ; EJECT ;************************************************ ;* * ;* MISCELLANEOUS EQUATES * ;* * ;************************************************ FALSE EQU 0 TRUE EQU NOT FALSE CLOCK EQU TRUE ;TRUE FOR SYSTEM CLOCK ;YOU MUST SUPPLY RDTIME ROUTINE TFCB EQU 005CH ;TRANSIENT PROGRAM FCB TBUF EQU 0080H ;TRANSIENT PROGRAM BUFFER OPEN EQU 15 ;OPEN FUNCTION CODE READ EQU 20 ;READ FUNCTION CODE BS EQU 08H ;ASCII Back Space TAB EQU 09H ;ASCII TAB LF EQU 0AH ;ASCII Line Feed FORMF EQU 0CH ;ASCII Form Feed CR EQU 0DH ;ASCII Carriage Return SPACE EQU 20H ;ASCII Blank FILLER EQU 00H ;USED AS FF NULL PAGSZ EQU 66 ;LINES/PAGE MAXLN EQU 58 ;USABLE LINES/PAGE NULLS EQU 1 ;NULLS AFTER A FORM FEED ODEV EQU 5 ;CON:=2 LST:=5 M EQU Byte Ptr 0[BX] ;Handy for ASM86 EJECT CSEG ORG 100H ;************************************************ ;* * ;* GET PARAMETERS FROM COMMAND LINE * ;* * ;************************************************ PRINT: RDTIME: ;PUT YOUR CLOCK ROUTINE HERE AND SET CLOCK EQUATE TRUE IF CLOCK ;COMPUPRO CLOCK ROUTINE CLKCP EQU 50H+10 ;CLOCK COMMAND PORT MOV BX,OFFSET DATESTR ;POINT TO DATE STRING MOV SI,OFFSET DIGTAB ;POINT TO DIGIT TABLE MOV CL,6 ;READ TWO COUNTER RTWO: MOV CH,2 ;READ ONE COUNTER ; ; READ A DIGIT FROM CLOCK CHIP ; ENTRY: SI => DIGIT TABLE DATA ENTRY ; BX => STRING POSITION ; EXIT: ASCII DIGIT LOADED IN STRING ; SI & BX INCREMENTED ; RONE: MOV AL,[SI] ;GET DIGIT TABLE DATA INC SI ;BUMP TO NEXT ENTRY ADD AL,10H ;SET READ BIT OUT CLKCP,AL ;OUTPUT DIGIT DATA CMP AL,15H ;CHECK FOR HOURS 10 DIGIT IN AL,CLKCP+1 ;READ BCD DIGIT FROM CLOCK JNE NOHOUR SUB AL,8 NOHOUR: ADD AL,'0' ;MAKE ASCII MOV [BX],AL INC BX ;POINT TO NEXT STR POSITION DEC CH JNZ RONE ;GET SECOND DIGIT INC BX ;BUMP OVER SEPERATOR CMP CL,4 JNE NOBUMP INC BX ;BIG BUMP OVER WHITE SPACE NOBUMP: DEC CL JNZ RTWO ;READ TWO MORE DIGITS JMPS GOTOIT ;GO TO IT DIGTAB DB 10,9,8,7,12,11,5,4,3,2,1,0 ;CLOCK DIGIT TABLE ENDIF ;CLOCK GOTOIT: MOV BX,TBUF ;POINT TO BUFFER MOV CH,M ;GET COUNT OF CHARACTERS IN CMD MOV AL,M ;GET COUNT AGAIN OR AL,AL ;TEST FOR ZERO JNZ L_1 JMP PERR ;YES, NO ARGUMENTS L_1: INC BX ;SKIP COUNT SKP1: MOV AL,M ;GET BYTE CMP AL,' ' ;SPACE? JNZ SKP2 ;NO INC BX ;BUMP POINTER DEC CH ;DECRMENT COUNT JNZ SKP1 ;SKIP TO FIRST NON-SPACE JMPS PERR ;NO, NON SPACE AFTER FILE ID SKP2: MOV AL,M ;GET CHAR CMP AL,' ' ;SPACE? JZ SKP3 ;YES INC BX ;BUMP POINTER DEC CH ;DECREMENT COUNT JNZ SKP2 ;SKIP TO SPACE JMP PEND ;NO SPACE AFTER FILE ID SKP3: MOV AL,M ;GET CHAR CMP AL,' ' ;TEST FOR NON,SPACE JNZ SKP4 ;FOUND ARGUMENTS INC BX ;BUMP POINTER DEC CH ;DECREMENT COUNT JNZ SKP3 JMP PEND SKP4: MOV DX,(Offset PARMS) SKP4A: MOV AL,M MOV SI,DX MOV [SI],AL INC BX INC DX DEC CH JNZ SKP4A MOV AL,' ' MOV SI,DX ;INDICATE END OF PARMS MOV [SI],AL ;************************************************ ;* * ;* PROCESS PARAMETERS * ;* * ;************************************************ PPARM: MOV DX,(Offset PARMS) ;POINT TO PARMS AREA PLP0: MOV BX,(Offset PTAB) ;POINT TO PARM TABLE MOV CH,(Offset PTABS) ;SIZE OF PARM TABLE PLP1: MOV SI,DX ;GET PARM BYTE MOV AL,[SI] CMP AL,' ' ;END OF PARMS? JZ PEND ;YES, DONE CMP AL,00 ;END OF PARMS? JZ PEND ;YES, DONE CMP AL,M ;COMPARE TO TABLE ENTRY JZ PFND ;FOUND IT INC BX ;BUMP PARM TABLE PTR INC BX INC BX DEC CH ;DECREMENT COUNT JNZ PLP1 ;KEEP LOOKING PERR: MOV DX,(Offset PERMSG) ;POINT TO PARM ERROR MSG MOV CL,09 ;WRITE MSG INT 224 MOV CL,0 ;EXIT MOV DL,0 INT 224 PFND: INC BX ;POINT TO ROUTINE ADDR PUSH DX ;SAVE PARM POINTER MOV DL,M INC BX MOV DH,M ;GET ROUTINE ADDR MOV BX,(Offset PRET) ;RETURN ADDRESS PUSH BX ;SIMULATE CALL XCHG BX,DX ;GET ROUTINE ADDR JMP BX ;EXIT TO PARM PROC. ROUTINE PRET: POP DX ;GET PARM POINTER AGAIN INC DX ;POINT TO NEXT ONE JMPS PLP0 ;CONTINUE ; ;************************************************ ;* * ;* PARAMETER PROCESSING ROUTINES * ;* * ;************************************************ NPARM: MOV AL,0 ;RESET 'NO HEADING' SWITCH MOV Byte Ptr NSWT,AL RET ; CPARM: MOV AL,0 ;RESET 'NO PAGINATION' SWITCH MOV Byte Ptr CSWT,AL RET ;************************************************ ;* * ;* OPEN FILE FOR INPUT * ;* * ;************************************************ PEND: MOV DX,TFCB ;POINT TO FCB CALL FOPEN ;OPEN FILE JNB L_2 JMP ERR ;IF ERROR, EXIT L_2: CALL HEAD ;PRINT HEADING ;**************************************** ;* * ;* MAIN PROCESSING LOOP * ;* * ;**************************************** LOOP: CALL GETBT ;GET A BYTE JNB L_3 JMP ERR ;ERROR L_3: CMP AL,1AH ;EOF? JZ DONE ;YES CMP AL,CR ;CR? JZ CRET ;YES CMP AL,LF ;LF? JZ LFEED ;YES CMP AL,TAB ;TAB? JZ TABMOV ;YES CMP AL,FORMF ;FORM FEED? JZ FFEED ;YES CMP AL,BS ;BACKSPACE JZ BSPACE ;YES CMP AL,SPACE ;ODD CONTROL CHR? JB LOOP ;YES, IGNORE IT CALL PBYT ;OTHERWISE PRINT IT JMPS LOOP ;CONTINUE ;************************************************ ;* * ;* FINAL PROCESSING * ;* * ;************************************************ DONE: CALL TPAGE ;MOVE TO TOP OF PAGE MOV CL,0 ;EXIT TO BDOS MOV DL,0 INT 224 ;************************************************ ;* * ;* PROCESS TABS * ;* * ;************************************************ TABMOV: MOV BX,(Offset COL) ;POINT TO COLUMN TBLP: MOV AL,SPACE ;PRINT ONE SPACE CALL PBYT MOV AL,M ;GET COLUMN AND AL,07H ;MODULO 8 JNZ TBLP ;IF NOT AT TAB STOP, KEEP TYPING JMPS LOOP CALL PBYT ;PRINT BYTE JMPS LOOP ;************************************************ ;* * ;* PROCESS * ;* * ;************************************************ CRET: XOR AL,AL MOV Byte Ptr COL,AL MOV AL,CR CALL PBYT ;PRINT JMPS LOOP ;CONTINUE IN MAIN LOOP ;************************************************ ;* * ;* PROCESS * ;* * ;************************************************ LFEED: MOV AL,Byte Ptr CSWT ;GET PAGINATION SWITCH OR AL,AL ;SEE IF 'NO PAGINATION' JNZ LFEED2 ;TRUE, SKIP PAGINATION TEST MOV AL,Byte Ptr LINE ;GET LINE COUNT CMP AL,MAXLN ;PAGE OVERFLOW? JZ FFEED ;YES LFEED2: MOV AL,Byte Ptr LINE ;GET LINE COUNT INC AL ;BUMP LINE COUNT MOV Byte Ptr LINE,AL MOV AL,LF CALL PBYT JMP LOOP ;**************************************** ;* * ;* PROCESS * ;* * ;**************************************** BSPACE: MOV AL,BS CALL PBYT MOV AL,Byte Ptr COL ;GET COLUMN COUNTER OR AL,AL ;IF ZERO, DONT DECREMENT IT JNZ L_4 JMP LOOP L_4: DEC AL MOV Byte Ptr COL,AL ;DECREMENT COLUMN COUNT JMP LOOP ;************************************************ ;* * ;* PROCESS FORM FEED * ;* * ;************************************************ FFEED: MOV AL,CR CALL PBYT ;PRINT CR CALL TPAGE ;POSITION AT TOP OF PAGE CALL HEAD ;PRINT HEADING JMP LOOP ;CONTINUE IN MAIN LOOP ;************************************************ ;* * ;* HEADING PRINT ROUTINE * ;* * ;************************************************ HEAD: MOV AL,PAGE1 ;IF THIS PAGE 1 OR AL,AL JNZ FPAGE1 ;ALWAYS PRINT FILE NAME & DATE MOV AL,Byte Ptr NSWT ;NO HEADING SWITCH OR AL,AL ;IF SET, NO HEADING JNZ HEADA FPAGE1: MOV BX,(Offset FMSG) ;POINT TO MESSAGE CALL PSTRNG ;PRINT STRING MOV BX,TFCB+1 ;POINT TO NAME MOV CH,8 ;SIZE OF NAME CALL PCNT ;PRINT COUNT MOV AL,SPACE ;PRINT A SPACE CALL PBYT MOV BX,TFCB+9 ;POINT TO TYPE MOV CH,03 ;SIZE OF TYPE CALL PCNT ;PRINT COUNT MOV BX,(Offset PMSG) ;POINT TO MESSAGE CALL PSTRNG ;PRINT STRING MOV AL,Byte Ptr NSWT ;NO HEADING SWITCH OR AL,AL ;IF SET, NO HEADING JZ HEAD1 MOV AL,PAGE1 ;IF THIS PAGE 1 OR AL,AL JNZ FPAGE2 ;DONT PRINT 'PAGE 001' HEAD1: MOV BX,(Offset PPMSG) ;POINT TO PAGE MESSAGE CALL PSTRNG ;PRINT STRING MOV AL,Byte Ptr PAGEN ;GET PAGE NUMBER INC AL ;BUMP IT MOV Byte Ptr PAGEN,AL ;SAVE IT CALL DEC ;CONVERT TO DECIMAL MOV BX,(Offset DECWRK) ;POINT TO DEC STRING MOV CH,3 CALL PCNT ;PRINT PAGE NUMBER FPAGE2: MOV PAGE1,0 ;SET PAGE1 FLAG FALSE MOV AL,CR ;PRINT CR CALL PBYT MOV AL,LF CALL PBYT ;PRINT LF MOV AL,LF CALL PBYT ;AND SECOND MOV AL,LF CALL PBYT ;AND A THIRD MOV AL,3 ;SET NUMBER OF LINES PRINTED JMPS HEADB HEADA: XOR AL,AL HEADB: MOV Byte Ptr LINE,AL ;RESET LINE COUNT XOR AL,AL ;RESET COLUMN MOV Byte Ptr COL,AL ;RESET COLUMN RET ;************************************************ ;* * ;* CHARACTER PRINT ROUTINE * ;* * ;************************************************ PBYT: PUSH BX PUSH CX PUSH AX MOV DL,AL MOV CL,ODEV INT 224 ;PRINT POP AX CMP AL,SPACE ;NON-PRINTING? JB PBY2 ;YES, DONT BUMP COL MOV BX,(Offset COL) ;INCREMENT COLUMN INC M PBY2: MOV CL,11 ;GET CONSOLE STATUS INT 224 CMP AL,00 ;BREAK? JZ L_5 MOV CL,0 ;YES, DONE MOV DL,0 INT 224 L_5: POP CX POP BX RET ;************************************************ ;* * ;* STRING PRINT ROUTINE * ;* * ;************************************************ PSTRNG: MOV AL,M ;GET BYTE CMP AL,'$' ;STRING END? JNZ L_6 RET ;YES, DONE L_6: CALL PBYT ;PRINT BYTE INC BX ;BUMP POINTER JMPS PSTRNG ;LOOP ;************************************************ ;* * ;* STRING PRINT ROUTINE (COUNT IN B) * ;* * ;************************************************ PCNT: MOV AL,M ;GET BYTE CALL PBYT ;PRINT IT INC BX ;BUMP POINTER DEC CH ;DECREMENT COUNT JNZ PCNT RET ;************************************************ ;* * ;* DECIMAL OUTPUT ROUTINE * ;* * ;************************************************ DEC: MOV BX,(Offset DECWRK) MOV CL,100 CALL DIGIT MOV CL,10 CALL DIGIT MOV CL,1 CALL DIGIT RET DIGIT: MOV M,'0' DI0: SUB AL,CL JS DI1 INC M JMPS DI0 DI1: ADD AL,CL LAHF INC BX SAHF RET ;************************************************ ;* * ;* TOP OF PAGE ROUTINE * ;* * ;************************************************ TPAGE: MOV CL,Byte Ptr LINE ;GET LINE COUNT TPAGE1: MOV AL,LF ;FAKE A FORM FEED CALL PBYT INC CL CMP CL,PAGSZ ;AT TOP OF PAGE? JB TPAGE1 ;NO-LOOP AGAIN ;TPAGE: ;CODE TO USE FORM FEEDS ; MOV AL,FORMF ;ISSUE FORM FEED ; CALL PBYT MOV CH,NULLS ;NUMBER OF NULLS TPAGE2: MOV AL,FILLER CALL PBYT DEC CH ;PRINT N FILLERS JNZ TPAGE2 RET ;************************************************ ;* * ;* I/O ERROR MESSAGE ROUTINE * ;* * ;************************************************ ERR: MOV DX,(Offset ERMSG) MOV CL,09H ;WRITE MSG INT 224 MOV CL,0 MOV DL,0 INT 224 ;************************************************ ;* * ;* F O P E N * ;* ROUTINE TO OPEN A DISK FILE * ;* * ;* INPUT: DX= pointer to FCB * ;* OUTPUT: CARRY=ERROR * ;* * ;************************************************ FOPEN: MOV CL,OPEN ;OPEN CODE INT 224 ;ISSUE OPEN CMP AL,0FFH ;ERROR? JZ FOERR ;YES XOR AL,AL ;CLEAR CARRY RET FOERR: STC RET ;******************************************************** ;* * ;* G E T B T * ;* ROUTINE TO READ A BYTE * ;* * ;* OUTPUTS: AL = BYTE * ;* CARRY = ERROR * ;* * ;******************************************************** GETBT: MOV BX,TBUF+128 XCHG BX,DX ;BUFFER END ADDR. IN DE MOV BX,Word Ptr INPTR ;CURRENT POINTER IN HL CMP BX,DX ;TEST FOR END OF BUFFER JZ GETB2 ;YES, READ GETB1: MOV AL,M ;GET BYTE INC BX ;BUMP POINTER INC Word Ptr INPTR ;BUMP POINTER OR AL,AL ;RESET CARRY RET GETB2: MOV CL,READ ;READ CODE MOV DX,TFCB ;FCB ADDRESS INT 224 ;ISSUE READ CMP AL,00 ;ERROR? JNZ IERR ;YES MOV BX,TBUF ;RESET BUFFER POINTER MOV Word Ptr INPTR,BX JMPS GETB1 ;CONTINUE IERR: STC RET EJECT ;************************************************ ;* * ;* D A T A * ;* * ;************************************************ L_8 EQU $ DSEG ORG Offset L_8 DB 'PRINT.CMD - File PRINT Utility, CP/M-86 Version 1.0, ' DB '(C) Copyright March 1982, ' DB 'By Bill Bolton, Software Tools, Sydney, Australia' BD 'Revised 10/06/83 v1.0B by H.M. Van Tassell' NSWT DB 0FFH ;NO HEADING SWITCH CSWT DB 0FFH ;NO PAGINATION SWITCH PAGE1 DB 0FFH ;FIRST PAGE FLAG INPTR DW TBUF+128 ;INPUT POINTER DECWRK DB '000' ;DECIMAL WORK AREA COL DB 0 ;COLUMN COUNTER LINE DB 0 ;LINE COUNTER PAGEN DB 0 ;PAGE COUNTER FMSG DB CR,'FILE: $' PMSG DB ' ' IF CLOCK DATESTR DB 'MM/DD/YY HH:MM:SS $' ;DATE & TIME GO HERE ENDIF IF NOT CLOCK DB ' $' ENDIF PPMSG DB ' PAGE $' PERMSG DB 'Parameter error',CR,LF,LF ERMSG DB 'Usage:',CR,LF,LF DB 'A> PRINT FILENAME.TYP {pram1,pram2...}',CR,LF,LF DB 'Parameters are:',CR,LF DB TAB,'H = Header',CR,LF DB TAB,'P = Pagination',CR,LF DB '$' PARMS RS 16 ;PARAMETER STORAGE AREA ;************************************************ ;* * ;* PARAMETER PROCESSING TABLE * ;* * ;* ENTRIES ARE 3 BYTES WIDE * ;* * ;* BYTE 1 = PARAMETER BYTE * ;* * ;* BYTES 2,3 = ROUTINE ADDRESS * ;* * ;************************************************ PTAB DB 'H' DW (Offset NPARM) DB 'P' DW (Offset CPARM) PTABS EQU ((Offset $)-(Offset PTAB))/3 END