Google
 

Trailing-Edge - PDP-10 Archives - decuslib20-06 - decus/20-158/acct20.mac
There are no other files named acct20.mac in the archive.
00100		TITLE	ACCT20	DECSYSTEM-20 usage reporting program
00200		COMMENT	\
00300	
00400		This program generates usage reports for the DECSYSTEM-20
00500	from binary files which contain entries in the format of the
00600	<ACCOUNTS>SYSTEM-DATA.BIN file.  A single file or a series of
00700	files may be processed at once; reports for a single user, tape
00800	drive, or TTY may be generated in detail or as a summary; 
00900	complete report of usage by all users may be generated; and 
01000	values may be assigned to usage by means of a charge-rate schedule,
01100	including possibly different charges at different times of the
01200	day.
01300	
01400	
01500			Written at Wesleyan University 
01600			  by David Todd
01700			  August, 1980.
01800			Version 2 by HDT, June 1983.	\
01900	
02000	SUBTTL	Edit History
02100	
02200	;[1]	HDT:  Include code to report metering statistics generated in
02300	;	AVL tree routines (edit [1] of TREE.MAC).
02400	;[2]	HDT:	Implement LIST-CATEGORY-TOTALS and LIST-SUMMARY-TOTALS
02500	;	to dump summary and category totals in a form suitable
02600	;	for database processing
02700	;[3]	HDT: Implement REPROCESS command to reprocess DUMPed binary
02800	;	file and generate new summary and/or categorization listing
02900	;[4]	HDT: Get system name with JSYS rather than using embedded
03000	;	system name string.
03100	;[5]	HDT: Fix miscount of words for string part of record in
03200	;	DUMP processing
03300	;[6]	HDT: Fix calculation of commerical charges to account for
03400	;	possible disparity between application of daylight savings
03500	;	offset between date/time of entry and date/time of processing
03600	;[7]	HDT: Correct bug which gave incorrect account-string
03700	;	pointer when REPORT (by) ACCOUNT is enabled.  Note that
03800	;	this string not available in all record types
03900	;	and can't be used to account for disk usage, etc.
04000	;[8]	HDT: Invoke report generators from the EXIT command 
04100	;	processor.  This makes processing of the raw accounting
04200	;	files and the summary binary files consistent in the way
04300	;	the reports are generated.
04400	;[9]	HDT: Change column widths of CATEGORY report to accommodate
04500	;	sizes seen in routine processing
04600	;[10]	HDT:  correctly identify entry type 5000. as user type
04610	;[11]	HDT:  If entry type is user-defined, dispatch to last
04620	;	entry in SETSTR to determine correct user name string
04630	;[12]	HDT:  In case of user-defined entry type, don't attempt
04640	;	      to process record (pop and discard return address)
04650	;	      before attempting to get next record
04660	;[13]	HDT:  Type out erroneous word addresses in radix 8
04670	;[14]	HDT:  Type out record types/lengths in decimal in error msgs
04680	;[15]	HDT:  Compute word count correctly by adding in size of recs
04690	;	as they're read in
04700	;[16]   HDT:  Fix to get correct file name printed on error report
     
00100	Subttl	Table of contents for ACCT20
00200	
00300	;	   -- Section --					   -- Page --
00400	;
00500	;  1.   Edit history.................................................. 1
00600	;  2.	Table of contents............................................. 2
00700	;  3.	Definitions................................................... 4
00800	;  4.	Definition of offsets to values in tree nodes................. 5
00900	;  5.	Definitions of fields in SYSTEM-DATA.BIN file entries......... 6
01000	;  6.	Definition of processing flag bits............................ 7
01100	;  7.	Command processing loop - main program control................ 8
01200	;  8.	BEGIN/END command processing.................................. 9
01300	;  9.	CATEGORIZE command processing................................. 10
01400	;  10.	CHARGE-RATE command processing................................ 11
01500	;  11.	DEBUG and STATISTICS command processing....................... 12
01600	;  12.	DUMP command processing....................................... 13
01700	;  13.	EXIT/QUIT command processing.................................. 14
01800	;  14.	FORMS command processing...................................... 15
01900	;  15.	LIST command processing....................................... 16
02000	;  16.	NAME command processing....................................... 17
02100	;  17.	PROCESS command processing.................................... 18
02200	;  18.	PROCESS command support routines.............................. 19
02300	;  19.	Summary printing routines for PROCESS command................. 20
02400	;  20.	TYPERR - Routine to process erroneous entry records........... 21
02500	;  21.	PROUSR - Routine to process user-defined entry records........ 22
02600	;  22.	SESS - Routine to handle SESSION record types................. 23
02700	;  23.	RESTART - Routine to process RESTART record types............. 24
02800	;  24.	CHKPNT - Routine to process CHECKPOINT record types........... 25
02900	;  25.	DATTIM - Routine to process DATE/TIME CHANGE records.......... 26
03000	;  26.	BATCH - Routine to process BATCH records...................... 27
03100	;  27.	INPUT - Routine to process INPUT spooler records.............. 28
03200	;  28.	OUTPUT - Routine to process OUTPUT spooler records............ 29
03300	;  29.	DSKUSG - Routine to process disk usage records................ 30
03400	;  30.	SPNUSG - Routine to process spindle usage records............. 31
03500	;  31.	STRMNT - Routine to process structure mount records........... 32
03600	;  32.	MTAMNT - Routine to process magnetic tape mount records....... 33
03700	;  33.	FILRET - Routine to process file retrieval records............ 34
03800	;  34.	FILARC - Routine to process file archival records............. 35
03900	;  35.	FILMIG - Routine to process file migration records............ 36
04000	;  36.	FILCOL - Routine to process file collection records........... 37
04100	;  37.	Routine to support record processing routines................. 38
04200	;  38.	DETAIL command processing..................................... 39
04300	;  39.	SUMMARIZE command processing.................................. 40
04400	;
04500	;		    (Continued on next page)
     
00100	;
00200	;		  (Continued from previous page)
00300	;
00400	;  40.	PRINTER-CHARGES command processing............................ 41
00500	;  41.	REPORT command processing..................................... 42
00600	;  42.	RESET command processing...................................... 43
00700	;  43.	WRITE-DETAIL-BINARY command processing........................ 44
00800	;  44.	Storage....................................................... 45
00900	;
01000	;		     (End of table of contents)
     
