        .TITLE  DISK USAGE SUMMARY
        .SBTTL  INTRODUCTION
;
;  THIS TASK PREPARES A REPORT OF DISK USAGE ON PER GROUP
;    AND A PER USER BASIS. IT IS USED IN CONJUNCTION WITH
;    THE TASK LIMITS AND THE TASK ...HEL TO SET, CHECK,
;    AND REPORT ON DISK STORAGE USAGE.
;
;  OUTPUT OF THIS TASK IS A REPORT AND A SUMMARY FILE.
;    THE SUMMARY FILE IS USED AS INPUT TO THE OTHER TWO
;    TASKS AS IT CONTAINS THE CURRENTLY SET MAXIMUMS FOR
;    EACH GROUP AND USER. THE REPORT IS FOR THE USE OF THE
;    SYSTEM MANAGER IN DETERMINING GREEDY SORTS.
;
;************ REPORT FORMAT ******************
;
;  SPECIAL NOTE		GROUP	USER	USED	ALLOC	FILES	LIMIT
;
;	SPECIAL NOTE WILL EITHER BE BLANK, OR
;		WILL INDICATE A UIC OVER ITS LIMIT **GREEDY**, OR
;		WILL INDICATE A UIC WITHOUT AN IMPOSED LIMIT **NOLIMIT**
;	GROUP CONTAINS THE GROUP ID
;	USER CONTAINS THE USER ID
;	USED GIVES THE NUMBER OF DISK BLOCKS IN USE FOR THIS UIC
;	ALLOC GIVES THE NUMBER OF DISK BLOCKS ALLOCATED TO THIS UIC
;	FILES GIVES THE NUMBER OF FILES ALLOCATED IN THIS UIC
;	LIMIT IS THE CURRENTLY IMPOSED LIMIT ON THIS UIC
;
;**********************************************
;
;	MODS MADE BY B. N. MARTENSEN ON 22MAR77 TO INCLUDE USER NAME
;	ON THE LISTING REPORT. MOD INVOLVES READING IN ALL ENTRIES FROM
;	USER PROFILE FILE AND SEARCHING THIS LIST FOR UIC-USER NAME
;	CORRELATIONS. MODS ARE COMMENTED WITH	BNMMOD
;
;	THE PROGRAM HAS BEEN CONDITIONALIZED TO GENERATE THE UPF TYPE
;	CODE ONLY ON A SYSTEM WITH DISK USAGE ACCOUNTING. THIS IS DONE
;	SO IT WILL RUN ON RSX11D, RSX11M V2 WITH NO AUSER NAME FILE
;	AS WELL AS RSX11M V3 AND IAS WITH USER NAME FILES
;
;	HISTORY
;
;	D.R. ROSS			;INITIAL FILE CREATION
;
;BNMMOD	B.N. MARTENSEN	22MAR77		;ADD USER NAME DETERMINING CODE
;
;MBK001	M. BLAKE-KNOX	21JUN77		;CONDITIONALIZE USER NAME CODE
;
;MBK002	M. BLAKE-KNOX	27JUN77		;SUM USED BLOCKS OVER WHOLE DISK
;
;	ASSEMBLY PARAMETER CONTROL
;
;ACCOUNT=1		;GENERATE USER NAME ACCOUNTING INFO
;IAS=1			;GENERATE IAS VERSION
;RSX11D=1		;GENERATE RSX11D VERSION
RSX11M= 1				;GENERATE RSX11M VERSION
;QIOW=1		;USE THE QIOW DIRECTIVE
;
;
	.IIF  DF,IAS QIOW= 1
	.IIF  DF,RSX11D QIOW= 1
;
;	MACROS
;
;	GIVEN A POINTER TO THE MESSAGE AND THE LENGTH SEND THE MESSAGE TO
;	THE TERMINAL
;
	.MACRO	EREPRT MESS,LENG
	ERPRT1
	MOV  #MESS,$.$EDB+Q.IOPL
	MOV  #LENG,$.$EDB+Q.IOPL+2
	DIR$  #$.$EDB
	.IIF  NDF,QIOW WTSE$S #1
	.MACRO	ERPRT1
	.ENDM  ERPRT1
	.ENDM  EREPRT
;
	.MACRO	ERPRT1
	.MCALL	DIR$
	.PSECT	$$ERP
	.IF  DF,QIOW
	.MCALL	QIOW$
$.$EDB:
	QIOW$  IO.WVB,5,1,0,0,0,<0,0,40>
	.IFF
	.MCALL	QIO$,WTSE$S
$.$EDB:
	QIO$  IO.WVB,5,1,0,0,0,<0,0,40>
	.ENDC
	.PSECT	CODE
	.ENDM  ERPRT1
	.PAGE
        .SBTTL  DATA SECTION
	.MCALL	FDBDF$,FDAT$A,FDOP$A,FSRSZ$,OPEN$R,GET$,OPEN$W,EXIT$S
	.MCALL	PUT$,DELET$,CLOSE$,PRINT$
	.PSECT	DATA
; GENERAL VALUES
GROUP:	.WORD  0			;GROUP ID
USER:	.WORD  0			;USER ID
USED:	.WORD  0,0			;# OF BLOCKS USED
ALLOC:	.WORD  0,0			;# OF BLOCKS ALLOCATED
FILES:	.WORD  0			;# OF FILES ALLOCATED
;
;
;
;MBK002	DUMMY NODE FOR WHOLE DISK TOTALS
;MBK002
TOTALS: .WORD  -1			;MBK002
	.WORD  0			;MBK002 GROUP ID ='*'
