	.TITLE	DISK_FRAGMENTATION_STATISTICS
	.SUBTITLE	DECLARE CONSTANTS AND MACROS
	.ENABLE		DEBUG
;	DISK FRAGMENTATION DISPLAY PROGRAM
;	MICHAEL N. LEVINE
;	CODE 3514
;	NAVAL WEAPONS CENTER
;	CHINA LAKE
;	CA
;	(619)939-2465	AVN 437-2465
	$DVIDEF
	$DCDEF
;  MACRO TO CONVERT A LONG WORD BINARY NUMBER TO AN UNSIGNED INTEGER STRING
	.MACRO	GENSTR	SIZE,LOC,VAR
		MOVL	SIZE,DESCRIPTER
		MOVAL	LOC,DESCRIPTER+4
		$FAO_S	CTRSTR,,DESCRIPTER,VAR
	.ENDM
	.MACRO	GENPCT	VAR,LOC,DIVISOR,MULT,?AAA,?BBB,?CCC,?DDD,?EEE
		CVTLD	VAR,TEMP
		BEQL	DDD
		MULD2	TEN_K,TEMP
		.IF	NB	MULT
			CVTLD	MULT,TEMP_2
			MULD2	TEMP_2,TEMP
		.ENDC
		CVTLD	DIVISOR,TEMP_2
		BNEQ	EEE
		CLRF	TEMP
		BRB	DDD
EEE:		DIVD2	TEMP_2,TEMP
		ADDD2	HALF,TEMP
DDD:		CVTDL	TEMP,TEMP
		MOVL	#5,DESCRIPTER
		MOVAL	LOC,DESCRIPTER+4
		$FAO_S	CTRSTR_2,,DESCRIPTER,TEMP
		MOVC3	#2,LOC+3,LOC+4
		MOVB	#^A/./,LOC+3
		CMPB	#^A/ /,LOC+5
		BNEQ	AAA
		MOVB	#^A/0/,LOC+5
AAA:		CMPB	#^A/ /,LOC+4
		BNEQ	BBB
		MOVB	#^A/0/,LOC+4
BBB:		CMPB	#^A/ /,LOC+2
		BNEQ	CCC
		MOVB	#^A/0/,LOC+2
CCC:
	.ENDM
;  MACRO TO PRINT OUT A STRING
	.MACRO	PUTSTR	SIZE,LOC
		MOVL	SIZE,DESCRIPTER
		MOVAL	LOC,DESCRIPTER+4
		CALLG	OUTPUT_ARG,G^LIB$PUT_OUTPUT
	.ENDM
	.PAGE
	.SUBTITLE	DATA STORAGE
	.PSECT	PURE_DATA,RD,NOWRT,SHR,NOEXE,LONG,GBL,CON
;
;	ARGUMENT LIST FOR ERROR MESSAGE THAT SELECTED DEVICE IS NOT A DISK
;
NOT_DISK_ARG:
	.LONG	1
	.ADDRESS	NOT_DISK_STRING
NOT_DISK_STRING:
	.ASCID	/Specified device is not a disk/
;
;	ARGUMENT LIST FOR LIB$GET_FOREIGN
;
GET_ARG:
	.LONG	4
	.ADDRESS	DEVICE_NAME
	.ADDRESS	PROMPT
	.ADDRESS	LENGTH
	.ADDRESS	FORCE
PROMPT:	.ASCID	/Device ? /
;
;	Unable to flush bitmap message
;
NO_FLUSH:	.ASCID	/Unable to flush bitmap-useing old data/
;
;	ITEM LIST FOR THE $GETDVI CALL
;
ITEM_LIST:
	.WORD	4,DVI$_CLUSTER
	.ADDRESS	CLUSTER_SIZE
	.LONG	0
	.WORD	4,DVI$_DEVCLASS
	.ADDRESS	CLASS
	.LONG	0
	.WORD	4,DVI$_MAXBLOCK
	.ADDRESS	MAXBLOCK
	.LONG	0
	.WORD	4,DVI$_FREEBLOCKS
	.ADDRESS	FREE
	.LONG	0
	.LONG	0
;
;	LIST OF BOUNDRY VALUES FOR BUCKETS. THE FIRST MUST BE "1" AND THE
;	LAST "-1", TO CHANGE THE BUCKET BOUNDRY VALUES AND NUMBER OF BUCKETS,
;	JUST CHANGE THE LIST BELOW. THE PROGRAM IS WRITTEN TO TAKE CARE
;	OF THE DETAILS.-- THE LIST MUST BE MONOTONICALLY INCREASING.
;
BUCKET_SIZE_LIST:
	.LONG	1,5,10,25,50,75,100,250,500,750,1000,2500,5000,7500
	.LONG	10000,25000,50000,75000,100000,250000,500000,750000
	.LONG	1000000,2500000,5000000,7500000,10000000
	.LONG	-1
