; ; PROGRAM: LDIRZ ; VERSION: 2.0 ; AUTHOR: RICHARD CONN ; DATE: 16 JAN 83 ; PREVIOUS VERSIONS: 1.0 (12 JAN 83) ; vers equ 20 ; ; LDIRZ prints a sorted directory of the default library file ; (installable via GENINS). The printout gives file name and size. ; It is sorted alphabetically by file name and type. Only one option ; is permitted, and that is a file spec (wild cards are OK). Forms ; of the LDIRZ command are: ; ; LDIRZ <-- All Files ; LDIRZ file.typ <-- Selected Files ; LDIRZ -library file.typ <-- Selected Files in Library ; LDIRZ // <-- Help Message ; ; ; CP/M Constants ; cpm equ 0 ;base bdose equ cpm+5 fcb equ cpm+5ch tbuff equ cpm+80h cr equ 0dh lf equ 0ah ; ; SYSLIB Routines ; ext zgpins,print,zpfind,initfcb,f$open,f$read ext sort,moveb,putud,logud,shftrh,phldc,codend ext hmovb,crlf,cout,fname,cline ; ; Branch to Start of Program ; jmp start ; ;****************************************************************** ; ; SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format ; ; This data block precisely defines the data format for ; initial features of a ZCPR2 system which are required for proper ; initialization of the ZCPR2-Specific Routines in SYSLIB. ; ; ; EXTERNAL PATH DATA ; EPAVAIL: DB 0FFH ; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES) EPADR: DW 40H ; ADDRESS OF EXTERNAL PATH IF AVAILABLE ; ; INTERNAL PATH DATA ; INTPATH: DB 0,0 ; DISK, USER FOR FIRST PATH ELEMENT ; DISK = 1 FOR A, '$' FOR CURRENT ; USER = NUMBER, '$' FOR CURRENT DB 0,0 DB 0,0 DB 0,0 DB 0,0 DB 0,0 DB 0,0 DB 0,0 ; DISK, USER FOR 8TH PATH ELEMENT DB 0 ; END OF PATH ; ; MULTIPLE COMMAND LINE BUFFER DATA ; MCAVAIL: DB 0FFH ; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE? MCADR: DW 0FF00H ; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE ; ; DISK/USER LIMITS ; MDISK: DB 4 ; MAXIMUM NUMBER OF DISKS MUSER: DB 31 ; MAXIMUM USER NUMBER ; ; FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK ; DOK: DB 0FFH ; ALLOW DISK CHANGE? (0=NO, 0FFH=YES) UOK: DB 0FFH ; ALLOW USER CHANGE? (0=NO, 0FFH=YES) ; ; PRIVILEGED USER DATA ; PUSER: DB 10 ; BEGINNING OF PRIVILEGED USER AREAS PPASS: DB 'chdir',0 ; PASSWORD FOR MOVING INTO PRIV USER AREAS DS 41-($-PPASS) ; 40 CHARS MAX IN BUFFER + 1 for ending NULL ; ; CURRENT USER/DISK INDICATOR ; CINDIC: DB '$' ; USUAL VALUE (FOR PATH EXPRESSIONS) ; ; DMA ADDRESS FOR DISK TRANSFERS ; DMADR: DW 80H ; TBUFF AREA ; ; NAMED DIRECTORY INFORMATION ; NDRADR: DW 00000H ; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY NDNAMES: DB 64 ; MAX NUMBER OF DIRECTORY NAMES DNFILE: DB 'NAMES ' ; NAME OF DISK NAME FILE DB 'DIR' ; TYPE OF DISK NAME FILE ; ; REQUIREMENTS FLAGS ; EPREQD: DB 0FFH ; EXTERNAL PATH? MCREQD: DB 000H ; MULTIPLE COMMAND LINE? MXREQD: DB 000H ; MAX USER/DISK? UDREQD: DB 000H ; ALLOW USER/DISK CHANGE? PUREQD: DB 000H ; PRIVILEGED USER? CDREQD: DB 0FFH ; CURRENT INDIC AND DMA? NDREQD: DB 000H ; NAMED DIRECTORIES? Z2CLASS: DB 5 ; CLASS 5 DB 'ZCPR2' DS 10 ; RESERVED ; ; END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA ; ;****************************************************************** ; library: DB 'COMMAND ' ; <---change this if you like--- libtyp: DB 'LBR' ; ; START OF PROGRAM ; start: call zgpins ; init ZCPR2 buffers call putud ; save current user/disk ; ; Print Banner ; call print db 'LDIRZ Version ' db vers/10+'0','.',(vers mod 10)+'0',0 ; ; Set Default Library Name ; lxi h,library lxi d,fcb+1 ; copy into FCB mvi b,11 ; 11 chars call moveb ; ; Extract Information ; lxi h,tbuff ; get command line from buffer call cline call sblank ; skip to non-blank ora a ; EOL? jz help cpi '/' ; Help? jnz start0 ; ; Print Help Message ; help: call print db cr,lf,' LDIRZ prints a sorted directory of the current' db cr,lf,'Library File. It is invoked by one of the forms:' db cr,lf,' LDIRZ <-- All Files' db cr,lf,' LDIRZ filename.typ <-- Selected Files' db cr,lf,' LDIRZ -lib filename.typ <-- Files from LIB' db cr,lf,' LDIRZ // <-- Print Help' db cr,lf,' Wild Cards (*,?) are permitted.' db cr,lf,0 ret ; ; Check for Library Name and Set it if so ; start0: cpi '-' ; library follows? jnz start1 inx h ; pt to library name lxi d,fcb ; pt to FCB call fname ; extract library name call sblank ; skip to non-blank lxi d,fcb+9 ; check file type ldax d cpi ' ' ; none? jnz start1 push h ; save ptr lxi h,libtyp ; default type mvi b,3 ; 3 chars call moveb ; copy it pop h ; get ptr ; ; Check for File Spec and Set if so ; start1: ora a ; any chars? jz start2 ; fspec is already wild lxi d,filesp ; copy into file spec call fname ; extract file name ; ; Find Library ; start2: lxi d,fcb ; pt to FCB call initfcb mvi b,0ffh ; search current call zpfind ; look for library file jnz start3 call print db cr,lf,'Library File ',0 lxi h,fcb+1 ; pt to name call prfn ; print file name call print db ' Not Found',0 ret ; ; Read in First Block of Library ; start3: call logud ; log into directory call f$open ; open file call f$read ; read first block ora a ; ok? jz readdir ; extract directory info call print db cr,lf,'Library File ',0 lxi h,fcb+1 call prfn call print db ' is Empty',0 ret readdir: lxi h,tbuff+14 ; pt to dir size mov a,m inx h mov h,m ; HL=size of directory mov l,a mov b,h ; BC=number of blocks in dir mov c,l lxi h,0 ; set file count shld filecnt call codend ; pt to spare buffer shld bufptr ; set buffer ptr shld ssbstart ; set starting address of first record lxi h,tbuff+32 ; pt to first entry jmp getentry ; get next entry ; ; Read Next Block ; readblock: push b ; save count lxi d,fcb ; pt to FCB call f$read ; read block pop b ; restore regs lxi h,tbuff ; pt to next entry ora a ; error? jz getentry ; get next entry call print db cr,lf,'Premature End of Library File ',0 lxi h,fcb+1 call prfn call print db ' -- Aborting',0 ret ; ; Get next entry from library directory ; On entry, HL pts to entry, BC=count ; getentry: push h ; save ptr push b ; save count mov a,m ; entry present? cpi 0ffh ; none? jz gete1 cpi 0 ; deleted? jnz gete1 inx h ; pt to file name push h ; save ptr to entry lxi d,fspec ; pt to file spec mvi b,11 ; check 11 bytes getent1: ldax d ; check for match with wild cards mov c,m ; get target char inx h ; pt to next inx d cpi '?' ; wild match? jz getent2 cmp c ; match? jnz gete0 ; skip if not getent2: dcr b ; count down jnz getent1 pop h ; file matches -- continue push h ; save ptr lhld filecnt ; increment file count inx h shld filecnt pop h xchg ; ptr to file name in DE lhld bufptr ; get buffer ptr mvi b,11 ; 11 bytes xchg ; HL pts to entry call hmovb ; copy and affect HL and DE inx h ; skip index inx h mvi b,2 ; copy size call hmovb xchg ; get buffer ptr in HL shld bufptr ; save buffer ptr xchg ; put back in DE lhld bdose+1 ; memory full? mov a,h ; check pages sui 10 ; below CCP cmp d ; in range? jnz gete1 pop b pop h ; clear stack call print db cr,lf,'Memory Overflow',0 ret gete0: pop h ; clear stack gete1: pop b ; get count pop h ; get ptr to block lxi d,32 ; pt to next dad d lxi d,tbuff+80h ; pt to end of buffer mov a,e ; new block if low-order is the same cmp l jnz getentry dcx b ; count down mov a,b ; done? ora c jnz readblock ; continue with next block ; ; Done with Buffer Load ; lhld filecnt ; set record count shld ssbcnt lxi d,ssb ; pt to ssb call sort ; perform sort mov a,l ; get low (remainder) ani 3 ; select remainder sta remain call shftrh ; shift right 2 bits call shftrh shld loopcnt ; number of loops xchg ; count in DE lxi h,0 ; compute sum lxi b,13 ; bytes/entry col0: mov a,d ; done? ora e jz col1 dcx d ; count down dad b ; add in size jmp col0 col1: xchg ; DE is size of list lhld ssbstart ; pt to first entry shld entry1 dad d ; pt to next entry lda remain ; add 1? ora a ; no if zero jz col2 dad b ; add in another entry col2: shld entry2 ; set ptr to 2nd entry dad d ; pt to next entry cpi 2 ; remainder >=2? jc col3 dad b ; add in another entry col3: shld entry3 ; set ptr to 3rd entry dad d ; pt to last entry cpi 3 ; add 1? jnz col4 dad b ; add in another entry col4: shld entry4 ; ; Directory Print -- ENTRYn pts to first element in each col, DE is ; number of loops, and REMAIN is number of extra entries ; lxi h,0 ; clear sum shld sum call print db cr,lf db 'Filename.Typ Size ' db 'Filename.Typ Size ' db 'Filename.Typ Size ' db 'Filename.Typ Size' db cr,lf db '-------- --- ----- ' db '-------- --- ----- ' db '-------- --- ----- ' db '-------- --- -----',0 lhld loopcnt ; get loop count xchg ; ... in DE dirloop: mov a,d ; Done? ora e jz dirdone dcx d ; count down call crlf ; new line lhld entry1 ; print entry call prentry shld entry1 lhld entry2 call prentry shld entry2 lhld entry3 call prentry shld entry3 lhld entry4 call prentry shld entry4 jmp dirloop dirdone: lda remain ; print last line ora a ; none? jz done mov d,a ; count in D call crlf ; new line lhld entry1 ; print first col call prentry dcr d ; count down jz done lhld entry2 ; print 2nd col call prentry dcr d ; count down jz done lhld entry3 ; print 3rd col call prentry done: call crlf ; new line lhld filecnt ; print number of entries call phldc call print db ' Files Selected occupying a Total of ',0 lhld sum ; print sum of sizes call phldc call print db 'K Bytes',0 ret ; ; Print File Name Entry ; prentry: push d push h push b call prfn ; print file name lxi d,11 ; pt to size dad d mov c,m ; get size in BC inx h mov b,m mov a,c ; part of a K? ani 7 sta kpart mov h,b ; file size in HL mov l,c call shftrh ; move right 3 bits for size in K call shftrh call shftrh lda kpart ; add 1 for overflow? ora a ; 0=no jz prent1 inx h ; add 1 K prent1: call phldc ; print as decimal mvi a,'K' ; print K call cout mvi a,' ' ; print 2 spaces call cout call cout xchg ; size in DE lhld sum ; add to sum dad d shld sum pop b ; get regs pop h lxi d,13 ; pt to next entry dad d pop d ret ; ; Print file name pted to by HL ; prfn: push h ; save regs push b mvi b,8 ; 8 chars call prfn1 mvi a,'.' call cout mvi b,3 ; 3 chars call prfn1 pop b ; get regs pop h ret prfn1: mov a,m ; print chars inx h ; pt to next call cout dcr b ; count down jnz prfn1 ret ; ; Compare Routine ; Compare (DE) to (HL) and Return with Carry if (DE) < (HL) ; compare: push h ; save regs push d push b mvi b,11 ; 11 bytes to compare comp: ldax d ; get byte cmp m ; compare jnz compd ; done if not same inx h ; pt to next inx d dcr b ; count down jnz comp compd: pop b ; restore regs pop d pop h ret ; ; Skip to Non-Blank ; sblank: mov a,m ; skip to non-blank inx h cpi ' ' jz sblank dcx h ret ; ; Buffers ; ssb: ; sort specification block ssbstart: ds 2 ; ptr to first byte of first record ssbcnt: ds 2 ; number of records dw 13 ; 13 bytes/record dw compare ; address of compare routine dw 0 ; no ptr table db 0,0 ; don't use ptrs filesp: db 0 fspec: db '????????' ; file spec db '???' ds 24 remain: ds 1 ; column remainder kpart: ds 1 ; K remainder filecnt: ds 2 ; number of files bufptr: ds 2 ; scratch buffer ptr sum: ds 2 ; sum of file sizes loopcnt: ds 2 ; number of lines to print entry1: ds 2 entry2: ds 2 entry3: ds 2 entry4: ds 2 end