00100	SUBTTL	Definitions
00200		DEBUG==1
00300		WESU==0
00400		IFNDEF	DEBUG,<DEBUG==0>	;default is no debug
00500		IFNDEF	CHKBUG,<CHKBUG==1>	;if 1, enables assembly of code
00600						;which ignores CHECKPOINT
00700						;records (and the erroneous
00800						;records with header 3,,200
00900						;which have no matching trailer
01000		IFNDEF	MTABUG,<MTABUG==1>	;if 1, enables assembly of code
01100						;which ignores MTA MOUNT records
01200						;which have negative read or
01300						;write frame counts or connect
01400						;times
01500		IFNDEF	WESU,<WESU==0>		;default Wesleyan switch off
01600						;if =1, enables certain code
01700						;which may only be desirable
01800						;at Wesleyan University
01900						;In particular, enables output
02000						;to DETAILS.BIN file of any
02100						;session entry on which an
02200						;account string was entered.
02300						;These LOGINS will thus be
02400						;billed.
02500		SALL
02600		SEARCH	MACSYM,MONSYM,CMD,ACTSYM
02700		.REQUIRE	SYS:MACREL
02800		.REQUIRE	SYS:CMD
02900	
03000	
03100		EXTERN	BINADD,GETBLK,GETNOD,DMPTRE,BINLUK
03200	;[1]	Counters for AVL tree stats from tree routine
03300		EXTERN	.SROTS,.DROTS,.ADJBF	
03400		MAJOR==2
03500		MINOR==1
03600		VEDIT==3
03700		VWHO==2			;2=WCC
03800	
03900		PGVER.	MAJOR,MINOR,VEDIT,VWHO
04000	
04100	;Accumulator definitions
04200	
04300		T0==0
04400		A==1
04500		B==2
04600		C==3
04700		D==4
04800		Q1==5
04900		Q2==6
05000		Q3==7
05100		P1==10
05200		P2==11
05300		P3==12
05400		P4==13
05500		F==15
05600		L==16
05700		P=17
05800	
05900		PDLEN==200
06000		BUFLEN==^D500		;MAXIMUM SIZE OF ENTRY IN SYSTEM-DATA.BIN
06100		.JBREL==44	;from TOPS-10 job data area
06200		.JBFF==121
06300		PTTBLN==^D500	;Maximum number of special printer forms
06400		SUMPAG==^D60	;Number of lines of summary listing page
06500		CATPAG==^D60	;Number of lines of category lising page
06600		DETPAG==^D60	;Number of lines of detail listing page
06700		..SELN==4	;[1]SELECT-DETAILS processing node fixed-part size
06800		SL%COM==1	;SELECT-DETAILS node flag for COMMERCIAL users
06900		..BILN==4	;[1]CHARGE BILL-subcommand node length
07000		..CTLN==4	;[1]Size of CATEGORIZE directory-string nodes
07100		BL%COM==1	;CHARGE BILL-subcommand node flag for
07200				; commercial users
07300		..DTLN==3	;[1]Node length for DETAILS tree
07400		SHFMAX==5	;Size of shift table for charge rates
07500		SESTYP==2	;session type code
07600	
07700	
07800		DEFINE	TXT(TEXT)<POINT 7,[ASCIZ/TEXT/]>
07900	
08000		DEFINE	U(WORD,ADDRES,FLAGS)<
08100			IFB <FLAGS>, <IFB <ADDRES>, <[ASCIZ/WORD/],,.'WORD>
08200				      IFNB <ADDRES>, <[ASCIZ/WORD/],,ADDRES> >
08300			IFNB <FLAGS>,	<IFB <ADDRES>,<[FLAGS&3777777777!CM%FW
08400							ASCIZ/WORD/],,.'WORD>
08500					<IFNB <ADDRES>,<[FLAGS&3777777777!CM%FW
08600							ASCIZ/WORD/],,ADDRES> > > >
08700	
08800	
08900	;SPACE(n) outputs n blanks to JFN/string in A.  Destroys B,C.
09000		DEFINE	SPACE(N)	<
09100		MOVEI	C,N
09200		CALL	SPACES	>
09300	
09400		DEFINE	CMDSTG <
09500	CMDBLN==:<^D80*^D50>/5+1			;room for 50 line command
09600	CMDBUF::BLOCK	CMDBLN
09700	CMDACS::BLOCK	20			;saved ac's from beginning of command line
09800	ATMBLN==:CMDBLN
09900	ATMBUF::BLOCK	ATMBLN			;holds last parsed field
10000	SBK::	BLOCK	20			;COMND JSYS state block
10100	CJFNLN==:20
10200	CJFNBK::BLOCK	CJFNLN			;GTJFN block for COMND JSYS
10300	REPARA::0				;reparse address for COMND
10400	CMDFRM::0				;marks bottom of stack
10500	CMDPLN==:200				;amount of stack we can save
10600	CMDPDL::BLOCK	CMDPLN			;room to save PDL
10700	>
     
00100	SUBTTL	Definition of offsets to values in tree nodes
00200	
00300	;	Summary record entries - offsets into tree nodes
00400	;	for items contained in per-user summary
00500	
00600		DEFINE	SUMENT(NAM)<
00700			.S'NAM==..SLEN
00800			..SLEN=..SLEN+1	>
00900	
01000		DEFINE	SUMNOD<
01100		SUMENT	USER	;POINTER TO ASCIZ USER NAME STRING
01200		SUMENT	PTRS	;POINTERS TO SUBTREES
01300		SUMENT	REFS	;NUMBER OF REFERENCES TO THIS NODE
01400	;Next three entries must appear in this order for summary processing
01500		SUMENT	TSES	;# TIMESHARING SESSIONS
01600		SUMENT	TCON	;TIMESHARING TERMINAL CONNECT TIME
01700		SUMENT	TCPU	;TIMESHARING CPU USAGE
01800	;Next three entries must appear in this order for summary processing
01900		SUMENT	BSES	;#BATCH SESSIONS
02000		SUMENT	BCON	;BATCH CONNECT TIME
02100		SUMENT	BCPU	;BATCH CPU USAGE
02200	;	SUMENT	TTIN	;TTY INPUT CHAR COUNT - not supported by DEC
02300	;	SUMENT	TTOU	;TTY OUTPUT CHAR COUNT - not supported by DEC
02400	;	SUMENT	KCS	;CORE-TIME INTEGRAL - not supported by DEC
02500	;	SUMENT	DSKR	;DISK READS - not supported by DEC
02600	;	SUMENT	DSKW	;DISK WRITES - not supported by DEC
02700		SUMENT	DSKP	;DIS PERMANENT STORAGE LIMIT (CUMULATIVE)
02800		SUMENT	DSKU	;DISK STORAGE USED (CUMULATIVE)
02900		SUMENT	DSKC	;COUNT OF DISK USAGE ENTRIES (FOR AVERAGING)
03000		SUMENT	STRM	;STRUCTURE MOUNTS
03100		SUMENT	STRT	;TIME USED ON STRUCTURES
03200		SUMENT	MTAM	;TAPE MOUNTS
03300		SUMENT	MTAU	;DURATION OF USE OF TAPE DRIVE
03400		SUMENT	MTAR	;TAPE FRAMES READ
03500		SUMENT	MTAW	;TAPE FRAMES WRITTEN
03600		SUMENT	CDRR	;CARDS READ
03700		SUMENT	LPTW	;PRINTER PAGES WRITTEN
03800		SUMENT	PLTM	;MINUTES OF PLOTTER TIME
03900		SUMENT	FILR	;FILE PAGES RETRIEVED
04000		SUMENT	FILA	;FILE PAGES ARCHIVED
04100		SUMENT	FILM	;FILE PAGES MIGRATED
04200		SUMENT	FILC	;FILE PAGES COLLECTED
04300		SUMENT	VALU	;VALUE OF SERVICES
04400	>
04500	
04600		..SLEN==0
04700		SUMNOD
     
00100	SUBTTL	Definitions of fields in SYSTEM-DATA.BIN file entries
00200	
00300	;	FOLLOWING DEFINITIONS TAKEN FROM CHKPNT.MAC-4(114)
00400	;	AS A PROTOTYPE FOR THE LAYOUT OF THE SYSTEM-DATA.BIN FILE
00500	;
00600		DEFSTR	(SDTYP,BUFF+0,17,18)	;TYPE CODE
00700		DEFSTR	(SDLEN,BUFF+0,35,18)	;ENTRY LENGTH
00800		DEFSTR	(SDTAD,BUFF+1,35,36)	;TIME AND DATE
00900		DEFSTR	(SDDRV,BUFF+2,5,6)	;DEC REVISION #
01000		DEFSTR	(SDCRV,BUFF+2,11,6)	;CUSTOMER REVISION #
01100		DEFSTR	(SDTMT,BUFF+2,17,6)	;TERMINAL TYPE CODE
01200		DEFSTR	(SDJNO,BUFF+2,35,18)	;JOB NUMBER
01300		DEFSTR	(SDPNM,BUFF+3,35,36)	;PROGRAM NAME (SIXBIT)
01400		DEFSTR	(SDPVR,BUFF+4,35,36)	;PROGRAM VERSION NUMBER
01500		DEFSTR	(SDMVR,BUFF+5,35,36)	;MONITOR VERSION NUMBER
01600		DEFSTR	(SDJTS,BUFF+6,0,1)	;BATCH/TS FLAG
01700		DEFSTR	(SDULN,BUFF+6,5,5)	;USER NAME STRING LENGTH
01800		DEFSTR	(SDSL1,BUFF+6,11,6)	;STRING LENGTH 1 (ACCOUNT)
01900		DEFSTR	(SDSL2,BUFF+6,17,6)	;STRING LENGTH 2 (SESSION REMARK)
02000		DEFSTR	(SDLNO,BUFF+6,35,18)	;LINE NUMBER
02100		DEFSTR	(SDNOD,BUFF+7,35,36)	;NODE NAME (SIXBIT)
02200	
02300		.SDNAM=BUFF+10
02400		.SDMIN=.SDNAM-BUFF+1		;MINIMUM ENTRY SIZE
02500		MXRTYP==.UTCOL			;MAXIMUM RECORD TYPE
     
00100	SUBTTL	Definition of processing flag bits
00200	
00300	
00400		DEFINE FLAG(NAM)<
00500		IF1	<
00600			IFNDEF	..FPOS,<..FPOS==0>
00700			F%'NAM==1B<..FPOS>
00800			..FPOS==..FPOS+1
00900			IFG ..FPOS-^D36,<PRINTX ?TOO MANY FLAG BITS>
01000			>	>
01100	
01200		FLAG	DEB	;DEBUG requested by user
01300		FLAG	DMP	;Binary DUMP of summary tree requested by user
01400		FLAG	STS	;STATISTICS requested by user
01500		FLAG	BDT	;BEGIN date/time
01600		FLAG	EDT	;END date/time
01700		FLAG	CAT	;CATEGORIZE command was given
01800		FLAG	CHA	;CHARGE rates were given
01900		FLAG	DETT	;Temporary flag for DETAIL command
02000		FLAG	DCP	;DETAIL for CPU use was requested
02100		FLAG	DDS	;DETAIL for disk usage was requested
02200		FLAG	DIN	;DETAIL for input spooler was requested
02300		FLAG	DOU	;DETAIL for output spooler was requested
02400		FLAG	DTA	;DETAIL for tape usage was requested
02500		FLAG	DTT	;DETAIL for TTY usage was requested
02600		FLAG	DET	;DETAIL processing to be done for current record
02700		FLAG	SUMT	;Temporary flag for SUMMARY command
02800		FLAG	SCP	;SUMMARY for CPU use was requested
02900		FLAG	SDS	;SUMMARY for disk usage was requested
03000		FLAG	SIN	;SUMMARY for input spooler was requested
03100		FLAG	SOU	;SUMMARY for output spooler was requested
03200		FLAG	STA	;SUMMARY for tape usage was requested
03300		FLAG	STT	;SUMMARY for TTY usage was requested
03400		FLAG	SUM	;SUMMARY processing to be done for current record
03500		FLAG	PCG	;PRINTER-CHARGES were set
03600		FLAG	RPT	;0==> REPORT by directory, 1==> by account string
03700		FLAG	BIL	;Accounts for separate billing were specified
03800		FLAG	TTIN	;Is TTY source of input data for commands?
03900		FLAG	BAT	;Value 1 ==> record is for batch work
04000		FLAG	BIN	;Write selected DETAILS to binary file
04100		FLAG	COM	;This user record is for commercial user
04200		FLAG	OUT	;Flags this record for output to the DETAILS-BINARY file
04300		FLAG	NAM	;Name command was seen
04400		FLAG	NMT	;NO-MTA-DETAILS was seen
04500				;(Needed because MOUNTR incorrectly attributes
04600				; magtape usage)
04700		FLAG	FRM	;FORMS command seen
04800		FLAG	LSC	;[2]LIST-CATEGORY-TOTALS seen
04900		FLAG	LSS	;[2]LIST-SUMMARY-TOTALS seen
05000	
05100		F%DAL==F%DCP!F%DDS!F%DIN!F%DOU!F%DTA!F%DTT	;all DETAILs
05200		F%SAL==F%SCP!F%SDS!F%SIN!F%SOU!F%STA!F%STT	;all SUMMARYs
     
00100	SUBTTL	Command processing loop - main program control
00200	ACCT20:	RESET
00300		MOVE	P,[IOWD PDLEN,PDL]
00400		CALL	CMDINI		;Initialize for command scanning
00500		MOVE	T0,.JBREL	;Save initial start of free memory
00600		MOVEM	T0,MEM0
00700		MOVE	F,DEFFLG	;Set up default processing flags
00800	;[4]	set up system name for printing from system table
00900	
01000		MOVE	A,[SIXBIT/SYSVER/]	;Get table index for SYSVER
01100		SYSGT
01200		MOVEI	D,(B)		;Put 0,,table index into D
01300		HLL	C,B		;Get -count,,dest adr into C
01400		HRRI	C,SYSNAM
01500	NAMLUP:	MOVE	A,D		;Get successive words of table
01600		GETAB
01700		 JRST	[TMSG	<%ACCT20: Can't get system name from table
01800	>
01900			 JRST	GOTNAM]
02000		MOVEM	A,(C)		;Store away the word we got
02100		ADD	D,[1,,0]	;Set to request next word from system
02200		AOBJN	C,NAMLUP	;count and point to next word of dest
02300	GOTNAM:				;finished
02400		TMSG	<ACCT20 - DEC-20 accounting program
02500		  Type HELP for a list of commands
02600	>
02700	LOOP:	HRROI	A,[ASCIZ/ACCT20>/]
02800		CALL	DPROMP		;Prompt for a command
02900		MOVEI	A,[FLDDB. .CMKEY,,COMTAB]
03000		CALL	RFIELD		;Go get command
03100		HRRZ	A,(B)
03200		CALL	@A		;And dispatch to processing routine
03300		JRST	LOOP		;Now go back for more
03400	
03500	COMTAB:	XWD	TABEND-.-1,TABEND-.-1
03600		T	BEGIN,.BEG
03700		T	CATEGORIZE,.CAT
03800		T	CHARGE-RATES,.CHA
03900		U	DEBUG,.DEB,CM%INV
04000		T	DETAIL,.DET
04100		T	DUMP,.DMP
04200		T	END,.END
04300		T	EXIT,.EXI
04400		T	FORMS,.FRM
04500		T	HELP,.HEL
04600		T	LIST-CATEGORY-TOTALS,.LSC	;[2]
04700		T	LIST-SUMMARY-TOTALS,.LSS	;[2]
04800		T	NAME,.NAM
04900		U	NO-MTA-DETAILS,.NMT,CM%INV
05000		T	PRINTER-CHARGES,.PRI
05100		T	PROCESS,.PRO
05200		U	QUIT,.EXI,CM%INV
05300		T	REPORT,.REP
05400		T	REPROCESS,.RPR		;[3]
05500		T	RESET,.RES
05600		T	STATISTICS,.STS
05700		T	SUMMARIZE,.SUM
05800		T	WRITE-DETAIL-BINARY,.WDB
05900		TABEND==.
     
00100	SUBTTL	BEGIN/END command processing
00200	.BEG:	NOISE	<with starting date/time>
00300		MOVEI	A,[FLDDB. .CMTAD,,CM%IDA!CM%ITM+TMPBLK]
00400		CALL	CFIELD		;get date/time and confirm with CR
00500		MOVEM	B,BEGDT		;Save date/time for processing
00600		TXO	F,F%BDT		;And tell processing to use it
00700		RET
00800	
00900	.END:	NOISE	<at starting date/time>
01000		MOVEI	A,[FLDDB. .CMTAD,,CM%IDA!CM%ITM+TMPBLK]
01100		CALL	CFIELD		;get date/time and confirm with CR
01200		MOVEM	B,ENDDT		;Save date/time for processing
01300		TXO	F,F%EDT		;And tell processing to use it
01400		RET
     
00100	SUBTTL	CATEGORIZE command processing
00200	.CAT:	NOISE	<using file>
00300		MOVEI	A,[FLDDB. .CMIFI,CM%DPP,,,DSK:ACCT20.CAT.0]
00400		CALL	CFIELD		;Get file spec and confirm
00500		HRLM	B,SBK+.CMIOJ	;And tell CMD macros where to look
00600		MOVE	A,B		;Now open file
00700		MOVEM	A,CATJFN	;Save JFN for closing
00800		DVCHR			;is it a TTY?
00900		LSH	b,-^D18
01000		ANDI	B,777
01100		CAIN	B,.DVTTY
01200		 TXO	F,F%TTIN	;yes
01300		MOVE	A,CATJFN	;Open file
01400		MOVX	B,FLD(7,OF%BSZ)!OF%HER!OF%RD
01500		OPENF			;And open file for reading
01600		 JRST	[TMSG <%ACCT20 can't open category definition  file>
01700			 HRRI	A,.PRIIN
01800			 HRLM	A,SBK+.CMIOJ	;reset command macros input
01900			 TXZ	F,F%TTIN	;and turn off tty input mode
02000			 RET]
02100	
02200		SETZM	USGPTR		;[2,3]  create new category tree from
02300		SETZM	CATPTR		;       new file
02400	
02500	CATLUP:	HRROI	A,[ASCIZ/ACCT20 Category>/]
02600		TXNE	F,F%TTIN
02700		 CALL	DPROMP
02800		MOVE	A,SBK+.CMFLG
02900		TXO	A,CM%RAI!CM%XIF
03000		MOVEM	A,SBK+.CMFLG
03100		MOVEI	A,[FLDBK. .CMFLD,CM%BRK,,<directory/account name prefix>,,[BRMSK. (FLDB0.,FLDB1.,FLDB2.,FLDB3.,<*,%,.>,<	, >)]]
03200		CALL	RFIELD
03300		MOVE	A,SBK+.CMABP		;get pointer to buffer
03400		MOVE	B,[TXT<END-CATEGORIES>]		;see if we're finished
03500		STCMP
03600		SKIPN	A
03700		 CALLRET CATEND			;yes - finish up
03800		MOVE	A,SBK+.CMABP
03900		MOVE	B,[POINT 7,TMPBLK]	;copy out directory name temporarily
04000		MOVEI	C,^D39
04100		SETZ	D,
04200		SIN
04300		MOVN	C,C
04400		ADDI	C,^D40+^D4		;compute word length of string
04500		IDIVI	C,5
04600		PUSH	P,C			;save word length
04700		NOISE	<under category name>
04800		MOVEI	A,[FLDDB. .CMFLD,,,<category title>]
04900		CALL	CFIELD
05000		MOVE	A,SBK+.CMABP		;compute length of category name
05100		MOVE	B,[POINT 7,T2BLK]
05200		MOVEI	C,^D39
05300		SETZ	D,
05400		SIN
05500		MOVN	C,C
05600		ADDI	C,^D40+^D4
05700		IDIVI	C,5
05800		MOVEI	P1,USGPTR		;create category summary node
05900		HRLI	P1,..SLEN
06000		MOVE	P2,SBK+.CMABP
06100		MOVE	P3,C			;length of variable part
06200		CALL	GETNOD
06300		JUMPE	P1,CATERR		;report if we failed
06400		POP	P,P3			;retrieve length of directory string
06500		PUSH	P,P1			;save pointer to usage node for now
06600		MOVEI	P1,CATPTR	;create node for category name, if necessary
06700		HRLI	P1,..CTLN
06800		MOVE	P2,[POINT 7,TMPBLK]
06900		CALL	GETNOD
07000		JUMPE	P1,CATERR
07100		POP	P,..CTLN-1(P1)	;[1]store address of usage node in
07200					; categorization node labeled by the
07300					; directory string
07400		JRST	CATLUP		;and go back for more
07500	
07600	
07700	CATEND:	MOVE	A,SBK+.CMFLG
07800		TXZ	A,CM%RAI!CM%XIF	;reset flags for CMD
07900		MOVEM	A,SBK+.CMFLG
08000		HRRI	A,.PRIIN
08100		HRLM	A,SBK+.CMIOJ
08200		TXZ	F,F%TTIN
08300		MOVE	A,CATJFN
08400		CLOSF
08500		 ERMSG	<%ACCT20:	Can't close category definition file>
08600		TXO	F,F%CAT		;And remember to process it
08610	;[1]  Need to reorder tree so that wildcard categories appear at the
08620	;	top of the tree.  This section does the relinking 
08630	;	by putting wildcard entries at the top of the tree as a linked
08640	;	list (though they are also left at their proper place in the 
08650	;	tree, too).
08660		MOVEI	A,FRSTLK	;init linked list of wildcard nodes
08662		MOVEM	A,NXTLNK	;  to point to first link
08664		SETZM	1(A)		;and zero its pointer to the wildcard node
08665		MOVE	P1,CATPTR
08666		MOVEI	P2,CATREO
08667		CALL	DMPTRE		;process the tree through reorder
08669		MOVEI	B,CATPTR	;B points to ptr to current top of tree
08671		MOVEI	A,FRSTLK	;A points to next wildcard link to reorder
08673	RELINK:	SKIPN	C,1(A)		;get next wildcard node to relink
08675		 RET			;none left -- we're done
08677		HRR	D,(B)		;get ptr to top of tree
08679		HRRM	C,(B)		;make end of linked list point to 
08681					;  wildcard node
08683		HRRM	D,.SPTRS(C)	;make wildcard node point to rest of tree
08685		MOVEI	B,.SPTRS(C)	;point B to pointer to top of tree again
08687		HRRZ	A,(A)		;get next link in list
08689		JRST	RELINK		;and relink it (if present)
08699	;[1]	end of reordering procedure
08700		RET
08800	
08900	CATERR:	TMSG	<%ACCT20 categorization: insufficient memory for entry
09000	>
09100		TMSG	<	Processing of category definition terminated
09200	>
09300		CALLRET CATEND
09400	
09402	;[1]	Code added to reorder wildcards in tree
09404	CATREO:	MOVE	A,(P1)		;get ptr to node key
09406		ILDB	T0,A		;get first char of key string
09408		CAIN	T0,"*"		;if it"s a wildcard
09410		 JRST	WLDLNK		;relink it to top of tree
09412		CAIN	T0,"%"		;ditto
09414		 JRST	WLDLNK
09416		RET			;if not, return
09418	
09420	WLDLNK:	HRRZ	C,NXTLNK	;get addr of next node to fill
09422		HRRZM	P1,1(C)		;add this wildcard node addr to fill it
09424		MOVEI	A,2		;add a new unfilled node
09426		CALL	GETBLK	
09428		 JRST	[TMSG<?ACCT20:  Insufficient memory for category processing
09430	>
09432			 HALTF	.-1]
09434		SETZM	1(A)		;zero the pointer to the wildcard node
09436		HRRZM	A,(C)		;add the new link to the old list
09438		HRRZM	A,NXTLNK	;and make it the next to be filled
09440		RET			;done
09495	;[1]	end of reordering additions
09497	
09500	CATDMP:	MOVEI	A,.PRIOU	;[8] tell what we're doing
09510		TMSG	<
09520	[Generating CATEGORIES report]
09530	>
09550		MOVE	B,[TXT<ACCT20>]		;assume standard name prefix
09600		TXNE	F,F%NAM			;was a default name given?
09700		 MOVE	B,[POINT 7,NAMES]	;yes - use it
09800		MOVE	A,[POINT 7,TMPBLK]
09900		SETZB	C,D
10000		SOUT				;copy it out
10100		MOVE	B,[TXT<-CATEGORIES.LST>]	;finish name
10200		SETZB	C,D
10300		SOUT
10400		MOVE	A,[GJ%FOU!GJ%SHT]	;now open file
10500		MOVE	B,[POINT 7,TMPBLK]
10600		GTJFN
10700		 CALLRET	[ERMSG <%ACCT20:	Can't open category output file>
10800				 RET]
10900		MOVEM	A,CATJFN
11000		MOVX	B,FLD(7,OF%BSZ)!OF%WR
11100		OPENF
11200		 CALLRET	[ERMSG <%ACCT20:	Can't open category output file>
11300				 RET]
11400	CAT2:	HRRZ	A,CATJFN	;output header for category listing
11500		SPACE	<^D10>
11600		MOVE	B,[POINT 7,SYSNAM]
11700		SETZB	C,D
11800		SOUT
11900		CALL	CRLF
12000		SPACE	<^D39>
12100		MOVE	B,[TXT<DECSYSTEM-20 Usage Report by Categories>]
12200		SETZB	C,D
12300		SOUT
12400		CALL	CRLF
12500		CALL	CRLF
12600		SPACE	<^D39>
12700		MOVE	B,[TXT<Report generated on >]
12800		SETZB	C,D
12900		SOUT
13000		SETO	B,
13100		SETZ	C,
13200		ODTIM
13300		CALL	CRLF
13400		CALL	CRLF
13500		CALL	CRLF
13600		CALL	CHDR1
13700		MOVEI	B,CATPAG-^D9
13800		MOVEM	B,CATLIN
13900		CALL	CATPRC		;[2,3] process summary tree into category tree
14000		HRRZ	A,CATJFN
14100		MOVE	P1,USGPTR	;now list category usage tree 
14200		MOVEI	P2,CATOUT
14300		CALL	DMPTRE
14405		HRRZ	A,CATJFN	;get JFN for category report again
14410		CALL	CRLF		;output the total value of services
14415		CALL	CRLF
14420		SPACE	<^D106>
14425		MOVE	B,[TXT<TOTAL>]
14430		SETZB	C,D
14435		SOUT
14440		MOVE	B,CATVAL	;print total value of services
14445		MOVX	C,FL%ONE!FL%DOL!FL%PNT!FL%OVL!FLD(^D10,FL%FST)!FLD(2,FL%SND)
14450		FLOUT
14455		 CAI
14460		CALL	CRLF
14500		CLOSF
14600		 ERMSG	<%ACCT20:	Can't close category listing file>
14700		RET
14800	
14900	;[2,3]	Process usage tree into categorization tree
15000	CATPRC:	MOVE	P1,USGPTR	;zero existing usage tree
15100		MOVEI	P2,ZERNOD
15200		CALL	DMPTRE
15300		MOVE	P1,SUMPTR	;process usage summary into category tree
15400		MOVEI	P2,CATSUM
15500		SETZM	CATVAL		;and compute total value of use
15600		CALL	DMPTRE
15700		RET
15800	
15900	;[2,3]	This procedure zeros the category usage node for reprocessing
16000	ZERNOD:	SETZM	.STSES(P1)	;zero out the data part of the node
16100		HRLI	T0,.STSES(P1)
16200		HRRI	T0,.STSES+1(P1)
16300		BLT	T0,..SLEN-1(P1)
16400		RET
16500	
16600	CATSUM:	PUSH	P,P1		;save tree pointers
16700		PUSH	P,P2
16800		MOVEM	P1,MSCPTR	;and record in case we have miscellaneous
16900		MOVE	P2,(P1)		;get pointer to directory string in summary node
17000		MOVEI	P1,CATPTR	;and pointer to categorization tree
17100		CALL	WLDNOD		;find directory prefix in cat tree
17200		 CALL	MSCCAT		;can't - generate MISCELLANEOUS category
17300		MOVE	Q1,..CTLN-1(P1) ;[1]get address of category summary node
17400		POP	P,P2		;retrieve saved summary tree pointers
17500		POP	P,P1
17600		MOVE	B,.STSES(P1)	;and add values from summary node
17700		ADDM	B,.STSES(Q1)	; into category summary node
17800		MOVE	B,.STCON(P1)
17900		FADRM	B,.STCON(Q1)
18000		MOVE	B,.STCPU(P1)
18100		FADRM	B,.STCPU(Q1)
18200		MOVE	B,.SBSES(P1)
18300		ADDM	B,.SBSES(Q1)
18400		MOVE	B,.SBCON(P1)
18500		FADRM	B,.SBCON(Q1)
18600		MOVE	B,.SBCPU(P1)
18700		FADRM	B,.SBCPU(Q1)
18800		MOVE	B,.SDSKP(P1)
18900		IDIV	B,.SDSKC(P1)
19000		ADDM	B,.SDSKP(Q1)
19100		MOVE	B,.SDSKU(P1)
19200		IDIV	B,.SDSKC(P1)
19300		ADDM	B,.SDSKU(Q1)
19400		MOVE	B,.SSTRM(P1)
19500		ADDM	B,.SSTRM(Q1)
19600		MOVE	B,.SSTRT(P1)
19700		FADRM	B,.SSTRT(Q1)
19800		MOVE	B,.SMTAM(P1)
19900		ADDM	B,.SMTAM(Q1)
20000		MOVE	B,.SMTAU(P1)
20100		FADRM	B,.SMTAU(Q1)
20200		MOVE	B,.SMTAR(P1)
20300		FADRM	B,.SMTAR(Q1)
20400		MOVE	B,.SMTAW(P1)
20500		FADRM	B,.SMTAW(Q1)
20600		MOVE	B,.SCDRR(P1)
20700		ADDM	B,.SCDRR(Q1)
20800		MOVE	B,.SLPTW(P1)
20900		ADDM	B,.SLPTW(Q1)
21000		MOVE	B,.SPLTM(P1)
21100		ADDM	B,.SPLTM(Q1)
21200		MOVE	B,.SFILR(P1)
21300		ADDM	B,.SFILR(Q1)
21400		MOVE	B,.SFILA(P1)
21500		ADDM	B,.SFILA(Q1)
21600		MOVE	B,.SFILM(P1)
21700		ADDM	B,.SFILM(Q1)
21800		MOVE	B,.SFILC(P1)
21900		ADDM	B,.SFILC(Q1)
22000		MOVE	B,.SVALU(P1)
22100		FADRM	B,.SVALU(Q1)
22200		FADRM	B,CATVAL
22300		RET
22400	
22500	CATOUT:	HRRZ	A,CATJFN
22600		SOSGE	CATLIN
22700		 CALL	CATHDR
22800	C1OUT:	MOVE	D,.SUSER(P1)	;[9]
22900		MOVEI	C,^D18
22910	OUTLUP:	ILDB	B,D		;get next byte of string
22920		JUMPE	B,FILIN		;if null, fill with spaces
22930		BOUT			;otherwise output
22940		SOJG	C,OUTLUP	;and go back if more to output
23300	FILIN:	 CALL	SPACES
23400		SPACE	2
23500		MOVE	B,.STSES(P1)	;count of sessions
23600		MOVX	C,NO%LFL!NO%OOV!FLD(5,NO%COL)!FLD(12,NO%RDX)
23700		NOUT
23800		 CAI
23900		SPACE	<2>
24000		MOVE	B,.STCPU(P1)	;get cpu time in real sec
24100		MOVX	C,FL%ONE!FL%OVL!FLD(7,FL%FST)
24200		FLOUT
24300		 CAI
24400		SPACE	<2>
24500		MOVE	B,.STCON(P1)	;get connect time in real sec
24600		FIXR	B,B		;go to integer sec for output
24610		IDIVI	B,^D60*^D60	;output hours of connect time
24620		MOVX	C,NO%LFL!NO%OOV!FLD(8,NO%COL)!FLD(12,NO%RDX)
24630		NOUT
24640		 CAI
24900		SPACE	<3>
25000		MOVE	B,.SBSES(P1)	;number of batch sessions
25100		MOVX	C,NO%LFL!NO%OOV!FLD(5,NO%COL)!FLD(12,NO%RDX)
25200		NOUT
25300		 CAI
25400		SPACE	<2>
25500		MOVE	B,.SBCPU(P1)	;batch CPU time in real sec
25600		MOVX	C,FL%ONE!FL%OVL!FLD(7,FL%FST)
25700		FLOUT
25800		 CAI
25900		SPACE	<2>
26000		MOVE	B,.SCDRR(P1)	;cards read
26100		MOVX	C,NO%LFL!NO%OOV!FLD(6,NO%COL)!FLD(12,NO%RDX)
26200		NOUT
26300		 CAI
26400		SPACE	<3>
26500		MOVE	B,.SLPTW(P1)	;pages printed
26600		MOVX	C,NO%LFL!NO%OOV!FLD(7,NO%COL)!FLD(12,NO%RDX)
26700		NOUT
26800		 CAI
26900		SPACE	<3>
27000		MOVE	B,.SPLTM(P1)	;plotter minutes
27100		MOVX	C,NO%LFL!NO%OOV!FLD(4,NO%COL)!FLD(12,NO%RDX)
27200		NOUT
27300		 CAI
27400		SPACE	<3>
27500		MOVE	B,.SDSKU(P1)	;disk space used
27600		MOVX	C,NO%LFL!NO%OOV!FLD(7,NO%COL)!FLD(12,NO%RDX)
27700		NOUT
27800		 CAI
27900		SPACE	<2>
28000		MOVE	B,.SMTAM(P1)	;tape mounts
28100		MOVX	C,NO%LFL!NO%OOV!FLD(5,NO%COL)!FLD(12,NO%RDX)
28200		NOUT
28300		 CAI
28400		SPACE	<2>
28500		MOVE	B,.SMTAU(P1)	;mta time used in real sec
28600		FDVRI	B,(60.)		;convert to minutes
28700		FIXR	B,B		;and convert to integer minutes
28800		MOVX	C,NO%LFL!NO%OOV!FLD(6,NO%COL)!FLD(12,NO%RDX)
28900		NOUT
29000		 CAI
29100		SPACE	<1>
29200		MOVE	B,.SVALU(P1)	;value of services
29300		MOVX	C,FL%ONE!FL%DOL!FL%PNT!FL%OVL!FLD(7,FL%FST)!FLD(2,FL%SND)
29400		FLOUT
29500		 CAI
29600		SPACE	1
29700		MOVE	B,.SVALU(P1)
29800		FDVR	B,CATVAL
29900		FMPRI	B,(100.)
30000		MOVX	C,FL%ONE!FL%PNT!FL%OVL!FLD(3,FL%FST)!FLD(1,FL%SND)
30100		FLOUT
30200		 CAI
30300		MOVEI	B,"%"
30400		BOUT
30500		CALL	CRLF
30600		RET
30700	
30800	CATHDR:	MOVEI	B,.CHFFD
30900		BOUT
31000	CHDR1:	SPACE	<^D21>
31100		MOVE	B,[TXT <------Time Sharing------   ----Batch------   Cards   Pages     PLT    DSK Pgs   MTA    MTA     Value of  % of
31200	>]
31300		SETZB	C,D
31400		SOUT
31500		MOVE	B,[TXT <Category >]
31600		SETZB	C,D
31700		SOUT
31800		SPACE	<^D12>
31900		MOVE	B,[TXT <Sess   CPU Sec  Conn Hrs    Sess   CPU Sec   Read    Printed   Mins   Used      Mnts   Mins    Services  Total>]
32000		SETZB	C,D
32100		SOUT
32200		MOVEI	B,.CHCRT
32300		BOUT				;return only - do underlining
32400		MOVE	B,[TXT <_________________   _____   _______  ________   _____   _______   _____   _______   ____   _______   ____   _____   ________  _____
32500	>]
32600		SETZB	C,D
32700		SOUT
32800		CALL	CRLF
32900		MOVEI	B,CATPAG-3
33000		MOVEM	B,CATLIN		;reinit line counter
33100		RET
33200	
33300	MSCCAT:	MOVEI	P1,USGPTR		;create or locate "Miscellaneous" category
33400		HRLI	P1,..SLEN
33500		MOVE	P2,[TXT<MISCELLANEOUS>]
33600		MOVEI	P3,3
33700		CALL	GETNOD
33800		JUMPE	P1,CATERR
33900		PUSH	P,P1			;save address of that node
34000		MOVE	A,MSCPTR
34100		MOVE	A,(A)			;get pointer to directory string
34200		MOVE	B,[POINT 7,TMPBLK]
34300		MOVEI	C,^D39
34400		SETZ	D,
34500		SIN				;count chars in it
34600		MOVN	C,C
34700		ADDI	C,^D40+^D4
34800		IDIVI	C,5
34900		MOVEI	P1,CATPTR		;add this directory string to category tree
35000		HRLI	P1,..CTLN
35100		MOVE	P2,[POINT 7,TMPBLK]
35200		MOVE	P3,C
35300		CALL	GETNOD
35400		JUMPE	P1,CATERR
35500		POP	P,..CTLN-1(P1)	 ;[1]make categorization node point to usage node
35600		TMSG	<[ACCT20 Categorization: Added >
35700		MOVEI	A,.PRIOU
35800		MOVE	B,[POINT 7,TMPBLK]
35900		SETZB	C,D
36000		SOUT
36100		TMSG	< to MISCELLANEOUS category]
36200	>
36300		RET
36400	
36500	WLDNOD:	SKIPN	(P1)		;if no tree,
36600		 RET			; no match.  Non-skip return on failure
36700		HRR	P1,(P1)		;get address of first node
36800	WLDLUP:	MOVE	A,(P1)		;get pointer to node value
36900		MOVE	B,P2		;and pointer to directory/account string
37000		STCMP			;compare them
37100		SKIPN	A		;exact match?
37200		 RETSKP			; yes - return skip on success
37300		MOVEM	A,WLDCMP	;not exact match.  Wildcard?  Save comparative values
37400		MOVE	B,(P1)		;get (possibly) wildcard string
37500		MOVE	C,P2		;and test string
37600		MOVE	A,[.WLSTR]	;say we want string match
37700		WILD%			;and try for match
37800		SKIPN	A		;match?
37900		 RETSKP			; yes - skip return
38000		MOVE	A,WLDCMP	;no.  Do we take left or right subtree?
38100		MOVE	B,1(P1)		;get subtree pointers
38200		TXNN	A,SC%LSS!SC%SUB	;take left or right?
38300		 MOVSS	B		;left - swap halves
38400		HRRZ	B,B		;get just the address
38500		SKIPN	B		;is there a subtree?
38600		 RET			;no - can't match, so do failure return
38700		HRR	P1,B		;put subtree pointer into correct register
38800		JRST	WLDLUP		;and try again
     
00100	SUBTTL	CHARGE-RATE command processing
00200	.CHA:	NOISE	<from file>
00300		MOVEI	A,[FLDDB. .CMIFI,CM%DPP,,,DSK:ACCT20.CHG.0]
00400		CALL	CFIELD		;get source of input data
00500		HRLM	B,SBK+.CMIOJ	;and tell CMD macros where to look
00600		MOVE	A,B		;ready to open file
00700		MOVEM	A,FILJFN	;Save JFN for closing
00800		PUSH	P,A		;save JFN for OPEN
00900		DVCHR			;is it a TTY we're going to read?
01000		LSH	B,-^D18
01100		ANDI	B,777
01200		CAIN	B,.DVTTY
01300		 TXO	F,F%TTIN	;yes
01400		POP	P,A		;get JFN back
01500		MOVX	B,FLD(7,OF%BSZ)!FLD(.GSNRM,OF%MOD)!OF%RD
01600		OPENF			;open input source
01700		 JRST	[TMSG <%ACCT20 Can't open charge-rate file>
01800			 HRRI	A,.PRIIN
01900			 HRLM	A,SBK+.CMIOJ	;reset CMD macros input
02000			 TXZ	F,F%TTIN	;turn off TTY input flag
02100			 RET]
02200		TXO	F,F%CHA		;Remember switch for processing
02300	CHALUP:	HRROI	A,[ASCIZ/ACCT20 charge> /]
02400		TXNE	F,F%TTIN	;are we reading from TTY?
02500		 CALL	DPROMP		;yes - do prompt
02600		MOVEI	A,[FLDDB.	.CMKEY,,CHATAB]
02700		CALL	RFIELD
02800		HRRZ	A,(B)		;get address of routine to process
02900					;rate for this resource
03000		CALL	@A		;go process
03100		JRST	CHALUP		;and get another
03200	
03300	CHATAB:	XWD	.CHEND-.-1,.CHEND-.-1
03400		T	Bill,.CHABL
03500		T	Cards-read,.CHACD
03600		T	Connect-time,.CHACO
03700		U	Core-occupancy,.CHACR,CM%NOR
03800		T	CPU-time,.CHACP
03900		U	Disk-allocation,.CHADA,CM%NOR
04000		U	Disk-reads,.CHADR,CM%NOR
04100		T	Disk-storage,.CHADS
04200		U	Disk-writes,.CHADW,CM%NOR
04300		T	End-charges,.CHAEN
04400		T	Printer-pages,.CHAPG
04500		T	Shift,.CHASH
04600		T	Structure-mount,.CHASM
04700		T	Structure-usage,.CHASU
04800		T	Tape-mount,.CHATM
04900		T	Tape-usage,.CHATU
05000		T	Tax(%),.CHATX
05100		U	TTY-characters-in,.CHATI,CM%NOR
05200		U	TTY-characters-out,.CHATO,CM%NOR
05300		T	Weekend,.CHAWK
05400		.CHEND==.
05500	
05600	.CHABL:	NOISE	<user>
05700		MOVEI	A,[FLDDB. .CMFLD,,,<account/directory string>]
05800		CALL	RFIELD
05900		MOVE	A,SBK+.CMABP	;Get pointer to atom
06000		MOVE	B,[POINT 7,BILNAM]	;Copy name string
06100		MOVEI	C,^D40
06200		SETZ	D,
06300		SIN
06400		MOVN	C,C
06500		ADDI	C,^D40+^D4	;Count words in string
06600		IDIVI	C,5		;length of string in words in C now
06700		MOVEM	C,BILLEN	;Save it
06800		MOVEI	A,[FLDDB. .CMKEY,,BILTAB,,NON-PROFIT]
06900		CALL	CFIELD		;get COMMERCIAL/NON-PROFIT status
07000		TXO	F,F%BIL
07100		PUSH	P,B		;Save pointer to command match address
07200		MOVEI	P1,BILPTR	;get pointer to DETAIL tree
07300		HRLI	P1,..BILN	;length of fixed part in left half
07400		MOVE	P2,[POINT 7,BILNAM]	;String to find in P2
07500		MOVE	P3,BILLEN	;length of varaible (string) part in P3
07600		CALL	GETNOD		;get a node for it
07700		JUMPE	A,BILERR	;error if we can't get one
07800		POP	P,B		;Retrieve address of command match
07900		MOVE	C,..BILN-1(P1)	;[1]get flag word from node
08000		HRRZ	A,(B)		;And flag bits from command match
08100		CAIE	B,.COM		;should we set or reset it?
08200		 TRZA	C,(A)		;Non-profit - reset flag
08300		  TRO	C,(A)		;commercial - set flag
08400		MOVEM	C,..BILN-1(P1)	;restore flag word to node
08500		RET
08600	
08700	.CHAEN:	CONFRM	
08800		HRRI	A,.PRIIN
08900		HRLM	A,SBK+.CMIOJ	;reset for commands from primary
09000					; input, just in case file was used
09100		TXZ	F,F%TTIN	;turn off TTY input flag
09200		MOVE	A,FILJFN	;Close file
09300		CLOSF
09400		 JRST	[TMSG	<%ACCT20: Can't close CHARGE-RATE file>
09500			 JSERR
09600			 RET]
09700		POP	P,A		;SKIP OUT OF CHARGE LOOP
09800		RET			;AND RETURN TO MAIN COMMAND LOOP
09900	
10000	.CHACD:	NOISE	<is $>
10100		CALL	GETUNI
10200		MOVEM	P1,.PRCRD
10300		RET
10400	
10500	.CHACO:	NOISE	<is $>
10600		CALL	GETTIM
10700		MOVEM	P1,.PRCON
10800		RET
10900	
11000	.CHACR:	NOISE	<in KCS is $>
11100		CALL	GETUNI
11200		MOVEM	P1,.PRCOR
11300		RET
11400	
11500	.CHACP:	NOISE	<is $>
11600		CALL	GETTIM
11700		MOVEM	P1,.PRCPU
11800		RET
11900	
12000	.CHADA:	NOISE	<in pages/month is $>
12100		CALL	GETUNI
12200		MOVEM	P1,.PRDSA
12300		RET
12400	
12500	.CHADR:	NOISE	<in pages is $>
12600		CALL	GETUNI
12700		MOVEM	P1,.PRDSR
12800		RET
12900	
13000	.CHADS:	NOISE	<in pages/month is $>
13100		CALL	GETUNI
13200		MOVEM	P1,.PRDSS
13300		RET
13400	
13500	.CHADW:	NOISE	<in pages is $>
13600		CALL	GETUNI
13700		MOVEM	P1,.PRDSW
13800		RET
13900	
14000	.CHAPG:	NOISE	<for printed pages is $>
14100		CALL	GETUNI
14200		MOVEM	P1,.PRPGS
14300		RET
14400	
14500	.CHASH:	NOISE	<starts at>
14600		MOVEI	A,[FLDDB. .CMTAD,,CM%ITM+TMPBLK]	;get start time of shift
14700		CALL	RFIELD
14800		SETZ	D,		;[6] convert date/time to sec past 
14900		ODCNV			;[6] midnight and whether or not
15000		HRRZM	D,SHFTIM	;[6] Save start time of shift temporarily
15100		NOISE	<and is billed at base rate times>
15200		MOVEI	A,[FLDDB. .CMFLT]
15300		CALL	CFIELD
15400		MOVEM	B,SHFCHG	;save charge multiplier 
15500		MOVEI	A,2		;create a node to hold the entry
15600		CALL	GETBLK
15700		 JRST	SHFMEM
15800		HRRZ	B,SHFTIM	;put time into node
15900		MOVEM	B,(A)
16000		MOVE	B,SHFCHG	;and multiplier
16100		MOVEM	B,1(A)
16200		HRLI	B,(A)
16300		HRRI	B,1(A)
16400		MOVEI	A,SHFTBL	;add node to binary lookup table
16500		CALL	BINADD
16600		SKIPL	A		;error?
16700		 RET			;no
16800		HLRE	B,A
16900		CAMN	B,[-1]		;table full?
17000		 JRST	SHTBFL		;yes
17100		CAMN	B,[-2]		;previous entry?
17200		 JRST	SHMUNT		;yes
17300		TMSG	<?ACCT20 Printer charges: undiagnosed error in table entry>
17400		RET
17500	
17600	SHTBFL:	TMSG	<%ACCT20 shift charges: shift table is full
17700	>
17800		TMSG	<	shift starting at >
17900		MOVE	B,SHFTIM
18000		MOVEI	A,.PRIOU
18100		MOVX	C,OT%NDA
18200		ODTIM
18300		TMSG	< was not entered into table.
18400	>
18500		RET
18600	
18700	SHMUNT:	TMSG	<[ACCT20 Shift charges: multiple entries for time >
18800		MOVE	B,SHFTIM
18900		MOVEI	A,.PRIOU
19000		MOVX	C,OT%NDA
19100		ODTIM
19200		TMSG	<]
19300	>
19400		RET
19500	
19600	
19700	.CHASM:	NOISE	<for structure mounts requiring operator attention is $>
19800		CALL	GETUNI
19900		MOVEM	P1,.PRSTM
20000		RET
20100	
20200	.CHASU:	NOISE	<for use of operator-mounted structures is $>
20300		CALL	GETTIM
20400		MOVEM	P1,.PRSTU
20500		RET
20600	
20700	.CHATM:	NOISE	<for tape mounts is $>
20800		CALL	GETUNI
20900		MOVEM	P1,.PRTPM
21000		RET
21100	
21200	.CHATU:	NOISE	<for tape use is $>
21300		CALL	GETTIM
21400		MOVEM	P1,.PRTPU
21500		RET
21600	
21700	.CHATI:	NOISE	<for TTY characters in is $>
21800		CALL	GETUNI
21900		MOVEM	P1,.PRTTI
22000		RET
22100	
22200	.CHATO:	NOISE	<for TTY characters out is $>
22300		CALL	GETUNI
22400		MOVEM	P1,.PRTTO
22500		RET
22600	
22700	.CHATX:	NOISE	<commercial users at percentage rate >
22800		MOVEI	A,[FLDDB. .CMFLT]
22900		CALL	CFIELD
23000		MOVEM	B,.PRTAX
23100		RET
23200	
23300	.CHAWK:	NOISE	<rates for commercial users is base rate times>
23400		MOVEI	A,[FLDDB. .CMFLT]
23500		CALL	CFIELD
23600		MOVEM	B,.PRWKN
23700		RET
23800	
23900	
24000	;THIS ROUTINE GETS THE UNIT PRICE FOR ITEMS WHICH MAY COME IN
24100	;UNITS OF "EACH" OR PACKAGE OF N ITEMS
24200	GETUNI:	MOVEI	A,[FLDDB. .CMFLT]	;REAL NUMBER FOR RATE
24300		CALL	RFIELD
24400		MOVEM	B,P1		;keep it handy
24500		MOVEI	A,[FLDDB. .CMKEY,,UNITAB]	;get units
24600		CALL	RFIELD
24700		CAIN	B,.EACH		;did we get "EACH" ?
24800		 JRST	[	CONFRM
24900				RET]			; yes - just return value read
25000		HRRZ	A,(B)		;no - go find number of units
25100		CALL	@A
25200		FDVR	P1,B		;get actual unit rate
25300		RET
25400	
25500	UNITAB:	XWD	UNIEND-.-1,UNIEND-.-1	;TABLE OF UNITS
25600	.EACH:	T	EACH,1
25700		T	PER,.PER
25800		UNIEND==.
25900	
26000	.PER:	MOVEI	A,[FLDDB. .CMFLT]
26100		CALL	CFIELD
26200		RET
26300	
26400	;This routine gets the unit cost (per second) for items which may
26500	;be supplied in units of hours, minutes, or seconds.
26600	
26700	GETTIM:	MOVEI	A,[FLDDB. .CMFLT]
26800		CALL	RFIELD
26900		MOVEM	B,P1
27000		MOVEI	A,[FLDDB.  .CMSWI,,TIMTAB]
27100		CALL	CFIELD
27200		HRRZ	A,(B)		;get number of seconds this unit was
27300		FLTR	A,A		;float it
27400		FDVR	P1,A		;compute rate in units of seconds
27500		RET
27600	
27700	TIMTAB:	XWD	TIMEND-.-1,TIMEND-.-1
27800		T	HR,^D60*^D60
27900		U	HOUR,^D60*^D60,CM%INV
28000		T	MIN,^D60
28100		U	MINUTE,^D60,CM%INV
28200		T	SEC,1
28300		U	SECOND,1,CM%INV
28400		TIMEND==.
28500	BILERR:	TMSG	<%ACCT20: Can't enter BILL information for directory/account >
28600		MOVE	A,SBK+.CMABP
28700		PSOUT
28800		TMSG	<
28900		Entry has been ignored in charging and producing DETAILS-BINARY file
29000	>
29100		IFN	DEBUG,<
29200		TMSG	<	Error type is >
29300		MOVEI	A,.PRIOU
29400		HLRE	B,P1
29500		MOVX	C,FLD(10,NO%RDX)
29600		NOUT
29700		 CAI	>	;end IFN DEBUG
29800		RET
29900	
30000	BILTAB:	XWD	BILTND-.-1,BILTND-.-1
30100	.COM:	T	COMMERCIAL,BL%COM
30200		T	NON-PROFIT,BL%COM
30300		BILTND==.
30400	
30500	SHFMEM:	TMSG	<%ACCT20 Shift charges: insufficient memory for entry>
30600		RET
     
00100	SUBTTL	DEBUG and STATISTICS command processing
00200	.DEB:	CONFRM
00300		MOVE	B,[TXT <[ACCT20: DEBUG option disabled]>]
00400		TXCN	F,F%DEB		;Reverse condition and test
00500		 MOVE	B,[TXT <[ACCT20: DEBUG option enabled]>]
00600		TXO	F,F%STS		;enable statistics too
00700		MOVEI	A,.PRIOU
00800		SETZB	C,D
00900		SOUT
01000		RET
01100	.STS:	CONFRM
01200		MOVE	B,[TXT <[ACCT20: STATISTICS option disabled]>]
01300		TXCN	F,F%STS		;Reverse condition and test
01400		 MOVE	B,[TXT <[ACCT20: STATISTICS option enabled]>]
01500		MOVEI	A,.PRIOU
01600		SETZB	C,D
01700		SOUT
01800		RET
     
00100	SUBTTL	DUMP command processing
00200	.DMP:	NOISE	<binary summary to file>
00300		MOVE	A,CJFNBK+.GJGEN
00400		TXO	A,GJ%FOU		;set up output file
00500		TXZ	A,GJ%OLD!GJ%IFG
00600		MOVEM	A,CJFNBK+.GJGEN
00700		MOVE	B,[TXT<ACCT20>]		;assume ACCT20 name prefix
00800		TXNE	F,F%NAM			;was a default name given
00900		 MOVE	B,[POINT 7,NAMES]	;yes - use that one
01000		MOVE	A,[POINT 7,TMPBLK]	;copy in prefix
01100		SETZB	C,D
01200		SOUT
01300		MOVE	B,[TXT<-SUMMARY>]
01400		SETZB	C,D
01500		SOUT
01600		MOVE	A,[POINT 7,TMPBLK]	;now make CMD routines use this
01700		MOVEM	A,CJFNBK+.GJNAM
01800		MOVE	A,[TXT<BIN>]
01900		MOVEM	A,CJFNBK+.GJEXT		;set up default extention
02000		MOVEI	A,[FLDDB. .CMFIL]	;now go get file name
02100		CALL	CFIELD
02200		MOVEM	B,DMPJFN
02300		TXO	F,F%DMP
02400		RET
02500	SUMDMP:	MOVEI	A,.PRIOU	;[8] tell what we're doing
02510		TMSG	<
02520	[Generating DUMP of binary summary]
02530	>
02550		MOVE	A,DMPJFN	;Open file for dumping
02600		MOVX	B,FLD(44,OF%BSZ)!OF%WR
02700		OPENF
02800		 JRST	[TMSG <%ACCT20: Can't open file >
02900			 HRRZ	B,DMPJFN
03000			 MOVEI	A,.PRIOU
03100			 JFNS
03200			 JSERR
03300			 TMSG <
03400		Binary summary file will not be generated.
03500	>
03600			 RET]
03700		MOVE	A,[TXT<ACCT20>]
03800		TXNE	F,F%NAM		;was a default name supplied?
03900		 MOVE	A,[POINT 7,NAMES]	;yes - use it
04000		CALL	ASCSIX		;convert to SIXBIT
04100		MOVE	B,A		;put into output register
04200		MOVE	A,DMPJFN	;Write out header to dump file
04300		BOUT
04400		MOVE	B,.JBVER		;Version number
04500		BOUT
04600		MOVE	B,FSTTAD		;First date/time in file
04700		BOUT
04800		MOVE	B,LSTTAD		;Last date/time in file
04900		BOUT
05000		MOVE	P1,SUMPTR	;point to summary tree for processing
05100		MOVEI	P2,DMPOUT	;and to routine to dump nodes
05200		CALL	DMPTRE		;dump the tree
05300		TXZ	F,F%DMP		;reset flag
05400		HRRZ	A,DMPJFN	;close file
05500		CLOSF
05600		 ERMSG	<?ACCT20:	Can't close summary DUMP file>
05700		RET
05800	
05900	DMPOUT:	MOVE	A,(P1)		;determine length of string
06000		MOVE	B,[POINT 7,BILPTR]
06100		MOVEI	C,^D40
06200		SETZ	D,		;[5]
06300		SIN
06400		MOVN	C,C
06500		ADDI	C,^D40+^D4	;by counting chars and rounding up words
06600		IDIVI	C,5
06700		HRR	B,C		;Output header word as
06800		HRLI	B,..SLEN-2	; fixed size,,string size
06900		MOVE	A,DMPJFN
07000		BOUT
07100		MOVN	C,C		;need negative for SOUT
07200		HRRZ	B,(P1)		;Address of string
07300		HRLI	B,(POINT 36,)	;Write as words
07400		SOUT			;Output the string
07500		MOVEI	B,.SREFS(P1)	;Write fixed-length portion
07600		HRLI	B,(POINT 36,)
07700		MOVNI	C,..SLEN-2
07800		SOUT
07900		RET			;And we're done
     
00100	SUBTTL	EXIT/QUIT command processing
00200	.EXI:	NOISE	<from ACCT20>
00300		CONFRM			;confirm it with CR
00301	;[8] Moved report generation here from RPRPRC and PRORPT so that
00302	;    processing is done consistently in processing the raw accounting
00303	;    files as well as the summary binary files.
00305		TXZE	F,F%DAL		;Details requested?
00310		 CALL	DETPRC		;yes
00315		TXZE	F,F%BIN		;write out user name list for DETAILS?
00320		 CALL	USRDMP		;yes
00325		TXZE	F,F%CAT		;[4]categories requested?
00330		 CALL	CATDMP		;[4]yes -- process them
00335		TXZE	F,F%SAL		;summary requested?
00340		 CALL	SUMPRC		;yes - process it
00345		TXZE	F,F%LSC		;[2] Want database-compatible cat list?
00350		 CALL	LSCDMP		;[2] Yes.  Do it.
00355		TXZE	F,F%LSS		;[2] Want database-compatible listing?
00360		 CALL	LSSDMP		;[2] Yes.  Do it.
00365					;[4] moved here from PRORPT
00370		TXZE	F,F%DMP		;Wanted to dump summary binary file?
00375		 CALL	SUMDMP		;Yes - do it
00400		SETO	A,		;close all open JFN's
00500		CLOSF
00600		  ERMSG	<?ACCT20: Can't close open JFN's>
00700		HALTF
00800		JRST	.-1
     
00100		SUBTTL	FORMS command processing
00200	.FRM:	NOISE	<usage report to be generated>
00300		CONFRM
00400		MOVE	B,[TXT<ACCT20>]		;assume standard name prefix
00500		TXNE	F,F%NAM			;was a default name given?
00600		 MOVE	B,[POINT 7,NAMES]	;yes - use it
00700		MOVE	A,[POINT 7,TMPBLK]
00800		SETZB	C,D
00900		SOUT				;copy it out
01000		MOVE	B,[TXT<-FORMS.DMI>]	;finish name
01100		SETZB	C,D
01200		SOUT
01300		MOVE	A,[GJ%FOU!GJ%SHT]	;now open file
01400		MOVE	B,[POINT 7,TMPBLK]
01500		GTJFN
01600		 CALLRET	[ERMSG <%ACCT20:	Can't open forms output file>
01700				 RET]
01800		MOVEM	A,FRMJFN
01900		MOVX	B,FLD(7,OF%BSZ)!OF%WR
02000		OPENF
02100		 CALLRET	[ERMSG <%ACCT20:	Can't open forms output file>
02200				 RET]
02300		TXO	F,F%FRM
02400		RET
02500	
02600	FRMPRC:	MOVE	A,FRMJFN	;process output entry to record form usage
02700		MOVE	C,4(Q1)		;LPT entry?
02800		CAME	C,[SIXBIT/LPT/]
02900		 RET			;no. ignore it.
03000		LOAD	B,SDTAD		;output date/time stamp
03100		SETZ	C,
03200		ODTIM
03300		SPACE	2
03400		MOVE	B,USRPTR	;and the name of the user
03500		MOVEI	C,^D40		; in a field of 40 chars
03600		SETZ	D,
03700		SOUT
03800		CALL	SPACES
03900		MOVE	C,15(Q1)		;output forms type
04000		CALL	SIXOUT
04100		SPACE	2
04200		MOVE	B,7(Q1)		;output page count
04300		MOVX	C,NO%LFL!NO%OOV!FLD(5,NO%COL)!FLD(12,NO%RDX)
04400		NOUT
04500		 CAI
04600		SPACE	3
04700		CALL	SPLPRC		;lookup price
04800		FLTR	B,7(Q1)		;compute value
04900		FMPR	B,T0
05000		FADRM	B,DETTOT+.SVALU	;add to total
05100		MOVX	C,FL%ONE!FL%PNT!FL%OVL!FLD(5,FL%FST)!FLD(2,FL%SND)
05200		FLOUT
05300		 CAI
05400		CALL	CRLF
05500		RET
     
00100	SUBTTL	HELP command processing
00200	.HEL:	HRROI	A,PHELP	;get message
00300		PSOUT		;type it
00400		RET
00500	
00600		XLIST
00700	PHELP:	ASCIZ\ACCT20 commands:
00800		BEGIN		Begin processing at specified date/time.
00900		CATEGORIZE	Use the contents of specified file (default 
01000				ACCT20.CAT) to	define a categorization scheme,
01100				then list use by categories after SUMMARY
01200				processing has been done (SUMMARY command must
01300				also be given before PROCESSing).
01400		CHARGES		Use the specified file (default ACCT20.CHG) to 
01500				establish charge rates for usage.
01600		DETAIL		Generate a detailed listing of resource use for
01700				specified directories or accounts (default is
01800				for all directories or accounts]).
01900		DUMP		Write a copy of the internal usage summary
02000				information to the specified file (default
02100				ACCT20-SUMMARY.BIN or <userdefault>-SUMMARY.BIN)
02200				at the end of PROCESSing.
02300		END		Stop processing with specified date/time.
02400		EXIT		Exit from ACCT20.
02500		FORMS		Generate a listing of all printer usage to the
02600				specified file (default ACCT20-FORMS.DMI or
02700				<userdefault>-FORMS.DMI).
02800		HELP		Give this help message.
02900		LIST-CATEGORY-TOTALS Lists category totals to file
03000				<name>-CATEGORIES.DMI in a format suitable
03100				for database processing.
03200		LIST-SUMMARY-TOTALS Lists summary totals to <name>-SUMMARIES.DMI
03300				in a format suitable for database processing.
03400		NAME		Establish the <userdefault> filename prefix for
03500				all subsequent command processing.
03600		PRINTER-CHARGES	Use the specified file (default ACCT20.PCG) to
03700				set charges for forms for printer output.
03800		PROCESS		Process the specified SYSTEM-DATA.BIN input 
03900				file or sequence of files using the options 
04000				previously selected.
04100		REPORT		Generate the reports of usage based
04200				on DIRECTORY name or ACCOUNT string.
04300		REPROCESS	Reprocess the <summary>.BIN file which was
04400				created by the DUMP command of a previous
04500				processing run.  The REPROCESS command
04600				can be used to generate new listings of
04700				all use and to recategorize use (but not
04800				to modify charge rates).
04900		RESET		Close all files and reset the state of
05000				ACCT20 to that at startup (except that
05100				STATISTICS is still enabled if initially
05200				requested).
05300		STATISTICS	At completion of processing, generate
05400				a summary of the types of records processed.
05500		SUMMARIZE	Generate a summary listing of resource use for
05600				specified directories or accounts (default
05700				is for all directories or accounts).
05800		WRITE-DETAIL-BINARY
05900				Copy to file ACCT20-DETAILS.BIN or
06000				<userdefault>-DETAILS.BIN the input records
06100				selected for BILLing by the CHARGE file.
06200	\
06300		LIST
     