NUMBER_OF_BUCKETS = <<<.-BUCKET_SIZE_LIST>/4>-1>
;
;	MAP THE BITS IN EACH 32 BIT WORD
;
BIT_MAP:.LONG	^X1,^X2,^X4,^X8,^X10,^X20,^X40,^X80,^X100,^X200,^X400,^X800
	.LONG	^X1000,^X2000,^X4000,^X8000,^X10000,^X20000,^X40000,^X80000
	.LONG	^X100000,^X200000,^X400000,^X800000
	.LONG	^X1000000,^X2000000,^X4000000,^X8000000
	.LONG	^X10000000,^X20000000,^X40000000,^X80000000
;
;	STATISTICS CONSTANTS
;
TEN_K:	.DOUBLE	10000.0
HALF:	.DOUBLE	0.5
;
;	Argument list for LIB$GET_COMMAND to see if next disspla is wanted
;
NEXT_DISSPLA_ARG:
	.LONG	3
	.ADDRESS	YES_NO
	.ADDRESS	P_PROMPT
	.ADDRESS	YES_NO_LENGTH
P_PROMPT:	.ASCID	!Do you want the distribution display (Y/N) [N] ? !
;
;	Plotting dispatch table
;
PLOT_DISPATCH_TABLE:
	.ADDRESS	PLT_5+11
	.ADDRESS	PLT_10+11
	.ADDRESS	PLT_15+11
	.ADDRESS	PLT_20+11
	.ADDRESS	PLT_25+11
	.ADDRESS	PLT_30+11
	.ADDRESS	PLT_35+11
	.ADDRESS	PLT_40+11
	.ADDRESS	PLT_45+11
	.ADDRESS	PLT_50+11
	.ADDRESS	PLT_55+11
	.ADDRESS	PLT_60+11
	.ADDRESS	PLT_65+11
	.ADDRESS	PLT_70+11
	.ADDRESS	PLT_75+11
	.ADDRESS	PLT_80+11
	.ADDRESS	PLT_85+11
	.ADDRESS	PLT_90+11
	.ADDRESS	PLT_95+11
	.ADDRESS	PLT_100+11
	.PAGE
	.PSECT	IMPURE_DATA,RD,WRT,NOSHR,NOEXE,QUAD,GBL,CON
;
;	ARGUMENT LIST FOR LIB$PUT_OUTPUT
;
OUTPUT_ARG:
	.LONG	1,DESCRIPTER
;
;	FORMAT LIST FOR $FAO_S
;
CTRSTR:	.ASCID	/!10UL/
CTRSTR_2:.ASCID	/!5UL/
;
;	GENERIC STRING DESCRIPTER
;
DESCRIPTER:
	.LONG	0,0
;
;	ASSORTED TEXT LINES AWAITING INSERTION OF INTEGER STRINGS FOR OUTPUT
;
LINE_1:	.ASCII	/Disk size in blocks             /
LINE_1_DATA:
	.ASCII	/              /
LINE_2:	.ASCII	/Number of free blocks           /
LINE_2_DATA:
	.ASCII	/              /
LINE_3:	.ASCII	/Cluster size in blocks          /
LINE_3_DATA:
	.ASCII	/              /
LINE_4:	.ASCII	/Largest free space in clusters  /
LINE_4_DATA:
	.ASCII	/              /
LINE_9:	.ASCII	/Fragmentation factor (0-100%)   /
LINE_9_A:.ASCII	/      %       /
LINE_5:	.ASCII	/ /
LINE_6:	.ASCII	/Free area size in clusters      Count of       Total   /
	.ASCII	/        % Disk  % Free/
LINE_6_A:.ASCII	/                                Fragments      Clusters/
	.ASCII	/        Space   Space /
LINE_7:	.ASCII	/              -/
LINE_7_B:.ASCII	/                 /
LINE_7_A:
	.ASCII	/              (/
LINE_7_C:.ASCII	?              /?
LINE_7_D:.ASCII	?      %/?
LINE_7_E:.ASCII	/      %)/
LINE_8:	.ASCII	/                        Total   /
LINE_8_A:.ASCII	/              (/
LINE_8_B:.ASCII	?              /?
LINE_8_C:.ASCII	?      %/?
LINE_8_D:.ASCII	/      %)/
;
;	BUCKETS FOR COUNT OF NUMBER OF FRAGMENTS OF IN GIVEN SIZE RANGE
;
BUCKET_BRIGADE:
	.BLKL	NUMBER_OF_BUCKETS
