home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
ZSYS
/
SIMTEL20
/
ZCPR3
/
XDIR.MAC
< prev
next >
Wrap
Text File
|
2000-06-30
|
39KB
|
1,888 lines
;
; PROGRAM: XDIR III
; AUTHOR: RICHARD CONN
; VERSION: 2.0
; DATE: 9 APR 84
; PREVIOUS VERSIONS: 1.6 (19 NOV 83)
; PREVIOUS VERSIONS: 1.5 (9 JAN 83), 1.4 (6 JAN 83), 1.3 (7 DEC 82)
; PREVIOUS VERSIONS: 1.2 (2 NOV 82), 1.1 (30 OCT 82), 1.0 (20 OCT 82)
;
vers equ 20
z3env SET 0f400h
;
; XDIR III -- Extended Disk Directory Program
; ZCPR3 Version
;
; XDIR III produces a formatted, alphabetized listing of the contents
; of the disk directory of the implied (current logged-in) or specified disk.
;
; XDIR III is invoked by a command line of the following form --
;
; XDIR dir:filename.typ ooo...
; or
;
; XDIR /oooo...
;
; where:
; dir is an optional directory name or a disk/user specification (du)
; if dir is omitted, XDIR III defaults to the current disk/user
; filename.typ is an ambiguous file name and type (* and ? may be used)
; o are option letters as follows:
; Aa - Set the attributes of the files to be displayed;
; a=S for System Files, a=N for Non-System Files
; a=A for All Files (System and Non-System)
; D - Send Output to Disk as well as screen
; Ff - Engage File Name Buffer Facility
; f=L to Log File Names to Disk
; f=P to Print Names Logged to Disk
; f=S to Scan Disk for File Names and Compare to Logged
; I - Inspect files selected by FL option for inclusion
; N - Negate selection; select those files which do NOT
; match the ambiguous file name
; Oo - Set Output Parameters;
; o=A to Toggle File Attributes, o=F to Form Feed at end
; o=G to Toggle Grouping, o=H to Toggle Hor/Vert
; P - Print display as well as show it on the screen
; PF - Same as POF
; U - Select All User Areas
;
; Options may be combined as desired; note that AA is the same as AS and AN,
; but AS by itself negates AN and vice-versa, with AN taking precident
;
;
; CP/M Equates
;
base equ 0
wboot equ base
bdose equ base+5
fcb equ base+5ch
buff equ base+80h
ctrlc equ 'C'-'@'
cr equ 0dh
ff equ 0ch
lf equ 0ah
esize equ 16 ; size of directory entries
optch equ '/' ; option char
maxent equ 54 ; maximum number of entries/screen
;
; External Routines
;
ext bdos ; BDOS
ext dutdir ; convert DU to DIR form
ext z3log ; log into DU or DIR
ext z3init ; init buffers
ext dbuffer ; disk routines
ext dfree
ext diralpha
ext dirsload
ext dirpack
ext dirnpack
ext dirsel
ext dparam
ext fsize
ext fo0$open ; byte-oriented file output
ext fo0$close
ext f0$put
ext fo1$open
ext fo1$close
ext f1$put
ext fi1$open
ext fi1$close
ext f1$get
ext bbline ; input line editor
ext retud ; get current user and disk
ext print ; print routines
ext pstr
ext lpstr
ext lcrlf
ext caps ; capitalize char
ext cin ; console in char
ext lout ; print char
ext cout ; console out char
ext crlf ; new line
ext madc ; a as dec chars in memory
ext mhldc ; hl as dec chars in memory
ext fillb ; memory fill
ext moveb ; memory move
ext codend ; beginning of buffer area
;
; Environment Definition
;
if z3env ne 0
;
; External ZCPR3 Environment Descriptor
;
jmp start
db 'Z3ENV' ;This is a ZCPR3 Utility
db 1 ;External Environment Descriptor
z3eadr:
dw z3env
start:
lhld z3eadr ;pt to ZCPR3 environment
;
else
;
; Internal ZCPR3 Environment Descriptor
;
MACLIB Z3BASE.LIB
MACLIB SYSENV.LIB
z3eadr:
jmp start
SYSENV
start:
lxi h,z3eadr ;pt to ZCPR3 environment
endif
;
; Start of Program -- Initialize ZCPR3 Environment
;
call z3init ;initialize the ZCPR3 Env and the VLIB Env
jmp start0
;
; Other Buffers (Set by GENINS)
;
igrp: db 0ffh ; Group by file type and name
ifmt: db 0 ; vertical format
iatt: db 10000000b ; Non-System files only
iscn: db 0 ; 0=dir display, 0ffh=scan for files by default
fenab: db 0ffh ; enable F options (0=no)
lenab: db 0ffh ; enable FL option (0=no)
asenab: db 0ffh ; enable AS option (0=no)
irs: db 0ffh ; enable attribute display (0=no)
iff: db 0 ; enable form feed at end (0=no)
;
; Command Line Option Table
;
optab:
db 'A'
dw opta
db 'D'
dw optd
db 'F'
dw optf
db 'I'
dw opti
db 'N'
dw optn
db 'O'
dw opto
db 'P'
dw optp
db 'U'
dw optu
db 0
;
; **** Start of XDIR III ****
;
start0:
;
; Save stack ptr for return later
;
lxi h,0 ; get stack
dad sp
shld stack ; save stack ptr for return
call codend ; determine free space (CODEND also pts to Command
; Line Save Area)
lxi d,100h ; block size to save
dad d
dad d ; allow for 256-byte stack
shld buffer ; start of free buffer area
sphl ; set stack ptr
;
; Save command line in CMDLNE buffer
;
call codend ; pt to command line buffer
xchg ; ... in DE
lxi h,buff+1 ; copy input line into command line buffer
start1:
mov a,m ; get byte
stax d ; put byte
inx h ; pt to next
inx d
ora a ; end of line?
jnz start1
;
; Get and save current user number
;
noext:
call retud ; get current user and disk
mov a,b ; get disk into A
sta curdisk ; current disk number
mov a,c ; set current user
sta curuser
;
; Log into DU or DIR
;
lxi d,fcb ; use data determined by ZCPR3
call z3log ; ZCPR3 command line interpretation
call retud ; get current user and disk
mov a,c ; set current user
sta aflg
mov a,b ; set disk
sta disk
;
; Set flag values
;
lda irs ; get RS display option
sta rsflg ; set RS display option
lda iff ; get form feed option
sta ffflg ; set form feed option
lda igrp ; set grouping (file name/type or type/name)
sta gflg
lda ifmt ; set listing format (vertical or horizontal, 0=vert)
sta hflg
lda iatt ; set file attributes
mov c,a ; save in c
lda aflg ; get current user number
ora c ; mask in file attributes
sta aflg ; save flag
lda iscn ; set initial function (Scan or Dir)
sta fflg
xra a ; A=0
sta nflg ; set no negation
sta dflg ; set no disk output
sta pflg ; set no printer output
sta iflg ; set no file name inspection (for /FP)
;
; Assume wild file name
;
lxi h,fcb+1 ; store '?' chars
mvi b,11 ; 11 chars
mov a,m ; check for entry specified
cpi ' ' ; test for space (means no entry)
mvi a,'?' ; prepare for '?' fill
cz fillb
mov a,m ; check for option caught
cpi optch ; test for option flag
mvi a,'?' ; prepare for '?' fill
cz fillb
;
; Scan command line for options
;
call codend ; pt to first char
call sblank ; skip over blanks
ora a ; end of line?
jz xdir ; begin main processing
inx h ; prep for invalid option
cpi optch ; option?
jz opt ; process options
dcx h ; ok to process for dir:filename.typ form
;
; skip over character of file name
;
skipo1:
mov a,m ; get char
inx h ; pt to next
cpi ' '
jz skipo2
ora a
jnz skipo1
jmp xdir ; run XDIR if no options follow
;
; Scan complete -- look for possible following option char
;
skipo2:
call sblank ; skip over blanks
mov a,m ; option char follows?
cpi optch
jnz opt
inx h ; skip over option char
;
; Look for options -- main loop; HL pts to next char
;
opt:
mov a,m ; get option char
inx h ; pt to next
ora a ; end of line?
jz xdir ; begin main processing
cpi ' ' ; skip over spaces
jz opt
cpi optch ; option char?
jz opterr ; loop back if so
lxi d,optab ; pt to option table
mov b,a ; option char in b
;
; Scan option table
;
opt1:
ldax d ; get option table char
ora a ; end of table?
jz opterr ; invalid option error
cmp b ; compare to passed option
jz opt2 ; process if match
inx d ; skip address
inx d
inx d ; pt to next opt char
jmp opt1
;
; Process option found
;
opt2:
inx d ; pt to low-order address
ldax d ; get it
mov c,a ; low in C
inx d ; pt to high-order address
ldax d ; get it
mov b,a ; high in B
push b ; BC on stack
ret ; Process option routine
;
; Option A -- File Attributes
;
opta:
mov a,m ; get next option letter
cpi 'N' ; Non-System files?
jz optan
cpi 'S' ; System files?
jz optas
cpi 'A' ; All files?
jnz opterr ; error if not
;
; Option AA -- All Files
;
optaa:
lda asenab ; enable system files?
ora a ; 0=no
jz optan
mvi c,11000000b ; System and Non-system
optaret:
lda aflg ; get flag
ani 3fh ; leave in user selection
ora c ; mask in sys/non-sys
sta aflg ; restore flag
inx h ; pt to next
jmp opt
;
; Option AS -- System Files
;
optas:
lda asenab ; enable system files?
ora a ; 0=no
jz optan
mvi c,01000000b ; System Only
jmp optaret
;
; Option AN -- Non-System Files
;
optan:
mvi c,10000000b ; Non-system Only
jmp optaret
;
; Option F - select file name buffer functions
;
optf:
mvi a,0ffh ; set flag
sta fflg
mov a,m ; get option char
sta fopt
cpi 'L' ; log file names to disk
jz optfok
cpi 'P' ; print names of files
jz optfok
cpi 'S' ; scan disk for files
jz optfok
jmp opterr ; error otherwise
optfok:
inx h ; pt to next option letter
jmp opt
;
; Option I -- enable it; inspect for FL option only
;
opti:
mvi a,0ffh ; ON
sta iflg
jmp opt
;
; Option D -- enable it; Disk output
;
optd:
mvi a,0ffh ; ON
sta dflg
jmp opt
;
; Option P -- enable it; Printer output
;
optp:
mvi a,0ffh ; ON
sta pflg
mov a,m ; get possible 2nd letter
cpi 'F' ; set form feed if F
jnz opt ; process as next option letter if not F
inx h ; pt to next
jmp optof
;
; Option O -- control Output parameters
;
opto:
mov a,m ; get 2nd letter
inx h ; pt to next
cpi 'A' ; attributes?
jz optoa
cpi 'F' ; form feed?
jz optof
cpi 'G' ; grouping?
jz optog
cpi 'H' ; horizontal/vertical?
jz optoh
dcx h ; adjust back
jmp opterr
;
; Toggle File Attributes Flag
;
optoa:
lda rsflg ; flip flag
cma
sta rsflg
jmp opt
;
; Toggle Form Feed Flag
;
optof:
lda ffflg ; flip flag
cma
sta ffflg
jmp opt
;
; Toggle Grouping
;
optog:
lda gflg ; flip flag
cma
sta gflg ; 0=file name and type
jmp opt
;
; Toggle Horizontal/Vertical Listing
;
optoh:
lda hflg ; flip flag
cma
sta hflg ; 0=vertical
jmp opt
;
; Option N -- enable it; Negate Selection
;
optn:
mvi a,0ffh ; ON
sta nflg
jmp opt
;
; Option U - enable it; Select All User Areas
;
optu:
lda aflg ; get current attributes flag
ori 20h ; select all user areas
sta aflg ; put flag back
jmp opt
;
; Option error message
;
opterr:
xra a ; set no disk or printer output
sta dflg
sta pflg
call banner ; print banner
call print
db cr,lf,'Syntax:'
db cr,lf,' XDIR dir:filename.typ ooo...'
db cr,lf,'or XDIR /oooo...'
db cr,lf,'Options:'
db cr,lf,' Aa - File Attributes'
db cr,lf,' a=S for System, a=N for Non-System'
db cr,lf,' a=A for All Files (System and Non-System)'
db cr,lf,' D - Send Output to Disk File XDIR.DIR'
db cr,lf,' Ff - Enable a File Buffer Function'
db cr,lf,' f=L for Log Names to FNAMES.DIR'
db cr,lf,' f=P to Print Names stored in FNAMES.DIR'
db cr,lf,' f=S to Scan Disk and Compare to FNAMES.DIR'
db cr,lf,' I - Inspect Logged Files (FL Option Only)'
db cr,lf,' N - Negate Selection'
db cr,lf,' Oo - Toggle Output Features'
db cr,lf,' o=A for File Attributes, o=F for Form Feed'
db cr,lf,' o=G for Grouping, o=H for Horiz/Vert Format'
db cr,lf,' P - Send Display to Printer'
db cr,lf,' PF - Same as POF'
db cr,lf,' U - Select All User Areas'
db 0
;
; Return to CP/M
;
return:
lda dflg ; disk output?
ora a ; 0=no
cnz fo0$close ; close file if so
lhld stack ; get old stack ptr
sphl
ret ; return to CP/M
;
; Memory Overflow Error
;
memerr:
call printx
db cr,lf,'TPA Error',0
jmp return
;
; Print banner of XDIR III
;
banner:
call printx
db 'XDIR III, Version '
db vers/10+'0','.',(vers mod 10)+'0',0
ret
;
; Begin XDIR III processing
;
xdir:
;
; This section disables the /Ff option and /FL option if default set
;
lda fenab ; enable FFLG? (/Ff option)
ora a ; 0=no
jnz xdst1
xra a ; turn off FFLG
sta fflg
xdst1:
lda lenab ; enable FL option?
ora a ; 0=no
jnz xdst2
lda fflg ; FFLG on?
ora a ; 0=no
jz xdst2
lda fopt ; check for L
cpi 'L'
jnz xdst2
mvi a,'P' ; switch L to P
sta fopt
xdst2:
lda fflg ; file name buffer option?
ora a ; 0=no
jz xdirst
xra a ; A=0
sta gflg ; group by file name and type
lda fopt ; print immediately if P option
cpi 'P' ; print?
jnz xdirst
call banner ; print banner
jmp xdirfp ; print file names
; Check for Print Option and Ask for and Print Header if so
xdirst:
lda pflg ; printer output?
ora a ; 0=no
jz xdirgo
call print ; message to user
db cr,lf,'Please Input Header: ',0
xra a ; no caps
call bbline ; input line from user
ora a ; no chars?
jz xdirgo
call lcrlf ; new line
call lpstr ; print header line
call lcrlf ; new line
; Get Files from Disk
xdirgo:
lhld buffer ; end of code
call dbuffer ; set buffers
jz memerr ; memory overflow error?
push h ; save regs
push d
call dfree ; compute amount of free space on disk
xchg ; amount in hl
shld freesiz ; save free space count
pop d ; get regs
pop h
call dirsload ; load with sizing information
jz memerr ; memory overflow error?
push h ; save hl
mov h,b ; HL=number of files loaded
mov l,c
shld totfil ; save total count
push b ; save bc
lda curdisk ; prepare to relog in disk
mov e,a
mvi c,14 ; select disk
call bdos
lda curuser ; prepare to relog in user
mov e,a
mvi c,32 ; select user
call bdos
; Open disk file if necessary for disk output
lda dflg ; disk output?
ora a ; 0=no
jz xdir0
lxi d,dskfcb ; open disk file for char output
call fo0$open ; open file for output
xdir0:
pop b ; get count
pop h ; get ptr
; Continue processing; select desired files
lda aflg ; get file attributes
lxi d,fcb ; get ptr to fcb
call dirsel ; select files
; Now, pack and alphabetize directory
lda nflg ; negate selection?
ora a ; 0=no
cz dirpack ; select marked entries
cnz dirnpack ; select unmarked entries
lda gflg ; get grouping flag
call diralpha ; alphabetize directory
shld firstf ; save ptr to first file
mov h,b ; HL=file count
mov l,c
shld fcount ; save file count
shld countf ; save file down count
lxi h,0 ; set file size counter
shld totsiz ; save counter
lda dflg ; set temp flags
sta dflgt
lda pflg
sta pflgt
;
; Major feature selection --
; Two major features of XDIR are selected at this time:
; 1. Directory Display Functions
; 2. File Name Buffer Functions
; At this point, the following key values are know:
; FIRSTF - Pointer to First File
; FCOUNT, COUNTF - Number of Files
;
lda fflg ; get flag
ora a ; Z=Directory Display, NZ=File Name Buffer Fcts
jnz xdirf ; Do File Name Buffer Fcts
;
; Main Directory Print Routine -- This routine displays the directory to
; the console, printer, or disk as desired
;
; Print header lines and one screen of entries
xdir2:
lda dflg ; save disk and print output flags
sta dflgs
lda pflg
sta pflgs
lda dflgt ; use temp flags
sta dflg
lda pflgt
sta pflg
xra a ; A=0
sta dflgt ; clear temp flags so no banner 2nd time around
sta pflgt
; Print: Main Banner
call banner ; print banner
; Print: Horizontal/Vertical Listing Message
call printx
db ' ',0
lda hflg ; get horizontal/vertical flag
ora a ; 0=vertical
jnz xdir2a
call printx
db 'Vertical',0
jmp xdir3
xdir2a:
call printx
db 'Horizontal',0
; Print: Listing by File Name and Type or Type and Name Message
xdir3:
call printx
db ' Listing by File ',0
lda gflg ; grouping flag
ora a ; 0=name and type
jnz xdir3a
call printx
db 'Name/Type',0
jmp xdir4
xdir3a:
call printx
db 'Type/Name',0
;
; Print: Disk and User
;
xdir4:
call printx ; print everywhere
db cr,lf,' Disk: ',0
lda disk ; get current disk
adi 'A' ; convert to ASCII
call coutx ; print everywhere
call printx ; print everywhere
db ' User: ',0
lda aflg ; get user number
ani 20h ; all?
jz xdir4b
call printx
db 'All',0
jmp xdir5
xdir4b:
lda aflg ; get selected user
ani 1fh ; select user number
lxi d,numbuf ; store number in buffer
call madc ; get number
mvi b,3 ; 3 digits
call prnumx ; print number everywhere
;
; Print: Directory Name
;
xdir5:
lda aflg ; check for all users
mov c,a ; save in C
ani 20h
jnz xdir5fa
mov a,c ; get user
ani 1fh ; mask for just user
mov c,a
lda disk ; select disk
mov b,a
call dutdir ; determine if name available
jz xdir5fa
call printx
db ' Name: ',0
mvi b,8 ; 8 chars to name
xdir5n:
mov a,m ; get char
inx h ; pt to next
cpi ' ' ; don't print spaces
cnz coutx
dcr b ; count down
jnz xdir5n
;
; Print: Selected File Attributes
;
xdir5fa:
call printx
db ', File Attributes: ',0
lda aflg ; get flag
push psw ; save A
ani 80h ; Non-system?
jz xdir5a
call printx
db ' Non-System',0
xdir5a:
pop psw ; get A
ani 40h ; System?
jz xdir5b
call printx
db ' System',0
; See if any files selected
xdir5b:
lhld countf ; get file down count
mov a,h ; any files?
ora l
jnz xdir6
call printx ; print everywhere
db cr,lf,'No files selected -- ',0
jmp xdir11
;
; This is the main looping entry point for each screen display
;
xdir6:
lda aflg ; all users selected?
ani 20h
jnz xdir6a
;
; This is the header which is printed if the files in only one user area are
; displayed
;
call crlfx ; new line
call hdr2 ; pt to header
lda rsflg
ora a ; Z=no
cnz sp0 ; print RS
call sp2 ; print leading spaces
call hdr2 ; print header
lda rsflg
ora a ; Z=no
cnz sp0 ; print RS
call sp2 ; print leading spaces
call hdr2 ; print header
lda rsflg
ora a
cnz sp0
call crlfx ; new line
call hdr1 ; print underlines
lda rsflg
ora a
cnz sp1
call sp2 ; leading spaces
call hdr1 ; underlines
lda rsflg
ora a
cnz sp1
call sp2 ; leading spaces
call hdr1 ; underlines
lda rsflg
ora a
cnz sp1
jmp xdir6b
;
; General-Purpose Header Print Routines
;
sp0:
call printx
db ' RS',0
ret
sp1:
call printx
db ' --',0
ret
sp2:
call printx
db ' ',0
ret
spu:
call printx
db ' U ',0
ret
spu1:
call printx
db ' ',0
ret
spu2:
call printx
db ' - ',0
ret
hdr1:
call printx
db '-------- --- ------',0
ret
hdr2:
call printx
db 'Filename.Typ Size K',0
ret
;
; This is the header which is printed if the files in all user areas are
; displayed
;
xdir6a:
call crlfx
call spu ; print U
call hdr2 ; print header
lda rsflg
ora a
cnz sp0 ; RS
call spu1
call spu ; print U
call hdr2 ; print header
lda rsflg
ora a
cnz sp0 ; RS
call spu1
call spu ; print U
call hdr2 ; print header
lda rsflg
ora a
cnz sp0 ; RS
call crlfx
call spu2 ; 1 underscore
call hdr1 ; underscores
lda rsflg
ora a
cnz sp1
call spu1
call spu2 ; 1 underscore
call hdr1 ; underscores
lda rsflg
ora a
cnz sp1
call spu1
call spu2 ; 1 underscore
call hdr1 ; underscores
lda rsflg
ora a
cnz sp1
;
; Prepare Columnar Output
;
xdir6b:
lda dflgs ; restore disk and print flags
sta dflg
lda pflgs
sta pflg
lhld countf ; get file count down
lxi d,maxent ; assume maxent entries to print
mov a,h ; within range?
ora a ; outside of range if not
jnz xdir7 ; subtract entries to print from total entries
mov a,l ; within range?
cpi maxent ; less than maxent entries left?
jnc xdir7 ; subtract entries to print from total entries
mov d,h ; DE=HL=number of entries to print
mov e,l
xdir7:
mov a,l ; subtract entries to print (DE) from total (HL)
sub e
mov l,a
mov a,h
sbb d
mov h,a ; HL=result
shld countf ; save new down count
mov b,h ; BC=count
mov c,l
lhld firstf ; pt to first file
;
; At this point, BC=number of remaining entries, DE=number of entries to
; print, and HL pts to first entry to print
;
shld ptr1 ; save ptr to 1st entry
lda hflg ; horizontal listing?
ora a ; 0ffh = yes
jnz xdir7c ; don't worry about columns if horizontal
push d ; save count
call divde3 ; divide DE by 3, result*esize in BC, remainder in A
lxi d,esize ; DE=ESIZE (size of entry)
dad b ; add BC as a minimum
ora a ; any remainder?
jz xdir7a ; skip if none
dad d ; add in ESIZE for additional length of 1st col
xdir7a:
shld ptr2 ; save ptr to col 2
dad b ; add BC as a minimum
cpi 2 ; if remainder 2, add ESIZE for additional
jc xdir7b
dad d ; add in ESIZE
xdir7b:
shld ptr3 ; save ptr to col 3
pop d ; get count in de
;
; Main entry print routine
;
xdir7c:
mvi d,1 ; set 3's counter
xdir8:
lhld ptr1 ; pt to first entry
call prentry ; print entry
shld ptr1 ; put ptr
lda hflg ; horizontal?
ora a ; 0ffh = yes
jnz xdir9
dcr e ; count down
jz xdir10
lhld ptr2 ; get ptr
call prentry ; print entry
shld ptr2 ; put ptr
dcr e ; count down
jz xdir10
lhld ptr3 ; get ptr
call prentry ; print entry
shld ptr3 ; put ptr
xdir9:
dcr e ; count down
jnz xdir8 ; continue if not zero
shld firstf ; save ptr to first of next set of entries to print
lhld countf ; get count of remaining entries
;
; At this point, HL=number of entries left
;
mov a,h ; anything left?
ora l
jz xdir10
lda dflg ; no message if disk or printer output
mov b,a
lda pflg
ora b
jnz xdir6
call print ; screen break
db cr,lf,' --> Screen Break -- Strike any char <-- ',0
call cin ; get response
cpi ctrlc ; abort?
jz return
jmp xdir6 ; new screen display
;
; Print end statistics and exit
;
xdir10:
call crlfx ; new line
lhld fcount ; print file count
call prhlx ; print it everywhere
call printx
db ' Files Using ',0
lhld totsiz ; get total of file sizes
call prhlx ; print it everywhere
call printx
db 'K, ',0
lhld totfil ; print total file count
call prhlx ; print it everywhere
call printx
db ' Files on Disk and ',0
;
; Print Amount of Free Space Left on Disk
; Entry Point if No Files Found
;
xdir11:
lhld freesiz ; get amount of free space
call prhlx ; print it everywhere
call printx
db 'K Left',0
lda dflg ; if disk or printer output, new line
mov b,a
lda pflg
ora b
jz return
call crlfx ; new line for disk and/or printer
lda pflg ; print output
mov b,a
lda ffflg ; form feed
ana b ; if print and form feed ... NZ is set
mvi a,ff ; form feed char
cnz lout ; form feed to printer
jmp return
;
; File Name Buffer Functions
;
xdirf:
call banner ; print banner
lda iscn ; just scan?
ora a ; 0=no
jnz xdirfs
lda fopt ; get option of F command
cpi 'L' ; log names to disk?
jz xdirfl
cpi 'S' ; scan names on disk?
jz xdirfs
;
; File Name Print Option; /FP option
;
xdirfp:
call openin ; open FNAMES.DIR for input
xdfp0:
call printx
db cr,lf,cr,lf
db 'Printout of Recorded File Names --',cr,lf,' ',0
;
; Extract File Name Count
;
call f1$get ; get low count
jnz geterr
mov l,a ; save in L
call f1$get ; get high count
jnz geterr
mov h,a ; save in H
push h ; save HL
call prhlx ; print HL everywhere
call printx
db ' File Names',cr,lf,0
call prfhdr ; print file name header
pop h ; get HL
mvi c,0 ; set entry counter
;
; Loop for extracting names from FNAMES.DIR and printing them
;
xdfp1:
mov a,h ; no more entries?
ora l
jz xdfp2
dcx h ; count down
call getdfn ; get next disk file name from FNAMES.DIR
call prfnfx ; print file name entry
inr c ; increment count
mov a,c ; new line time?
ani 3
cz crlfx
jmp xdfp1
xdfp2:
call fi1$close
call crlfx ; new line
jmp return
;
; Log File Names to Disk; /FL option
; Structure of FNAMES.DIR file is:
; File Name Count, Low-Order Byte
; File Name Count, High-Order Byte
; File Names, stored as 12 bytes -- User Number, FN, and FT
;
xdirfl:
lxi d,fnfcb ; open file for output
call fo1$open
jz xdfl1
call printx
db cr,lf,'Cannot Create FNAMES.DIR',0
jmp return
; Log Files to Disk with possible initial inspect and select by user
xdfl1:
lda iflg ; inspect?
ora a ; 0=no
cnz flinsp ; inspect if selected
; Print file count
call printx
db cr,lf,cr,lf
db 'Logging File Names to Disk --',cr,lf,' ',0
lhld fcount ; get count
call prhlx ; print it
call printx
db ' File Names',cr,lf,0
; Check file count and print appropriate header
lhld fcount ; get number of files
mov a,h ; any files?
ora l
jz xdfl1a
call prfhdr ; print file name header
jmp xdfl1b
xdfl1a:
call printx ; no files
db ' No Files to be Logged',0
; Store file count to disk
xdfl1b:
mov a,l ; store low count
call f1$put
jnz puterr
mov a,h ; store high count
call f1$put
jnz puterr
xchg ; ... in DE
lhld firstf ; pt to first file
mvi c,0 ; set display counter
; Loop to store files names
xdfl2:
mov a,d ; done?
ora e
jz xdfl3
dcx d ; count down
; Write entry to disk
push d ; save count
push h ; save ptr to file
mov a,m ; get user number
call f1$put ; save it
jnz puterr
lxi d,numbuf ; print user number
push d ; save ptr
call madc
pop d ; get ptr
inx d ; pt to 1st digit
ldax d ; get it
call coutx
inx d ; pt to last digit
ldax d ; get it
call coutx
mvi a,' ' ; <SP>
call coutx
inx h ; pt to FN
mvi b,8 ; 8 chars
call xdput
mvi a,'.'
call coutx
mvi b,3 ; 3 chars
call xdput
mvi a,' ' ; print <SP>
call coutx
call coutx
inr c ; increment count
mov a,c ; get count
ani 3
cz crlfx
pop h ; get ptr to first file
pop d ; get count
push b
lxi b,esize ; pt to next file
dad b
pop b
jmp xdfl2
; Done with creation of FNAMES.DIR
xdfl3:
call fo1$close ; close file
call crlfx
jmp return
; Write B chars pted to by HL to FNAMES.DIR and user
xdput:
mov a,m ; get char
call coutx ; print it everywhere
call f1$put ; put it on disk
jnz puterr
inx h ; pt to next
dcr b ; count down
jnz xdput
ret
;
; Inspect Files for Logging to Disk
;
flinsp:
lhld fcount ; get count of files
xchg ; ... in DE
mov a,d ; any files selected?
ora e
rz ; abort if none
; Inspection banner
call printx
db cr,lf,'Inspection of Files to be Logged',0
lhld firstf ; pt to first file
; Main inspection loop
flil1:
mov a,d ; any files selected?
ora e
jz flil3 ; done if not
dcx d ; count down
push d ; save count
lxi d,dfnbuf ; copy file name to buffer
mvi b,12 ; 12 bytes
call moveb
call printx
db cr,lf,'Log ',0
call prfnfx ; print file name for prompt
call printx
db ' to Disk (Y/N)? ',0
call cin ; get response
call caps ; capitalize
call coutx
cpi 'N' ; No?
jz flil2
mov a,m ; mark user number
ori 80h
mov m,a
flil2:
lxi d,esize ; skip to next entry
dad d
pop d ; get count
jmp flil1
flil3:
lhld fcount ; get number of files
mov b,h ; count in BC
mov c,l
lhld firstf ; pt to first file
call dirpack ; pack directory
mov h,b ; new count in HL
mov l,c
shld fcount ; set counts
shld countf
ret
;
; Error Message for Output
;
puterr:
call printx
db cr,lf,'Disk Write Error',0
jmp return
;
; Scan Disk for File Names; /FS option
;
xdirfs:
call printx
db cr,lf,'File Name Scanner',0
call openin ; open FNAMES.DIR for input
xdfs1:
call printx
db cr,lf,'Files Named in FNAMES.DIR missing from Disk --',cr,lf,0
; Get file name count
call f1$get ; get file name count from disk
jnz geterr
mov c,a ; store low
call f1$get
jnz geterr
mov b,a ; store high
lhld fcount ; get count of number of files
xchg ; ... in DE
lhld firstf ; pt to first file
xra a ; A=0
sta crcnt ; set counter for CRLF
sta fmark ; mark no first file yet
;
; At this point, HL pts to first file in buffer, DE is number of files in
; buffer, and BC is number of files in FNAMES.DIR
;
mov a,b ; any names in FNAMES.DIR?
ora c
jz xdfs5 ; mark all names in buffer if not
call getdfn ; get first disk name
xdfs2:
mov a,b ; see if any more files in FNAMES.DIR
ora c
jz xdfs5 ; mark rest of files in buffer and continue
mov a,d ; see if any more files in buffer
ora e
jz xdfs6 ; name rest of files in FNAMES.DIR as missing and cont
call compfn ; compare to file name pted to by HL
jz xdfs3a ; advance to next file if they match
jc xdfs3 ; mark file name pted to by HL as additional
lda fmark ; first file?
ora a ; 0=yes
jnz xdfs2a
mvi a,0ffh ; set mark
sta fmark
call prfhdr ; print header
xdfs2a:
call prfnfx ; print file name in FNAMES.DIR
dcx b ; count down
mov a,b ; done?
ora c
jz xdfs2
call getdfn ; get next name
lda crcnt ; get entry counter
inr a ; increment
sta crcnt
ani 3 ; mask
cz crlfx ; new line every 4
jmp xdfs2
xdfs3:
mov a,m ; get user number
ori 80h ; mark it
mov m,a ; put it back
jmp xdfs4
xdfs3a:
call getdfn ; get next name
dcx b ; count down on names
xdfs4:
push d ; save count
lxi d,esize ; pt to next entry
dad d
pop d ; get count
dcx d ; count down
jmp xdfs2 ; continue
; Mark rest of files in buffer
xdfs5:
mov a,d ; check count
ora e
jz xdfs7
dcx d ; count down
mov a,m ; get user number
ori 80h ; mark it
mov m,a ; put user number
lxi b,esize ; skip to next file
dad b
jmp xdfs5 ; continue
; Name rest of files in FNAMES.DIR as missing
xdfs6:
call prfnfx ; print file name in FNAMES.DIR
dcx b ; count down
mov a,b ; done?
ora c
jz xdfs7 ; next phase
lda crcnt ; get entry counter
inr a ; increment
sta crcnt
ani 3 ; mask
cz crlfx ; new line every 4
call getdfn ; get next name
jmp xdfs6
; Part 2 of Scan - Name Additional Files
xdfs7:
lda fmark ; no files printed?
ora a ; 0=none
jnz xdfs7a
call printx
db ' No Files Missing',0
xdfs7a:
xra a ; A=0
sta fmark ; set mark for 2nd part
call printx
db cr,lf,'Additional Files on Disk NOT in FNAMES.DIR --',cr,lf,0
lhld fcount ; get count of files
xchg ; ... in DE
lhld firstf ; pt to first file
xra a ; A=0
sta crcnt ; set counter
xdfs8:
mov a,d ; check count
ora e
jz xdfs9 ; done if zero
dcx d ; count down
mov a,m ; get user number
ani 80h ; marked?
jz xdfs8b ; skip if not
mov a,m ; get user number
ani 7fh ; mask
mov m,a ; replace
lda fmark ; first time?
ora a ; 0=yes
jnz xdfs8a
mvi a,0ffh ; set mark
sta fmark
call prfhdr ; print header
xdfs8a:
push d ; save count
lxi d,dfnbuf ; copy to buffer for print
mvi b,12 ; 12 bytes
call moveb ; copy
pop d
call prfnfx ; print file name
lda crcnt ; count down
inr a
sta crcnt
ani 3 ; new line?
cz crlfx
xdfs8b:
lxi b,esize ; pt to next entry
dad b
jmp xdfs8 ; continue
; Done with Scan
xdfs9:
lda fmark ; no files printed?
ora a ; 0=none
jnz xdfs9a
call printx
db ' No Additional Files',0
xdfs9a:
jmp return
;
; Compare file name pted to by HL with that in DFNBUF; return with Z if same,
; C if (HL)<(DFNBUF)
;
compfn:
push h ; save regs
push d
push b
lxi d,dfnbuf ; pt to buffer
xchg ; DE pts to file name, HL pts to DFNBUF
push h ; save ptrs
push d
mvi b,11 ; compare FN and FT
cfn1:
inx h ; pt to next
inx d
mov a,m ; get char from DFNBUF
ani 7fh ; mask MSB
mov c,a ; save in C
ldax d ; get name in memory buffer
ani 7fh ; mask MSB
cmp c ; compare to name in DFNBUF
jnz cfn2 ; not same, so exit with flag set
dcr b ; count down
jnz cfn1
pop d ; same so far, so compare user numbers
pop h
mov a,m ; get user number
ani 7fh ; mask MSB
mov c,a ; save in C
ldax d ; get user number
ani 7fh ; mask MSB
cmp c ; compare
push h ; fill stack for ext
push h
cfn2:
pop h ; clear stack
pop h
pop b ; get regs and exit
pop d
pop h
ret
;
; General Utility Routines
;
;
; Print user and file name stored in DFNBUF for /Ff functions
;
prfnfx:
push h ; save regs
push d
push b
lxi h,dfnbuf ; pt to first byte of buffer
mov a,m ; get first byte (user number)
lxi d,numbuf ; convert to chars in memory
call madc
lxi d,numbuf+1 ; pt to first char
ldax d ; get it
call coutx
inx d ; pt to 2nd char
ldax d ; get it
call coutx
mvi a,' ' ; <SP>
call coutx
inx h ; pt to FN
mvi b,8 ; 8 chars for FN
call prch
mvi a,'.'
call coutx
mvi b,3 ; 3 chars for FT
call prch
call prfhs ; 2 <sp>
pop b ; get regs
pop d
pop h
ret
;
; Get next User Number, FN, and FT from disk and save it in buffer
;
getdfn:
push h ; save regs
push d
push b
lxi h,dfnbuf ; pt to buffer
mvi b,12 ; 12 bytes
getdf1:
call f1$get ; get user
jnz geterr
mov m,a ; store user
inx h ; pt to next
dcr b ; count down
jnz getdf1
pop b ; restore regs
pop d
pop h
ret
;
; Print File Buffer Names Header Everywhere
;
prfhdr:
mvi b,3 ; 3 times
prfhd1:
call prfh1 ; print header
call prfhs ; print 2 spaces
dcr b
jnz prfhd1
call prfh1
call crlfx
mvi b,3 ; 3 times
prfhd2:
call prfh2 ; print header
call prfhs ; print 2 spaces
dcr b
jnz prfhd2
call prfh2
call crlfx
ret
prfhs:
call printx
db ' ',0
ret
prfh1:
call printx
db ' U Filename.Typ',0
ret
prfh2:
call printx
db ' - -------- ---',0
ret
;
; Get Error Message and Abort
;
geterr:
call printx
db cr,lf,'Premature EOF',0
jmp return
;
; Open FNAMES.DIR for byte-oriented input
;
openin:
lxi d,fnfcb ; open file
call fi1$open ; open for input
rz
call printx
db cr,lf,'FNAMES.DIR Not Found',0
jmp return
;
; Print disk entry for normal directory display functions
;
prentry:
dcr d ; count <CRLF> counter
jnz prent1
mvi d,3 ; reset count
call crlfx
prent1:
shld entptr ; save entry ptr
lda aflg ; all users selected?
ani 20h
jz prent2
;
; The following prints the user number if all user numbers are selected
;
push h ; save regs
push d
push b
mov a,m ; get user number
ani 1fh ; mask it
lxi d,numbuf
call madc ; convert to chars in memory
lxi h,numbuf+1 ; pt to first char
mov a,m ; get it
call coutx
inx h ; get 2nd char
mov a,m
call coutx
mvi a,' ' ; print <SP>
call coutx
pop b ; get regs
pop d
pop h
prent2:
inx h ; pt to first char of file name
mvi b,8 ; print 8 chars
call prch
mvi a,'.' ; print dot
call coutx
push h ; save RS ptr
mvi b,3 ; print 3 chars
call prch
push d ; save de
lhld entptr ; pt to entry
mvi a,' ' ; skip 2 spaces
call coutx
call coutx
call fsize ; compute file size
lhld totsiz ; get total file size counter
dad d ; add in new file
shld totsiz ; save new total file size counter
xchg ; get file size into HL
call prhlx ; print HL value
pop d ; get de
pop h ; pt to RS
lda rsflg ; print RS fields?
ora a ; Z=no
jz pren2a
mvi a,' ' ; print 1 space
call coutx
mvi b,'R' ; letter
call prletx ; print R if bit set
inx h
mvi b,'S' ; letter
call prletx ; print S if bit set
dcx h ; ... for following inx h
pren2a:
inx h ; point correctly
mvi a,' ' ; 1 space
call coutx
lda aflg ; all users?
ani 20h
jnz prent3
;
; The following prints 2 additional spaces if only one user area is selected
;
mvi a,' ' ; 2 more spaces for not all users
call coutx
call coutx
prent3:
lxi b,6 ; pt to next entry
dad b
ret
;
; Print B chars pted to by HL
;
prch:
mov a,m ; get char
inx h ; pt to next
ani 7fh ; mask out msb
cpi ' ' ; within range?
jnc prch1 ; print special char if not valid char
mvi a,'?' ; print ? if not valid char
prch1:
call coutx ; print it
dcr b ; count down
jnz prch
ret
;
; Extended Print Routines
;
prletx:
mov a,m ; get byte
ani 80h ; look at msb
jz prlets
mov a,b ; get letter
call coutx
ret
prlets:
mvi a,' ' ; print <sp>
call coutx
ret
prhlx:
lxi d,numbuf ; store in number buffer
call mhldc ; hl into memory as decimal
mvi b,5 ; 5 digits
prnumx:
lxi h,numbuf ; pt to buffer
prnum:
mov a,m ; get digit
inx h ; pt to next
call coutx ; print everywhere
dcr b ; count down
jnz prnum
ret
printx:
xthl ; pt to string
call prxl ; print string at HL
xthl
ret
prxl:
mov a,m ; get byte
inx h ; pt to next
ora a ; done?
rz
call coutx ; print everywhere
jmp prxl
coutx:
push b ; save bc
push psw ; save char
ani 7fh ; mask out msb
mov b,a ; char in B
call cout ; print to screen
lda pflg ; printer on?
ora a ; 0=no
mov a,b ; get char
cnz lout ; printer output if on
lda dflg ; disk on?
ora a ; 0=no
mov a,b ; get char
cnz f0$put ; output to file
pop psw ; get char
pop b ; get bc
ret
crlfx:
push psw ; save A
call printx
db cr,lf,0
pop psw ; get A
ret
;
; Divide DE by 3; return with BC=result*esize, a=remainder
;
divde3:
push d ; save de, hl
push h
mvi d,0 ; make sure D=0
mov a,e ; value in A
divd31:
sui 3 ; subtract 3
jc divd32
jz divd33
inr d ; add 1 to result
jmp divd31
divd32:
adi 3 ; add back in
jmp divd34
divd33:
inr d ; add 1 for even division
divd34:
sta rem ; save remainder
lxi b,esize
lxi h,0
divd35:
mov a,d ; done?
ora a ; 0=yes
jz divd36
dcr d
dad b ; add in another ESIZE
jmp divd35
divd36:
mov b,h ; BC is result
mov c,l
lda rem ; A is remainder
pop h ; restore regs
pop d
ret
;
; Skip blanks
;
sblank:
mov a,m ; pt to char
cpi ' ' ; blank?
rnz
inx h ; pt to next
jmp sblank
;
; Buffers
;
aflg: ds 1 ; attibute flag
dflg: ds 1 ; disk output on flag
fflg: ds 1 ; 0=no file name buffer function
gflg: ds 1 ; 0=group by name/type
hflg: ds 1 ; 0=vertical list
iflg: ds 1 ; 0=no inspect
nflg: ds 1 ; 0=no negate
pflg: ds 1 ; printer output on flag
fopt: ds 1 ; file name buffer option
crcnt: ds 1 ; entry counter
fmark: ds 1 ; first file marker
dflgt: ds 1 ; temp flags
pflgt: ds 1
dflgs: ds 1
pflgs: ds 1
rsflg: ds 1 ; RS Display Flag
ffflg: ds 1 ; form feed flag
disk: ds 1 ; selected disk
curdisk:
ds 1 ; current disk
curuser:
ds 1 ; current user
rem: ds 1 ; remainder buffer
firstf: ds 2 ; ptr to first file of group to print
totfil: ds 2 ; total number of files on disk
fcount: ds 2 ; count of files
countf: ds 2 ; down count of files
freesiz:
ds 2 ; amount of free space on disk
totsiz:
ds 2 ; total size of all files
ptr1: ds 2 ; col output ptrs
ptr2: ds 2
ptr3: ds 2
entptr: ds 2 ; current entry ptr
numbuf: ds 6 ; number buffer
dfnbuf:
ds 12 ; disk file name buffer
dskfcb:
db 0
db 'XDIR DIR'
db 0,0,0,0
ds 16
ds 4
fnfcb:
db 0
db 'FNAMES DIR'
db 0,0,0,0
ds 16
ds 4
cmdlne: ds 2 ; pointer to command line
buffer: ds 2 ; pointer to free space buffer
stack: ds 2 ; stack ptr
end