;
; TITLE DU
;
; Disk usage by PPn for a device
;
; THIS PROGRAM MAY BE FREELY DISTRIBUTED TO AMUS MEMBERS
; COURTESY OF WHITE HOUSE SOFTWARE, INC.
;
; Note: to get a sorted listing of disk usage, do the following
; DU X.LST=DSK2:
; SORT X.LST
; record length = 80
; key size = 11
; key position = 11
; order = d (descending)
; Press RETURN on next key size question
;
;Edit History:
;
; 5/30/86 1.0(0) - David Greene
; Written
;
VEDIT=0.
SEARCH SYS
SEARCH SYSSYM
; Define TAB and Carriage Return
TAB=9.
CR=13.
; Define Version Information
VMAJOR=1.
VMINOR=0.
VSUB=0.
VWHO=0.
; Start of program
PHEAD: PHDR -1,0,PH$REE!PH$REU
TYPECR <DU is courtesy of White House Software, Inc.>
BYP ; skip blanks and tabs
LIN ; end of string?
JNE DU10
DU0:
TYPECR <Usage: DU Dev: - Print listing to screen>
TYPECR < DU =Dev: - Print listing to DU.LST>
TYPECR < DU outfil=Dev: - Pring listing to specified output file>
TYPECR < (Default extention is .LST)>
CRLF
EXIT
;
; get command string file specifications
;
DU10:
GETIMP IMPSIZ,A5 ; get impure area
CLR TOTCNT(A5) ; no kilobytes yet
SETB FILOUT(A5) ; assume output is to a file
CMPB @A2,#'= ; output to file.LST?
BEQ DU30 ; yup
MOV A2,D4 ; save A2 for a second
FSPEC DDBOUT(A5),LST ; output file specification
BYP ; ignore spaces
CMPB @A2,#'= ; was that the output file?
BEQ DU20 ; yup
MOV D4,A2 ; ->start of input file name
CLRB FILOUT(A5) ; output is not to a file
BR DU80
; DU file.out=Dev:
; (full input and output specification)
DU20:
INC A2 ; bypass '='
BYP ; any device spec?
LIN ; no - show user how to invoke
JEQ DU0
BR DU80 ; done with file specifications
; DU =Dev:
; (output is to file.LST)
DU30:
INC A2 ; bypass '='
BYP ;
LIN ; any device specification?
JEQ DU0 ; no - show user how to invoke
MOV A2,D4 ; ->start of input file name
PUSH A2 ; save A2 a second
LEA A2,OPNFIL ; index default output filename
FSPEC DDBOUT(A5),LST ; DU.LST
POP A2
BR DU80
; Default filename when .DU =Dev#:
OPNFIL:
ASCII /DU/
BYTE 0
EVEN
DU80:
;
; set up input device
;
CLRW DDBIN(A5) ; not yet INITed
INIT DDBIN(A5) ; get buffers
SET D6 ; stop scanning after device spec
FSPEC DDBIN(A5) ; process device spec
;
; open output file
;
TSTB FILOUT(A5) ; output to a file?
BEQ MAIN ; nope
CLRW DDBOUT(A5) ; not yet INITed
INIT DDBOUT(A5) ; get buffers
LOOKUP DDBOUT(A5) ; look it up
BNE 40$
DSKDEL DDBOUT(A5) ; delete existing file
40$:
OPENO DDBOUT(A5) ; open for output
; output header for file
LEA A2,DDBOUT(A5) ; A2 must point to output DDB
OUTS OT$DDB,<Disk Usage listing for >
OFILE DDBIN(A5),OT$DDB
OUTCR OT$DDB
PAGE
;*************
;* MAIN *
;*************
; Main processing loop
; We go from PPn to PPn and call DOPPN which calculate disk usage
; for that account.
MAIN:
; MFD starts with block number 1
MOV #1,DDBIN+D.REC(A5) ; block number 1
; Main MFD loop
5$:
READ DDBIN(A5) ; read MFD
MOV DDBIN+D.BUF(A5),A2 ; A2->MFD buffer
10$:
TSTW MF.PPN(A2) ; end of MFD?
BEQ 20$ ; Yes
; process a PPn
CTRLC EXIT$ ; allow CTRL-C
CALL DOPPN ; process one PPn
; get next PPn for loop
ADD #MF.SIZ,A2 ; Advance to next MFD entry
MOV DDBIN+D.BUF(A5),A6 ; End of buffer?
ADD DDBIN+D.SIZ(A5),A6
SUB #MF.SIZ,A6
CMP A2,A6 ; are we at the end of an MFD block?
BLO 10$ ; no - continue
; we are past the last PPn in this block, get the next one
; if there is one
MOVW MF.NXT(A6),DDBIN+D.REC+2(A5);Advance to next MFD record
BNE 5$ ; And continue unless no more blocks
; no more PPns
; output total kilobytes used
20$:
LEA A2,OUTLIN(A5)
OUTSP OT$MEM,<Total disk space used is>
MOV TOTCNT(A5),D4
ROR D4,#1 ; divide by 2; N bit set if remainder
CLR D1
MOVW D4,D1 ; get number of kilobytes
; output kilobytes used
DCVT 0,OT$MEM ; output number of Kilobytes
MOVB #'.,(A2)+ ; output decimal point
MOVB #'0,D1 ; no remainder yet
TST D4 ; any remaider from before?
BPL 25$ ; no - finish
MOVB #'5,D1 ; .5 remainder
; output remainder
25$:
MOVB D1,(A2)+ ; yes - show user
OUTS OT$MEM,<K bytes> ; show number is kilobytes
MOVB #CR,(A2)+ ; output Carriage return
CLRB @A2 ; we need null terminator
; print line to appropriate place
CALL LINOUT ; output last line
; close output file if open
TSTB FILOUT(A5) ; are we outputing to a file?
BEQ EXIT$ ; no - no need to close
CLOSE DDBOUT(A5) ; yes - wrap it up
EXIT$:
EXIT ; we're done
PAGE
;*************
;* DOPPN *
;*************
; Entry:
; A2->PPN @ MFD
; Exit:
; A1,A3,A4,D1,D4 modified
DOPPN:
; we have a PPn match
PUSH A2 ; save MFD pointer
PUSH D.REC+DDBIN(A5) ; save MFD block number
PUSH D.BUF+DDBIN(A5) ; save buffer address
; Use a seperate buffer for the directory
LEA A6,DIRBUF(A5) ; don't use any registers
MOV A6,D.BUF+DDBIN(A5) ; set buffer for directory to use
; output PPn
MOV A2,A3 ; yes - save PPn pointer
; set octal
JOBIDX A4 ; get my job
PUSHW JOBTYP(A4) ; save my type
ANDW #^C<J.HEX>,JOBTYP(A4) ; make sure we are octal
; output PPn to output line buffer
LEA A2,OUTLIN(A5) ; A2-> output buffer
CLR D1
MOVB #'[,(A2)+
MOVB 1(A3),D1 ; get project number
OCVT 0,OT$MEM ; output it
MOVB #',,(A2)+
MOVB @A3,D1 ; programmer number
OCVT 0,OT$MEM ; output it
MOVB #'],(A2)+
MOVB #40,(A2)+ ; followed by some blanks
MOVB #40,(A2)+
MOVB #40,(A2)+
MOVB #40,(A2)+
MOVB #40,(A2)+
; set directory info and get space used in this UFD
MOVW 2(A2),D.REC+2+DDBIN(A5) ; set directory block number
; SCNDIR returns D4 with number of blocks in directory
CALL SCNDIR ; scan directory (D4)
; Now D4 contains number of blocks. After we rotate, (which will divide the
; number of blocks by 2, giving us kilobytes,) we will have the N-bit set if
; set if we have an extra half a kilobyte
; first accumulate total
ADD D4,TOTCNT(A5) ; keep running total
; now calculate kilobytes
ROR D4,#1 ; divide by 2; N bit set if remainder
CLR D1
MOVW D4,D1 ; get number of kilobytes
; output kilobytes used
PUSH A2 ; save pointer
LEA A2,10.+OUTLIN(A5) ; allow exactly 10 spaces for [PPN]
DCVT 5,OT$MEM!OT$ZER ; output number of Kilobytes
MOVB #'.,(A2)+ ; output decimal point
MOVB #'0,D1 ; no remainder yet
TST D4 ; any remainder from before?
BPL 25$ ; no - finish
MOV #'5,D1 ; .5 remainder
; output remainder
25$:
MOVB D1,(A2)+ ; yes - show user
MOVB #'K,(A2)+ ; show number is kilobytes
MOVB #CR,(A2)+ ; output Carriage return
CLRB @A2 ; place at end of output buffer
POP A2
; Now print line
CALL LINOUT ; output line to appropriate place
; Done with this PPn - restore info
100$:
POP D.BUF+DDBIN(A5) ; restore MFD areas
POP D.REC+DDBIN(A5)
POP A2
RTN
PAGE
;*************
;* SCNDIR *
;*************
; Entry:
; A2->PPn buffer[not used]
; DDBIN set up for directory reads
;
; Exit:
; D4 contains number of total blocks in this directory
;
SCNDIR:
SAVE A2,D1,D3 ; save work registers
CLR D4 ; clear block count
TST D.REC+DDBIN(A5) ; is there a directory ?
JEQ RTNDIR ; no - just return
; This is the master loop
DIRLOP:
READ DDBIN(A5) ; get a directory block
MOV D.BUF+DDBIN(A5),A2 ; A2 -> directory buffer
MOVW (A2)+,D1 ; D1 -> next block number
MOV #42.,D3 ; 42 entries per block
; This loop scans an entire block and checks for matches
DIRLP2:
TSTW @A2 ; are we at the end of the directory?
BEQ RTNDIR ; yes - return
CMPW @A2,#-1 ; empty slot ?
BEQ NXTDIR ; yes - get the next one
ADDW 6(A2),D4
; get the next directory item, if end of block
; then set up for next block
NXTDIR:
ADD #14,A2 ; next directory item please
SOB D3,DIRLP2 ; are we at the end of the block ?
MOVW D1,D.REC+2+DDBIN(A5) ; yes - set next block number
BNE DIRLOP ; if zero we're done
RTNDIR:
REST A2,D1,D3
RTN
PAGE
;*************
;* LINOUT *
;*************
;Output OUTLIN(A5) to terminal or file
; Entry:
; FILOUT(A5) set if we want to output to file
; clear if we want output to terminal
; Exit:
; Line outputted
LINOUT:
PUSH A2
TSTB FILOUT(A5) ; are we outputting to a file ?
BEQ 10$ ; no - output to screen
; output line to file
LEA A2,DDBOUT(A5) ; A2->output DDB for OUTL call
OUTL OUTLIN(A5),OT$DDB ; output line to file
BR 20$
; output line to terminal
10$:
TTYL OUTLIN(A5)
; finish routine
20$:
POP A2
RTN
;define impure area
SAVDOT=.
=0
DDBIN: BLKB D.DDB ; input ddb
DDBOUT: BLKB D.DDB ; output ddb
DIRBUF: BLKB 512. ; disk buffer for UFD reads
OUTLIN: BLKB 40. ; output file buffer
TOTCNT: BLKL 1 ; total kilobytes used
FILOUT: BLKB 1 ; output flag
EVEN
IMPSIZ=.
=SAVDOT