;
;	TOTAL NUMBER OF CLUSTERS IN A GIVEN BUCKET AND TOTAL FOUND (LAST SLOT)
;
TOTALS:	.BLKL	NUMBER_OF_BUCKETS+1
;
;	TOTAL NUMBER OF FRAGMENTS FOUND
;
TOTAL_FRAGS:
	.LONG	0
;
;	TEMPORARY STORAGE
;
TEMP:	.LONG	0,0
TEMP_2:	.LONG	0,0
;
;	LAST BLOCK NUMBER IN SYS$DISK:[000000]BITMAP.SYS READ IN
;
BLOCK_NUMBER:
	.LONG	0
	.ALIGN	QUAD
;
;	BIT MAP BLOCK
;
BLOCK:	.BLKB	512
;
;	LONGEST FRAGMENT FOUND
;
LONGEST:.LONG	0
;
;	WHAT DOES THE SYSTEM SAY THE NUMBER OF FREE BLOCKS IS
;
FREE:	.LONG	0
;
;	DISK SIZE IN BLOCKS
;
MAXBLOCK:
	.LONG	0
;
;	WHAT TYPE OF DEVICE IS THIS (SHOULD BE A DISK)
;
CLASS:	.LONG	0
;
;	GET DISK CLUSTER SIZE
;
CLUSTER_SIZE:
	.LONG	0
FRAGMENTATION_FACTOR:
	.LONG	0
;
;	FORCE THE PROMPT IF NO DEVICE SPECIFIED ON COMMAND LINE
;
FORCE:	.LONG	0
;
;	LENGTH OF INPUT STRING
;
LENGTH:	.LONG	0
;
;	SPECIFIED DEVICE STRING STORED HERE
;
DEVICE_NAME:
	.ASCID	/                                                            /
;
;	IO STATUS BLOCK
;
IOSB:	.LONG	0,0
;
;	THIS IS THE FILE WANTED FOR THE BIT MAP
;
DEFAULT_NAME:
	.ASCII	/SYS$DISK:[000000]BITMAP.SYS/
DFLT_NAM_SIZ=.-DEFAULT_NAME
;
;	DEFINE THE FAB AND RAB FORTHE BIT MAP FILE
;
	.ALIGN	LONG
FAB_1:	$FAB	ALQ=0,-
		DEQ=0,-
		DNA=DEFAULT_NAME,DNS=DFLT_NAM_SIZ,-
		FAC=<BIO,BRO,GET,PUT,UPD>,-
		FNA=<DEVICE_NAME+8>,FNS=0,-
		SHR=<NIL>
	.ALIGN	LONG
RAB_1:	$RAB	BKT=1,-
		FAB=FAB_1,-
		ROP=<BIO>,-
		UBF=BLOCK,USZ=512
	.ALIGN	LONG
FAB_2:	$FAB	ALQ=0,-
		DEQ=0,-
		DNA=DEFAULT_NAME,DNS=DFLT_NAM_SIZ,-
		FAC=<BIO,BRO,GET>,-
		FNA=<DEVICE_NAME+8>,FNS=0,-
		FOP=<SQO>,SHR=<PUT,GET,DEL,UPD,UPI>
	.ALIGN	LONG
RAB_2:	$RAB	BKT=1,-
		FAB=FAB_2,-
		ROP=<BIO>,-
		UBF=BLOCK,USZ=512
;
;	Input for distribution dissplay
;
YES_NO:	.ASCID	/ /
YES_NO_LENGTH:	.LONG	0
;
;	Terminal dissplay for distribution-build up area
;
	.ASCID	/ Free fragment size (% of largest fragment) vs starting LBN (% of disk size)/