00100	SUBTTL	LIST-CATEGORY-TOTALS command processing
00200	;[2]	This command is new to version 2
00300	
00400	
00500	.LSC:	NOISE	<to file>
00600		MOVE	A,CJFNBK+.GJGEN
00700		TXO	A,GJ%FOU		;set up output file
00800		TXZ	A,GJ%OLD!GJ%IFG
00900		MOVEM	A,CJFNBK+.GJGEN
01000		MOVE	B,[TXT<ACCT20>]		;assume ACCT20 name prefix
01100		TXNE	F,F%NAM			;was a default name given
01200		 MOVE	B,[POINT 7,NAMES]	;yes - use that one
01300		MOVE	A,[POINT 7,TMPBLK]	;copy in prefix
01400		SETZB	C,D
01500		SOUT
01600		MOVE	B,[TXT<-CATEGORIES>]
01700		SETZB	C,D
01800		SOUT
01900		MOVE	A,[POINT 7,TMPBLK]	;now make CMD routines use this
02000		MOVEM	A,CJFNBK+.GJNAM
02100		MOVE	A,[TXT<DMI>]
02200		MOVEM	A,CJFNBK+.GJEXT		;set up default extention
02300		MOVEI	A,[FLDDB. .CMFIL]	;now go get file name
02400		CALL	CFIELD
02500		MOVEM	B,LSCJFN
02600		TXO	F,F%LSC
02700		RET
02800	LSCDMP:	MOVEI	A,.PRIOU	;[8] tell what we're doing
02810		TMSG	<
02820	[Generating LIST-CATEGORY report for database use]
02830	>
02850		MOVE	A,LSCJFN	;Open file for dumping
02900		MOVX	B,FLD(7,OF%BSZ)!OF%WR
03000		OPENF
03100		 JRST	[TMSG <%ACCT20: Can't open file >
03200			 HRRZ	B,LSCJFN
03300			 MOVEI	A,.PRIOU
03400			 JFNS
03500			 JSERR
03600			 TMSG <
03700		Category listing file will not be generated.
03800	>
03900			 RET]
04100		MOVE	P1,USGPTR	;point to usage tree for processing
04150					;(assumes category processing already done!)
04200		MOVEI	P2,LSCOUT	;and to routine to dump nodes
04300		CALL	DMPTRE		;dump the tree
04400		TXZ	F,F%LSC		;reset flag
04500		HRRZ	A,LSCJFN	;close file
04600		CLOSF
04700		 ERMSG	<?ACCT20:	Can't close category listing file>
04800		RET
04900	
05000	LSCOUT:	HRRZ	A,LSCJFN
05100		MOVE	B,.SUSER(P1)
05200		MOVEI	C,^D20
05300		SETZ	D,
05400		SOUT
05500		SKIPLE	C
05600		 CALL	SPACES
05700		MOVE	B,.STSES(P1)	;count of sessions
05800		MOVX	C,NO%LFL!NO%OOV!FLD(6,NO%COL)!FLD(12,NO%RDX)
05900		NOUT
06000		 CAI
06100		MOVE	B,.STCPU(P1)	;get cpu time in real sec
06200		MOVX	C,FL%ONE!FL%PNT!FL%OVL!FLD(9,FL%FST)!FLD(1,FL%SND)
06300		FLOUT
06400		 CAI
06500		MOVE	B,.STCON(P1)	;get connect time in real sec
06600		MOVX	C,FL%ONE!FL%PNT!FL%OVL!FLD(9,FL%FST)!FLD(1,FL%SND)
06700		FLOUT
06800		 CAI
06900		MOVE	B,.SBSES(P1)	;number of batch sessions
07000		MOVX	C,NO%LFL!NO%OOV!FLD(7,NO%COL)!FLD(12,NO%RDX)
07100		NOUT
07200		 CAI
07300		MOVE	B,.SBCPU(P1)	;batch CPU time in real sec
07400		MOVX	C,FL%ONE!FL%PNT!FL%OVL!FLD(9,FL%FST)!FLD(1,FL%SND)
07500		FLOUT
07600		 CAI
07700		MOVE	B,.SCDRR(P1)	;cards read
07800		MOVX	C,NO%LFL!NO%OOV!FLD(7,NO%COL)!FLD(12,NO%RDX)
07900		NOUT
08000		 CAI
08100		MOVE	B,.SLPTW(P1)	;pages printed
08200		MOVX	C,NO%LFL!NO%OOV!FLD(7,NO%COL)!FLD(12,NO%RDX)
08300		NOUT
08400		 CAI
08500		MOVE	B,.SPLTM(P1)	;plotter minutes
08600		MOVX	C,NO%LFL!NO%OOV!FLD(6,NO%COL)!FLD(12,NO%RDX)
08700		NOUT
08800		 CAI
08900		MOVE	B,.SDSKU(P1)	;disk space used
09000		MOVX	C,NO%LFL!NO%OOV!FLD(8,NO%COL)!FLD(12,NO%RDX)
09100		NOUT
09200		 CAI
09300		MOVE	B,.SMTAM(P1)	;tape mounts
09400		MOVX	C,NO%LFL!NO%OOV!FLD(7,NO%COL)!FLD(12,NO%RDX)
09500		NOUT
09600		 CAI
09700		MOVE	B,.SMTAU(P1)	;mta time used in real sec
09800		FDVRI	B,(60.)		;convert to minutes
09900		FIXR	B,B		;and convert to integer minutes
10000		MOVX	C,NO%LFL!NO%OOV!FLD(6,NO%COL)!FLD(12,NO%RDX)
10100		NOUT
10200		 CAI
10300		MOVE	B,.SVALU(P1)	;value of services
10400		MOVX	C,FL%ONE!FL%PNT!FL%OVL!FLD(9,FL%FST)!FLD(2,FL%SND)
10500		FLOUT
10600		 CAI
10700		MOVE	B,.SVALU(P1)
10800		FDVR	B,CATVAL
10900		FMPRI	B,(100.)
11000		MOVX	C,FL%ONE!FL%PNT!FL%OVL!FLD(3,FL%FST)!FLD(1,FL%SND)
11100		FLOUT
11200		 CAI
11300		CALL	CRLF
11400		RET
     
