.comment \ TYPEL.MAC v3.5 (c) 1984 ESKAY Software Services 7120 Skillman #2104 Dallas, TX 75231 NOTE: ===== If you feel the urge to "improve" this program, PLEASE, call the SENECA RCPM first to see if there is a later version. THEN send me your update. Created from the LDIR code in LDIR12, LTYPE17, SYSLIB routines, and, of course, thanks to Dave Rand for the USQ baseline code. Revision history: 08/19/84 Rewrote USQB, added prompted mode 07/21/84 Allowed type of $SYS files, adapted for SYSLIB3 07/07/84 Fixed bug introduced in 3.2 05/23/84 Fixed problem with end-of-file detection 05/06/84 Added $L argument option 04/14/84 General cleanup, added $N argument option 02/15/84 Fixed problem in lbr member filename scanner 02/13/84 Single file mode skipped logging - could only type files in default drive/user. 02/12/84 MAJOR REVISION AND NAME CHANGE v2.00 Program now called TYPEL. It is now able to type (almost) any single file. See doc for more info 01/25/84 Added display of original file name if squeezed. 01/20/84 Made M80/L80 compatible, changed drive/user code to allow use in restricted area if already logged. Added page mode. 01/06/84 Rewrote part of LTYPE to allow reconfig without reassembly, other minor mods. SFK 12/09/83 Fixed ^C bug (problem with CONDIN when remote active) also fixed problem with 0-length files. SFK 12/09/83 Added code to save/restore default drive/user SFK. 11/29/83 Made ^C and ^S checks more frequent to fix a problem which sometimes caused it to ignore ^C. SFK 11/24/83 Strips bit 7, made MAXLIN a DB at 101H 11/20/83 Initially written. For further info and reassembly instructions read the DOC file! \ .8080 ; EXTRN BBLINE ;SYSLIB line input EXTRN CCOUT ;SYSLIB character out (convert ctl chars) EXTRN CLOUT ;SYSLIB list char out EXTRN COMPB ;SYSLIB compare .DE-.HL EXTRN CIN ;SYSLIB character in EXTRN DIVHD ;SYSLIB HL DIV DE EXTRN F$OPEN ;SYSLIB open file EXTRN F$READ ;SYSLIB file read EXTRN BDOS ;SYSLIB BDOS call EXTRN FNAME ;SYSLIB file name parser EXTRN PUTUD ;SYSLIB save current DU EXTRN GETUD ;SYSLIB restore default DU EXTRN LOGUD ;SYSLIB log drive/user EXTRN PRINT ;SYSLIB print routine EXTRN PSTR ;SYSLIB print EXTRN R$READ ;SYSLIB random read EXTRN RETUD ;SYSLIB return drive/user ; EXTRN USQ ;Baseline USQ code EXTRN UINIT ;USQ init code PUBLIC FCB PUBLIC BUFF ;start of buffer PUBLIC TOPRAM ;end of buffer location PUBLIC EREXT ;error intercept from USQ PUBLIC TABLE ;1032 bytes PUBLIC BUFULL ;buffer full (print) routine ; .request usqb,syslib ;take the workload off the user ; cr equ 0dh lf equ 0ah argch equ '$' ;option delimiter ; bufsz equ 1 ;buffer size in K bytes dbuf equ 80h ;default buffer dfcb equ 5ch ;default fcb ; begin: jmp skipc maxdrv: db 1+'B'-40H ;highest accessible drive + 1 (A=2) maxusr: db 1+30 ;highest accessible user + 1 maxlin: db 80 ;number of lines to print max (0=all) maxlps: db 23 ;max lines per screen -1 (0= no page) lsten: db 0 ;zero=list disable, nz=list enable sysen: db 0 ;zero=no sys files, nz=sys files ok ; ; refuse to type these file types ; (note that type check is done after USQ so no need to ; check for .CQM etc) ; notyp: db 'COM' db 'OBJ' ;renamed COM db 'LBR' ;library db 'OV?' ;OVR,OVL,OV1,OV2 etc db 'ARC' ;archive file ; db 'DIR' ;archive directory db 'BAD' ;locked out bad spot ; db 'SYS' ;system file db '??#' ;specially marked file (USERS.TX# etc) ; db 'LOG' ;log file db 'INT' ;intermediate file (CBASIC etc) db 'REL' ;relocatable object file db '?RL' ;PRL, CRL, IRL ; db 'CMD' ;hard to say... (dbase ok, cp/m86 no-go) db 'EXE' ;executable MSDOS file, renamed COMs db 0 ;end of table ds 9*3 ;room for 9 more types ; skipc: lxi sp,stack ;set up local stack call print db 'TYPEL v3.49 (c) ESKAY 10-07-84',cr,lf,0 lxi h,dbuf ;point to buffer mov b,m ;char count to b inr b arglp: dcr b jz sk1 inx h mov a,m cpi argch ;check for option delimiter jnz arglp dcx h mov a,m inx h cpi ' ' ;option must come after a blank jnz arglp dcx h mvi m,0 ;remove option inx h inx h ;point to arg mov a,m cpi 'N' ;N=nopage mvi m,0 jz na cpi 'L' jnz exarg sta lout na: xra a sta maxlps ;non paging exarg: lda lsten ora a jnz sk1 sta lout sk1: call putud ;save default DU lxi d,bufsz*1024 ;compute... lxi h,buff ;...buffer size dad d ;for disk read mov a,h sta topram call retud ;get current drive/user mov a,c ora a jz no00 mov h,b mov l,c shld userno ;save current DU lda dfcb+1 ;check if no file name specified cpi ' ' jnz single loop: call print db cr,lf,'* ',0 mvi a,1 sta singfl call bbline call print db cr,lf,lf,0 ora a jz finish lxi sp,stack jmp nextfl ; stlin: lda maxlin ;max number of lines displayed sta maxls sta maxls1 lda maxlps ora a jz mls dcr a ;first page is one less than normal mls: sta lps ret ; single: lxi h,dbuf+2 ;point to argument nextfl: lxi d,fcb call stlin call fname ;parse file name jz what ;not a valid file name mov a,m ;get delimiter sta fflag ;set flag LBR/non-LBR push h ;save command line ptr inx b ;check if current DU: mov a,b ora c dcx b ;restore DU: value jz currdu ;skip this if current call print db cr,lf,lf db 'Can only display current drive/user!',cr,lf,lf,0 rst 0 mov a,b ;get specified drive dcr b ;get into range 0..f cpi 0ffh ;ff means current drive lxi h,maxdrv jnz newdsk ;skip if different lda driveno mov b,a jmp curdsk ; newdsk: cmp m jnc illdu ;yes - complain curdsk: mov a,c ;get specified user area cpi '?' ;all user areas??? jz illdu ;yes - complain cpi 0ffh ;current user area? jnz newusr lda userno mov c,a jmp curusr ; newusr: inx h ;illegal user specified? cmp m jnc illdu ;yes - complain curusr: call logud ;log into specified DU: currdu: lda fflag ;get flag cpi ' ' ;LBR member request? pop h ;get cmd line ptr back jnz nolbf ;nope, must be singlefile inx h ;get next char lxi d,memfcb ;point to member fcb call fname ;parse member name lxi h,fcb+1 call ckamb ;check ambiguity lxi h,memfcb+1 call ckamb lxi h,FCB+9 ;default to .LBR mvi m,'L' inx h mvi m,'B' inx h mvi m,'R' lxi d,fcb call f$open ;attempt to open file jnz nofile ;not a LBR file xra a sta dirs ;set directory check size to 0 lda sysen ;if $SYS suppress ora a ;then... cz sysck ;check for $sys bit xra a sta lin ;set line count to 0 lxi h,memfcb+9 ;point to member type call typck ;check valid type call f$read ;read directory into default buffer jnz rderr lxi h,dbuf ;point to dbuf lxi d,dirname ;point to 8 blanks call cpfn ;compare jnz nolbr ;not equal lxi d,14 dad d mov a,m sta dirsiz ;directory size xra a sta memfcb jmp c00 ;skip into directory check ; dirlp: lxi d,fcb call f$read jnz rderr c00: lxi b,20h lxi h,dbuf lxi d,memfcb call cpfn jz found dad b call cpfn jz found dad b call cpfn jz found dad b call cpfn jz found lda dirs inr a sta dirs mov b,a lda dirsiz cmp b jnz dirlp call print db cr,lf db 'Member file not found in LBR directory',cr,lf,0 jmp erext ; ; Found the member file name in the LDIR ; found: lxi d,12 dad d push h ;save pointer for now, inx h ;point to size inx h mov a,m ;get low byte inx h ora m ;if a=0 then file is 0k jz nullen ;go complain pop h ;get pointer back mov a,m ;get file address inx h mov h,m mov l,a ; ; enter here from non-LBR routine with HL=0000 ; dotyp: lxi d,fcb ;get fcb... call r$read ;...and read random jnz rderr lxi b,dbuf ;point to buffer ldax b ;get first byte cpi 76h ;if not 76H (=not squeezed)... jnz plain ;...then process as text inx b ;point to and... ldax b ;...get next byte cpi 0ffh ;if FF then squeezed.. jnz plain ;...else plain text (?) call uinit lxi h,dbuf+4 ;point to original name call chktp ;check it's type mvi a,'(' ;print the original name... call ccout ;...in parentheses lxi h,dbuf+4 call pstr call print db ')',cr,lf,0 call usq ;now unsqueeze and print jmp goteof ; ; This routine fills the buffer then calls the print routine ; plain: lxi d,fcb lxi b,dbuf ;default buffer fnext: lxi h,buff rdlp: call f$read ;changed to properly detect eof... jnz goteof ;...in unsqueezed single files mlp: ldax b mov m,a inx h inr c jnz mlp mvi c,80h lda topram cmp h jnz rdlp call bufull ;print buffer contents jmp fnext ; goteof: call bufull jmp erext ; ; This is the print buffer routine (BUFULL) ; bufull: push h push d push b push psw lxi h,buff buflp: mov a,m cpi 1ah jz erext cpi 'I'-40h jz proctab ani 7fh ;strip high bits call putchr cpi lf jz eoln call condin ;get keybd char if available jz goon ;none there, go on cpi 'C'-40h ;if ^C... jz erext ;...then finished cpi 'S'-40h ;if not ^S... jnz goon ;...then go on, else... call cin ;...wait for keypress cpi 'C'-40h jz erext jmp goon ; ; This is NOT the SYSLIB routine by same name... ; condin: push h push d push b mvi c,6 mvi e,0ffh call bdos ora a pop b pop d pop h ret ; eoln: mvi a,0ffh ;reset tab counter sta tab lda maxlps ;get max lines per screen ora a jz nopag ;skip if no page mode lda lps dcr a sta lps jnz nopag call print db '[more]',cr,0 call cin cpi 'C'-40h jz erext call print db ' ',cr,0 lda maxlps sta lps nopag: mvi a,0 ;filled by program maxls equ $-1 ;if maxln=0... ora a jz goon ;..then skip line counter lda lin ;else increment... inr a sta lin ;...the line counter cpi 0 ;see if maxlin reached maxls1 equ $-1 jnz goon ;no, continue call print ;else abort with message db cr,lf db 'TYPEL aborted - maximum number of lines exceeded.',cr,lf db 'Please use XMODEM to transfer file to your system.' db cr,lf,lf,0 jmp erext ; proctab:lda tab ;get current tab value mov b,a ;save current ani 0f8h ;round down to last full 8 adi 8 ;make next tab stop tablp: call spout ;put space inr b ;continue spaces to.. cmp b ;...next tab stop jnz tablp sta tab ;save next tab stop jmp go1 ; ; Print a space ; spout: push psw mvi a,' ' call putchr pop psw ret ; goon: lda tab ;increment... inr a sta tab ;...tab counter go1: inx h ;increment buffer pointer lda topram ;get top of ram cmp h ;if not yet reached... jnz buflp ;...then get next char pop psw ;else return to caller... pop b ;...to get more pop d pop h ret ; ; process non-LBR file ; nolbf: lxi h,fcb+1 call ckamb lxi h,fcb+9 ;point to type call typck ;check valid type lxi d,fcb call f$open ;open the file jnz nofile ;not found... lda sysen ora a cz sysck ;$sys file? call f$read ;read first sector lxi h,0 jz dotyp ;type it now... call print db cr,lf db 'Unable to type - empty file?',cr,lf,0 jmp erext ; ; check type of squeezed file (HL=original fn) ; chktp: push b mvi b,9 ;9 char max chkt1: mov a,m inx h cpi '.' ;end of fn? jz typck1 dcr b jnz chkt1 pop b ret ; ; check file type at against table ; PSW, HL munched, ret only if ok ; typck: push b typck1: push d push h lxi d,notyp ;point to no-type table tck1: pop h push h mvi b,3 ;3 chars to compare tck2: ldax d ora a ;if end of table... jz typok ;...then return cpi '?' ;ambiguous? jz tck3 ;yes, skip cmp m ;if no match... jnz tck4 ;...then skip to next table entry inx h inx d dcr b jnz tck2 ;loop until all 3 match pop h pop d pop b jmp tckno ;not ok to type ; ; skip next character in table and filetype ; tck3: inx h inx d dcr b jnz tck2 jmp tck1 ; ; skip to next table entry ; tck4: inx d dcr b jnz tck4 jmp tck1 ; ; restore registers and return (ok to type) ; typok: pop h pop d pop b ret ; ; complain and abort (type found in table) ; tckno: call print db cr,lf db 'Can''t type a .',0 mvi b,3 tcl: mov a,m inx h call ccout dcr b jnz tcl call print db ' file!',cr,lf,0 jmp erext ; ; check if DE+10 has bit 7 set ($SYS file) ; sysck: push h ;save HL lxi h,10 dad d mov a,m pop h ani 80h rz jmp nofile ;pretend not there ; ; Here are the messages ; illdu: call print db cr,lf db 'Drive/user out of bounds',cr,lf,0 jmp erext ; nofile: call print db cr,lf db 'No such file on disk',cr,lf,0 jmp erext ; cpfn: push h push d push b mvi b,12 ;12 characters call compb pop b pop d pop h ret ; ckamb: mvi a,'?' ;see if there is any... mvi e,11 ;...ambiguity in the file spec ckamlp: cmp m jz noamb ;complain if ambiguous fn inx h dcr e jnz ckamlp ret ; putchr: push b mov b,a lda lout ora a mov a,b jnz cot call ccout pop b ret ; cot: call clout pop b ret ; nolbr: call print db cr,lf db 'LBR directory may be damaged - aborting',cr,lf,0 jmp erext ; nomem: call print db cr,lf db 'No member file name specified.',cr,lf,0 jmp what ; nullen: call print db cr,lf db 'Member file is 0k - cannot type.',cr,lf,0 jmp erext ; rderr: call print db cr,lf db 'Cannot read file',cr,lf,0 jmp erext ; no00: call print db cr,lf,lf,7 db 'ERROR - cannot use in users 0 and 31!',cr,lf,0 rst 0 ; noamb: call print db cr,lf db 'No ambiguous file names allowed',cr,lf,0 what: call print db cr,lf db 'TYPEL v3.5 universal single-file lister',cr,lf db 'Usage:',cr,lf db 9,'TYPEL [du:]fn[.ft] [fn.ft]',cr,lf db 'Examples:',cr,lf db 9,'TYPEL MDM722 MDM722.IQF types member file in LBR',cr,lf db 9,'TYPEL TEST.AQM types normal file',cr,lf db 9,'TYPEL F4:TEST.BQS accepts ZCPR drive/user',cr,lf db 9,'TYPEL FOO.ASM $N $N option=not paging',cr,lf db 9,'TYPEL BAR.ZOT $L $L option=LST: device',cr,lf db 'If 1 argument is supplied, single file is typed.',cr,lf db 'If 2 arguments, TYPEL assumes first arg is type LBR',cr,lf db 'and attempts to type LBR member.',cr,lf db 9,'Typing TYPEL without argument starts interactive mode.' db cr,lf,'You can enter individual filenames or RETURN to stop.' db cr,lf,lf,0 erext: call getud ;restore default DU lda singfl ora a jnz loop finish: rst 0 ; singfl: db 0 ;0=single files, 1=prompted lout: db 0 ;flag for list out fflag: db 0 ;flag for LBR/non-LBR topram: db 0 ;hi byte of buffer end dirs: db 0 ;# of dir sectors processed dirsiz: db 0 ;# of total dir sectors tab: db 0 ;current line tab lin: db 0 ;line count lps: db 0 ;line count for page mode userno: db 0 ;current user # driveno:db 0 ;current drive fcb: ds 36 ;out fcb memfcb: ds 12 ds 50 ;25 level stack stack: dw 0 ;save CP/M stack pointer here dirname:db 0,' ' buff equ 2000h ;start buffer table equ buff-1048 ;usq table end