PLT_100:.ASCII	/     100% +                                                  /
PLT_100_LEN=.-PLT_100
PLT_95:	.ASCII	/          |                                                  /
PLT_95_LEN=.-PLT_95
PLT_90:	.ASCII	/F  o      |                                                  /
PLT_90_LEN=.-PLT_90
PLT_85:	.ASCII	/r  f      |                                                  /
PLT_85_LEN=.-PLT_85
PLT_80:	.ASCII	/e     80% +                                                  /
PLT_80_LEN=.-PLT_80
PLT_75:	.ASCII	/e  l      |                                                  /
PLT_75_LEN=.-PLT_75
PLT_70:	.ASCII	/   a      |                                                  /
PLT_70_LEN=.-PLT_70
PLT_65:	.ASCII	/f  r      |                                                  /
PLT_65_LEN=.-PLT_65
PLT_60:	.ASCII	/r  g  60% +                                                  /
PLT_60_LEN=.-PLT_60
PLT_55:	.ASCII	/a  e      |                                                  /
PLT_55_LEN=.-PLT_55
PLT_50:	.ASCII	/g  s      |                                                  /
PLT_50_LEN=.-PLT_50
PLT_45:	.ASCII	/   t      |                                                  /
PLT_45_LEN=.-PLT_45
PLT_40:	.ASCII	/s     40% +                                                  /
PLT_40_LEN=.-PLT_40
PLT_35:	.ASCII	/i  f      |                                                  /
PLT_35_LEN=.-PLT_35
PLT_30:	.ASCII	/z  r      |                                                  /
PLT_30_LEN=.-PLT_30
PLT_25:	.ASCII	/e  a      |                                                  /
PLT_25_LEN=.-PLT_25
PLT_20:	.ASCII	/|  g  20% +                                                  /
PLT_20_LEN=.-PLT_20
PLT_15:	.ASCII	/%         |                                                  /
PLT_15_LEN=.-PLT_15
PLT_10:	.ASCII	/          |                                                  /
PLT_10_LEN=.-PLT_10
PLT_5:	.ASCII	/          |                                                  /
PLT_5_LEN=.-PLT_5
PLT_0:	.ASCII	/       0% +------------------------+------------------------+/
PLT_0_LEN=.-PLT_0
TITLE_2:.ASCID	/          0%                      50%                      100%/
TITLE_3:.ASCID	?           Free frag starting location-% (LBN/DISK_SIZE)*100?
PLOT_100:	.LONG	PLT_100_LEN
		.ADDRESS	PLT_100
PLOT_95:	.LONG	PLT_95_LEN
		.ADDRESS	PLT_95
PLOT_90:	.LONG	PLT_90_LEN
		.ADDRESS	PLT_90
PLOT_85:	.LONG	PLT_85_LEN
		.ADDRESS	PLT_85
PLOT_80:	.LONG	PLT_80_LEN
		.ADDRESS	PLT_80
PLOT_75:	.LONG	PLT_75_LEN
		.ADDRESS	PLT_75
PLOT_70:	.LONG	PLT_70_LEN
		.ADDRESS	PLT_70
PLOT_65:	.LONG	PLT_65_LEN
		.ADDRESS	PLT_65
PLOT_60:	.LONG	PLT_60_LEN
		.ADDRESS	PLT_60
PLOT_55:	.LONG	PLT_55_LEN
		.ADDRESS	PLT_55
PLOT_50:	.LONG	PLT_50_LEN
		.ADDRESS	PLT_50
PLOT_45:	.LONG	PLT_45_LEN
		.ADDRESS	PLT_45
PLOT_40:	.LONG	PLT_40_LEN
		.ADDRESS	PLT_40
PLOT_35:	.LONG	PLT_35_LEN
		.ADDRESS	PLT_35
PLOT_30:	.LONG	PLT_30_LEN
		.ADDRESS	PLT_30
PLOT_25:	.LONG	PLT_25_LEN
		.ADDRESS	PLT_25
PLOT_20:	.LONG	PLT_20_LEN
		.ADDRESS	PLT_20
PLOT_15:	.LONG	PLT_25_LEN
		.ADDRESS	PLT_15
PLOT_10:	.LONG	PLT_10_LEN
		.ADDRESS	PLT_10
PLOT_5:		.LONG	PLT_5_LEN
		.ADDRESS	PLT_5
PLOT_0:		.LONG	PLT_0_LEN
		.ADDRESS	PLT_0

	.PAGE
	.SUBTITLE	CODE
	.SUBTITLE	INITIALIZATION
	.PSECT	CODE,RD,NOWRT,SHR,EXE,LONG,GBL,CON
	.ENTRY	START,0
;
;	GET THE DEVICE NAME
;
	CALLG	GET_ARG,G^LIB$GET_FOREIGN
	CMPW	#SS$_NORMAL,R0
	BEQL	1$
	$EXIT_S	R0