TUSED:	.WORD  0,0			;MBK002 TOTAL USED BLOCKS
TALLOC: .WORD  0,0			;MBK002 TOTAL ALLOCATED BLOCKS
TFILES: .WORD  0			;MBK002 TOTAL NUMBER OF FILES
N=	0				;ASSEMBLY TIME COUNTER
GTABLE: .REPT  377			;1 ENTRY PER UIC POSSIBLE
N=	N+1
	.WORD  -1			;PTR TO 1ST UID OF THIS GROUP
	.WORD  N			;GROUP ID - FOR CONVENIENCE
	.WORD  0,0			;MBK002 USED
	.WORD  0,0			;MBK002 ALLOCATED
	.WORD  0			;FILES
	.ENDR
GEND=	.				;END OF TABLE
;
USERS=	400.				;TOTAL # OF UICS WHICH CAN BE PROCESSED
UNODES: .REPT  USERS			;FOR LINKED LIST OF UIDS OFF GID ENTRY
	.BLKW  5.
	.ENDR
UEND=	.
UFREE:	.WORD  UNODES			;PTR TO NEXT FREE NODE
;
;  OFFSETS INTO NODES
NODSZ=	16				;MBK002
N.ID=	2
N.PTR=	0
N.US=	4
N.AL=	10				;MBK002
N.FL=	14				;MBK002
;
	.IF  DF,ACCOUNT 		;MBK001
NAMES:	.REPT  USERS			;BNMMOD 400 ENTRIES FOR USERNAMES
	.BLKB  14.			;BNMMOD AND USER IC'S. USERNAME 12 CHAR
	.ENDR				;BNMMOD
NAMESL: .WORD  0			;BNMMOD NO. OF ENTRIES IN NAMES
GRP=	13.				;BNMMOD OFFSET FOR GROUP NO.
USR=	12.				;BNMMOD OFFSET FOR USER NO.
LNMS=	14.				;BNMMOD LENGTH OF NAMES BLOCK
BLNKNM: .ASCII  /            /          ;BNMMOD 12 BLANKS FOR NO NAME
	.ENDC				;MBK001
;  MATCH STRINGS
SQBR:   .ASCII  /[/<0>
OF:     .ASCII  /OF /<0>
DT:     .ASCII  /]/<0>
	.EVEN
;
BUFF:	.BLKB  132.
BUFSZ:	.WORD  132.
DEFUIC= 46.				;BNMMOD POSITION IN PROFILE RECORD OF
					;DEFAULTUIC
;
;  FILE SECTION
;
;    FOR THE INPUT FILE [1,1]USAGE.TB
;
SYSLUN= 2
TBFDB:
	FDBDF$
	FDOP$A	SYSLUN
;
TBDSP:	.WORD  SYL,SY			;FILE NAME INFORMATION BLOCK
	.WORD  0,0
	.WORD  TBL,TB
;
SY:     .ASCII  /SY0:/
SYL=	.-SY
TB:     .ASCII  /USAGE.TB/
TBL=	.-TB
	.EVEN
	.IF  DF,ACCOUNT 		;MBK001
;BNMMOD
;BNMMOD FDB FOR USER PROFILE FILE
;BNMMOD
PRFFDB:
	FDBDF$				;BNMMOD FILE DESCRIPTOR BLOCK FOR UPF
	FDAT$A	R.FIX,FD.CR		;BNMMOD FIXED LENGTH RECORDS
	FDOP$A	5			;BNMMOD LUN OF 5 BNMMOD
PRFDSP: .WORD  SYL,SY			;BNMMOD DEVICE
	.WORD  UFDL,UFD 		;BNMMOD DATASET DESCRIPTOR USER ID
	.WORD  PRFL,PRF 		;BNMMOD DATASET DESCRIPTOR FILE NAME
					;BNMMOD
PRF:    .ASCII  /PDSUPF.DAT/            ;BNMMOD FILE NAME
PRFL=	.-PRF				;BNMMOD LENGTH OF FILE NAME
UFD:    .ASCII  /[1,100]/               ;BNMMOD THE USER ID
UFDL=	.-UFD				;BNMMOD THE LENGTH OF THE USER ID
	.EVEN				;BNMMOD
	.ENDC				;MBK001
;
;  FILE FORMAT AND BUFFER
;
INBUF:	.BLKW  11.			;HOLDS INPUT AND OUTPUT RECORDS TO
					;SUMMARY
;
OUTBUF: .BLKW  11.			;FOR OUTPUT RECORD IF NO CORRESP  INPUT
;
UID=	0
GID=	1
MAX=	2
USF=	4
ALF=	6
FLF=	10
NME=	12
RECSIZ= 22.
;
;    FOR THE SUMMARY FILE USAGE.DAT. THE OLD VERSION IS READ-ONLY WHILE
;     THE NEW ONE IS CREATED AND WRITTEN HERE. BOTH ARE FIXED LENGTH
;
OLDFDB:
	FDBDF$
	FDAT$A	R.FIX,FD.CR
	FDOP$A	3
;
OLDDSP: .WORD  SYL,SY
	.WORD  0,0
	.WORD  OLDL,OLD
;
OLD:    .ASCII  /USAGE.DAT/
OLDL=	.-OLD
	.EVEN
;
NEWFDB:
	FDBDF$
	FDAT$A	R.FIX,FD.CR!FD.BLK,RECSIZ
	FDOP$A	4
;
LPFDB:
	FDBDF$
	FDAT$A	R.VAR,FD.CR
	FDOP$A	6
;
LPDSP:	.WORD  SYL,SY
	.WORD  0,0
	.WORD  RPTL,RPT
;
RPT:    .ASCII  /USAGE.RPT/
RPTL=	.-RPT
	.EVEN
;
;
	FSRSZ$	4
;
	.PSECT	DATA