00100	SUBTTL	LIST-SUMMARY-TOTALS command processing
00200	;[2]	This command is new to version 2
00300	.LSS:	NOISE	<to file>
00400		MOVE	A,CJFNBK+.GJGEN
00500		TXO	A,GJ%FOU		;set up output file
00600		TXZ	A,GJ%OLD!GJ%IFG
00700		MOVEM	A,CJFNBK+.GJGEN
00800		MOVE	B,[TXT<ACCT20>]		;assume ACCT20 name prefix
00900		TXNE	F,F%NAM			;was a default name given
01000		 MOVE	B,[POINT 7,NAMES]	;yes - use that one
01100		MOVE	A,[POINT 7,TMPBLK]	;copy in prefix
01200		SETZB	C,D
01300		SOUT
01400		MOVE	B,[TXT<-SUMMARIES>]
01500		SETZB	C,D
01600		SOUT
01700		MOVE	A,[POINT 7,TMPBLK]	;now make CMD routines use this
01800		MOVEM	A,CJFNBK+.GJNAM
01900		MOVE	A,[TXT<DMI>]
02000		MOVEM	A,CJFNBK+.GJEXT		;set up default extention
02100		MOVEI	A,[FLDDB. .CMFIL]	;now go get file name
02200		CALL	CFIELD
02300		MOVEM	B,LSSJFN
02400		TXO	F,F%LSS
02500		RET
02600	
02700	LSSDMP:	MOVEI	A,.PRIOU	;[8] tell what we're doing
02710		TMSG	<
02720	[Generating LIST-SUMMARY report for database use]
02730	>
02750		MOVE	A,LSSJFN	;Open file for dumping
02800		MOVX	B,FLD(7,OF%BSZ)!OF%WR
02900		OPENF
03000		 JRST	[TMSG <%ACCT20: Can't open file >
03100			 HRRZ	B,LSCJFN
03200			 MOVEI	A,.PRIOU
03300			 JFNS
03400			 JSERR
03500			 TMSG <
03600		Summary listing file will not be generated.
03700	>
03800			 RET]
03900		MOVE	P1,SUMPTR	;point to summary tree for processing
04000		MOVEI	P2,LSSOUT	;and to routine to dump nodes
04100		CALL	DMPTRE		;dump the tree
04200		TXZ	F,F%LSS		;reset flag
04300		HRRZ	A,LSSJFN	;close file
04400		CLOSF
04500		 ERMSG	<?ACCT20:	Can't close summary listing file>
04600		RET
04700	
04800	LSSOUT:	HRRZ	A,LSSJFN
04900		MOVE	B,.SUSER(P1)	;get user name
05000		MOVEI	C,^D40		;and output in a field of 40 chars
05100		SETZ	D,
05200		SOUT
05300		MOVE	B,[TXT<                                        >]
05400		SKIPLE	C
05500		 SOUT			;complete field
05600		MOVE	B,.STSES(P1)	;count of sessions
05700		MOVX	C,NO%LFL!NO%OOV!FLD(4,NO%COL)!FLD(12,NO%RDX)
05800		NOUT
05900		 CAI
06000		MOVE	B,.STCPU(P1)	;get cpu time in real sec
06100		MOVX	C,FL%ONE!FL%PNT!FL%OVL!FLD(10,FL%FST)!FLD(1,FL%SND)
06200		FLOUT
06300		 CAI
06400		MOVE	B,.STCON(P1)	;get connect time in real sec
06500		MOVX	C,FL%ONE!FL%PNT!FL%OVL!FLD(9,FL%FST)!FLD(1,FL%SND)
06600		FLOUT
06700		 CAI
06800		MOVE	B,.SBSES(P1)	;number of batch sessions
06900		MOVX	C,NO%LFL!NO%OOV!FLD(6,NO%COL)!FLD(12,NO%RDX)
07000		NOUT
07100		 CAI
07200		MOVE	B,.SBCPU(P1)	;batch CPU time in real sec
07300		MOVX	C,FL%ONE!FL%PNT!FL%OVL!FLD(9,FL%FST)!FLD(1,FL%SND)
07400		FLOUT
07500		 CAI
07600		MOVE	B,.SBCON(P1)	;batch connect time in real sec
07700					; note that this is not output
07800		MOVE	B,.SCDRR(P1)	;cards read
07900		MOVX	C,NO%LFL!NO%OOV!FLD(7,NO%COL)!FLD(12,NO%RDX)
08000		NOUT
08100		 CAI
08200		MOVE	B,.SLPTW(P1)	;pages printed
08300		MOVX	C,NO%LFL!NO%OOV!FLD(7,NO%COL)!FLD(12,NO%RDX)
08400		NOUT
08500		 CAI
08600		MOVE	B,.SPLTM(P1)	;plotter minutes
08700		MOVX	C,NO%LFL!NO%OOV!FLD(5,NO%COL)!FLD(12,NO%RDX)
08800		NOUT
08900		 CAI
09000		MOVE	B,.SDSKU(P1)	;disk space used
09100		SKIPE	C,.SDSKC(P1)	;count zero?
09200		 IDIV	B,C		;no - compute average usage
09300		MOVX	C,NO%LFL!NO%OOV!FLD(6,NO%COL)!FLD(12,NO%RDX)
09400		NOUT
09500		 CAI
09600		MOVE	B,.SMTAM(P1)	;tape mounts
09700		MOVX	C,NO%LFL!NO%OOV!FLD(6,NO%COL)!FLD(12,NO%RDX)
09800		NOUT
09900		 CAI
10000		MOVE	B,.SMTAU(P1)	;mta time used in real sec
10100		FDVRI	B,(60.)		;convert to minutes
10200		FIXR	B,B		;and convert to integer minutes
10300		MOVX	C,NO%LFL!NO%OOV!FLD(6,NO%COL)!FLD(12,NO%RDX)
10400		NOUT
10500		 CAI
10600		MOVE	B,.SVALU(P1)	;value of services
10700		MOVX	C,FL%ONE!FL%PNT!FL%OVL!FLD(7,FL%FST)!FLD(2,FL%SND)
10800		FLOUT
10900		 CAI
11000		CALL	CRLF
11100		RET
     
00100	SUBTTL	NAME command processing
00200	.NAM:	NOISE	<default for file is>
00300		MOVEI	A,[FLDDB. .CMFLD,,ACCT20]
00400		CALL	CFIELD
00500		TXO	F,F%NAM
00600		MOVE	B,SBK+.CMABP		;get pointer to atom buffer
00700		MOVE	A,[POINT 7,NAMES]	;copy name into storage
00800		MOVEI	C,^D40
00900		SETZ	D,
01000		SOUT
01100		RET
01200	
01300	.NMT:	CONFRM
01400		TXO	F,F%NMT
01500		RET
     