1$:	MOVL	LENGTH,DEVICE_NAME
;
;	GET INFORMATION ON SPECIFIED DEVICE
;
	$GETDVI_S	#1,,DEVICE_NAME,ITEM_LIST,IOSB
	CMPW	#SS$_NORMAL,R0
	BEQL	2$
	$EXIT_S	R0
2$:	$WAITFR_S	#1
	CMPW	#SS$_NORMAL,IOSB
	BEQL	3$
	CVTWL	IOSB,R0
	$EXIT_S	R0
;
;	MUST BE A DISK
;
3$:	CMPL	#DC$_DISK,CLASS
	BEQL	103$
	CALLG	NOT_DISK_ARG,G^LIB$PUT_OUTPUT
	$EXIT_S
;
;	OPEN THE BITMAP FILE TWICE
;	THE FIRST TIME WITH NOSHARE OPTION TO FORCE THE
;	BLOCKS OF THE BITMAP CACHED BY THE ACP TO BE
;	WRITTEN OUT, AND THE TIME SECOND WITH SHARE OPTION
;	TO ALLOW OHTER PEOPLE TO USE THE DISK
;
103$:	MOVB	LENGTH,FAB_1+FAB$B_FNS
	MOVB	LENGTH,FAB_2+FAB$B_FNS
	$OPEN	FAB=FAB_1
	BLBC	R0,4$
	$CLOSE		FAB=FAB_1
	BLBS	R0,5$
4$:	CMPL	#RMS$_FLK,R0
	BEQL	7$
	$EXIT_S	R0
7$:	PUSHAL	NO_FLUSH
	CALLS	#1,G^LIB$PUT_OUTPUT
5$:	$OPEN	FAB=FAB_2
	BLBS	R0,1004$
	$EXIT_S	R0
1004$:	$CONNECT	RAB=RAB_2
	BLBS	R0,1005$
	$EXIT_S	R0
1005$:
;
;	INIT ALL INTERNAL VARIBALES AND ARRAYS
;
	CLRL	LONGEST
	MOVC5	#0,LONGEST,#0,#<NUMBER_OF_BUCKETS*4>,BUCKET_BRIGADE
	MOVC5	#0,LONGEST,#0,#<<NUMBER_OF_BUCKETS+1>*4>,TOTALS
	CLRL	TOTAL_FRAGS
;
;	BIT MAP STARTS IN LBN 2
;
	MOVL	#2,BLOCK_NUMBER
	MOVL	#2,RAB_1+RAB$L_BKT
	MOVL	#2,RAB_2+RAB$L_BKT
;
;	READ IN FIRST BLOCK OF BITMAP AN INIT ALL REGISTERS
;
	$READ	RAB=RAB_2
	BLBS	R0,6$
	$EXIT_S	R0
6$:	CLRL	R11				;OFFSET INTO BITMAP BLOCK
	MOVL	#32,R8				;BITS PER WORD
	CLRL	R6				;OFFSET INTO BIT MASK ARRAY
	MOVL	BLOCK(R11),R9			;GET FIRST WORD IN BLOCK
	ADDL2	#4,R11				;OFFSET TO NEXT WORD NEEDED
	CLRL	R10				;INIT FRAGMENT SIZE COUNT
	.PAGE
	.SUBTITLE	ACCUMULATE DATA
LOOP:	BITL	BIT_MAP[R6],R9			;IS BIT SET SAYING IN USE
	BEQL	NOT_SET				;BIT CLEAR-CLUSTER NO IN USE
	INCL	R10				;BUMP CLUSTER SIZE COUNT
	BRW	END_LOOP			;GO TO NEXT CLUSTER FOR CHECK
NOT_SET:					;BIT NOT SET
	TSTL	R10				;DOES IT SIGNAL END OF FRAGMENT
	BEQL	END_LOOP			;NO
	CLRL	R7				;FIND BUCKET TO PUT COUNT IN
BUCKET_LOOP:
	CMPL	<BUCKET_SIZE_LIST+4>[R7],R10	;CMP CLUSTER SIZE TO BUCKET 
	BGTRU	1$				;FOUND BUCKET BRACKETING SIZE
	INCL	R7				;NO-SKIP TO NEXT BUCKET
	BRW	BUCKET_LOOP			;AND TEST IT
1$:	INCL	BUCKET_BRIGADE[R7]		;INC BUCKET COUNT
	INCL	TOTAL_FRAGS			;IN TOTAL FRAGMENT COUNT
	ADDL2	R10,TOTALS[R7]			;INC BUCKET TOTAL CLUSTERS
	ADDL2	R10,TOTALS+<NUMBER_OF_BUCKETS*4>;INC TOTAL FREE CLUSTERS
	CMPL	R10,LONGEST			;SEE IF THIS LONGEST
	BLEQ	2$				;NO
	MOVL	R10,LONGEST			;YES-UPDATE LONGEST