;
;  ERROR MESSAGES
;
OPN:    .ASCII  /[USE - CAN'T OPEN USAGE.TB]/<15><12>
OPNL=	.-OPN
;
OP2:    .ASCII  /[USE - CAN'T  OPEN OLD USAGE.DAT]/<15><12>
OP2L=	.-OP2
;
OP3:    .ASCII  /[USE - CAN'T CREATE NEW USAGE.DAT]/<15><12>
OP3L=	.-OP3
;
OP4:    .ASCII  /[USE - CAN'T OPEN FOR OUTPUT ON LUN 6]/<15><12>
OP4L=	.-OP4
;
	.IF  DF,ACCOUNT 		;MBK001 BNMMOD
OP5:    .ASCII  /[USE - CAN'T OPEN USER PROFILE FILE]/<15><12>
OP5L=	.-OP5				;BNMMOD LENGTH OF ERROR MESSAGE BNMMOD
FERR:   .ASCII  /[USE - READ ERROR ON PROFILE FILE ]/<15><12> ;BNMMOD
FERRL=	.-FERR				;BNMMOD  ERROR ON READ OF PROFILE FILE
					;BNMMOD
	.ENDC				;MBK001
					;
UIC:    .ASCII  /[USE - PREPOSTEROUS UIC FOUND IN USAGE.DAT]/<15><12>
UICL=	.-UIC
RERR:   .ASCII  /[USE - ENCOUNTERED READ ERROR ON USAGE.TB]/<15><12>
RERRL=	.-RERR
;
OVR:    .ASCII  /[USE - INTERNAL TABLE OVERFLOW]/<15><12>
OVRL=	.-OVR
;
QUIT:   .ASCII  /[USE - FINISHED]/<15><12>
QUITL=	.-QUIT
;
	.EVEN
;
;
;  REPORT SECTION
;
HEADER: .ASCII  /  DISK USAGE SUMMARY     DATE: /
DATE:	.BLKB  15.			;TO HOLD ASCII DATE STRING
HEADL=	.-HEADER
;
HEAD2:					;SECOND LINE OF HEADER
        .ASCII  /        /
        .ASCII  /NOTE/                  ;THESE FORM COLUMN HEADINGS
        .ASCII  /      /
	.IF  DF,ACCOUNT 		;MBK001
        .ASCII  /USER NAME     /        ;BNMMOD HEADING FOR USER NAME
	.ENDC				;MBK001
        .ASCII  /GROUP/
        .ASCII  /  /
        .ASCII  /USER/
        .ASCII  /     /                 ;MBK002
        .ASCII  /USED/
        .ASCII  /     /                 ;MBK002
        .ASCII  /ALLOC/
        .ASCII  /        /              ;MBK002
        .ASCII  /FILES/
        .ASCII  /        /              ;MBK002
        .ASCII  /LIMIT/
HEAD2L= .-HEAD2
;
;  SPECIAL NOTES
;
GREEDY: .ASCII  /**GREEDY** /
NOLIM:  .ASCII  /NO LIMIT/
NOLIML= .-NOLIM
NEWONE: .ASCII  /**NEW UIC**/
REMOVE: .ASCII  /**REMOVED**/
BLANKS: .ASCII  /           /
	.EVEN
;
;
;
LPBUFF: .BLKB  5			;LEADING 5 BLANKS
NOTE1:	.BLKB  11.			;SPECIAL NOTEFIELD
LP.NOT= .-NOTE1
	.BLKB  4			;SPACER  BNMMOD CHANGED 5 TO 4
	.IF  DF,ACCOUNT 		;MBK001
NM1:	.BLKB  12.			;BNMMOD USER NAME GOES IN HERE
LP.NM=	.-NM1				;BNMMOD LENGTH OF USER NAME
	.ENDC				;MBK001
	.BLKB  1			;BNMMOD SPACER OF 1 BYTE
GRP1:	.BLKB  3			;GROUP ID
LP.GID= .-GRP1
	.BLKB  3
USR1:	.BLKB  3			;USER ID
LP.UID= .-USR1
	.BLKB  4
USD1:	.BLKB  9.			;MBK002 # OF BLOCKS USED
LP.US=	.-USD1
	.BLKB  2
ALL1:	.BLKB  9.			;MBK002 # OF BLOCKS ALLOCATED
LP.AL=	.-ALL1
	.BLKB  2
FIL1:	.BLKB  5			;# OF FILES ALLOCATED
LP.FL=	.-FIL1
	.BLKB  2
LIM1:	.BLKB  12			;ASSIGNED BLOCK LIMIT
LP.LM=	.-LIM1
LPBSIZ= .-LPBUFF
	.EVEN
;
;  EXTRA LOCATIONS NEEDED FOR REPORT PART
;
DFLAG:	.WORD  0			;FLAGS DISC IN UIC BETWEEN FILE AND INT
DONE:	.WORD  0			;FLAGS END OF FILE &/OR INTERNAL TABLE
TMP:	.WORD  0
FUIC:	.WORD  0			;HOLDS UIC FROM FILE RECORD
IUIC:	.WORD  0			;HOLDS UIC FROM CURRENT NODE
GRPPTR: .WORD  0			;PTS AT CURRENT GROUP NODE
NODPTR: .WORD  0			;CURRENT NODE
NOTPTR: .WORD  0			;PTR TO A SPECIAL MESSAGE
LASTGR: .WORD  -1			;FOR FORMAT CONTROL ON OUTPUT
SKIP2:	.BYTE  15,12,12 		;TO SPACE TWO LINES
SKIP2L= .-SKIP2
	.EVEN
	.PAGE
        .SBTTL  MAIN ROUTINE
;
;
;  OPEN THE PIP PREPARED FILE USAGE.TB, EXTRACT USAGE INFORMATION
;    AND ADD THAT INFORMATION TO THE GROUP-USER DATA STRUCTURE. THIS PUTS
;    THE INFORMATION IN A CONVENIENT FORM, AS WELL AS SORTING IT
;    INTO NUMERIC ORDER. ONCE THE TB FILE HAS BEEN PROCESSED THE OUTPUT
;    REPORT AND SUMMARY FILE ARE PRODUCED.
;
;
	.PSECT	CODE
USAGE:					;TASK ENTRY POINT
	OPEN$R	#TBFDB,,#TBDSP,,,,OPNERR
NEWL:
	GET$  #TBFDB,#BUFF,#BUFSZ,EOF	;PROCESS UNTIL END OF FILE
;
	JSR  PC,GETDAT			;NOOP AFTER 1ST PASS
	MOV  #BUFF,R0			;PTR TO START OF STRING
	MOV  #SQBR,R1			;SEARCH FOR SQUARE BRACKET
	MOV  F.NRBD+TBFDB,R2		;LENGTH OF STRING
SQSCAN:
	JSR  PC,SCAN			;LOCATE UIC STRING
	BCS  NEWL			;NOTHING IN THIS BUFFER, GET NEXT
	JSR  PC,GETUIC			;LOAD GROUP AND USER
	BCC  3$ 			;GOOD RETURN
	JMP  UICERR			;FATAL ERROR
;
;  NOW GET STATISTICS FOR THIS DIRECTORY
;
3$:
	MOV  F.NRBD+TBFDB,R2		;FIX UP LENGTH AGAIN
	MOV  R0,R3
	SUB  #BUFF,R3			;# OF CHAR USED ALREADY
	SUB  R3,R2			;# LEFT
	MOV  #OF,R1			;SET UP FOR SCAN TO FIND NEXT FIELD
2$:
	JSR  PC,SCAN			;SCAN
	BCC  1$ 			;FOUND IT IN THIS BUFFER
	GET$  #TBFDB,#BUFF,#BUFSZ,RDERR ;BETTER NOT REACH EOF HERE!!
	MOV  #BUFF,R0			;RESET PTR
	MOV  F.NRBD+TBFDB,R2		;RESET LENGTH
	BR  2$				;KEEP LOOKING
1$:
	JSR  PC,DSTATS
;
;  HAVE THE STATS NOW FILL IN THE APPROPRIATE SLOTS OF GROUP TABLE
;
	MOV  GROUP,R3			;NUMERIC GID
	DEC  R3 			;TABLE INDEXES FROM 0
	MUL  #NODSZ,R3			;CONVERT TO OFFSET INTO TABLE
	ADD  #GTABLE,R3 		;PTR TO NODE IN TABLE
	ADD  USED,N.US+2(R3)		;MBK002 UPDATE FIELDS
	ADC  N.US(R3)			;MBK002 (DOUBLE PRECISION)
	ADD  ALLOC,N.AL+2(R3)
	ADC  N.AL(R3)			;MBK002
	ADD  FILES,N.FL(R3)
;
;  GET A NEW NODE FROR THIS USER AND PLACE THE NODE
;    IN THE LINKED LIST OFF ITS GROUP ENTRY. PUT NODE IN ASCENDING
;    UID ORDER.
;
NODE:
	CMP  UFREE,#UEND		;CHECK VALIDITY OF THE PTR
	BLO  3$ 			;OK
	JMP  OVRFLO			;OUT OF NODES!!!!!
3$:
	MOV  UFREE,R4			;FREE NODE
	ADD  #NODSZ,UFREE		;UPDATE FREE PTR
	MOV  USER,N.ID(R4)		;FILL IN THE NODE - UID
	MOV  USED,N.US+2(R4)		;MBK002
	MOV  ALLOC,N.AL+2(R4)		;MBK002
	MOV  FILES,N.FL(R4)
	ADD  USED,TUSED+2		;MBK002 UPDATE DISK TOTALS
	ADC  TUSED			;MBK002
	ADD  ALLOC,TALLOC+2		;MBK002
	ADC  TALLOC			;MBK002
	ADD  FILES,TFILES		;MBK002
;
;  NOW LINK IT IN
;
1$:
	CMP  #-1,N.PTR(R3)		;END OF LIST?
	BNE  2$ 			;NOPE
	MOV  R4,N.PTR(R3)		;ADD NODE
	MOV  #-1,N.PTR(R4)		;NEW EOL
	BR  JMPBCK
;
;  SEE IF THE NODE SQUEEZES IN HERE
;
2$:
	MOV  N.PTR(R3),R2		;LOOK AT NEXT NODE
	CMP  N.ID(R4),N.ID(R2)		;IN HERE?
	BLT  4$ 			;YES, PUT IT IN
	MOV  R2,R3			;UPDATE R3 PTR
	BR  1$				;CHECK THIS NODE
4$:
	MOV  R2,N.PTR(R4)		;PUT IN IN BETWEEN R2 & R3
	MOV  R4,N.PTR(R3)
JMPBCK:
	MOV  F.NRBD+TBFDB,R2		;FIX UP REMAINIG LENGTH FOR NEXT SCAN
	MOV  R0,R3
	SUB  #BUFF,R3
	SUB  R3,R2
	MOV  #SQBR,R1
	JMP  SQSCAN			;NEXT DIRECTORY
;
;
;
;  READ ERROR WHILE LOOKING FOR A UIC MAY JUST BE END OF FILE.
;    VERIFY THIS AND CONTINUE IF THIS IS SO, ELSE THIS IS A REAL
;    ERROR WHICH MUST BE REOPRTED.
;
EOF:
	CMPB  #-10.,F.ERR+TBFDB 	;IS IT EOF?
	BEQ  1$ 			;KEEP GOING
	JMP  RDERR
1$:
	TST  (SP)+			;WON'T BE RETURNING
	DELET$	#TBFDB
	.IF  DF,ACCOUNT 		;MBK001 BNMMOD	BNMMOD	NOW GET THE
					;USER PROFILE DATA BNMMOD
	OPEN$R	#PRFFDB,,#PRFDSP,,,,OP5ERR ;BNMMOD OPEN FILE
	MOV  #132.,BUFSZ		;BNMMOD INITIALIZE SIZE OF BUFFER
	GET$  #PRFFDB,#BUFF,#BUFSZ,PRFERR ;BNMMOD GET 1ST RECORD
	MOV  BUFF,R3			;BNMMOD 1ST WORD IS RECORD # OF 1ST USER
	DEC  R3 			;BNMMOD ALREADY HAVE READ ONE RECORD
	DEC  R3 			;BNMMOD DONT READ 1ST PROFILE RECORD
2$:
	GET$  #PRFFDB,#BUFF,#BUFSZ,PRFERR ;BNMMOD GET REST OF RECORDS
	SOB  R3,2$			;BNMMOD UNTIL 1ST USER PROFILE RECORD
	MOV  #NAMES,R0			;BNMMOD WHERE ASCII NAME IS TO GO
PROFS:
	MOV  R0,-(SP)			;BNMMOD SAVE R0 ELSE GET$ DESTROYS IT
	GET$  #PRFFDB,#BUFF,#BUFSZ,EOFL ;BNMMOD GET USERS UNTIL EOF
	MOV  (SP)+,R0			;BNMMOD RESTORE REG 0
	MOV  #BUFF,R3			;BNMMOD ADDRESS OF RAD50 USERNAME
	MOV  #4,R4			;BNMMOD HAVE 4 RAD50 WORDS TO DECODE
1$:
	MOV  (R3)+,R1			;BNMMOD PUT EACH RAD50 WORD INTO
					;REGISTER
	JSR  PC,$C5TA			;BNMMOD AND CONVERT IT TO 3 ASCII CHARS.
	SOB  R4,1$			;BNMMOD REPEAT FOR EACH WORD
	MOV  BUFF+DEFUIC,(R0)+		;BNMMOD COPY OVER THE GROUP,USER IC
	INC  NAMESL			;BNMMOD COUNT NO. OF USER NAMES
	BR  PROFS			;BNMMOD GET NEXT USER PROFILE RECORD
EOFL:
	CLOSE$	#PRFFDB 		;BNMMOD CLOSE USER PROFILE FILE
	.ENDC				;MBK001
;
;  NOW PREPARE REPORT
;
	OPEN$R	#OLDFDB,,#OLDDSP,,,,OP2ERR
	OPEN$W	#NEWFDB,,#OLDDSP,,,,OP3ERR
	OPEN$W	#LPFDB,,#LPDSP,,,,OP4ERR
;
;  PRINT HEADER ON THE REPORT
;
	JSR  PC,HEADR
;
;  CYCLE THROUGH UICS PREPARING REPORT AND NEW SUMMARY FILE
;
	MOV  #TOTALS,GRPPTR		;TO FIND FIRST VALID UIC WE MUST
	MOV  #TOTALS,NODPTR		;FAKE IT
	JSR  PC,NXTFIL			;GET NEXT FILE ENTRY - LOAD FUIC
;
;
COMP:
	JSR  PC,CLRBUF			;BLANKS IN LPBUFF
	CMP  FUIC,IUIC			;ARE THE UICS IDENTICAL
	BEQ  SAME
	BHI  NEWUIC			;FOUND A UIC NOT EXISTING LAST TIME
;
;  THERE IS A UIC WHICH APPEARED LAST TIME BUT NOT THIS. THIS MAY
;    MEAN THAT A UIC HAS BEEN DELETED, OR THAT THE PIP /TB FILE
;    DID NOT DO [*,*]. NOTE ABSCENSE ON REPORT BY **REMOVED**.
;
	MOV  #REMOVE,NOTPTR		;PUT MESSAGE ADDRESS IN PTR
	MOVB  FUIC+1,GROUP		;STORE GROUP ID
	MOVB  FUIC,USER
	MOV  #-1,DFLAG			;FLAG THE DIFFERENCE
	BR  FORMAT			;TO PREPARE OUTPUT
;
NEWUIC:
	MOV  #NEWONE,NOTPTR		;TO REPORT NEW UIC
	MOV  #1,DFLAG			;FLAG DIFFERENCE
	BR  S1
;
SAME:
	MOV  #BLANKS,NOTPTR		;FIELD WILL BE BLANK, NOTHING SPECIAL
	CLR  DFLAG
S1:
	MOVB  IUIC+1,GROUP
	MOVB  IUIC,USER
;
;  NOW FORMAT THE OUTPUT LINE
;
FORMAT:
	CMP  GROUP,LASTGR		;WANT TO PUT IN SPACING BETWEEN GROUPS
	BEQ  1$ 			;SAME GROUP, DON'T SPACE
	MOV  GROUP,LASTGR		;GET IT UP TO DATE
	PUT$  #LPFDB,#SKIP2,#SKIP2L,OPNERR ;PUT TWO LINES
1$:					;MBK001
	.IF  DF,ACCOUNT 		;MBK001
	JSR  PC,USERNM			;BNMMOD FILL IN USER NAME IN LP AND DAT 
					;BUFFER
	.ENDC				;MBK001
	JSR  PC,LDLPBF			;FILL IN THE LP BUFFER
	PUT$  #LPFDB,#LPBUFF,#LPBSIZ,OP2ERR
	JSR  PC,LDSUMM			;FILL IN NEW OUTPUT RECORD
;
;  PREPARE FOR NEXT OUTPUT
;
	TST  DFLAG			;WERE THE RECORD IN BOTH
	BLT  2$ 			;ONLY IN FILE
	BGT  3$ 			;ONLY IN THE INTERNAL TABLE
	JSR  PC,NXTINT			;GET INTERNAL ONE
2$:
	JSR  PC,NXTFIL
	BR  CHKDON			;MAYBE THIS IS ALL!!!
3$:
	JSR  PC,NXTINT
CHKDON:
	CMP  #3,DONE
	BEQ  CLOSUP			;ALL DONE
	JMP  COMP			;DO THE NEXT ONE
;
;
CLOSUP:
	EREPRT	QUIT,QUITL
	CLOSE$	#LPFDB
	CLOSE$	#OLDFDB
	CLOSE$	#NEWFDB
EXIT:
	EXIT$S
	.PAGE
        .SBTTL  ERROR HANDLING
;
;
OPNERR:
	EREPRT	OPN,OPNL
	BR  CLEAR
;
OP2ERR:
	EREPRT	OP2,OP2L		;REPORT THIS.
	BIS  #2,DONE			;MARK IT AS EOF
	MOV  #177777,FUIC		;HIGHEST UIC POSSIBLE
	RTS  PC
;
;
OP3ERR:
	EREPRT	OP3,OP3L
	BR  CLEAR
;
;
OP4ERR:
	EREPRT	OP4,OP4L
	BR  CLEAR
	.IF  DF,ACCOUNT 		;MBK001
;
OP5ERR:
	EREPRT	OP5,OP5L		;BNMMOD REPORT ERROR ON OPEN
	BR  CLEAR			;BNMMOD  BNMMOD
PRFERR:
	EREPRT	FERR,FERRL		;BNMMOD ERROR READING PROFILE FILE
	BR  CLEAR			;BNMMOD BNMMOD
	.ENDC				;MBK001
RDERR:
	EREPRT	RERR,RERRL
	BR  CLEAR
;
UICERR:
	EREPRT	UIC,UICL
	BR  CLEAR+2
;
OVRFLO:
	EREPRT	OVR,OVRL
	BR  CLEAR+2
;
CLEAR:
	TST  (SP)+
	JMP  EXIT
	.PAGE
        .SBTTL  SCAN FOR SEQUENCE
;
;  SUBROUTINE TO SCAN FOR A GIVEN CHARACTER SEQUENCE.
;    IT RETURNS PTR TO 1ST CHAR PAST SEQ IN R0
;		LENGTH OF MATCHED SEQ IN R2
;		C-BIT CLEAR IF WHOLE STRING MATCHED
;		C-BIT SET IF RAN OUT OF STRING (R2 STILL
;		  CONTAINS AMOUNT MATCHED SO FAR.
;
;	R0 PTR TO STRING BEING SCANNED
;	R1 PTR TO NULL TERMINATED SEQ BEING SOUGHT
;	R2 LENGTH OF INPUT STRING
;
	.PSECT	CODE
SCAN:
	CLR  R4
1$:
	CMPB  (R0)+,(R1)		;SAME?
	BEQ  2$ 			;SO FAR
	TST  R4 			;ANY MATCH UP TO HERE
	BEQ  11$			;NO, NO CLEAN UP NECESSARY
	SUB  R4,R1			;RESET SEQ PTR TO BEGINNING
11$:
	CLR  R4
12$:
	SOB  R2,1$			;UNTIL END OF STRING
	MOV  R4,R2			;RETURN LENGTH MATCHED SO FAR
	SEC				;RAN OUT OF INPUT STRING
	RTS  PC
2$:
	INC  R4 			;ANOTHER CHAR MATCHED
	INC  R1 			;UPDATE SEQ PTR
	TSTB  (R1)			;END OF SEQ TO MATCH
	BEQ  3$ 			;THAT'S ALL
	BR  12$ 			;KEEP AT IT
3$:
	CLC				;SIGNAL SUCESSFUL MATCH
	RTS  PC
	.PAGE
        .SBTTL  GET DATE FROM FIRST BUFFER
;
;  THIS ROUTINE SCANS THE FIRST BUFFER FULL TO FIND
;    THE DATE FIELD. IT LOADS THE 9 CHAR FIELD INTO
;    THE HEADER BUFFER DATE FOR INCLUSION IN THE REPORT
;
GETDAT:
	TSTB  DATE			;WILL BE NON ZERO AFTER DATE IS READ
	BNE  1$ 			;SKIP THE REST
	MOV  #BUFF,R0			;POINT TO BEGINNING IF ASCII STRING
	MOV  #DT,R1			;SEARCH STRING
	MOV  F.NRBD+TBFDB,R2		;LENGTH
	JSR  PC,SCAN
	BCS  2$ 			;COULDN'T FIND IT
	MOV  #15.,R2
	MOV  #DATE,R1			;BUFFER TO HOLD STRING
	ADD  #2,R0			;PT TO BEGINNING OF BUFFER
3$:
	MOVB  (R0)+,(R1)+
	SOB  R2,3$
	BR  1$
2$:
	MOV  #15.,R2			;FILL WITH BLANKS
	MOV  #DATE,R1
4$:
	MOVB  #' ,(R1)+
	SOB  R2,4$
1$:
	RTS  PC
	.PAGE
        .SBTTL  GET UIC FROM ASCII STRING
;
;  GIVEN A PTR TO THE ASCII STRING REPRESENTING A UIC,
;    CONVERT THE STRING TO A GROUP ID (PLACE IT IN GROUP)
;    AND A USER ID (PLACE IT IN USER). PTR PTS PAST STRING
;    ON EXIT. SET C-BIT IF EITHER GID OR UID GTR 377(OCTAL)
;
GETUIC:
	JSR  PC,$COTB			;CONVERT
	MOV  R1,GROUP			;STORE GID
	CMP  #377,R1			;VALID?
	BLO  1$
	JSR  PC,$COTB
	CMP  #377,R1
	BLO  1$ 			;INVALID UID
	MOV  R1,USER
	CLC
	BR  2$				;RETURN - SUCCESS
1$:
	SEC
2$:
	RTS  PC
	.PAGE
        .SBTTL  USAGE STATS GATHERER
;
;  PICK UP THE UIC USAGE STATISTICS. ASSUMES FORMAT AS GENERATED BY
;    PIP /TB. R0 PTS TO IS DIGIT ON ENTRY AND JUST PAST THE
;    LAST DIGIT OF THE FILES ON EXIT
;
DSTATS:
	JSR  PC,$CDTB			;CONVERT DEC TO BINARY
	MOV  R1,USED			;STORE IT
	INC  R0 			;STEP PAST THE '/'
	JSR  PC,$CDTB
	MOV  R1,ALLOC
	ADD  #13,R0
	JSR  PC,$CDTB
	MOV  R1,FILES
	RTS  PC
	.PAGE
        .SBTTL  NXTINT
;
;  NXTINT GETS THE NEXT VALID UIC FROM THE INTERNAL DATA STRUCTURE.
;    TO FACILITATE CHANGE FROM ONE GROUP TO THE NEXT THE CURRENT
;    GROUP NODE PTR IS KEPT IN GRPPTR.
;    ON ENTRY R0 PTS AT CURRENT NODE
;    ON EXIT  R0 PTS AT THE NEW NODE (IF ANY)
;	      IUIC CONTAINS UID IN LOW BYTE AND GID IN HIGH BYTE
;	      DONE=+1 TO SIGNIFY END OF INTERNAL TABLE
;
NXTINT:
	BIT  #1,DONE			;ALREADY AT THE END
	BNE  OUT			;JUST LEAVE
	MOV  NODPTR,R0
	CMP  N.PTR(R0),#-1		;END OF GROUP
	BEQ  1$
	MOV  N.PTR(R0),R0		;NEXT NODE
	MOVB  N.ID(R0),IUIC		;GROUP ID ALREADY SET
	MOV  R0,NODPTR
	BR  OUT
;
1$:
	MOV  GRPPTR,R0			;RESET NODE PTR TO GROUP NODE
3$:
	ADD  #NODSZ,R0			;LOOK AT NEXT ONE
	CMP  #GEND,R0			;END OF TABLE?
	BLE  2$ 			;YES
	CMP  N.PTR(R0),#-1		;ANY ENTRIES IN THIS GROUP
	BEQ  3$ 			;KEEP LOOKING
	MOV  R0,GRPPTR			;KEEP TRACK OF GROUP NODE
	MOVB  N.ID(R0),IUIC+1
	CLRB  IUIC			;UID FOR GROUP ENTRY
	MOV  R0,NODPTR
	BR  OUT
;
2$:
	MOV  #177777,IUIC		;HIGHEST UIC WE CAN PUT IN
	BIS  #1,DONE			;SIGNAL INTERNAL TABLE FINISHED
OUT:
	RTS  PC
	.PAGE
        .SBTTL  GET NEXT RECORD FROM FILE
;
;
;
NXTFIL:
	BIT  #2,DONE			;ALREADY AT END OF FILE?
	BNE  OUTFIL			;YES,LEAVE
	GET$  #OLDFDB,#INBUF,#RECSIZ,FILEND
	BIT  #2,DONE			;MAY HAVE JUST REACHED EOF
	BNE  OUTFIL
	MOVB  GID+INBUF,FUIC+1
	MOVB  UID+INBUF,FUIC
OUTFIL:
	RTS  PC
;
;
FILEND:
	CMPB  #-10.,F.ERR+OLDFDB	;EOF?
	BEQ  1$
	DELET$	#NEWFDB 		;UNRECOVERABLE ERROR- GET RID OF THE
					;NEW ONE
	JMP  RDERR			;REPORT ERROR
1$:
	BIS  #2,DONE			;SIGNAL EOF
	MOV  #177777,FUIC
	RTS  PC
	.PAGE
        .SBTTL  CLEAR THE LINE PRINTER BUFFER
;
;
;
CLRBUF:
	MOV  #LPBUFF,R4
	MOV  #LPBSIZ/2,R3
1$:
	MOV  #"  ,(R4)+
	SOB  R3,1$
	RTS  PC
	.PAGE
        .SBTTL  PRINT HEADER MESSAGE
;
;
;
HEADR:
	PUT$  #LPFDB,#HEADER,#HEADL
	PUT$  #LPFDB,#SKIP2,#SKIP2L
	PUT$  #LPFDB,#HEAD2,#HEAD2L
	RTS  PC
	.PAGE
        .SBTTL  FILL IN USERNAME IN LPBUFFER AND BUFFER FOR USAGE.DAT
	.IF  DF,ACCOUNT 		;MBK001
;BNMMOD
					;BNMMOD BNMMOD BNMMOD BNMMOD SEARCH
					;NAMES FOR GROUP+USER
USERNM:
	MOV  #NAMES,R1			;BNMMOD START OF USER NAME LIST
	MOV  NAMESL,R2			;BNMMOD NO. OF NAMES IN LIST
1$:
	CMPB  GROUP,GRP(R1)		;BNMMOD IS THE GROUP THE SAME
	BNE  2$ 			;BNMMOD NO SO CHECK NEXT ENTRY IN LIST
	CMPB  USER,USR(R1)		;BNMMOD IS THE USER ALSO THE SAME
	BEQ  3$ 			;BNMMOD YES SO PUT USER NAME IN LP
					;BUFFER
2$:
	ADD  #LNMS,R1			;BNMMOD R1 POINTS TO NEXT ENTRY IN NAMES
	SOB  R2,1$			;BNMMOD REPEAT FOR ALL ENTRIES IN LIST
	MOV  #BLNKNM,R1 		;BNMMOD ADDRESS OF BLANKED OUT NAME
3$:
	MOV  #NM1,R3			;BNMMOD WHERE USER NAME TO BE PUT
	MOV  #NME+INBUF,R2		;BNMMOD WHERE IN INBUFF NAME IS TO GO
	MOV  #NME+OUTBUF,R0		;BNMMOD WHERE IN OUTBUF NAME IS TO GO
	MOV  #LP.NM,R4			;BNMMOD LENGTH OF USER NAME
4$:
	MOVB  @R1,(R3)+ 		;BNMMOD PUT IN NAME 1 CHAR AT A TIME
	MOVB  @R1,(R2)+ 		;BNMMOD PUT CHAR IN INBUFF
	MOVB  (R1)+,(R0)+		;BNMMOD PUT CHAR IN OUTBUF
	SOB  R4,4$			;BNMMOD DO IT FOR EACH CHAR
	RTS  PC 			;BNMMOD RETURN BNMMOD
	.ENDC				;MBK001
	.PAGE
        .SBTTL  LOAD LINE PRINTER BUFFER
;
;
;
LDLPBF:
	MOV  #NOTE1,R3			;LP BUFFER POSITION FOR SPEC NOTE
	MOV  NOTPTR,R5			;PICK UP ADDRESS OF NOTE
	MOV  #LP.NOT,R4 		;LENGTH
1$:
	MOVB  (R5)+,(R3)+
	SOB  R4,1$
;
	MOVB  #'[,GRP1-1
	MOV  #GRP1,R0			;INTO BUFFER
	CLR  R2 			;SUPRESS LEADING ZEROES
	MOV  GROUP,R1			;GROUP UID
	BEQ  50$			;MBK002 (ALL GROUUPS)
	JSR  PC,$CBOMG			;CONVERT TO ASCII
	BR  60$ 			;MBK002
50$:
	MOVB  #'*,(R0)+ 		;MBK002 GROUP NUMBER ='*'
60$:					;MBK002
;
	MOVB  #',,USR1-2
	MOV  #USR1,R0
	MOV  USER,R1
	BEQ  10$			;GROUP ENTRY
	CLR  R2 			;SUPRESS LEADING ZEROES
	JSR  PC,$CBOMG
	BR  11$
10$:
	MOVB  #'*,(R0)+
11$:
	MOVB  #'],(R0)
;
	CMP  #-1,DFLAG			;NO ENTRY THIS TIME?
	BEQ  2$ 			;NO OUTPUT
	MOV  NODPTR,R1
	ADD  #N.US,R1			;MBK002 BLOCKS USED THIS TIME
	MOV  #USD1,R0
	CLR  R2 			;SUPRESS LEADING ZEROES
	JSR  PC,$CDDMG			;MBK002
;
	MOV  NODPTR,R1
	ADD  #N.AL,R1			;MBK002 BLOCKS ALLOCATED
	MOV  #ALL1,R0
	CLR  R2 			;SUPRESS LEADING ZEROES
	JSR  PC,$CDDMG			;MBK002
;
	MOV  NODPTR,R1
	MOV  N.FL(R1),R1
	MOV  #FIL1,R0
	CLR  R2 			;SUPRESS LEADING ZEROES
	JSR  PC,$CBDMG
;
	MOV  #LIM1,R0
	TST  DFLAG			;WAS THERE AN ENTRY LAST TIME
	BEQ  3$ 			;YES THERE WAS
	BR  5$
3$:
	MOV  MAX+INBUF,R1		;CURRENT LIMIT
	BEQ  5$
	JSR  PC,$CBDMG
	CLR  R2 			;SUPRESS LEADING ZEROES
	BR  2$
5$:
	MOV  #NOLIM,R5
	MOV  #NOLIML,R1
4$:
	MOVB  (R5)+,(R0)+
	SOB  R1,4$
;
2$:
	RTS  PC
	.PAGE
        .SBTTL  LOAD SUMMARY BUFFER
;
;
;
LDSUMM:
	CMP  #-1,DFLAG			;NO RECORD THIS TIME?
	BEQ  2$ 			;NO, THERE ISN'T
	MOV  NODPTR,R0			;PT AT CURRENT NODE FOR DATA
	TST  DFLAG			;CAN WE USE INPUT RECORD?
	BNE  1$ 			;NO, THIS IS FIRST APPEARANCE OF REC
	MOV  N.US(R0),USF+INBUF
	MOV  N.AL(R0),ALF+INBUF
	MOV  N.FL(R0),FLF+INBUF
	PUT$  #NEWFDB,#INBUF,#RECSIZ
	BR  2$
;
;
1$:
	MOVB  GROUP,GID+OUTBUF
	MOVB  USER,UID+OUTBUF
	CLR  MAX+OUTBUF
	MOV  N.US(R0),USF+OUTBUF
	MOV  N.AL(R0),ALF+OUTBUF
	MOV  N.FL(R0),FLF+OUTBUF
	PUT$  #NEWFDB,#OUTBUF,#RECSIZ
2$:
	RTS  PC
	.END  USAGE