00100	SUBTTL	PROCESS command processing
00200	.PRO:	NOISE	<from file (sequence)>
00300		MOVE	A,CJFNBK+.GJGEN		;get GTJFN block from COMND
00400		TXZ	A,GJ%FOU!GJ%NEW
00500		TXO	A,GJ%OLD!GJ%IFG!GJ%FLG
00600					;note that this is an old file,
00700					;we'll take wildcards, and we want
00800					; the flags back from the call
00900		MOVEM	A,CJFNBK+.GJGEN
01000		MOVE	A,[TXT<SYSTEM-DATA>]
01100		TXNN	F,F%NAM		;was a default name supplied?
01200		 JRST	PROFN		;no - use standard name
01300		MOVE	A,[POINT 7,TMPBLK]	;yes.  Build a wildcard name
01400		MOVE	B,[TXT<*>]
01500		SETZB	C,D
01600		SOUT
01700		MOVE	B,[POINT 7,NAMES]
01800		MOVEI	C,^D40
01900		SETZ	D,
02000		SOUT
02100		MOVE	A,[POINT 7,TMPBLK]
02200	PROFN:	MOVEM	A,CJFNBK+.GJNAM		;assign default file name
02300		MOVE	A,[POINT 7,[ASCIZ/BIN/]]
02400		MOVEM	A,CJFNBK+.GJEXT		;default .BIN extention
02500	;	MOVE	A,[POINT 7,[ASCIZ/ACCOUNTS/]]
02600	;	MOVEM	A,CJFNBK+.GJDIR		;default <ACCOUNTS>
02700		MOVEI	A,[FLDDB. .CMFIL]
02800		CALL	CFIELD
02900		MOVEM	B,PROJFN	;save JFN
03000		MOVNI	A,5		;get time at start of process
03100		RUNTM
03200		MOVNM	A,RUNTIM
03300		MOVNM	C,CONTIM
03400		GTAD			;Initialize date/time range variables
03500		MOVEM	A,FSTTAD		;expect entries to be earlier than now
03600		SETZM	LSTTAD		;expect entries to be later than 0
03700	
03800	PROLUP:	HRRZ	A,PROJFN	;open next file in sequence
03900		MOVX	B,FLD(44,OF%BSZ)!OF%RD
04000		OPENF
04100		 JRST	[TMSG	<%ACCT20: Can't open file >
04200			 HRRZ	B,PROJFN
04300			 MOVEI	A,.PRIOU
04400			 SETZ	C,
04500			 JFNS
04600			 JSERR
04700			 TMSG	<%No processing done on that file
04800	>
04900			 RET]
05000		TMSG	<[Processing file >
05100		HRRZ	B,PROJFN
05200		MOVEI	A,.PRIOU
05300		SETZ	C,
05400		JFNS
05500		TMSG	<]
05600	>
05700		IFN	DEBUG,<
05800			SETZM	WRDCNT>
05900	PROENT:	CALL	GETITM		;get next record
06000		 JRST	PRONXT		;isn't one - get next file
06100		LOAD	A,SDTAD		;get date/time of this entry
06200		CAMGE	A,FSTTAD	;put earliest into "FIRST"
06300		 MOVEM	A,FSTTAD
06400		CAMLE	A,LSTTAD	;and latest into "LAST"
06500		 MOVEM	A,LSTTAD
06600		LOAD	A,SDTYP		;get type code
06620		CAILE	A,MXRTYP	;[11] is it a standard type?
06630		 MOVEI	A,MXRTYP+1	;[11] no - all user types go through last
06680					;[11]  entry in dispatch table
06700		CALL	@SETSTR(A)	;set up pointer to account or directory
06800					;string in record buffer (depending upon
06900					;value of F%RPT.  Pointer left in USRPTR
07000					;Length of string left in NAMLEN.
07100		CALL	SETRAT		;set commercial/non-profit flag and
07200					; possibly flag record for output
07300					; to DETAILS-BINARY file
07400		TXNE	F,F%BIN		;Need to write selected binary records?
07500		 CALL	WRTBIN		;Yes 
07600		TXNE	F,F%BDT		;Beginning date/time set?
07700		 CALL	CHKBDT		;yes - see if this record matches.
07800					;Return + 1 if so, go back to
07900					;PROENT if not.
08000		TXNE	F,F%EDT		;ENDing date/time set?
08100		 CALL	CHKEDT		;Yes - check it (same result as CHKBDT)
08200		TXNE	F,F%DAL		;DETAIL requested?
08300		 CALL	VLDDET		;yes - validate this user for listing
08400		TXNE	F,F%SAL!F%CAT!F%LSC!F%LSS	;[2,3] need to generate	
08500							;  summary tree?
08600		 CALL	VLDSUM		;yes - validate this user for summary
08700		TXNE	F,F%SUM		;if we are to include this record in summary
08800		 CALL	LOCNOD		;then locate node for this user string in
08900					;tree (loc of node returns in P1)
09000		MOVEM	P1,THSNOD	;save node address
09100		MOVEI	Q1,.SDNAM	;compute offset into buffer of
09200					;first word after strings
09300		LOAD	Q2,SDULN
09400		ADD	Q1,Q2
09500		LOAD	Q2,SDSL1
09600		ADD	Q1,Q2
09700		LOAD	Q2,SDSL2
09800		ADD	Q1,Q2
09900		LOAD	A,SDTYP		;get type again
10000		CAILE	A,MXRTYP	;is it a standard type?
10100		 MOVEI	A,MXRTYP+1	;no - all user types go through last
10200					; entry in dispatch table
10300		AOS	ENTCNT(A)	;count entries
10400		CALL	@PRODIS(A)	;process this record
10500		JRST	PROENT		;and go back for more
10600	PRONXT:	HRRZ	A,PROJFN	;Process next file in sequence
10700		TXO	A,CO%NRJ	;keep the JFN
10800		CLOSF
10900		 JRST	[TMSG	<?ACCT20: Can't close file >
11000			 HRRZ	B,PROJFN
11100			 MOVEI	A,.PRIOU
11200			 SETZ	C,
11300			 JFNS
11400			 JSHLT]
11500		MOVE	A,PROJFN	;get next file in sequence
11600		GNJFN
11700		 CALLRET PRORPT		;isn't one - do report cleanup
11800		JRST	PROLUP		;got next file JFN - process it
11900	
12000	PRORPT:	TMSG	<
12100	[ACCT20:	Time and date of first entry processed was >
12200		MOVEI	A,.PRIOU
12300		MOVE	B,FSTTAD
12400		SETZ	C,
12500		ODTIM
12600		TMSG	<
12700			Time and date of last entry processed was >
12800		MOVEI	A,.PRIOU
12900		MOVE	B,LSTTAD
13000		SETZ	C,
13100		ODTIM
13200		TMSG	<]
13300	>
13400		TXNE	F,F%STS		;want a statistics report?
13500		 CALL	STSOUT		;yes
13600	;[8]  remove calls to report generators to the EXIT routine
15200		TMSG	<
15300	[ACCT20: Processed >
15400		MOVE	C,[XWD -ENTMAX,ENTCNT]
15500		SETZ	B,
15600		ADD	B,(C)
15700		AOBJN	C,.-1
15800		MOVEI	A,.PRIOU
15900		MOVE	C,[NO%OOV!FLD(0,NO%COL)!FLD(12,NO%RDX)]
16000		NOUT
16100		 CAI
16200		TMSG	< records in >
16300		MOVNI	A,5
16400		RUNTM
16500		ADDM	C,CONTIM
16600		ADD	A,RUNTIM
16700		FLTR	B,A
16800		FDVRI	B,(1000.)
16900		MOVEI	A,.PRIOU
17000		MOVX	C,FL%PNT!FLD(1,FL%SND)
17100		FLOUT
17200		 CAI
17300		TMSG	< sec CPU time, >
17400		FLTR	B,CONTIM
17500		FDVRI	B,(1000.)
17600		MOVEI	A,.PRIOU
17700		MOVX	C,FL%PNT!FLD(1,FL%SND)
17800		FLOUT
17900		 CAI
18000		TMSG	< sec elapsed time]
18100	>
18200		RET
18300	
18400	
18500	SUMPRC:	SETZM	SUMLIN		;[4]initialize line count
18600		MOVE	A,SUMJFN	;remaining output to SUMMARY output file
18700		MOVE	P1,SUMPTR	;point to summary tree
18800		MOVEI	P2,SUMOUT	;point to summary output printer
18900		CALL	DMPTRE		;print summary
19000		CALL	CRLF
19100		CALL	CRLF
19200		MOVEI	A,1		;now print totals line
19300		MOVEI	P1,TOTNOD
19400		MOVEM	A,.SDSKC(P1)	;remember to set averaging count to 1
19500		CALL	SUMOUT
19600		RET
19700	
19800	STSOUT:	TMSG	<
19900	[ACCT20: Cumulative summary of record types processed:
20000	>
20100		TMSG	<		COUNT  TYPE
20200	>
20300		MOVE	P1,[-ENTMAX,,0]	;looping index
20400		MOVEI	A,.PRIOU
20500	CNTLUP:	MOVEI	B,.CHTAB
20600		BOUT
20700		SPACE	<4>
20800		MOVE	B,ENTCNT(P1)	;get count
20900		MOVX	C,NO%LFL!NO%OOV!FLD(^D8,NO%COL)!FLD(12,NO%RDX)
21000		NOUT
21100		 CAI
21200		MOVEI	C,3
21300		SPACE	<3>
21400		MOVE	B,ENTNAM(P1)	;now output name of record type
21500		SETZB	C,D
21600		SOUT
21700		CALL	CRLF
21800		AOBJN	P1,CNTLUP	;and loop over all types
21900	;[1]	Give the statistics on tree usage
22000		TXNN	F,F%SAL		;any summary in effect?
22100		 RET			;no -- we're done
22200		TMSG	<
22300		Tree height = >
22400		MOVEI	A,.PRIOU
22500		HLRZ	B,SUMPTR	;heading word for tree contains height
22600		MOVE	C,[NO%OOV!FLD(0,NO%COL)!FLD(12,NO%RDX)]
22700		NOUT
22800		 CAI
22900		TMSG	<
23000		Height balance adjustment count = >
23100		MOVEI	A,.PRIOU
23200		MOVE	B,.ADJBF	;get that count from the TREE routine
23300		MOVE	C,[NO%OOV!FLD(0,NO%COL)!FLD(12,NO%RDX)]
23400		NOUT
23500		 CAI
23600		TMSG	<
23700		Number of single rotations to balance height = >
23800		MOVEI	A,.PRIOU
23900		MOVE	B,.SROTS
24000		MOVE	C,[NO%OOV!FLD(0,NO%COL)!FLD(12,NO%RDX)]
24100		NOUT
24200		 CAI
24300		TMSG	<
24400		Number of double rotations to balance height = >
24500		MOVEI	A,.PRIOU
24600		MOVE	B,.DROTS
24700		MOVE	C,[NO%OOV!FLD(0,NO%COL)!FLD(12,NO%RDX)]
24800		NOUT
24900		 CAI
25000		TMSG	<	]
25100	>
25200		RET
25300	
25400	
25500	;Dispatch table for record processing
25600	
25700	PRODIS:	Z	TYPERR		;0 - illegal
25800		Z	RESTART		;1 - restart
25900		Z	SESS		;2 - session
26000		Z	CHKPNT		;3 - checkpoint
26100		Z	TYPERR		;4 - illegal
26200		Z	DATTIM		;5 - date/time change
26300		Z	BATCH		;6 - batch system entry
26400		Z	INPUT		;7 - input spooler
26500		Z	OUTPUT		;8 - output spooler
26600		Z	DSKUSG		;9 - disk storage
26700		Z	SPNUSG		;10 - spindle usage
26800		Z	STRMNT		;11 - structure mount
26900		Z	MTAMNT		;12 - magtape mount
27000		Z	TYPERR		;13 - illegal (DECtape mount)
27100		Z	TYPERR		;14 - illegal (DEC-10 FILE command)
27200		Z	FILRET		;15 - file retrieval
27300		Z	FILARC		;16 - file archival
27400		Z	FILMIG		;17 - file migration
27500		Z	FILCOL		;18 - file collection
27600		Z	PROUSR		;>MXRTYP ==> user record type
27700		ENTMAX==.-PRODIS	;number of record types to process
27800	
27900	ENTNAM:	TXT	<NULL (illegal)>
28000		TXT	<RESTART>
28100		TXT	<SESSION>
28200		TXT	<CHECKPOINT>
28300		TXT	<TOPS-10 USAGE HEADER (illegal)>
28400		TXT	<DATE-TIME CHANGE>
28500		TXT	<BATCH - unsupported>
28600		TXT	<INPUT SPOOLER>
28700		TXT	<OUTPUT SPOOLER>
28800		TXT	<DISK USAGE>
28900		TXT	<SPINDLE USAGE - unsupported>
29000		TXT	<STRUCTURE MOUNT>
29100		TXT	<MAGNETIC TAPE MOUNT>
29200		TXT	<DECtape MOUNT - unsupported>
29300		TXT	<DECtape FILE - unsupported>
29400		TXT	<FILE RETRIEVAL>
29500		TXT	<FILE ARCHIVAL>
29600		TXT	<FILE MIGRATION>
29700		TXT	<FILE COLLECTION>
29800		TXT	<USER ENTRIES>
29900	
30000		IFN	.-ENTNAM-ENTMAX, <PRINTX ?Entry name table in PROCESS command too short>
     
00100	SUBTTL	PROCESS command support routines
00200	
00300	;	GETITM - gets an entry record with type code in valid range
00400	;		and length in valid range and with trailer word
00500	;		matching header word.  Resulting record is left in
00600	;		BUFF
00700	
00800	GETITM:	HRRZ	A,PROJFN	;get JFN
00900		BIN
01000		IFN	DEBUG,<
01100			AOS	WRDCNT>	;count words if debugging
01200		JUMPE	B,CKEOF		;check for EOF or error
01300	GTITM1:	MOVEM	B,BUFF		;save header
01400		LOAD	B,SDTYP		;check for valid type
01500		CAIGE	B,^D0001
01600		 JRST	GETUNK
01700		CAIG	B,MXRTYP	; > standard DEC type?
01800		 JRST	HDROK		;no - valid type
01900		CAIGE	B,.UTUSR	;[10] yes - is it in range to be user type?
02000		 JRST	GETUNK		;no - must be error
02100		CAILE	B,^D9999	;maybe
02200		 JRST	GETUNK		;no - must be error
02300	HDROK:	LOAD	B,SDLEN		;type is ok.  Is length?
02400		CAIL	B,.SDMIN	;is it too small?
02500		 CAILE	B,BUFLEN	;or too big?
02600		  JRST	GETUNK		;yes - note error and try again
02612					;[15]  add rec size (minus 1 for header)
02624					;to WRDCNT to record loc of entry in file
02636		IFN	DEBUG,<
02648			ADDM	B,WRDCNT
02660			SOS	WRDCNT>
02700		MOVNI	C,-1(B)		;compute counter for remaining record
02800		MOVE	B,[POINT 36,BUFF+1]	;ready to read in rest
02900		SIN
03000		IFN	CHKBUG,<
03100			LOAD	A,SDTYP		;get type of record
03200			CAIN	A,.UTCKP	;if it's checkpoint ignore it
03300			 JRST	GETITM	>
03400		MOVE	C,0(B)		;get last word
03500		CAME	C,BUFF		;does trailer match header?
03600		 JRST	GETNOM		;NO Match - ignore record
03700		RETSKP			;record is ok - return
03800	
03900	CKEOF:	GTSTS			;get file status
04000		TXNE	B,GS%EOF	;is it an eof?
04100		 RET			;yes - non-skip return
04200		TMSG	<%ACCT20: zeros in file
04300	>
04400		IFN	DEBUG,<CALL	FILLOC>	;tell where if DEBUG is on
04500	CKEOF1:	HRRZ	A,PROJFN	;get JFN again
04600	CKEOF2:	BIN			;read another word
04700		ERJMP	R		;attempt failed - must be at EOF
04800		IFN	DEBUG,<
04900			AOS	WRDCNT>	;count word read if debugging
05000		JUMPN	B,GTITM1	;if not zero, got a header successfully
05100		JRST	CKEOF2		;otherwise, ignore extra zeros
05200	
05300	GETUNK:	TMSG	<%ACCT20: PROCESSing found invalid type or entry length in header word
05400	>
05500		TMSG	<	  Type = >
05600		CALL	TYPOUT
05700		TMSG	<	Length = >
05800		CALL	LENOUT
05900		TMSG	<
06000	>
06100		IFN	DEBUG,<
06200			CALL	FILLOC>	;tell where error is in the file
06300		JRST	GETITM		;try again
06400	
06500	
06600	;GETNOM	- tells user that a record with a header and trailer didn't
06700	;	  match.
06800	GETNOM:	PUSH	P,B		;save trailer
06900		TMSG	<%ACCT20: PROCESSing found invalid record in input file
07000	>
07100		TMSG	<	  entry trailer word did not match header word
07200	>
07300		TMSG	<	  Header word = >
07400		HRRZI	A,.PRIOU
07500		MOVE	B,BUFF
07600		MOVX	C,NO%MAG!NO%LFL!NO%ZRO!FLD(12,NO%COL)!FLD(8,NO%RDX)
07700		NOUT
07800		 JSERR
07900		TMSG	<	trailer word = >
08000		HRRZI	A,.PRIOU
08100		POP	P,B
08200		MOVX	C,NO%MAG!NO%LFL!NO%ZRO!FLD(12,NO%COL)!FLD(8,NO%RDX)
08300		NOUT
08400		 JSERR
08500		TMSG	<
08600	>
08700		IFN	DEBUG,<CALL	RECLOC>
08800		JRST	GETITM		;try again
08900	IFN	DEBUG,<
09000	;	This routine types out the location in a file in which an
09100	;	erroneous record was found.
09200	
09300	FILLOC:	TXNN	F,F%DEB		;does user want the info?
09400		 RET			;no
09500		HRRZ	B,PROJFN	;yes - output name of file
09600		HRRZI	A,.PRIOU
09610		SETZB	C,D		;[16]
09700		JFNS
09800		TMSG	<	word address >
09900		HRRZI	A,.PRIOU
10000		MOVE	B,WRDCNT
10100		MOVX	C,NO%OOV!FLD(8,NO%RDX)	;[13]
10200		NOUT
10300		 CAI
10400		TMSG	<
10500	>
10600		RET
10700	
10800	;	Types out location of erroneous record in file when the
10900	;	remainder of the record has been already read in (and
11000	;	the value of WRDCNT has been updated accordingly) by
11100	;	temporarily modifying WRDCNT to point to the first word of
11200	;	the record.
11300	RECLOC:	PUSH	P,WRDCNT	;save word count for later restoration
11400		LOAD	B,SDLEN		;get length of record
11500		MOVNI	B,(B)		;[13]
11510		ADDM	B,WRDCNT	;[13]  point to first word of record
11700		CALL	FILLOC		;output that information
11800		POP	P,WRDCNT	;get back current word count
11900		RET			;and go back
12000			>		;end IFN DEBUG
12100	
12200	
12300	;LENOUT	- types out record length value
12400	;TYPOUT - types out record type value
12500	LENOUT:	LOAD	B,SDLEN		;get length
12600		JRST	HLFOUT
12700	TYPOUT:	LOAD	B,SDTYP
12800	HLFOUT:	MOVEI	A,.PRIOU
12900		MOVX	C,NO%LFL!NO%ZRO!NO%OOV!FLD(6,NO%COL)!FLD(^D10,NO%RDX) ;[14]
13000		NOUT
13100		 CAI
13200		RET
13300	
13400	;CHKBDT	- checks to see if date/time of record entry is after the BEGIN
13500	;	  date/time set by user.  If so, returns;  if not, returns to
13600	;	  PROENT (directly!) to get next record for processing
13700	
13800	CHKBDT:	LOAD	A,SDTAD		;get record date/time
13900		CAML	A,BEGDT		;is entry date/time < that requested?
14000		 RET			;no - process this record
14100		POP	P,A		;yes - don't return to call
14200		JRST	PROENT		; just go on to next record
14300	
14400	;CHKEDT	- checks to see if date/time of record entry is before the END
14500	;	  date/time set by user.  If so, returns; if not, returns to
14600	;	  PROENT (directly!) to get next record for processing.
14700	
14800	CHKEDT:	LOAD	A,SDTAD		;get record date/time
14900		CAMG	A,ENDDT		;is entry date/time > that requested?
15000		 RET			;no - process this record
15100		POP	P,A		;yes - don't return to call,
15200		JRST	PROENT		; just go for next record
15300	
15400	
15500	;SETSTR	- set up pointer to user name string, which may be either
15600	;	  the directory name or account string, depending upon the
15700	;	  F%RPT bit.  Returns the pointer to the correct string in
15800	;	  location USRPTR
15900	
16000	
16100	
16200	;VLDDET - determines if the user requested DETAILs to be listed for
16300	;	  entries with the name given in this record (pointed to by
16400	;	  USRPTR).  If DETNAM is nul, all entries are assumed to match;
16500	;	  otherwise do wildcard test of candidate string against
16600	;	  that contained in DETNAM.  Returns flag bit F%DET if record
16700	;	  is to be listed in details listing.
16800	
16900	VLDDET:	SKIPN	DETNAM		;match all?
17000		 JRST	VLDDE1		;yes
17100		MOVE	B,[POINT 7,DETNAM]	;no - get (possibly wild) string
17200		MOVE	C,USRPTR	;and pointer to this user
17300		SETZ	A,
17400		WILD%
17500		SKIPN	A		;match?
17600	VLDDE1:	TXOA	F,F%DET		;yes - set bit
17700		 TXZ	F,F%DET		;no - make sure flag is off
17800		RET
17900	
18000	;VLDSUM	- determines if the user requested summary information to be
18100	;	  listed for entries with the name given in this record.
18200	;	  Functions in same way as VLDDET except that it sets F%SUM.
18300	
18400	
18500	VLDSUM:	SKIPN	SUMNAM		;match all entries?
18600		 JRST	VLDSU1		;yes
18700		MOVE	B,[POINT 7,SUMNAM]	;no - point to summary string
18800		MOVE	C,USRPTR	; and name of this record
18900		SETZ	A,
19000		WILD%
19100		SKIPN	A		;match?
19200	VLDSU1:	TXOA	F,F%SUM		;yes
19300		 TXZ	F,F%SUM		;no- make sure it's off
19400		RET
19500	
19600	
19700	;LOCNOD - locate the node in the summary tree which contains value
19800	;	  pointed to by USRPTR - i.e., find where the data supplied by
19900	;	  this entry is to be summarized.
20000	
20100	LOCNOD:	MOVEI	P1,SUMPTR	;point to tree
20200		HRLI	P1,..SLEN	;length of fixed part of node
20300		MOVE	P2,USRPTR	;point to string identifying this entry
20400		MOVE	P3,NAMLEN	;length of variable part
20500		CALL	GETNOD		;locate node
20600		JUMPE	P1,TREERR	;Can't - give error message
20700		RET			;got it - return
20800	
20900	TREERR:	TMSG	<%ACCT20: Can't enter summary information for directory/account >
21000		MOVE	A,USRPTR
21100		PSOUT
21200		TMSG	<
21300		Entry has been ignored in summary
21400	>
21500		TXZ	F,F%SUM
21600		IFN	DEBUG,<
21700			TMSG	<	  Error type is >
21800			MOVEI	A,.PRIOU
21900			HLRE	B,P1
22000			MOVX	C,FLD(10,NO%RDX)
22100			NOUT
22200			 CAI	>	;end IFN DEBUG
22300		RET
22400	
22500	;SETSTR - table of routines to set the string pointing to the user
22600	;	  name in the buffer.  The location of the string depends
22700	;	  on the entry type, so this dispatch table is used to
22800	;	  simplify the process
22900	SETSTR:	Z	SETNAM		;0 - illegal (name string only)
23000		Z	SETNAM		;restart
23100		Z	SETUSR		;session
23200		Z	SETUSR		;checkpoint
23300		Z	SETNAM		;4 - illegal
23400		Z	SETNAM		;date/time
23500		Z	SETNAM		;batch
23600		Z	SETUSR		;input
23700		Z	SETUSR		;output
23800		Z	SETST2		;disk usage
23900		Z	SETNAM		;spindle usage
24000		Z	SETUSR		;structure mount
24100		Z	SETUSR		;magtape mount
24200		Z	SETNAM		;13 - illegal
24300		Z	SETNAM		;14 - illegal
24400		Z	SETUSR		;file retrieval
24500		Z	SETUSR		;file archival
24600		Z	SETUSR		;file migration
24700		Z	SETUSR		;file collection
24800		Z	SETUSR		;user-defined type
24900	
25000		IFN	.-SETSTR-ENTMAX, <PRINTX ?User string dispatch table too short>
25100	
25200	SETNAM:	MOVE	A,[POINT 7,.SDNAM]	;name field of record
25300		MOVEM	A,USRPTR
25400		LOAD	B,SDULN		;length of string
25500		MOVEM	B,NAMLEN
25600		RET
25700	
25800	SETUSR:	TXNN	F,F%RPT		;report by directory or account
25900		 JRST	SETNAM		;directory
26000	SETST1:	HRLZI	A,(POINT 7,)	;account
26100		LOAD	B,SDULN
26200		HRRI	A,.SDNAM(B)	;[7] address is .SDNAM + <len of name field>
26300		MOVEM	A,USRPTR
26400		LOAD	B,SDSL1		;length of string
26500		MOVEM	B,NAMLEN
26600		RET
26700	
26800	SETST2:	LOAD	A,SDULN		;address is .SDNAM + <len of name field>
26900		LOAD	B,SDSL1		;		   + <len of string 1>
27000		ADDI	A,.SDNAM(B)
27100		HRLI	A,(POINT 7,)
27200		MOVEM	A,USRPTR
27300		LOAD	B,SDSL2		;length of string
27400		MOVEM	B,NAMLEN
27500		RET
27600	
27700	SETRAT:	TXZ	F,F%COM!F%OUT		;Assume non-profit user, don't output record
27800		IFN	WESU,<
27900			      LOAD	A,SDTYP		;if not a session record,
28000			      CAIE	A,SESTYP	; ignore non-null account strings
28100			       JRST	NOACNT
28200			      LOAD	A,SDULN		;at Wesleyan, record
28300			      HRR	A,.SDNAM(A)	;entries with non-null
28400			      SKIPE	A		;account strings
28500			      TXO	F,F%OUT	
28600			      NOACNT: >	;end IFN WESU
28700		MOVE	P2,USRPTR	;Get pointer to user name string
28800		MOVEI	P1,BILPTR	;And pointer to tree of selected users
28900		CALL	FNDNOD		;Check for substring match
29000		 RET			;No match - just return
29100		MOVE	A,..BILN-1(P1)	;[1] Got a match.  Which type of user?
29200		TXNE	A,BL%COM	;Commercial?
29300		 TXO	F,F%COM		;Yes - set program-wide flag
29400		TXO	F,F%OUT		;In any case, flag for possible output
29500		RET
29600	
29700	WRTBIN:	TXNN	F,F%OUT		;Write out this record?
29800		 RET			;no
29900		MOVEI	P1,DETPTR	;Yes - record this particular
30000					; user in the list of those in DETAIL file
30100		HRLI	P1,..DTLN	;Fixed node size
30200		MOVE	P2,USRPTR	;Point to string to add
30300		MOVE	P3,NAMLEN	;Length of name string
30400		CALL	GETNOD		;Add it
30500		JUMPE	P1,WBERR		;Couldn't?
30600		MOVE	A,BINJFN	;Now write to DETAILS binary file
30700		MOVE	B,[POINT 36,BUFF]
30800		LOAD	C,SDLEN
30900		MOVN	C,C
31000		SETZ	D,
31100		SOUT
31200		RET
31300	
31400	WBERR:	TMSG	<%ACCT20: Can't enter binary DETAILS information for directory/account >
31500		MOVE	A,USRPTR
31600		PSOUT
31700		TMSG	<
31800		Entry has been omitted from list of DETAILS users
31900	>
32000		IFN	DEBUG,<
32100			TMSG	<	Error type is
32200			MOVEI	A,.PRIOU
32300			HLRE	B,P1
32400			MOVX	C,FLD(10,NO%RDX)
32500			NOUT
32600			 CAI	>	;End IFN DEBUG
32700		RET
32800	
32900	;Routine to dump users for whom records were written to DETAILS-BINARY
33000	USRDMP:	MOVE	B,[TXT<ACCT20>]		;assume standard name
33100		TXNE	F,F%NAM			;was a default name given?
33200		 MOVE	B,[POINT 7,NAMES]	;yes.  Use it
33300		MOVE	A,[POINT 7,TMPBLK]	;copy into temp area
33400		SETZB	C,D
33500		SOUT
33600		MOVE	B,[TXT<-BILLED-USERS.TMP>]	;complete the filename
33700		SETZB	C,D
33800		SOUT
33900		MOVE	A,[GJ%FOU!GJ%SHT]	;open up a new file
34000		MOVE	B,[POINT 7,TMPBLK]
34100		GTJFN
34200		 CALLRET [ERMSG <%ACCT20:	Can't get JFN for billed-users listing file>
34300			  RET]
34400		MOVEM	A,FILJFN
34500		MOVX	B,FLD(7,OF%BSZ)!FLD(.GSNRM,OF%MOD)!OF%WR
34600		OPENF
34700		 CALLRET [ERMSG <%ACCT20:	Can't open billed-users listing file>
34800			  RET]
34900		MOVE	P1,DETPTR
35000		MOVEI	P2,DMPUSR
35100		CALL	DMPTRE
35200		HRRZ	A,FILJFN
35300		CLOSF
35400		 ERMSG <%ACCT20:	Can't close billed-users listing file>
35500		RET
35600	
35700	DMPUSR:	MOVE	A,FILJFN
35800		MOVE	B,(P1)		;just dump the name of the user
35900		SETZB	C,D
36000		SOUT
36100		MOVE	B,[TXT <
36200	>]				;terminated by a <CR><LF>
36300		SETZB	C,D
36400		SOUT
36500		RET
36600	
36700	FNDNOD:	SKIPN	(P1)		;Is there a tree?
36800		 RET			;No - failure is non-skip return
36900		HRR	P1,(P1)		;Yes - get first node
37000	FNDLUP:	MOVE	A,(P1)		;Get pointer to node value
37100		MOVE	B,P2		;Get pointer to test string
37200		STCMP			;Compare
37300		SKIPE	A		;exact match?
37400		 TXNE	A,SC%SUB	;No. Substring?
37500		  RETSKP		;Some sort of match.  Success is skip return
37600		MOVE	B,1(P1)		;Ready to point to next subtree
37700		TXNN	A,SC%LSS	;Do we take left or right?
37800		 MOVSS	B		;Take left by swapping halves
37900		HRRZ	B,B		;Get just that address
38000		SKIPN	B		;If no further subtrees, no match.
38100		 RET			;and failure is a non-skip return
38200		HRR	P1,B		;otherwise go look at that subtree
38300		JRST	FNDLUP
     
00100	SUBTTL	Summary printing routines for PROCESS command
00200	
00300	SUMOUT:	MOVE	A,SUMJFN	;get JFN for summary output
00400		MOVEI	Q1,TOTNOD	;set up pointer for summary operation
00500		SOSG	SUMLIN		;end of page?
00600		 CALL	SUMHDR		;yes - start and head new one
00700	S1OUT:	MOVE	B,.SUSER(P1)	;get user name
00800		MOVEI	C,^D41		;and output in a field of 41 chars
00900		SETZ	D,
01000		SOUT
01100		MOVE	B,[TXT<                                        >]
01200		SKIPLE	C
01300		 SOUT			;complete field
01400		MOVE	B,.STSES(P1)	;count of sessions
01500		ADDM	B,.STSES(Q1)	;add to totals
01600		MOVX	C,NO%LFL!NO%OOV!FLD(4,NO%COL)!FLD(12,NO%RDX)
01700		NOUT
01800		 CAI
01900		SPACE	<2>
02000		MOVE	B,.STCPU(P1)	;get cpu time in real sec
02100		FADRM	B,.STCPU(Q1)	;add to totals
02200		MOVX	C,FL%ONE!FL%PNT!FL%OVL!FLD(8,FL%FST)!FLD(1,FL%SND)
02300		FLOUT
02400		 CAI
02500		SPACE	<1>
02600		MOVE	B,.STCON(P1)	;get connect time in real sec
02700		FADRM	B,.STCON(Q1)	;sum to totals
02800		FIXR	B,B		;go to integer sec for output
02900		MOVEI	D,4		;4 cols out for hours
03000		CALL	TIMOUT		;write it
03100		SPACE	<2>
03200		MOVE	B,.SBSES(P1)	;number of batch sessions
03300		ADDM	B,.SBSES(Q1)	;sum to totals
03400		MOVX	C,NO%LFL!NO%OOV!FLD(4,NO%COL)!FLD(12,NO%RDX)
03500		NOUT
03600		 CAI
03700		SPACE	<1>
03800		MOVE	B,.SBCPU(P1)	;batch CPU time in real sec
03900		FADRM	B,.SBCPU(Q1)	;sum to totals
04000		MOVX	C,FL%ONE!FL%PNT!FL%OVL!FLD(8,FL%FST)!FLD(1,FL%SND)
04100		FLOUT
04200		 CAI
04300		SPACE	<2>
04400		MOVE	B,.SBCON(P1)	;batch connect time in real sec
04500		FADRM	B,.SBCON(Q1)	;sum to totals
04600					; note that this is not output
04700		MOVE	B,.SCDRR(P1)	;cards read
04800		ADDM	B,.SCDRR(Q1)	;sum to total
04900		MOVX	C,NO%LFL!NO%OOV!FLD(5,NO%COL)!FLD(12,NO%RDX)
05000		NOUT
05100		 CAI
05200		SPACE	<2>
05300		MOVE	B,.SLPTW(P1)	;pages printed
05400		ADDM	B,.SLPTW(Q1)	;sum to total
05500		MOVX	C,NO%LFL!NO%OOV!FLD(5,NO%COL)!FLD(12,NO%RDX)
05600		NOUT
05700		 CAI
05800		SPACE	<2>
05900		MOVE	B,.SPLTM(P1)	;plotter minutes
06000		ADDM	B,.SPLTM(Q1)	;sum to totals
06100		MOVX	C,NO%LFL!NO%OOV!FLD(3,NO%COL)!FLD(12,NO%RDX)
06200		NOUT
06300		 CAI
06400		SPACE	<2>
06500		MOVE	B,.SDSKU(P1)	;disk space used
06600		SKIPE	C,.SDSKC(P1)	;count zero?
06700		 IDIV	B,C		;no - compute average usage
06800		ADDM	B,.SDSKU(Q1)	;sum average to totals
06900		MOVX	C,NO%LFL!NO%OOV!FLD(4,NO%COL)!FLD(12,NO%RDX)
07000		NOUT
07100		 CAI
07200		SPACE	<2>
07300		MOVE	B,.SMTAM(P1)	;tape mounts
07400		ADDM	B,.SMTAM(Q1)	;sum to totals
07500		MOVX	C,NO%LFL!NO%OOV!FLD(4,NO%COL)!FLD(12,NO%RDX)
07600		NOUT
07700		 CAI
07800		SPACE	<2>
07900		MOVE	B,.SMTAU(P1)	;mta time used in real sec
08000		FADRM	B,.SMTAU(Q1)	;sum to totals
08100		FDVRI	B,(60.)		;convert to minutes
08200		FIXR	B,B		;and convert to integer minutes
08300		MOVX	C,NO%LFL!NO%OOV!FLD(4,NO%COL)!FLD(12,NO%RDX)
08400		NOUT
08500		 CAI
08600		SPACE	<2>
08700		MOVE	B,.SVALU(P1)	;value of services
08800		FADRM	B,.SVALU(Q1)	;sum to totals
08900		MOVX	C,FL%ONE!FL%DOL!FL%PNT!FL%OVL!FLD(5,FL%FST)!FLD(2,FL%SND)
09000		FLOUT
09100		 CAI
09200		CALL	CRLF
09300		RET
09400	
09500	SUMHDR:	MOVEI	B,.CHFFD
09600		BOUT			;force new page
09700	SHDR1:	SPACE	<^D41>
09800		MOVE	B,[TXT <------Time Sharing-------   -----Batch-----  Cards  Pages  PLT   DSK   MTA   MTA
09900	>]
10000		SETZB	C,D
10100		SOUT
10200		MOVE	B,[TXT <User Name>]
10300		SETZB	C,D
10400		SOUT
10500		SPACE	<^D32>
10600		MOVE	B,[TXT <SESS      CPU     Connect   SESS      CPU    Read   Prntd  Min   Used  Mnts  Conn    Value>]
10700		SETZ	C,D
10800		SOUT
10900		MOVEI	B,.CHCRT
11000		BOUT				;return only - do underlining
11100		MOVE	B,[TXT<_______________________________________  ____  _________   _______   ____    _______  _____  _____  ___   ____  ____  ____   _______
11200	>]
11300		SOUT
11400		CALL	CRLF
11500		MOVEI	B,SUMPAG-3
11600		MOVEM	B,SUMLIN		;reinit line counter
11700		RET
     
00100	SUBTTL	TYPERR - Routine to process erroneous entry records
00200	
00300	
00400	;TYPERR - error message for invalid type
00500	
00600	TYPERR:	TMSG	<%ACCT20: unsupported standard record type encountered>
00700		TMSG	<	 Type = >
00800		CALL	TYPOUT
00900		TMSG	<
01000	>
01100		IFN	DEBUG,<CALL	RECLOC>
01200		RET
     
00100	SUBTTL	PROUSR - Routine to process user-defined entry records
00200	
00300	;PROUSR - record processing for user-defined record types.
00400	;	  ALL user-defined record types go through here
00500	PROUSR:	TMSG	<%ACCT20: User record type >
00600		CALL	TYPOUT
00700		TMSG	< encountered.
00800		  No support for user-defined records.
00900	>
01000		TMSG	<	  Record ignored
01100	>
01200		IFN	DEBUG,<
01300			TXNN	F,F%DEB		;want more info?
01400			 JRST	USRRET		;[12] no
01800			TMSG	<	>
02000			CALL	RECLOC
02100			TMSG	<
02200	>
02300				>	;end IFN DEBUG
02310	USRRET:	POP	P,T0		;[12] don't expect to return to process
02320					;user entry types.  Remove this if you
02330					;want to return for processing
02400		JRST	PROENT
     
00100	SUBTTL	SESS - Routine to handle SESSION record types
00200	
00300	;SESS	- Process session record
00400	
00500	SESS:	TXNN	F,F%DET		;details wanted?
00600		 JRST	SESSUM		;no - try summary
00700		TXNN	F,F%DCP!F%DDS!F%DTT	;want anything we have?
00800		 JRST	SESSUM		;no
00900		MOVEI	Q2,DETTOT+.STSES	;assume timesharing job
01000		LOAD	P2,SDJTS
01100		SKIPE	P2			;is it?
01200		 MOVEI	Q2,DETTOT+.SBSES	;no, point to batch total
01300		AOS	(Q2)			;count session
01400		CALL	DETCMN		;yes - write common header
01500		MOVE	A,DETJFN
01600		MOVE	B,[TXT (SESS  CPU=)]
01700		SETZB	C,D
01800		SOUT
01900	CHKCMN:	MOVE	B,2(Q1)		;get cpu time in msec
02000		FLTR	B,B		;convert to real
02100		FDVRI	B,(1000.)	;and to seconds
02200		FADRM	B,2(Q2)		;add to total
02300		MOVX	C,FL%ONE!FL%OVL!FL%PNT!FLD(4,FL%FST)!FLD(3,FL%SND)
02310		POP	P,A		;[12]
02400		FLOUT
02500		 CAI
02600		SPACE	2
02700		MOVE	B,[TXT<on at >]
02800		SETZB	C,D
02900		SOUT
03000		MOVE	B,0(Q1)		;get session on time
03100		MOVX	C,OT%NDA	;output time only
03200		ODTIM
03300		SPACE	2
03400		MOVE	B,[TXT<conn=>]
03500		SETZB	C,D
03600		SOUT
03700		FLTR	B,1(Q1)		;connect time in msec
03800		FDVRI	B,(1000.)	;convert to sec
03900		FADRM	B,1(Q2)		;add to totals
04000		FIXR	B,B		;convert back to integer sec for output
04100		MOVEI	D,2		;2 cols for hour field
04200		CALL	TIMOUT
04300		SPACE	2
04400		FLTR	B,1(Q1)		;get connect time again (in MSEC!)
04500		FMPR	B,.PRCON	;and compute value (using rate for sec!)
04600		LOAD	C,SDJTS		;if job is batch,
04700		SKIPE	C
04800		 SETZ	B,		; don't charge for connect
04900		FLTR	C,2(Q1)		;now runtime
05000		FMPR	C,.PRCPU	;compute value
05100		FADR	B,C		;add together
05200		FDVRI	B,(1000.)	;and adjust for units of sec, not msec.
05300		TXNE	F,F%COM		;commercial user?
05400		 CALL	ADJCHG		;yes - adjust charge
05500		FADRM	B,DETTOT+.SVALU	;add to total
05600		MOVX	C,FL%ONE!FL%PNT!FL%DOL!FL%OVL!FLD(5,FL%FST)!FLD(2,FL%SND)
05700		FLOUT
05800		 CAI
05900		CALL	CRLF
06000	SESSUM:	TXNN	F,F%SUM		;SUMMARY wanted?
06100		 RET			;no
06200		TXNN	F,F%SCP!F%SDS!F%STT	;anything we have?
06300		 RET			;no
06400		HRRZ	P1,THSNOD	;point to node for this user
06500		MOVEI	P3,.STSES(P1)	;assume this is timesharing
06600		LOAD	P2,SDJTS	;0 ==> TS, 1 ==> batch
06700		SKIPE	P2		;if this is really batch,
06800		 MOVEI	P3,.SBSES(P1)	; then point with P3 to where batch
06900					; work is summarized in the node
07000		AOS	(P3)		;count the session
07100		FLTR	B,1(Q1)		;get connect time from the record
07200		FDVRI	B,(1000.)	;convert to seconds
07300		FADRM	B,1(P3)		;and add it to the summary
07400		FMPR	B,.PRCON	;compute value
07500		LOAD	C,SDJTS		;if job is batch,
07600		SKIPE	C
07700		 SETZ	B,		; don't charge for connect
07800		FLTR	C,2(Q1)		;get runtime from the record
07900		FDVRI	C,(1000.)	;convert to seconds
08000		FADRM	C,2(P3)	;add to summary
08100		FMPR	C,.PRCPU
08200		FADR	B,C		;add cpu charge to connect
08300		TXNE	F,F%COM		;if commercial,
08400		 CALL	ADJCHG		; adjust charges
08500		HRRZ	P1,THSNOD
08600		FADRM	B,.SVALU(P1)	;and add to node
08700		RET
08800		
08900	;adjust charges for commercial users by shift differential
09000	
09100	ADJCHG:	LOAD	T0,SDTAD	;get date/time of entry
09200		HLRZ	C,T0		;check if weekend day
09300		IDIVI	C,7
09400		CAIN	D,3		;Saturday?
09500		 CALLRET WKEND
09600		CAIN	D,4		;Sunday?
09700		 CALLRET WKEND
09800		PUSH	P,B		;[6] save unadjusted cost
09900		MOVE	B,T0		;[6] convert time to sec after midnight
10000		SETZ	D,		;[6]
10100		ODCNV			;[6] 
10200		HRRZ	T0,D		;[6] copy sec into T0 for lookup
10300		POP	P,B		;[6] retrieve unadjusted cost
10400		HLRZ	D,SHFTBL+1	;Get earliest date/time in shift table
10500		CAMGE	T0,(D)		;if the time we want is < lowest time
10600					; in table, 
10700		 ADD	T0,[^D24*^D60*^D60] ;[6] force default to latest time in table
10800					; (wrap around 24:00 by adding 24 hrs)
10900		HLR	C,SHFTBL	;get size of table
11000		SKIPN	C
11100		 RET			;no table - don't adjust rates
11200		MOVN	C,C		;make an AOBJN pointer for lookup
11300		HRL	C,C
11400		HRRI	C,SHFTBL+1
11500	ADJLUP:	HLRZ	D,(C)		;pointer to data value is in lh of table entry
11600		CAMLE	T0,(D)		;if data value is < table value
11700		AOBJN	C,ADJLUP
11800		HRRZ	D,-1(C)		; then rate multiplier is pointed to by
11900		FMPR	B,(D)		; rhs of preceeding word in table
12000		RET
12100	
12200	WKEND:	FMPR	B,.PRWKN	;only one weekend rate
12300		RET
     
00100	SUBTTL	RESTART - Routine to process RESTART record types
00200	
00300	;RESTART - Process restart record
00400	
00500	RESTART: TXNN	F,F%DEB		;in debug mode?
00600		  RET			;no - don't process restarts
00700		TXNN	F,F%DCP		;CPU-RELATED?
00800		 RET			;NO
00900		CALL	DETCMN		;yes - write common header
01000		MOVE	A,DETJFN
01100		MOVE	B,[TXT (RESTART)]
01200		SETZB	C,D
01300		SOUT
01400		LOAD	B,SDULN		;point to string 1 (system name)
01500		MOVEI	B,.SDNAM(B)
01600		HRLI	B,(POINT 7,)
01700		SETZB	C,D
01800		SOUT
01900		SPACE	1
02000		MOVE	B,0(Q1)		;version
02100		CALL	VEROUT
02200		CALL	CRLF
02300	RESSUM:	RET			;no summary processing for restart
     
00100	SUBTTL	CHKPNT - Routine to process CHECKPOINT record types
00200	
00300	;CHKPNT	- Process checkpoint record
00400	;	In this distributed version, no charges are made for activities
00500	;	which are in progress when a crash and subsequent restart
00600	;	occur.  The routine here merely prints out the record info
00700	;	if the DEBUG option was selected.  To charge for work in
00800	;	progress, modify this section to call SESS when CHECKPOINT
00900	;	records are encountered immediately after a RESTART record.
01000	;
01100	
01200	CHKPNT:	TXNN	F,F%DEB		;DEBUG on?
01300		 RET			;no - don't process checkpoint
01400		TXNN	F,F%DET		;details wanted?
01500		 JRST	CHKSUM		;no - try SUMMARY
01600		TXNN	F,F%DCP!F%DDS!F%DTT	;WANT ANYTHING WE HAVE?
01700		 RET				;NO
01800		CALL	DETCMN		;yes - write common header
01900		MOVE	A,DETJFN
02000		MOVE	B,[TXT (CHK   CPU=)]
02100		SETZB	C,D
02200		SOUT
02300		CALL	CHKCMN
02400	CHKSUM:	RET			;no summary action other than what
02500					; SESS might have done if called
02600					; through CHKCMN
     
00100	SUBTTL	DATTIM - Routine to process DATE/TIME CHANGE records
00200	
00300	;DATTIM	- PROCESS date/time change record
00400	
00500	DATTIM:	TXNN	F,F%DEB		;DEBUG on?
00600		 RET			;no
00700		TXNN	F,F%DCP		;Details for CPU activity wanted?
00800		 RET			;no
00900		CALL	DETCMN		;yes
01000		MOVE	A,DETJFN
01100		MOVE	B,[TXT (DATE-TIME CHANGE   OLD DATE-TIME)]
01200		SETZB	C,D
01300		SOUT
01400		MOVE	B,0(Q1)		;get old date/time
01500		SETZ	C,
01600		ODTIM
01700		CALL	CRLF
01800		RET
     
00100	SUBTTL	BATCH - Routine to process BATCH records
00200	
00300	;BATCH	- PROCESS batch record
00400	
00500	BATCH:	TMSG	<%ACCT20: BATCH record encountered  - no code for processing
00600	>
00700		TXNN	F,F%DET		;details wanted?
00800		 JRST	BATSUM		;no
00900		TXNN	F,F%DCP!F%DDS!F%DTT	;want anything we have here?
01000		 JRST	BATSUM		;no
01100		CALL	DETCMN		;yes
01200		MOVE	A,DETJFN
01300		MOVE	B,[TXT (BATCH)]
01400		SETZB	C,D
01500		SOUT
01600		CALL	CRLF
01700	BATSUM:	RET
     
00100	SUBTTL	INPUT - Routine to process INPUT spooler records
00200	
00300	;INPUT	- PROCESS input spooler record
00400	
00500	INPUT:	TXNN	F,F%DET		;details wanted?
00600		 JRST	INPSUM		;no
00700		TXNN	F,F%DIN		;want spooler activity?
00800		 JRST	INPSUM		;no
00900		CALL	DETCMN		;yes
01000		MOVE	C,4(Q1)		;get queue name
01100		CALL	SIXOUT		;and print it
01200		MOVE	B,[TXT( Job )]
01300		SETZB	C,D
01400		SOUT
01500		MOVE	C,3(Q1)		;job name
01600		CALL	SIXOUT
01700		MOVE	B,[TXT(  Cards read = )]
01800		SETZB	C,D
01900		SOUT
02000		MOVE	B,7(Q1)		;count of cards
02100		ADDM	B,DETTOT+.SCDRR	;add to total
02200		MOVX	C,NO%OOV!FLD(5,NO%COL)!FLD(12,NO%RDX)
02300		NOUT
02400		 CAI			;ignore errors
02500		SPACE	^D14
02600		FLTR	B,7(Q1)		;card count again
02700		FMPR	B,.PRCRD	;value
02800		FADRM	B,DETTOT+.SVALU ;add to total
02900		MOVX	C,FL%ONE!FL%PNT!FL%DOL!FL%OVL!FLD(5,FL%FST)!FLD(2,FL%SND)
03000		FLOUT
03100		 CAI
03200		CALL	CRLF
03300	INPSUM:	TXNN	F,F%SUM		;Summary wanted?
03400		 RET
03500		TXNN	F,F%SIN		;Of input spooler?
03600		 RET
03700		MOVE	P1,THSNOD	;point to user node
03800		MOVE	B,7(Q1)		;card count
03900		ADDM	B,.SCDRR(P1)	;add to summary
04000		FLTR	B,B		;compute value
04100		FMPR	B,.PRCRD
04200		FADRM	B,.SVALU(P1)	;and add to summary
04300		RET
     
00100	SUBTTL	OUTPUT - Routine to process OUTPUT spooler records
00200	
00300	;OUTPUT	 - PROCESS output spooler record
00400	
00500	OUTPUT:	TXNE	F,F%FRM		;want forms usage output
00600		 CALL	FRMPRC		;yes, call routine
00700		TXNN	F,F%DET!F%SUM	;want summary or details?
00800		 RET			;no
00900		TXNN	F,F%DOU!F%SOU	;of output spooler?
01000		 RET			;no
01100		SETZ	T0,		;yes - default price of 0
01200		MOVE	C,4(Q1)		;get type of output
01300		CAMN	C,[SIXBIT /PLT/]	;plotter?
01400		 JRST	PLTDET		;yes
01500		CAMN	C,[SIXBIT /LPT/]	;printer?
01600		 CALL	SPLPRC		;yes - get price into T0
01700		TXNN	F,F%DET		;now handle record - DETAILS wanted?
01800		 JRST	LPTSUM		;no
01900		TXNN	F,F%DOU		;yes - output spooler?
02000		 JRST	LPTSUM		;no
02100		CALL	DETCMN		;yes - output header 
02200		MOVE	C,4(Q1)		;get queue name
02300		CALL	SIXOUT		;print it
02400		MOVE	B,[TXT( Job )]
02500		SETZB	C,D
02600		SOUT
02700		MOVE	C,3(Q1)		;job name
02800		CALL	SIXOUT		;print it
02900		SPACE	2
03000		MOVE	B,7(Q1)		;page count
03100		ADDM	B,DETTOT+.SLPTW	;add to total
03200		MOVX	C,NO%LFL!NO%OOV!FLD(5,NO%COL)!FLD(12,NO%RDX)
03300		NOUT
03400		 CAI
03500		MOVE	B,[TXT( Pages  )]
03600		SETZB	C,D
03700		SOUT
03800		MOVE	C,15(Q1)	;forms type
03900		CALL	SIXOUT
04000	
04100		MOVE	B,[TXT( forms)]
04200		SETZB	C,D
04300		SOUT
04400		SPACE	7
04500		FLTR	B,7(Q1)		;compute value
04600		FMPR	B,T0
04700		FADRM	B,DETTOT+.SVALU	;add to total
04800		MOVX	C,FL%ONE!FL%PNT!FL%DOL!FL%OVL!FLD(5,FL%FST)!FLD(2,FL%SND)
04900		FLOUT
05000		 CAI
05100		CALL	CRLF
05200	LPTSUM:	TXNN	F,F%SUM		;summary requested?
05300		 RET			;no
05400		TXNN	F,F%SOU		;for output spooler?
05500		 RET			;no
05600		MOVE	P1,THSNOD	;yes - point to node for this user
05700		MOVE	B,7(Q1)		;get page count
05800		ADDM	B,.SLPTW(P1)	;add to summary
05900		FLTR	B,B		;compute value
06000		FMPR	B,T0
06100		FADRM	B,.SVALU(P1)	;add to summary
06200		RET
06300	
06400	PLTDET:	TXNN	F,F%DET		;DETAILS wanted?
06500		 JRST	PLTSUM		;no
06600		TXNN	F,F%SOU		;yes - for output spooler?
06700		 JRST	PLTSUM		;no
06800		CALL	DETCMN		;yes - print header
06900		MOVE	C,4(Q1)		;get queue name
07000		CALL	SIXOUT
07100		MOVE	B,[TXT( Job )]
07200		SETZB	C,D	
07300		SOUT
07400		MOVE	C,3(Q1)		;Get job name
07500		CALL	SIXOUT		;print it
07600		SPACE	2
07700		MOVE	B,7(P1)		;minutes used
07800		ADDM	B,DETTOT+.SPLTM	;add to total
07900		MOVX	C,NO%LFL!NO%OOV!FLD(5,NO%COL)!FLD(12,NO%RDX)
08000		NOUT
08100		 CAI
08200		MOVE	B,[TXT( minutes, )]
08300		SETZB	C,D
08400		SOUT
08500		MOVE	C,15(Q1)	;forms type
08600		CALL	SIXOUT		;print it
08700		MOVE	B,[TXT( forms)]
08800		SETZB	C,D
08900		SOUT
09000		SPACE	5
09100		FLTR	B,15(Q1)	;compute value
09200		FMPR	B,.PRPLT
09300		FADRM	B,DETTOT+.SVALU	;add to total
09400		MOVX	C,FL%ONE!FL%PNT!FL%DOL!FL%OVL!FLD(5,FL%FST)!FLD(2,FL%SND)
09500		FLOUT
09600		 CAI
09700		CALL	CRLF
09800	PLTSUM:	TXNN	F,F%SUM		;SUMMARY wanted?
09900		 RET			;no
10000		TXNN	F,F%SOU		;yes - of output spooler?
10100		 RET			;no
10200		MOVE	P1,THSNOD	;yes - point to summary node for this user
10300		MOVE	B,7(Q1)		;minutes used
10400		ADDM	B,.SPLTM(P1)	;add to summary
10500		FLTR	B,B		;compute value
10600		FMPR	B,.PRPLT
10700		FADRM	B,.SVALU(P1)	;add to summary
10800		RET
10900	
11000	SPLPRC:	MOVE	T0,.PRPGS	;assume default price for output page
11100		TXNN	F,F%PCG		;if there's no table, proceed
11200		 RET
11300		PUSH	P,A		;save JFN of output
11400		MOVE	B,15(Q1)	;get form name
11500		MOVEI	A,PRTTBL	;and look up form in table
11600		CALL	BINLUK
11700		SKIPGE	A		;did we find this form?
11800		 JRST	ADDFRM		;no - add it
11900		HRRZ	A,(A)		;yes - get value
12000		MOVE	T0,(A)
12100		POP	P,A		;restore output JFN
12200		RET
12300	ADDFRM:	MOVEI	A,2		;get block for new entry
12400		CALL	GETBLK
12500		 CALL	PRTMEM
12600		MOVEM	B,(A)		;save name
12700		MOVEM	T0,1(A)		;and default price
12800		HRLI	B,(A)		;set up pointer for adding entry
12900		HRRI	B,1(A)
13000		MOVEI	A,PRTTBL
13100		CALL	BINADD
13200		SKIPGE	A		;did add succeed
13300		 JRST	ADDERR		;no - give message
13400		HLRZ	C,(A)		;pointer to forms name
13500		MOVE	C,(C)		;forms name
13600		TMSG	<[ACCT20: Added printer form >
13700		MOVEI	A,.PRIOU	
13800		CALL	SIXOUT
13900		TMSG	< to forms table]
14000	>
14100		POP	P,A		;restore JFN
14200		RET
14300	ADDERR:	MOVEI	A,.PRIOU
14400		TMSG	<%ACCT20: attempt to add form >
14500		HLRZ	C,B
14600		MOVE	C,(C)
14700		CALL	SIXOUT
14800		TMSG	< failed
14900	>
15000		POP	P,A
15100		RET
     
00100	SUBTTL	DSKUSG - Routine to process disk usage records
00200	
00300	;DSKUSG - PROCESS disk usage record
00400		
00500	DSKUSG:	TXNN	F,F%DET
00600		 JRST	DSKSUM		;no
00700		TXNN	F,F%DDS		;want disk statistics?
00800		 JRST	DSKSUM		;no
00900		MOVE	B,4(Q1)		;get permanent quota
01000		ADDM	B,DETTOT+.SDSKP	;add to totals
01100		CALL	DETCMN		;yes
01200		MOVE	A,DETJFN
01300		MOVE	B,[TXT (STORAGE USED )]
01400		SETZB	C,D
01500		SOUT
01600		MOVE	B,1(Q1)		;page count
01700		ADDM	B,DETTOT+.SDSKU	;add to total
01800		MOVX	C,NO%LFL!NO%OOV!FLD(5,NO%COL)!FLD(12,NO%RDX)
01900		NOUT
02000		 CAI
02100		MOVE	B,[TXT( Pages  )]
02200		SETZB	C,D
02300		SOUT
02400		MOVE	B,2(Q1)		;file count
02500		MOVX	C,NO%LFL!NO%OOV!FLD(4,NO%COL)!FLD(12,NO%RDX)
02600		NOUT
02700		 CAI
02800		MOVE	B,[TXT( files on )]
02900		SETZB	C,D
03000		SOUT
03100		LOAD	B,SDULN		;get string 1 (structure name)
03200		HRRZI	B,.SDNAM(B)
03300		HRLI	B,(POINT 7,)
03400		MOVEI	C,^D12
03500		SETZ	D
03600		SOUT
03700		MOVE	B,[TXT(         )]
03800		SETZ	D,
03900		SKIPLE	C
04000		 SOUT
04100		FLTR	B,1(Q1)		;compute value
04200		FMPR	B,.PRDSS
04300		FADRM	B,DETTOT+.SVALU	;add to total
04400		MOVX	C,FL%ONE!FL%PNT!FL%DOL!FL%OVL!FLD(5,FL%FST)!FLD(2,FL%SND)
04500		FLOUT
04600		 CAI
04700		CALL	CRLF
04800	DSKSUM:	TXNN	F,F%SUM		;SUMMARY wanted?
04900		 RET			;no
05000		TXNN	F,F%SDS		;of disk usage?
05100		 RET			;no
05200		MOVE	P1,THSNOD	;yes - point to summary node for this user
05300		AOS	.SDSKC(P1)	;count this entry for averaging
05400		MOVE	B,4(Q1)		;logged out quota
05500		ADDM	B,.SDSKP(P1)	;add to summary
05600		MOVE	B,1(Q1)		;pages used
05700		ADDM	B,.SDSKU(P1)	;add to summary
05800		FLTR	B,B		;compute value
05900		FMPR	B,.PRDSS
06000		FADRM	B,.SVALU(P1)	;add to summary
06100		RET
     
00100	SUBTTL	SPNUSG - Routine to process spindle usage records
00200	
00300	;SPNUSG - PROCESS spindle usage record
00400	
00500	SPNUSG:	TMSG	<%ACCT20: SPINDLE usage record encountered - no code for processing
00600	>
00700		TXNN	F,F%DET		;details wanted?
00800		 JRST	SPNSUM		;no
00900		TXNN	F,F%DDS		;want disk statistics?
01000		 JRST	SPNSUM		;no
01100		CALL	DETCMN		;yes
01200		MOVE	A,DETJFN
01300		MOVE	B,[TXT (SPINDLE USAGE)]
01400		SETZB	C,D
01500		SOUT
01600		CALL	CRLF
01700	SPNSUM:	RET
     
00100	SUBTTL	STRMNT - Routine to process structure mount records
00200	
00300	;STRMNT - PROCESS structure mount record
00400	
00500	STRMNT:	TXNN	F,F%DET		;details wanted?
00600		 JRST	STRSUM		;no
00700		TXNN	F,F%DDS		;want disk statistics?
00800		 JRST	STRSUM		;no
00900		AOS	DETTOT+.SSTRM	;increment count in total block
01000		CALL	DETCMN		;yes
01100		MOVE	A,DETJFN
01200		MOVE	B,[TXT (STR MNT of )]
01300		SETZB	C,D
01400		SOUT
01500		MOVE	C,0(Q1)		;structure name
01600		CALL	SIXOUT		;print it
01700		MOVE	B,[TXT (  used for  )]
01800		SETZB	C,D
01900		SOUT
02000		FLTR	B,14(Q1)	;time used in internal units
02100		FDVRI	B,(3.)		;convert to sec
02200		FADRM	B,DETTOT+.SSTRT	;add to total
02300		FIXR	B,B		;back to integer for output
02400		MOVEI	D,2		;2 cols for hour field
02500		CALL	TIMOUT
02600		FLTR	B,B		;convert time to real
02700		FMPR	B,.PRSTU	;compute value
02800		FADR	B,.PRSTM	;add cost of mounting
02900		FADRM	B,DETTOT+.SVALU	;add to totals
03000		SPACE	^D14
03100		MOVX	C,FL%ONE!FL%DOL!FL%PNT!FL%OVL!FLD(5,FL%FST)!FLD(2,FL%SND)
03200		FLOUT
03300		 CAI
03400		CALL	CRLF
03500	STRSUM:	TXNN	F,F%SUM		;SUMMARY wanted?
03600		 RET			;no
03700		TXNN	F,F%SDS		;of disk?
03800		 RET			;no
03900		MOVE	P1,THSNOD	;yes - point to summary node for this user
04000		AOS	.SSTRM(P1)	;count this mount
04100		FLTR	B,14(Q1)	;get time used in internal units
04200		FDVRI	B,(3.)		;convert to seconds
04300		FADRM	B,.SSTRT(P1)	;add to summary
04400		FMPR	B,.PRSTU	;compute value
04500		FADR	B,.PRSTM	;add cost of mounting
04600		FADRM	B,.SVALU(P1)	;add to summary
04700		RET
     
00100	SUBTTL	MTAMNT - Routine to process magnetic tape mount records
00200	
00300	;MTAMNT - PROCESS tape mount record
00400	
00500	MTAMNT:
00600		IFN	MTABUG,<	SKIPGE	2(Q1)	;frames read
00700					 RET
00800					SKIPGE	3(Q1)	;frames written
00900					 RET
01000					SKIPGE	B,22(Q1)	;connect time
01100					 RET
01200					CAML	B,[100,,000000]
01300					 RET				>
01400		TXNN	F,F%DET		;details wanted?
01500		 JRST	MTASUM		;no
01600		TXNE	F,F%NMT		;magtape details turned off?
01700		 JRST	MTASUM		;yes
01800		TXNN	F,F%DTA		;want magtape statistics?
01900		 JRST	MTASUM		;no
02000		AOS	DETTOT+.SMTAM	;increment count of mounts
02100		CALL	DETCMN		;yes
02200		MOVE	A,DETJFN
02300		MOVE	B,[TXT (MTA MNT )]
02400		SETZB	C,D
02500		SOUT
02600		MOVE	C,0(Q1)		;VOLID
02700		CALL	SIXOUT
02800		MOVE	B,[TXT(  R=)]
02900		SETZB	C,D
03000		SOUT
03100		FLTR	B,2(Q1)		;frames read
03200		FADRM	B,DETTOT+.SMTAR	;add to total
03300		MOVX	C,FL%ONE!FL%OVL!FLD(.FLEXE,FL%EXP)!FLD(3,FL%FST)!FLD(3,FL%THD)
03400		FLOUT
03500		 CAI
03600		MOVEI	B," "		;note if hard errors occurred
03700		SKIPE	20(Q1)
03800		 MOVEI	B,"E"
03900		BOUT
04000		MOVE	B,[TXT(  W=)]
04100		SETZB	C,D
04200		SOUT
04300		FLTR	B,3(Q1)		;frames written
04400		FADRM	B,DETTOT+.SMTAW	;add to total
04500		MOVX	C,FL%ONE!FL%OVL!FLD(.FLEXE,FL%EXP)!FLD(3,FL%FST)!FLD(3,FL%THD)
04600		FLOUT
04700		 CAI
04800		MOVEI	B," "		;note hard write errors
04900		SKIPE	21(Q1)
05000		 MOVEI	B,"E"
05100		BOUT
05200		MOVE	B,[TXT( used )]
05300		SETZB	C,D
05400		SOUT
05500		FLTR	B,22(Q1)	;connect time to drive in internal units
05600		FDVRI	B,(3.)		;convert to seconds
05700		FADRM	B,DETTOT+.SMTAU	;add to totals
05800		PUSH	P,B		;save it temporarily
05900		FIXR	B,B		;back to integer
06000		MOVEI	D,1		;1 col expected for hour value
06100		CALL	TIMOUT		;output it
06200		POP	P,B		;compute value
06300		FMPR	B,.PRTPU
06400		FADR	B,.PRTPM	;add in cost of mounting
06500		FADRM	B,DETTOT+.SVALU	;add to total
06600		MOVX	C,FL%ONE!FL%PNT!FL%DOL!FL%OVL!FLD(5,FL%FST)!FLD(2,FL%SND)
06700		FLOUT
06800		 CAI
06900		CALL	CRLF
07000	MTASUM:	TXNN	F,F%SUM		;SUMMARY wanted?
07100		 RET			;no
07200		TXNN	F,F%STA		;of tape statistics?
07300		 RET			;no
07400		MOVE	P1,THSNOD	;yes - point to summary node for this user
07500		AOS	.SMTAM(P1)	;count this mount
07600		FLTR	B,22(Q1)	;time used in internal units
07700		FDVRI	B,(3.)		;convert to seconds
07800		FADRM	B,.SMTAU(P1)	;add to summary
07900		FMPR	B,.PRTPU	;compute value
08000		FADR	B,.PRTPM
08100		FADRM	B,.SVALU(P1)
08200		FLTR	B,2(Q1)		;frames read
08300		FADRM	B,.SMTAR(P1)	;add to summary
08400		FLTR	B,3(Q1)		;frames written
08500		FADRM	B,.SMTAW(P1)	;add to summary
08600		RET
     
00100	SUBTTL	FILRET - Routine to process file retrieval records
00200	
00300	;FILRET	- PROCESS file retrieval record
00400	
00500	FILRET:	TXNN	F,F%DET		;details wanted?
00600		 JRST	RETSUM		;no
00700		TXNN	F,F%DTA		;want magtape statistics?
00800		 JRST	RETSUM		;no
00900		CALL	DETCMN		;yes
01000		MOVE	A,DETJFN
01100		MOVE	B,[TXT (RETRIEVE)]
01200		SETZB	C,D
01300		SOUT
01400		MOVE	B,1(Q1)	;number of pages
01500		MOVX	C,NO%OOV!FLD(^D9,NO%COL)!FLD(12,NO%RDX)
01600		NOUT
01700		 CAI
01800		MOVE	B,[TXT( pages)]
01900		SETZB	C,D
02000		SOUT
02100		
02200		CALL	CRLF
02300	RETSUM:	RET
     
00100	SUBTTL	FILARC - Routine to process file archival records
00200	
00300	FILARC:	TXNN	F,F%DET		;details wanted?
00400		 JRST	ARCSUM		;no
00500		TXNN	F,F%DTA		;want magtape statistics?
00600		 JRST	ARCSUM		;no
00700		CALL	DETCMN		;yes
00800		MOVE	A,DETJFN
00900		MOVE	B,[TXT (ARCHIVE)]
01000		SETZB	C,D
01100		SOUT
01200		MOVE	B,1(Q1)	;number of pages
01300		MOVX	C,NO%OOV!FLD(^D9,NO%COL)!FLD(12,NO%RDX)
01400		NOUT
01500		 CAI
01600		MOVE	B,[TXT( pages)]
01700		SETZB	C,D
01800		SOUT
01900		
02000		CALL	CRLF
02100	ARCSUM:	RET
     
00100	SUBTTL	FILMIG - Routine to process file migration records
00200	
00300	FILMIG:	TXNN	F,F%DET		;details wanted?
00400		 JRST	MIGSUM		;no
00500		TXNN	F,F%DTA		;want magtape statistics?
00600		 JRST	MIGSUM		;no
00700		CALL	DETCMN		;yes
00800		MOVE	A,DETJFN
00900		MOVE	B,[TXT (MIGRATION)]
01000		SETZB	C,D
01100		SOUT
01200		MOVE	B,1(Q1)	;number of pages
01300		MOVX	C,NO%OOV!FLD(^D9,NO%COL)!FLD(12,NO%RDX)
01400		NOUT
01500		 CAI
01600		MOVE	B,[TXT( pages)]
01700		SETZB	C,D
01800		SOUT
01900		
02000		CALL	CRLF
02100	MIGSUM:	RET
     
00100	SUBTTL	FILCOL - Routine to process file collection records
00200	
00300	FILCOL:	TXNN	F,F%DET		;details wanted?
00400		 JRST	COLSUM		;no
00500		TXNN	F,F%DTA		;want magtape statistics?
00600		 JRST	COLSUM		;no
00700		CALL	DETCMN		;yes
00800		MOVE	A,DETJFN
00900		MOVE	B,[TXT (COLLECT)]
01000		SETZB	C,D
01100		SOUT
01200		MOVE	B,1(Q1)	;number of pages
01300		MOVX	C,NO%OOV!FLD(^D9,NO%COL)!FLD(12,NO%RDX)
01400		NOUT
01500		 CAI
01600		MOVE	B,[TXT( pages)]
01700		SETZB	C,D
01800		SOUT
01900		
02000		CALL	CRLF
02100	COLSUM:	RET
     
00100	SUBTTL	Routine to support record processing routines
00200	
00300	;DETCMN	- Writes out the common header for DETAIL listing
00400	
00500	DETCMN:	MOVE	A,DETJFN	;output to DETAIL file
00600		SOSG	DETLIN		;enough room on this page?
00700		 CALL	DETHDR		;no - generate new page
00800		LOAD	B,SDTAD		;get date/time of record
00900		SETZ	C,
01000		ODTIM			;and output it
01100		MOVEI	C,2		;leave spaces
01200		CALL	SPACES
01300		LOAD	B,SDJNO		;get job number
01400		JUMPE	B,D1		;operator?
01500		MOVX	C,NO%LFL!NO%OOV!FLD(3,NO%COL)!FLD(10,NO%RDX)
01600		NOUT
01700		 CAI
01800		JRST	D2
01900	D1:	MOVE	B,[TXT(OPR)]
02000		SETZB	C,D
02100		SOUT
02200	D2:	SPACE	2
02300	
02400		LOAD	B,SDLNO		;output line number
02500		HRRE	B,B		;if negative, do it right
02600		JUMPL	B,D3		;detached?
02700		MOVX	C,NO%LFL!NO%OOV!FLD(3,NO%COL)!FLD(8,NO%RDX)
02800		NOUT
02900		 CAI
03000		JRST	D4
03100	D3:	MOVE	B,[TXT(DET)]
03200		SETZB	C,D
03300		SOUT
03400	D4:	SPACE	3
03500		MOVE	B,USRPTR	;now output name of user
03600		MOVEI	C,^D40
03700	;	MOVEI	C,^D25		;output  only 25 chars for now
03800		SETZ	D,
03900		SOUT
04000		MOVE	B,[POINT 7,[ASCIZ/                                        /] ]
04100		SETZ	D,
04200		SKIPLE	C
04300		 SOUT			;complete a field of 40
04400		MOVEI	C,2
04500		CALL	SPACES
04600		RET
04700	
04800	CRLF:	MOVE	B,[POINT 7,[BYTE (7) .CHCRT,.CHLFD,.CHNUL] ]
04900		SETZB	C,D
05000		SOUT
05100		RET
05110	
05120	;	Routine to output spaces to destination designated in A
05200	SPACES:	SKIPN	C		;don't output if count = 0
05225		 RET
05250		MOVE	B,[POINT 7,[ASCIZ/                                                                                                                                                         /]]
05300		SETZ	D,
05400		SOUT
05500		RET
05600	;TIMOUT - outputs time in seconds as HH:MM:SS with zero fill as necess
05700	;	A/	JFN or pointer
05800	;	B/	Time to be written, in sec
05900	;	D/	Number of digits (minimum) to be written in hours field
06000	
06100	TIMOUT:	IDIVI	B,^D60
06200		PUSH	P,C		;save seconds
06300		IDIVI	B,^D60
06400		PUSH	P,C		;save minutes
06500		MOVX	C,NO%LFL!NO%OOV!FLD(^D10,NO%RDX)
06600		DPB	D,[POINT 7,C,17]	;copy # of cols from arg
06700		NOUT
06800		 CAI
06900		MOVEI	B,":"
07000		BOUT
07100		POP	P,B		;retrieve minutes
07200		MOVX	C,NO%LFL!NO%ZRO!NO%OOV!FLD(2,NO%COL)!FLD(^D10,NO%RDX)
07300		NOUT
07400		 CAI
07500		MOVEI	B,":"
07600		BOUT
07700		POP	P,B		;retrieve minutes
07800		MOVX	C,NO%LFL!NO%ZRO!NO%OOV!FLD(2,NO%COL)!FLD(^D10,NO%RDX)
07900		NOUT
08000		 CAI
08100		RET
08200	
08300	DETHDR:	MOVEI	B,.CHFFD	;new page
08400		BOUT
08500	DHDR1:	MOVE	B,[TXT<Date-time of entry  Job  Line  User>]
08600		SETZB	C,D
08700		SOUT
08800		SPACE	<^D37>
08900		MOVE	B,[TXT<Type  Activity description>]
09000		SETZB	C,D
09100		SOUT
09200		SPACE	<^D28>
09300		MOVE	B,[TXT<Value>]
09400		SETZB	C,D
09500		SOUT
09600		MOVEI	B,.CHCRT	;return only - no line feed
09700		BOUT
09800		MOVE	B,[TXT<__________________  ___  ____  _______________________________________  ____  _____________________________________________  _______>]
09900		SETZB	C,D
10000		SOUT
10100		CALL	CRLF
10200		MOVEI	B,DETPAG-2	;reset line counter
10300		MOVEM	B,DETLIN
10400		RET
10500	
10600	;VEROUT - output standard DEC version number 
10700	;	A/	destination pointer
10800	;	B/	Version word
10900	;
11000	VEROUT:	STKVAR	<VERX>
11100		MOVEM	B,VERX		;save version word
11200		LDB	B,[POINT	9,VERX,11]	;major version
11300		MOVEI	C,10		;octal
11400		NOUT
11500		 CALL	TJSMSG
11600		LDB	B,[POINT 6,VERX,17]	;minor version
11700		JUMPE	B,VR1OUT		;skip if none
11800		SUBI	B,1		;normalize
11900		IDIVI	B,^D26		;mod 26
12000		SKIPE	B		;two digits?
12100		 CALL	[ADDI	B,"A"-1(B)
12200			 BOUT		;output first
12300			 RET]
12400		
12500		MOVEI	B,"A"(C)	;second digit (or maybe first)
12600		BOUT
12700	VR1OUT:	MOVEI	B,"("
12800		BOUT
12900		HRRZ	B,VERX		;edit number
13000		MOVEI	C,10		;octal
13100		NOUT
13200		 CALL	TJSMSG
13300		MOVEI	B,")"
13400		BOUT
13500		LDB	B,[POINT 3,VERX,2]	;last edit
13600		JUMPE	B,R		;none
13700		PUSH	P,B		;save temp
13800		MOVEI	B,"-"		; to make room for "-"
13900		BOUT
14000		POP	P,B
14100		ADDI	B,"0"
14200		BOUT
14300		RET
14400	
14500	
14600	TJSMSG:	PUSH	P,A
14700		JSERR
14800		POP	P,A
14900		RET
     
00100	SUBTTL	DETAIL command processing
00200	.DET:	NOISE	<use of resources>
00300		MOVEI	A,[FLDDB. .CMKEY,,DETOPT]
00400		CALL	RFIELD
00500		TXO	F,F%DETT	;flag as processing DETAIL option
00600		TXZ	F,F%SUMT
00700		HRRZ	A,(B)
00800		CALL	@A		;dispatch to handle specific request
00900		SKIPN	A,DETJFN	;is the output file open?
01000		 JRST	DET1		;no - go ahead with open
01100		CLOSF			;yes - close first
01200		 JRST	[ERMSG <%ACCT20: Can't close open DETAILS listing file>
01300			 JRST	DET2]
01400	DET1:	MOVE	A,[POINT 7,TMPBLK]	;create filename
01500		MOVE	B,[POINT 7,DETNAM]	;use user name
01600		SKIPN	DETNAM			;unless null
01700		 MOVE	B,[TXT <ACCT20>]
01800		HRLZI	C,-^D35		;leave room for ".LPT"
01900	DLUP:	ILDB	D,B		;get a char
02000		JUMPE	D,DLPEND	;terminate on null
02100		CAIN	D,"*"		;or "*"
02200		 JRST	DLPEND
02300		CAIN	D,"%"		;or "%"
02400		 JRST	DLPEND
02500		CAIE	D,"."
02600		 JRST	DLOUT
02700		MOVEI	D,.CHCNV	;CNTL-V OUT
02800		IDPB	D,A
02900		ADD	[1000001]	;record the extra char
03000		MOVEI	D,"."
03100	DLOUT:	IDPB	D,A
03200		AOBJN	C,DLUP
03300	DLPEND:
03400		MOVE	B,[TXT<.LPT>]	;complete the filename
03500		SETZB	C,D
03600		SOUT
03700		MOVE	A,[GJ%FOU!GJ%SHT]	;open up a new file
03800		MOVE	B,[POINT 7,TMPBLK]
03900		GTJFN
04000		 JRST	[TMSG	<%ACCT20: Can't get DETAIL output JFN>
04100			 JSERR
04200			 RET]
04300		MOVEM	A,DETJFN
04400		MOVX	B,FLD(7,OF%BSZ)!OF%WR
04500		OPENF
04600		 JRST	[TMSG	<%ACCT20: Can't open DETAIL output file>
04700			 JSERR
04800			 RET]
04900	DET2:	HRRZ	A,DETJFN	;output header for details listing
05000		SPACE	^D10
05100		MOVE	B,[POINT 7,SYSNAM]
05200		SETZB	C,D
05300		SOUT
05400		CALL	CRLF
05500		SPACE	<^D47>
05600		MOVE	B,[TXT<DECSYSTEM-20 Usage Report>]
05700		SETZB	C,D
05800		SOUT
05900		CALL	CRLF
06000		CALL	CRLF
06100		SPACE	<^D39>
06200		MOVE	B,[TXT<Report generated on >]
06300		SETZB	C,D
06400		SOUT
06500		SETO	B,
06600		SETZ	C,
06700		ODTIM
06800		CALL	CRLF
06900		CALL	CRLF
07000		CALL	CRLF
07100		CALL	DHDR1
07200		MOVEI	B,DETPAG-^D9
07300		MOVEM	B,DETLIN
07400	
07500		TXZ	F,F%DETT	;Turn off temp flag
07600		RET
07700	
07800	DETOPT:	XWD	DETEND-.-1,DETEND-.-1
07900		T	CPU-USE,.CPU
08000		T	DISK-USE,.DSK
08100		T	INPUT-SPOOLER,.INP
08200		T	NONE,.NON
08300		T	OUTPUT-SPOOLERS,.OUT
08400		T	SYSTEM-USE,.SYS
08500		T	TAPE-USE,.TAP
08600		T	TTY-USE,.TTY
08700		DETEND==.
08800	
08900	.CPU:	TXNN	F,F%DETT	;DETAIL or SUM option?
09000		TXOA	F,F%SCP		;SUM
09100		 TXO	F,F%DCP		;DETAIL
09200		JRST	USRNAM		;get user name 
09300	
09400	.DSK:	TXNN	F,F%DETT	;DETAIL or SUM option?
09500		TXOA	F,F%SDS		;SUM
09600		 TXO	F,F%DDS		;DETAIL
09700		JRST	USRNAM		;get user name 
09800	
09900	.NON:	CONFRM
10000		MOVE	A,DETJFN	;Close DETAIL file...?
10100		TXNE	F,F%SUMT	;... or should we close SUM file?
10200		 MOVE	A,SUMJFN	;make that the SUM file
10300		CLOSF
10400		 JRST	[TMSG	<%Can't close the SUMMARIZE or DETAIL JFN>
10500			 JSERR
10600			 RET]
10700		MOVEI	A,DETJFN	;say it's closed in any case 
10800		TXNE	F,F%SUMT	; .. but which one?
10900		 MOVEI	A,SUMJFN
11000		SETZM	(A)		;whichever
11100		TXZ	F,F%SUMT!F%DETT	;turn off temp switches
11200		SUB	P,[1,,1]	;NOTE WELL - does not return to caller
11300					;but to caller's caller!
11400		RET
11500		RET
11600	
11700	.INP:	TXNN	F,F%DETT	;DETAIL or SUM option?
11800		 TXOA	F,F%SIN		;SUM
11900		  TXO	F,F%DIN		;DETAIL
12000		JRST	USRNAM		;get user name
12100	
12200	
12300	.OUT:	TXNN	F,F%DETT	;DETAIL or SUM option?
12400		 TXOA	F,F%SOU		;SUM
12500		  TXO	F,F%DOU		;DETAIL
12600		JRST	USRNAM		;get user name
12700	
12800	.SYS:	TXNN	F,F%DETT	;DETAIL or SUM option?
12900		TXOA	F,F%SAL		;SUM
13000		TXO	F,F%DAL		;DETAIL
13100		JRST	USRNAM		;get user name
13200	
13300	.TAP:	TXNN	F,F%DETT	;DETAIL or SUM option?
13400		TXOA	F,F%STA		;SUM
13500		 TXO	F,F%DTA		;DETAIL
13600		JRST	USRNAM		;get user name
13700	
13800	.TTY:	TXNN	F,F%DETT	;DETAIL or SUM option?
13900		TXOA	F,F%STT		;SUM
14000		 TXO	F,F%DTT		;DETAIL
14100		JRST	USRNAM		;get user name
14200	
14300	USRNAM:	NOISE	<by user>
14400		MOVE	A,SBK+.CMFLG	;turn off lowercase for names
14500		TXO	A,CM%RAI
14600		MOVEM	A,SBK+.CMFLG
14700		MOVEI	A,[FLDDB. .CMTXT,,,Directory/account string]
14800		CALL	CFIELD
14900		MOVE	A,SBK+.CMFLG		;restore lowercase input
15000		TXZ	A,CM%RAI
15100		MOVEM	A,SBK+.CMFLG
15200		MOVE	A,[POINT 7,DETNAM]	;assume DETAIL option is on
15300		TXNE	F,F%SUMT	;Was it?
15400		 MOVE	A,[POINT 7,SUMNAM]	;No - SUMMARIZE was
15500		MOVE	B,[POINT 7,ATMBUF]
15600		SETZB	C,D
15700		SOUT			;copy user name
15800		RET
15900	DETPRC:	MOVE	A,DETLIN	;get lines left on page
16000		CAILE	A,^D8		;need 8 lines for totals
16100		 JRST	DPRC1
16200		MOVE	A,DETJFN	;don't have them - start a new page
16300		MOVEI	B,.CHFFD
16400		BOUT
16500		MOVEI	A,DETPAG
16600	DPRC1:	MOVEM	A,SUMLIN	;fake a summary heading
16700		MOVE	A,DETTOT+.SVALU	;round to cents
16800		FMPRI	A,(100.)
16900		FIXR	A,A
17000		FLTR	A,A
17100		FDVRI	A,(100.)
17200		MOVEM	A,DETTOT+.SVALU
17300		MOVEI	P1,DETTOT	;use the node for details totals
17400		MOVEI	Q1,D1TOT	; dummy node for summing to
17500		MOVE	A,DETJFN	;output to details file
17600		CALL	CRLF
17700		CALL	CRLF
17800		CALL	SHDR1		;write it
17900		CALL	S1OUT
18000		MOVE	P2,[POINT 7,DETNAM]	;is this user commercial?
18100		MOVEI	P1,BILPTR
18200		CALL	FNDNOD
18300		 RET				;no - done with totals
18400		MOVE	B,..BILN-1(P1)	;[1] get flag
18500		TXNN	B,BL%COM		;commercial user?
18600		 RET				;no - don't tax
18700		MOVE	A,DETJFN
18800		SPACE	<^D120>
18900		MOVE	B,[TXT <TAX>]
19000		SETZB	C,D
19100		SOUT
19200		MOVE	B,DETTOT+.SVALU		;compute tax
19300		FMPR	B,.PRTAX
19400		FMPRI	B,(100.)
19500		FIXR	B,B
19600		FLTR	B,B
19700		FDVRI	B,(100.)
19800		FDVRI	B,(100.)
19900		PUSH	P,B			;save it
20000		MOVX	C,FL%ONE!FL%DOL!FL%PNT!FL%OVL!FLD(5,FL%FST)!FLD(2,FL%SND)
20100		FLOUT
20200		 CAI
20300		CALL	CRLF
20400		SPACE	<^D110>
20500		MOVE	B,[TXT<Grand Total>]
20600		SETZB	C,D
20700		SOUT
20800		SPACE	2
20900		POP	P,B		;retrieve tax
21000		FADR	B,DETTOT+.SVALU	;add cost
21100		MOVX	C,FL%ONE!FL%DOL!FL%PNT!FL%OVL!FLD(5,FL%FST)!FLD(2,FL%SND)
21200		FLOUT
21300		 CAI
21400		CALL	CRLF
21500		RET
     
00100	SUBTTL	SUMMARIZE command processing
00200	.SUM:	NOISE	<use of resources>
00300		MOVEI	A,[FLDDB. .CMKEY,,DETOPT]
00400		CALL	RFIELD
00500		TXO	F,F%SUMT	;flag as summary processing
00600		TXZ	F,F%DETT
00700		HRRZ	A,(B)
00800		CALL	@A
00900		SKIPE	SUMJFN			;is the output file open?
01000		 JRST	SUM1			;yes - just turn on switches
01100		MOVE	B,[TXT<ACCT20>]		;assume standard name
01200		TXNE	F,F%NAM			;was a default name given?
01300		 MOVE	B,[POINT 7,NAMES]	;yes.  Use it
01400		MOVE	A,[POINT 7,TMPBLK]	;copy into temp area
01500		SETZB	C,D
01600		SOUT
01700		MOVE	B,[TXT<-SUMMARY.LST>]	;complete the filename
01800		SETZB	C,D
01900		SOUT
02000		MOVE	A,[GJ%FOU!GJ%SHT]	;open up a new file
02100		MOVE	B,[POINT 7,TMPBLK]
02200		GTJFN
02300		 JRST	[TMSG	<%ACCT20: Can't get SUMMARY output JFN>
02400			 JSERR
02500			 RET]
02600		MOVEM	A,SUMJFN
02700		MOVX	B,FLD(7,OF%BSZ)!OF%WR
02800		OPENF
02900		 JRST	[TMSG	<%ACCT20: Can't open SUMMARY output file>
03000			 JSERR
03100			 RET]
03200	SUM1:	TXZ	F,F%SUMT
03300		RET
     
00100	SUBTTL	PRINTER-CHARGES command processing
00200	.PRI:	NOISE	<from file>
00300		MOVEI	A,[FLDDB. .CMIFI,CM%DPP,,,DSK:ACCT20.PCG.0]
00400		CALL	CFIELD		;Get filename and confirm
00500		HRLM	B,SBK+.CMIOJ	;And tell CMD macros where to look
00600		MOVE	A,B		;Now open file
00700		MOVEM	A,FILJFN	;Save JFN for closing
00800		PUSH	P,A		;Save JFN for OPENF
00900		DVCHR			;is it a TTY?
01000		LSH	b,-^D18
01100		ANDI	B,777
01200		CAIN	B,.DVTTY
01300		 TXO	F,F%TTIN	;yes
01400		POP	P,A
01500		MOVX	B,FLD(7,OF%BSZ)!FLD(.GSNRM,OF%MOD)!OF%RD
01600		OPENF
01700		 JRST	[TMSG <?ACCT20 can't open printer charges file>
01800			 HRRI	A,.PRIIN
01900			 HRLM	A,SBK+.CMIOJ	;reset command macros input
02000			 TXZ	F,F%TTIN	;and turn off tty input mode
02100			 RET]
02200		TXO	F,F%PCG		;Remember switch for processing
02300	
02400	PRTLUP:	MOVEI	A,2		;need two words for table entry
02500		CALL	GETBLK		;get a memory block
02600		 JRST	PRTMEM		;none available!
02700		MOVE	P1,A		;save pointer to block
02800		HRROI	A,[ASCIZ/ACCT20 Printer charge> /]
02900		TXNE	F,F%TTIN	;reading from TTY?
03000		 CALL	DPROMP		;yes - do prompt
03100		MOVE	A,SBK+.CMFLG	;turn off indirecting, lowercase
03200		TXO	A,CM%RAI!CM%XIF
03300		MOVEM	A,SBK+.CMFLG
03400		MOVEI	A,[FLDDB. .CMFLD,CM%SDH,,<forms type and value>]
03500		CALL	RFIELD		;get forms type
03600		MOVE	A,SBK+.CMABP	;get pointer to atom buffer
03700		CALL	ASCSIX		;convert to SIXBIT
03800		CAMN	A,[SIXBIT/PRTEND/]	;all done?
03900		 JRST	PREXIT		;yes
04000		MOVEM	A,(P1)		;save sixbit name in entry
04100		MOVEI	A,[FLDDB. .CMFLT]	;get value
04200		CALL	CFIELD		; of price per page
04300		MOVEM	B,1(P1)		;and save in entry
04400		HRLI	B,(P1)		;create entry form for BINTAB
04500		HRRI	B,1(P1)
04600		MOVEI	A,PRTTBL	;get header address
04700		CALL	BINADD		;add entry
04800		SKIPL	A		;error condition?
04900		 JRST	PRTLUP		;no - see if we continue
05000		HLRE	B,A		;yes - which kind
05100		CAMN	B,[-1]		;table full?
05200		 JRST	PRTBFL		;yes
05300		CAMN	B,[-2]		;previous entry?
05400		 JRST	PRMUNT		;yes
05500		TMSG	<?ACCT20 Printer charges: undiagnosed error in table entry>
05600		JRST	PREXIT
05700	
05800	PRTBFL:	TMSG	<%ACCT20 Printer charges: forms table is full
05900	>
06000		TMSG	<  FORM >
06100		MOVE	C,(P1)
06200		MOVEI	A,.PRIOU
06300		CALL	SIXOUT
06400		TMSG	< was not entered into table.
06500	>
06600		JRST	PRTLUP
06700	
06800	PRMUNT:	TMSG	<[ACCT20 Printer charges: multiple entries for forms type >
06900		MOVE	C,(P1)
07000		MOVEI	A,.PRIOU
07100		CALL	SIXOUT
07200		TMSG	<]
07300	>
07400		JRST	PRTLUP
07500	
07600	PREXIT:	MOVE	A,SBK+.CMFLG	;turn on indirecting, lowercase again
07700		TXZ	A,CM%RAI!CM%XIF
07800		MOVEM	A,SBK+.CMFLG
07900		HRRI	A,.PRIIN	;go back to primary input
08000		HRLM	A,SBK+.CMIOJ
08100		TXZ	F,F%TTIN
08200	;	POP	P,A			;pop out of printer charges loop
08300		MOVE	A,FILJFN	;close file
08400		CLOSF
08500		 JRST	[TMSG	<%ACCT20: Can't close PRINTER-CHARGES file>
08600			 JSERR
08700			 RET]
08800		RET
08900	
09000	PRTMEM:	TMSG	<%ACCT20 Printer charges: insufficient memory for entry>
09100		TMSG	<  Processing of printer charges terminated.>
09200		RET
09300	;
09400	;	This routine just writes out six SIXBIT characters
09500	;
09600	SIXOUT:	MOVE	D,[POINT 6,C]
09700		ILDB	B,D
09800		ADDI	B," "
09900		BOUT
10000		ILDB	B,D
10100		ADDI	B," "
10200		BOUT
10300		ILDB	B,D
10400		ADDI	B," "
10500		BOUT
10600		ILDB	B,D
10700		ADDI	B," "
10800		BOUT
10900		ILDB	B,D
11000		ADDI	B," "
11100		BOUT
11200		ILDB	B,D
11300		ADDI	B," "
11400		BOUT
11500		RET
11600	
11700	
11800	;	This routine converts a string of at most 6 characters into
11900	;	a single SIXBIT word
12000	;
12100	ASCSIX:	PUSH	P,P1		;do 6 characters at most
12200		HRLZI	P1,-6
12300		SETZ	D,
12400		MOVE	B,[POINT 6,D]
12500	ASLUP:	ILDB	C,A		;get an input char
12600		SKIPN	C		;null?
12700		 JRST	ASEXIT		;yes
12800		CAIL	C,140		;lower case?
12900		 SUBI	C,40		;yes - get it into range
13000		ADDI	C,40
13100		IDPB	C,B
13200		AOBJN	P1,ASLUP
13300	ASEXIT:	POP	P,P1
13400		MOVE	A,D		;leave result in A
13500		RET
13600	
     
00100	SUBTTL	REPORT command processing
00200	.REP:	NOISE	<by>
00300		MOVEI	A,[FLDDB. .CMKEY,,REPTAB]
00400		CALL	CFIELD
00500		HRRZ	A,(B)
00600		CALL	@A
00700		RET
00800	
00900	REPTAB:	XWD	RPTBLN-.-1,RPTBLN-.-1
01000		T	ACCOUNT,.ARP
01100		T	DIRECTORY,.DRP
01200		RPTBLN==.
01300	
01400	.ARP:	TXO	F,F%RPT		;Flag on for report by account string
01500		RET
01600	
01700	.DRP:	TXZ	F,F%RPT		;Flag off for report by directory
01800		RET
     
00100	SUBTTL	REPROCESS command processing
00200	
00300	;[3]	This is a new command in version 2.
00400	;	It generates an unbalanced summary tree internally and
00500	;	then processes it through the SUMMARY and CATEGORY
00600	;	command processing sequence.
00700	
00800	.RPR:	NOISE	<from binary summary file named>
00802		MOVE	A,CJFNBK+.GJGEN	;set up conditions for file
00804		TXZ	A,GJ%FOU!GJ%IFG	;not an output file, no wildcards
00806		TXO	A,GJ%OLD	;must be an old file
00808		MOVEM	A,CJFNBK+.GJGEN
00810		MOVE	A,[POINT 7,[ASCIZ/BIN/]]	;default ext is .BIN
00820		MOVEM	A,CJFNBK+.GJEXT
00900		MOVEI	A,[FLDDB. .CMFIL]
01000		CALL	CFIELD
01100		MOVEM	B,RPRJFN	;save the JFN
01200		MOVE	A,B		;open the file in word mode for reading
01300		MOVX	B,FLD(44,OF%BSZ)!OF%HER!OF%RD
01400		OPENF
01500		 JRST	[TMSG	<%ACCT20: Can't open reprocessing file>
01600			 RET	]
01700		TMSG	<[ACCT20: Reprocessing file with header word >
01800		MOVE	A,RPRJFN	;get header word
01900		BIN
02000		 ERJMP	RPREOF		;warn of unexpected EOF & quit
02100		MOVE	C,B		;output the header name
02200		MOVEI	A,.PRIOU
02300		CALL	SIXOUT
02400		TMSG	<
02500		Created by ACCT20 version >
02600		MOVE	A,RPRJFN
02700		BIN
02800		 ERJMP	RPREOF
02900		MOVEI	A,.PRIOU
03000		CALL	VEROUT
03010		GTAD		;set up first/last entry time for DUMP if
03020				;necessary
03030		SKIPN	FSTTAD	;is earliest-entry time set?
03040		 MOVEM	A,FSTTAD	;no - must be earlier than present time,
03050				;though, so init it to now
03075		MOVEI	A,.PRIOU
03100		TMSG	<
03200		Contains entries starting at >
03300		MOVE	A,RPRJFN
03400		BIN
03500		 ERJMP	RPREOF
03510		CAMG	B,FSTTAD	;is earliest entry in file earlier than any
03520				;entries previously recorded?
03530		 MOVEM	B,FSTTAD	;yes - record it
03600		MOVEI	A,.PRIOU
03700		SETZ	C,
03800		ODTIM			;output earliest date in file
03900		TMSG	<
04000			and ending at >
04100		MOVE	A,RPRJFN
04200		BIN
04300		 ERJMP	RPREOF
04350		CAML	B,LSTTAD	;is latest entry in file later than any
04375				;entries previously recorded?
04387		MOVEM	B,LSTTAD	;yes - record it
04400		MOVEI	A,.PRIOU
04500		SETZ	C,
04600		ODTIM			;output last date in file
04700		TMSG	<]
04800	
04900	>
05000	
05100	RPRENT:	MOVE	A,RPRJFN	;loop over all entries in file
05200		BIN			;get header for next record
05300		 ERJMP	RPRPRC		;no more records -- go process
05400		MOVEM	B,BUFF		;save header
05500		MOVNI	C,(B)		;negative of count of words to read
05600		MOVE	B,[POINT 36,BUFF+1]  ;where to store string
05700		SIN			;read in the string
05800		 ERJMP	RPRERR		;if EOF, warn and then process
05900		MOVEI	P1,SUMPTR	;look up user in summary tree
06000		HLRZ	P2,BUFF		;fixed-length - 2 (2 overhead)
06100		HRLI	P1,.SREFS(P2)	;fixed-length,,sumptr
06200		MOVE	P2,[POINT 7,BUFF+1];  what to look up
06300		HRRZ	P3,BUFF		;variable length size
06400		CALL	GETNOD		;find it
06500		SKIPN	P1
06600		 JRST	[TMSG	<?ACCT20:  Insufficient memory to create summary tree.
06700		Reprocessing terminated.
06800	>
06900		RET]
07000		MOVE	A,RPRJFN	;read in the rest of the entry
07050					;into BUFF with correct offset locs
07300		MOVEI	B,.SREFS+BUFF	;now read in rest of data part
07400		HRLI	B,(POINT 36,)	;point to data part of node
07500		HLR	C,BUFF		;negative data word count into C
07600		MOVNI	C,(C)		;fixed-part count 
07700		SIN			;read it
07800		 ERJMP	RPRERR		;if error, warn then finish
07802	
07804	;	Now update the selected node with the data from this entry
07806	
07808		MOVE	A,.STSES+BUFF	;add in the count of timesharing sess
07810		ADDM	A,.STSES(P1)
07812		MOVE	A,.STCPU+BUFF	;add in CPU secs under timesharing
07814		FADRM	A,.STCPU(P1)
07816		MOVE	A,.STCON+BUFF	;connect time in real secs
07818		FADRM	A,.STCON(P1)
07820		MOVE	A,.SBSES+BUFF	;batch session counts
07822		ADDM	A,.SBSES(P1)
07824		MOVE	A,.SBCPU+BUFF	;batch CPU time as real secs
07826		FADRM	A,.SBCPU(P1)
07828		MOVE	A,.SBCON+BUFF	;batch connect time as real secs
07830		FADRM	A,.SBCON(P1)
07832		MOVE	A,.SCDRR+BUFF	;cards read
07834		ADDM	A,.SCDRR(P1)
07836		MOVE	A,.SLPTW+BUFF	;pages printed
07838		ADDM	A,.SLPTW(P1)
07840		MOVE	A,.SPLTM+BUFF	;plotter minutes
07842		ADDM	A,.SPLTM(P1)
07844		MOVE	A,.SDSKU+BUFF	;disk space used (as avg # pages)
07846		ADDM	A,.SDSKU(P1)
07848		MOVE	A,.SMTAM+BUFF	;mag tape mount count
07850		ADDM	A,.SMTAM(P1)
07852		MOVE	A,.SMTAU+BUFF	;mag tape time used in real secs
07854		FADRM	A,.SMTAU(P1)
07856		MOVE	A,.SVALU+BUFF	;value of services
07858		FADRM	A,.SVALU(P1)
07900		JRST	RPRENT		;now get next record
08000	
08100	RPRPRC:	RET			;[8] all done reprocessing binary file
09200	
09300	RPREOF:	TMSG	<%ACCT20:  Unexpected EOF attempting to read header.
09400		Reprocessing aborted.
09500	>
09600		RET
09700	
09800	RPRERR:	TMSG	<%ACCT20:  Unexpected EOF attempting to read summary record.
09900		Processing terminated.
10000	>
10100		JRST	RPRPRC
     
00100	SUBTTL	RESET command processing
00200	.RES:	CONFRM
00300		SETO	A,
00400		CLOSF			;Close all open files
00500		 ERMSG	<%ACCT20:	Can't close open files in RESET>
00600		RESET
00700		MOVE	T0,MEM0		;get free memory from startup
00800		MOVEM	T0,.JBFF	;and reset start of heap
00900		SETZ	A,		;reset flags for things we keep around
01000		TXNE	F,F%DEB
01100		 TXO	A,F%DEB
01200		TXNE	F,F%STS
01300		 TXO	A,F%STS
01400		TXNE	F,F%RPT
01500		 TXO	A,F%RPT
01600		MOVE	F,A
01700		SETZM	ZSTART		;Zero pointers and counters
01800		MOVE	A,[ZSTART,,ZSTART+1]
01900		BLT	A,ZEND
02000		MOVE	A,[TXT<***TOTALS***>]	;and reset non-zero parts
02100		MOVEM	A,TOTNOD
02200		MOVEM	A,DETTOT
02300		MOVE	A,[XWD 0,PTTBLN]
02400		MOVEM	A,PRTTBL
02500		MOVE	A,[XWD 0,SHFMAX]
02600		MOVEM	A,SHFTBL
02700		POP	P,A		;forget we were called
02800		JRST	LOOP		;and start again
     
00100	SUBTTL	WRITE-DETAIL-BINARY command processing
00200	.WDB:	NOISE	<to file>
00300		MOVE	A,CJFNBK+.GJGEN
00400		TXO	A,GJ%FOU		;set up output file
00500		TXZ	A,GJ%OLD!GJ%IFG
00600		MOVEM	A,CJFNBK+.GJGEN
00700		MOVE	B,[TXT<ACCT20>]		;assume ACCT20 name prefix
00800		TXNE	F,F%NAM			;was a default name given?
00900		 MOVE	B,[POINT 7,NAMES]	;yes - use that one
01000		MOVE	A,[POINT 7,TMPBLK]	;copy in prefix
01100		SETZB	C,D
01200		SOUT
01300		MOVE	B,[TXT<-DETAILS>]
01400		SETZB	C,D
01500		SOUT
01600		MOVE	A,[POINT 7,TMPBLK]	;now make CMD routines use this
01700		MOVEM	A,CJFNBK+.GJNAM
01800		MOVE	A,[TXT<BIN>]
01900		MOVEM	A,CJFNBK+.GJEXT		;set up default extention
02000		MOVEI	A,[FLDDB. .CMFIL]	;now go get file name
02100		CALL	CFIELD
02200		MOVEM	B,BINJFN
02300		MOVE	A,B
02400		MOVX	B,FLD(44,OF%BSZ)!OF%WR
02500		OPENF
02600		 JRST	[TMSG <%ACCT20:	Can't open file >
02700			 HRRZ	B,BINJFN
02800			 MOVEI	A,.PRIOU
02900			 SETZ	C,
03000			 JFNS
03100			 JSERR
03200			 TMSG	<
03300		No DETAIL binary file will be written
03400	>
03500			 RET]
03600		TXO	F,F%BIN
03700		RET
     
00100	SUBTTL	Storage
00200	PDL:	BLOCK	PDLEN		;Stack
00300	BUFF:	BLOCK	BUFLEN		;Buffer for SYSTEM-DATA.BIN entries
00400		CMDSTG			;Storage block for COMND JSYS
00500	MEM0:	BLOCK	1		;Initial start of free memory
00600	SYSNAM:	BLOCK	^D40		;Storage for system name string
00700	
00800	;PRICES FOR RESOURCES IN STANDARD UNITS
00900	PRTABL:	XWD	PRTABL+1,PREND
01000	.PRCRD:	.0040		;.40 CENT PER CARD
01100	.PRCON:	.00011111		;CONNECT TIME /SEC
01200	.PRCOR:	0.		;CORE OCCUPANCY /KCS
01300	.PRCPU:	0.045		;CPU TIME /SEC
01400	.PRDSA:	0.		;DISK ALLOCATION /PAGE /MONTH
01500	.PRDSS:	.05		;DISK STORAGE /PAGE /MONTH
01600	.PRDSR:	.0		;DISK READ /PAGE
01700	.PRDSW:	.0		;DISK WRITE /PAGE
01800	.PRPGS:	.02		;PAGES PRINTED /PAGE
01900	.PRPLT:	.10		;MINUTES USED
02000	.PRSTM:	0.		;STRUCTURE MOUNT
02100	.PRSTU:	0.		;STRUCTURE USAGE /SEC
02200	.PRTAX:	3.5		;Tax rate in %
02300	.PRTPM:	.5		;TAPE MOUNT
02400	.PRTPU:	.003333		;TAPE USAGE /SEC
02500	.PRTTI:	0.		;TTY CHARS IN
02600	.PRTTO:	0.		;TTY CHARS OUT
02700	.PRWKN:	1.4		;Multiplier to get weekend commercial rates from
02800				; base non-profit rates
02900	PREND==.
03000	
03100	
03200	ZSTART:		;** EVERYTHING FROM HERE ON IS ZEROED ON RESET **
03300	PRTTBL:	XWD	0,PTTBLN	;Table of prices for special printer
03400		BLOCK	PTTBLN		; forms
03500	SHFTBL:	XWD	0,SHFMAX	;Shift table for charge rates
03600		BLOCK	SHFMAX
03700	SUMNAM:	BLOCK	10		;storage for name for SUMMARIZE option
03800	DETNAM:	BLOCK	10		;storage for name for DETAIL option
03900	BILNAM:	BLOCK	10		;storage for name for CHARGE BILL option
04000	NAMES:	BLOCK	10		;storage for default names
04100	BILLEN:	Z			;length of BILL name
04200	SUMJFN:	Z			;JFN of summary output file
04300	DETJFN:	Z			;JFN of detail output file
04400	FILJFN:	Z			;JFN for general I/O
04500	PROJFN:	Z			;JFN for input file processing
04600	BINJFN:	Z			;JFN for WRITE-DETAILS processing
04700	DMPJFN:	Z			;JFN for DUMP processing
04800	CATJFN:	Z			;JFN for CATEGORIZE processing
04900	FRMJFN:	Z			;JFN for FORMS usage recording
05000	LSCJFN:	Z			;JFN for listing category file in
05100					;database format (no headings)
05200	LSSJFN:	Z			;JFN for listing summary file in
05300					;database format (no headings)
05400	RPRJFN:	Z			;JFN for REPROCESS command
05500	USRPTR:	Z			;Pointer to name of user in record buffer
05550	NXTLNK:	Z			;Pointer to tree for reordering wildcards
05575	FRSTLK:	BLOCK	2		;Linked list for wildcard node reordering
05600	NAMLEN:	Z			;Length of name of user
05700	SUMPTR:	z			;Pointer to summary tree
05800	BILPTR:	Z			;pointer to BILL tree
05900	DETPTR:	Z			;Pointer for tree of users written to
06000					; DETAILS file
06100	THSNOD:	Z			;Pointer for current node being processed
06200	PCGPRT:	Z			;Pointer to list for printer charges
06300	TTYPTR:	Z			;Pointer to list of TTY's to process
06400	TAPPTR:	Z			;Pointer to list of tape drives/volids
06500	CATPTR:	Z			;Pointer to category table
06600	USGPTR:	Z			;Pointer to directory name tree, in which
06700					; directories point to category nodes
06800	BEGDT:	Z			;Date/time to begin processing
06900	ENDDT:	Z			;Date/time to end processing
07000	TMPBLK:	BLOCK	10		;Block for use by various JSYS's.
07100	T2BLK:	BLOCK	10		;second temporary block
07200	DEFFLG:	Z			;Default initial flag settings
07300	SUMLIN:	Z			;Line counter for summary file
07400	DETLIN:	Z			;Line counter for detail file
07500	SHFTIM:	Z			;Temporary for SHIFT subcommand of CHARGES
07600	SHFCHG:	Z			;Temporary for SHIFT subcommand of CHARGES
07700	FSTTAD:	Z			;First date/time entry in files processed
07800	LSTTAD:	Z			;Last date/time entry in files processed
07900	RUNTIM:	Z			;CPU time  
08000	CONTIM:	Z			;connect time
08100	CATVAL:	Z			;value of all summary nodes for categorization
08200	MSCPTR:	Z			;temp ptr for adding miscelleous by categorization
08300	CATLIN:	Z			;line count for category file
08400	WLDCMP:	Z			;comparision value for WLDNOD
08500	
08600	TOTNOD:	TXT	<***TOTALS***>
08700		BLOCK	..SLEN-1
08800	DETTOT:	TXT	<***TOTALS***>
08900		BLOCK	..SLEN
09000	D1TOT:	BLOCK	..SLEN+1
09100	ENTCNT:	BLOCK	ENTMAX		;count of entries of each type processed
09200	
09300	
09400		IFN	DEBUG,<
09500	WRDCNT:	BLOCK	1
09600	>
09700	
09800	ZEND:		;** END OF ZEROING AREA **
09900	
10000		END	ACCT20