2$:	CLRL	R10				;RE-INIT SIZE OF FRAGMENT
END_LOOP:
	INCL	R6				;BUMP BIT MASK POINTER
	SOBGTR	R8,LOOP				;DEC COUNTER AND LOOP IF DONE
	CMPL	#512,R11			;SEE IF DONE WITH BITMAP BLOCK
	BGTR	1$				;NO-SKIP NEXT
	INCL	BLOCK_NUMBER			;SET UP READ OF NEXT BLOCK
	MOVL	BLOCK_NUMBER,RAB_2+RAB$L_BKT
	$READ	RAB=RAB_2
	BLBS	R0,2$
	CMPL	#RMS$_EOF,R0			;WAS ERROR E.O.F
	BEQL	BIT_MAP_IN			;YES-DONE-GO DO PRINTOUT
	$EXIT_S	R0
2$:	CLRL	R11				;INIT AS NEEDED FOR NEW BLOCK
1$:	MOVL	BLOCK(R11),R9			;GET NEXT WORD AND INIT
	ADDL2	#4,R11
	CLRL	R6
	MOVL	#32,R8
	BRW	LOOP				;CONTINUE LOOP
	.PAGE
	.SUBTITLE	CLEAN UP AND GEN OUTPUT
BIT_MAP_IN:					;BIT MAP COMPLETLY INPUT
	TSTL	R10				;SEE IF LAST FRAGMENT IN
	BEQL	CLOSE_DOWN_FILE			;NO-END OF DISK IN USE
	CLRL	R7				;FIND BUCKET TO PUT IT IN
BUCKET_LOOP_2:
	CMPL	<BIT_MAP+4>[R7],R10		;COMPARE TO BUCKET LIMITS
	BGTRU	1$				;FOUND BUCKET
	INCL	R7				;CHECK NEXT BUCKET
	BRW	BUCKET_LOOP_2			;REPEAT TILL DONE
1$:	INCL	BUCKET_BRIGADE[R7]		;INC BUCKET FRAGMENT COUNT
	INCL	TOTAL_FRAGS			;INC TOTAL FRAGMENT COUNT
	ADDL2	R10,TOTALS[R7]			;GET BUCKET TOTAL CLUSTERS
	ADDL2	R10,TOTALS+<NUMBER_OF_BUCKETS*4>;GET TOTAL CLUSTERS
	CMPL	R10,LONGEST			;CHECK IF LONGEST
	BLEQ	CLOSE_DOWN_FILE			;NO
	MOVL	R10,LONGEST			;YES-SAY SO
CLOSE_DOWN_FILE:
	$DISCONNECT	RAB=RAB_2		;CLOSE BITMAP FILE
	$CLOSE		FAB=FAB_2
;
;	FORMAT RESULTS FOR OUTPUT
;	FIRST PUT OUT THE GENERAL LIST  OF DATA ALWAYS DONE
;	PLUS FIXED HEADERS
;
	GENSTR	#14,LINE_1_DATA,MAXBLOCK
	GENSTR	#14,LINE_2_DATA,FREE
	GENSTR	#14,LINE_3_DATA,CLUSTER_SIZE
	GENSTR	#14,LINE_4_DATA,LONGEST
	GENPCT	TOTAL_FRAGS,LINE_9_A,<TOTALS+<4*NUMBER_OF_BUCKETS>>
	PUTSTR	#46,LINE_1
	PUTSTR	#46,LINE_2
	PUTSTR	#46,LINE_3
	PUTSTR	#46,LINE_4
	PUTSTR	#46,LINE_9
	PUTSTR	#1,LINE_5
	PUTSTR	#77,LINE_6
	PUTSTR	#77,LINE_6_A
;
;	INIT LOOP TO OUTPUT COLLECTED BUCKET STATS
;
	MOVL	#NUMBER_OF_BUCKETS,R11		;GET NUMBER OF BUCKETS
	CLRL	R10				;OFFSET INTO BUCKET ARRAYS
1$:	TSTL	BUCKET_BRIGADE[R10]		;SEE IF BUCKET EMPTY
	BNEQ	4$				;NOT EMPTY
	BRW	3$				;EMPTY-SKIP THIS BUCKET
4$:	GENSTR	#14,LINE_7,BUCKET_SIZE_LIST[R10];FILL IN BUCKET SIZE LIMITS
	SUBL3	#1,<BUCKET_SIZE_LIST+4>[R10],R0
	GENSTR	#14,LINE_7_B,R0
	GENSTR	#14,LINE_7_A,BUCKET_BRIGADE[R10];FILL IN FRAGMENT COUNT
	GENSTR	#14,LINE_7_C,TOTALS[R10]	;FILL IN CLUSTER COUNT
	GENPCT	TOTALS[R10],LINE_7_D,MAXBLOCK,CLUSTER_SIZE;% OF DISK
	GENPCT	TOTALS[R10],LINE_7_E,<TOTALS+<4*NUMBER_OF_BUCKETS>>;% OF FREE
	PUTSTR	#78,LINE_7
3$:	INCL	R10				;NEXT BUCKET
	DECL	R11				;DEC COUNTER
	BLEQ	2$				;IF DONE
	BRW	1$				;NO-LOOP
2$:	GENSTR	#14,LINE_8_A,TOTAL_FRAGS	;GEN AND OUTPUT DISK TOTALS
	GENSTR	#14,LINE_8_B,TOTALS[R10]
	GENPCT	TOTALS[R10],LINE_8_C,MAXBLOCK,CLUSTER_SIZE
	GENPCT	TOTALS[R10],LINE_8_D,TOTALS[R10]
	PUTSTR	#78,LINE_8
	.PAGE
	.SUBTITLE	SEE IF DISTRIBUTION DISPLAY WANTED
	CLRL	YES_NO_LENGTH
	CALLG	NEXT_DISSPLA_ARG,G^LIB$GET_COMMAND
	TSTL	YES_NO_LENGTH
	BNEQ	10$
	$EXIT_S
10$:	CMPB	#^A/Y/,@YES_NO+4
	BEQL	12$
	CMPB	#^A/y/,@YES_NO+4
	BEQL	12$
	$EXIT_S
12$:
	.PAGE
	.SUBTITLE	SET UP FOR RESCAN
;
;	Re-open the bitmap file for another scan
;
	$OPEN	FAB=FAB_2
	BLBS	R0,1004$
	$EXIT_S	R0
1004$:	$CONNECT	RAB=RAB_2
	BLBS	R0,1005$
	$EXIT_S	R0
1005$:
;
;	BIT MAP STARTS IN LBN 2
;
	MOVL	#2,BLOCK_NUMBER
	MOVL	#2,RAB_1+RAB$L_BKT
	MOVL	#2,RAB_2+RAB$L_BKT
;
;	READ IN FIRST BLOCK OF BITMAP AN INIT ALL REGISTERS
;
	$READ	RAB=RAB_2
	BLBS	R0,6$
	$EXIT_S	R0
6$:	CLRL	R11				;OFFSET INTO BITMAP BLOCK
	MOVL	#32,R8				;BITS PER WORD
	CLRL	R6				;OFFSET INTO BIT MASK ARRAY
	MOVL	BLOCK(R11),R9			;GET FIRST WORD IN BLOCK
	ADDL2	#4,R11				;OFFSET TO NEXT WORD NEEDED
	CLRL	R10				;INIT FRAGMENT SIZE COUNT
	CLRL	R7				;SET CURRENT LBN VALUE
	CLRL	R5				;SET STARTING LBN VALUE
	.PAGE
	.SUBTITLE	ACCUMULATE DATA
P_LOOP:	BITL	BIT_MAP[R6],R9			;IS BIT SET SAYING IN USE
	BEQL	P_NOT_SET			;BIT CLEAR-CLUSTER IN USE
	INCL	R10				;BUMP CLUSTER SIZE COUNT
	INCL	R7				;BUMP LBN COUNTER
	BRW	P_END_LOOP			;GO TO NEXT CLUSTER FOR CHECK
P_NOT_SET:					;BIT NOT SET
	INCL	R7				;BUMP LBN COUNTER
	TSTL	R10				;DOES IT SIGNAL END OF FRAGMENT
	BNEQ	6$
	BRW	PL_END_LOOP			;NO
6$:
;
;	CALC SIZE OF LBN IN DISPLAY BUCKETS
;
	SUBL3	#1,R10,R1			;GET END LBN OF FREE SPACE
	MULL2	#100,R1
	MULL2	CLUSTER_SIZE,R1
	DIVL2	MAXBLOCK,R1
	DIVL2	#2,R1
	CMPL	#49,R1
	BGEQ	3$
	MOVL	#49,R1
3$:	INCL	R1
;
;	FIRST CALC THE % SIZE OF FREE FRAG/LARGEST FRAG
;
	MULL2	#100,R10
	DIVL2	LONGEST,R10
	DIVL2	#5,R10
	CMPL	#19,R10
	BGEQ	1$
	MOVL	#19,R10
1$:	MOVL	PLOT_DISPATCH_TABLE[R10],R0	;GET ADDR OF PLOT LINE
;
;	NEXT CALC LOC OF STARTING LBN
;
	MULL2	#100,R5
	MULL2	CLUSTER_SIZE,R5
	DIVL2	MAXBLOCK,R5
	DIVL2	#2,R5
	CMPL	#49,R5
	BGEQ	2$
	MOVL	#49,R5
;
;	LOAD LOC WITH MARKER
;
2$:	MOVB	#^A/X/,(R0)[R5]
	DECL	R1
	BLEQ	4$
5$:	INCL	R0
	MOVB	#^A/-/,(R0)[R5]
	DECL	R1
	BGTR	5$
	MOVB	#^A/>/,(R0)[R5]
4$:	CLRL	R10
PL_END_LOOP:
	MOVL	R7,R5				;UPDATE STARTING LOC POINTER
P_END_LOOP:
	INCL	R6				;BUMP BIT MASK POINTER
	DECL	R8
	BLEQ	3$
	BRW	P_LOOP				;DEC COUNTER AND LOOP IF DONE
3$:	CMPL	#512,R11			;SEE IF DONE WITH BITMAP BLOCK
	BGTR	1$				;NO-SKIP NEXT
	INCL	BLOCK_NUMBER			;SET UP READ OF NEXT BLOCK
	MOVL	BLOCK_NUMBER,RAB_2+RAB$L_BKT
	$READ	RAB=RAB_2
	BLBS	R0,2$
	CMPL	#RMS$_EOF,R0			;WAS ERROR E.O.F
	BEQL	P_BIT_MAP_IN			;YES-DONE-GO DO PRINTOUT
	$EXIT_S	R0
2$:	CLRL	R11				;INIT AS NEEDED FOR NEW BLOCK
1$:	MOVL	BLOCK(R11),R9			;GET NEXT WORD AND INIT
	ADDL2	#4,R11
	CLRL	R6
	MOVL	#32,R8
	BRW	P_LOOP				;CONTINUE LOOP
	.PAGE
	.SUBTITLE	CLEAN UP AND GEN OUTPUT
P_BIT_MAP_IN:					;BIT MAP COMPLETLY INPUT
	TSTL	R10				;SEE IF LAST FRAGMENT IN
	BEQL	P_CLOSE_DOWN_FILE		;NO-END OF DISK IN USE
;
;	FIRST CALC THE % SIZE OF FREE FRAG/LARGEST FRAG
;
	MULL2	#100,R10
	DIVL2	LONGEST,R10
	DIVL2	#5,R10
	CMPL	#19,R10
	BGEQ	1$
	MOVL	#19,R10
1$:	MOVL	PLOT_DISPATCH_TABLE[R10],R0	;GET ADDR OF PLOT LINE
;
;	NEXT CALC LOC OF STARTING LBN
;
	MULL2	#100,R5
	MULL2	CLUSTER_SIZE,R5
	DIVL2	MAXBLOCK,R5
	DIVL2	#2,R5
	CMPL	#49,R5
	BGEQ	2$
	MOVL	#49,R5
;
;	LOAD LOC WITH MARKER
;
2$:	MOVB	#^A/X/,(R0)[R5]
P_CLOSE_DOWN_FILE:
	$DISCONNECT	RAB=RAB_2		;CLOSE BITMAP FILE
	$CLOSE		FAB=FAB_2
	.PAGE
	.SUBTITLE	OUTPUT DISTRIBUTION PLOT
	PUSHAL	PLOT_100
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	PLOT_95
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	PLOT_90
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	PLOT_85
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	PLOT_80
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	PLOT_75
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	PLOT_70
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	PLOT_65
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	PLOT_60
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	PLOT_55
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	PLOT_50
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	PLOT_45
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	PLOT_40
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	PLOT_35
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	PLOT_30
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	PLOT_25
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	PLOT_20
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	PLOT_15
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	PLOT_10
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	PLOT_5
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	PLOT_0
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	TITLE_2
	CALLS	#1,G^LIB$PUT_OUTPUT
	PUSHAL	TITLE_3
	CALLS	#1,G^LIB$PUT_OUTPUT
	$EXIT_S
	.END	START
