



		    mailing_page_.pl1               01/26/85  1301.2r w 01/22/85  1240.5       29970



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1982 *
   *                                                         *
   * Copyright (c) 1972 by Massachusetts Institute of        *
   * Technology and Honeywell Information Systems, Inc.      *
   *                                                         *
   *********************************************************** */


mailing_page_: proc (mc, name, address);

dcl  mc char (*), name char (*), address char (*);

dcl  fmt1 char (12) aligned int static init ("^10x* ^30a *");
dcl  fmt2 char (12) aligned int static init ("^25x* ^30a *");

dcl  stars char (30) aligned int static init ((30)"*");
dcl  stars1 char (30) aligned int static init ((30)"*");

dcl  get_wdir_ entry () returns (char (168) aligned);
dcl  hcs_$terminate_noname entry (ptr, fixed bin (35));
dcl  hcs_$initiate entry (char (*) aligned, char (*) aligned, char (*) aligned, fixed bin (1), fixed bin (2),
     ptr, fixed bin (35));
dcl  sadp ptr int static init (null);
dcl  first bit (1) int static init ("1"b);
dcl  ec fixed bin (35);

dcl  uao char (30) int static init ("MIT IPC User Accounts Office");
dcl  uaoa char (30) int static init ("MIT 39-213");
dcl  banner (3) char (10) int static init ("MIT INTER-", "DEPARTMENT", "MAIL");

dcl  bigletter_$five entry (char (*), entry);
dcl  ioa_$ioa_stream entry options (variable);

dcl  null builtin;

%include sys_admin_data;

/* ======================================================= */

	if first then do;
	     first = "0"b;
	     call hcs_$initiate ((get_wdir_ ()), "sys_admin_data", "", 0, 1, sadp, ec);
	     if sadp ^= null then
		if sys_admin_data.user_accounts_office > "" then do;
		     uao = sys_admin_data.user_accounts_office;
		     uaoa = sys_admin_data.user_accounts_addr;
		     banner (1) = sys_admin_data.mailing_banner (1);
		     banner (2) = sys_admin_data.mailing_banner (2);
		     banner (3) = sys_admin_data.mailing_banner (3);
		end;
	     call hcs_$terminate_noname (sadp, ec);
	end;

	call ioa_$ioa_stream (mc, "^|^10xINTERDEPARTMENTAL^3/");

	call ioa_$ioa_stream (mc, fmt1, stars1);
	call ioa_$ioa_stream (mc, fmt1, "");
	call ioa_$ioa_stream (mc, fmt1, "FROM:");
	call ioa_$ioa_stream (mc, fmt1, uao);
	call ioa_$ioa_stream (mc, fmt1, uaoa);
	call ioa_$ioa_stream (mc, fmt1, "");
	call ioa_$ioa_stream (mc, fmt1, stars1);

	call ioa_$ioa_stream (mc, "^3/");

	call ioa_$ioa_stream (mc, fmt2, stars);
	call ioa_$ioa_stream (mc, fmt2, "");
	call ioa_$ioa_stream (mc, fmt2, "TO:");
	call ioa_$ioa_stream (mc, fmt2, "");
	call ioa_$ioa_stream (mc, fmt2, name);
	call ioa_$ioa_stream (mc, fmt2, "");
	call ioa_$ioa_stream (mc, fmt2, address);
	call ioa_$ioa_stream (mc, fmt2, "");
	call ioa_$ioa_stream (mc, fmt2, stars);

	call ioa_$ioa_stream (mc, "^3/");

	call bigletter_$five (banner (1), writer);
	call ioa_$ioa_stream (mc, "^/");
	call bigletter_$five (banner (2), writer);
	call ioa_$ioa_stream (mc, "^/");
	call bigletter_$five (banner (3), writer);
	call ioa_$ioa_stream (mc, "^3/^10xINTERDEPARTMENTAL");
	return;

writer:	proc (mp, ml);
dcl  mp ptr, ml fixed bin;

dcl  bcs char (ml) based (mp);

	     call ioa_$ioa_stream (mc, "^a", bcs);

	end writer;

     end mailing_page_;




		    punch_MIT_deck.pl1              09/18/84  1252.0rew 09/18/84  0758.7       78183



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1982 *
   *                                                         *
   *********************************************************** */
%;
/* ******************************************************
   *                                                    *
   *                                                    *
   * Copyright (c) 1972 by Massachusetts Institute of   *
   * Technology and Honeywell Information Systems, Inc. *
   *                                                    *
   *                                                    *
   ****************************************************** */

punch_MIT_deck: proc;

/* Punch accounting cards in the peculiar format required by MIT accounting.

   This format is.:

   cc	lth	variable	contents
   -----	---	--------	--------
   01-03  3	-	"   "	(formerly accounting batch number)
   04-09	6	voucher	MIT accounting voucher number for deck (obtain from accounting)
   10-14	5	tacct	current MIT account number for Multics account
   15-17	3	objcd	MIT accounting object code (usually 896, computer service)
   18-20	3	tmon	3-letter month id
   21-24	4	-	", 19"
   25-26	2	year	2-digit year
   27-52	26	-	" IPC MULTICS COMPUTER REQ "
   53-62	10	treqn	current MIT requisition number for Multics account
   63-64	2	mm	2-digit month
   65-66	2	dd	2-digit day of last of month
   67-68	2	year	2-digit year
   69-77	9	dols	dollars charged
   78-79	2	cts	cents charged
   80	1	-	"J"

   So an example of a card produced by this program is:

   "   B9999979457896JUL, 1971 IPC MULTICS COMPUTER REQ 123456    07317100014732105J"

   NOTES:
   Object code is "896", computer services, except for the following accounts:
   10000-11149 and 11700-13299 (outside transfer accounts)	where it is "001"
   13565-13649 (IPC internal accounts)	where it is "421"

   Voucher numbers are obtained from the accounting office just before the run.

   No blanks are allowed in cc. 63-79.

   All letters must be capital for the Multics punch DIM.

   Two cards are punched at the end with a minus punch in cc 79.
   They represent the accounting-office credit input for our operating account
   which will result from billing the customers. (one is for IPC use, other for paying.)

   OPERATING INSTRUCTIONS:

   1. iocall attach cards "file_" cardfilename
   2. punch_MIT_deck mm dd yy Byyyyy
   3. iocall detach cards
   4. fo cards.print; p80 cardfilename; co
   5. dpunch1 -mcc cardfilename
   6. dprint1 cards.print

   HISTORY:

   Initial coding 7/71, THVV
   Credit vouchers added 11/71, THVV
   001 account range corrected 6/74, JLH

   */

dcl (i, j, k, l, m, n) fixed bin,
     ncards fixed bin init (0),
     requisition_total float bin init (0.0e0),
     tout float bin init (0e0),			/* total accounts 10000-11149, 11700-13299 */
     iptot float bin init (0e0),			/* total IPC */
     paytot float bin init (0e0),			/* total paying */
     cards char (32) aligned int static init ("cards"),
     dols fixed bin,
     cts fixed bin,
     buf char (80) aligned,
     objcd char (3) aligned,
     voucher char (6) aligned,
     tacct char (5) aligned,
     treqn char (10) aligned,
     xreqn char (10) aligned int static init ("CREDIT"),
     tmon char (3) aligned,
    (mm, dd, yy) fixed bin,
     oreq char (12) aligned init (""),
     oac char (12) aligned init (""),
     ap ptr,
     al fixed bin,
     bchr char (al) unaligned based (ap),
     ec fixed bin,
     qp ptr;

dcl  minus (0: 9) char (1) aligned int static init ("}", "J", "K", "L", "M", "N", "O", "P", "Q", "R");
dcl  month (12) char (3) aligned int static init ("JAN", "FEB", "MAR", "APR", "MAY", "JUN",
     "JUL", "AUG", "SEP", "OCT", "NOV", "DEC");

dcl  uppercase char (26) aligned int static init ("ABCDEFGHIJKLMNOPQRSTUVWXYZ"),
     lowercase char (26) aligned int static init ("abcdefghijklmnopqrstuvwxyz");
dcl (divide, index, mod, null, substr, abs) builtin;

dcl  cv_dec_check_ entry (char (*) unal, fixed bin) returns (fixed bin),
     ioa_$rsnnl entry options (variable),
     cu_$arg_ptr entry (fixed bin, ptr, fixed bin, fixed bin),
     get_wdir_ entry () returns (char (168) aligned),
     ioa_ entry options (variable),
     ioa_$ioa_stream entry options (variable),
     com_err_ entry options (variable),
     hcs_$initiate entry (char (*) aligned, char (*) aligned, char (*) aligned, fixed bin, fixed bin,
     ptr, fixed bin),
     hcs_$terminate_noname entry (ptr, fixed bin);

dcl  punchf char (80) int static aligned init
    ("^3x^6a^5a^3a^3a, 19^2d IPC MULTICS COMPUTER REQ ^10a^2d^2d^2d^9d^2dJ");

%include reqfile;

/* =============================================== */
	call cu_$arg_ptr (1, ap, al, ec);
	if ec ^= 0 then do;
aer:	     call com_err_ (0, "punch_MIT_deck", "illegal argument: mm dd yy Byyyyy");
	     return;
	end;
	mm = cv_dec_check_ (bchr, ec);
	if ec ^= 0 then go to aer;
	if mm > 12 then go to aer;
	if mm < 1 then go to aer;
	call cu_$arg_ptr (2, ap, al, ec);
	if ec ^= 0 then go to aer;
	dd = cv_dec_check_ (bchr, ec);
	if ec ^= 0 then go to er;
	call cu_$arg_ptr (3, ap, al, ec);
	if ec ^= 0 then go to aer;
	yy = cv_dec_check_ (bchr, ec);
	if ec ^= 0 then go to aer;
	call cu_$arg_ptr (4, ap, al, ec);
	if ec ^= 0 then go to aer;
	if al ^= 6 then go to aer;
	voucher = bchr;
	if substr (voucher, 1, 1) = "b" then substr (voucher, 1, 1) = "B";
	if substr (voucher, 1, 1) = "B" then do;
	     j = cv_dec_check_ (substr (voucher, 2), ec);
	     if ec ^= 0 then go to aer;
	end;
	else go to aer;

	tmon = month (mm);

	call hcs_$initiate ((get_wdir_ ()), "reqfile", "", 0, 1, qp, ec);
	if qp = null then do;
er:	     call com_err_ (ec, "punch_MIT_deck", "reqfile");
	     return;
	end;

	do i = 1 to nacts;
	     if chg_mo (i) = 0 then go to skipb;
	     if acctid (i) = "" then go to skipb;
	     if reqno (i) ^= oreq | mitacct (i) ^= oac then do;
		if oac ^= "" then call sub;
		requisition_total = 0.0e0;
		oreq = reqno (i);
		oac = mitacct (i);
	     end;
	     requisition_total = requisition_total + chg_mo (i);
skipb:	end;
	call sub;
	cts = 100 * (paytot + tout + 0.005e0);		/* compute total billed */
	dols = divide (cts, 100, 17, 0);
	cts = mod (cts, 100);
	call ioa_$rsnnl (punchf, buf, j, voucher, "13622", "146",
	     tmon, yy, xreqn, mm, dd, yy, dols, cts);
	do j = 63 to 79;
	     if substr (buf, j, 1) = " " then substr (buf, j, 1) = "0";
	end;
	j = mod (cts, 10);
	substr (buf, 79, 1) = minus (j);
	call ioa_$ioa_stream (cards, "^80a", buf);
	cts = 100 * (iptot + 0.005e0);		/* compute internal charges */
	dols = divide (cts, 100, 17, 0);
	cts = mod (cts, 100);
	call ioa_$rsnnl (punchf, buf, j, voucher, "13622", "421",
	     tmon, yy, xreqn, mm, dd, yy, dols, cts);
	do j = 63 to 79;
	     if substr (buf, j, 1) = " " then substr (buf, j, 1) = "0";
	end;
	j = mod (cts, 10);
	substr (buf, 79, 1) = minus (j);
	call ioa_$ioa_stream (cards, "^80a", buf);

	call ioa_$ioa_stream (cards, "^/");		/* run out the punch */

	call hcs_$terminate_noname (qp, ec);

	call ioa_ ("Accounting deck punched, ^d cards", ncards+2);
	call ioa_ ("Total billable $^.2f", paytot + tout);

	return;

/* ------------------------------------------------------- */

sub:	proc;

	     if (oac <= "11149" & oac >= "10000")|
		(oac <= "13299" & oac >= "11700") then do; /* External billing? */
		objcd = "001";
		tout = tout + requisition_total;
	     end;
	     else if oac = "nonbill" then return;
	     else if oac = "system" then return;
	     else if oac <= "13649" & oac >= "13565" then do;
		objcd = "421";
		iptot = iptot + requisition_total;
	     end;
	     else do;				/* paying */
		objcd = "896";			/* .. computer services */
		paytot = paytot + requisition_total;
	     end;
	     if abs(requisition_total) < 0.005e0 then return;	/* skip zero charge */
	     tacct = oac;				/* length */
	     treqn = oreq;
	     cts = 100 * (abs(requisition_total) + 0.005e0);
	     dols = divide (cts, 100, 17, 0);
	     cts = mod (cts, 100);
	     call ioa_$rsnnl (punchf, buf, j, voucher, tacct, objcd,
		tmon, yy, treqn, mm, dd, yy, dols, cts);
	     do j = 63 to 79;			/* change blanks to zero here */
		if substr (buf, j, 1) = "" then substr (buf, j, 1) = "0";
	     end;
	     if requisition_total<0e0
	     then do;
		j=mod(cts,10);
		substr(buf,79,1)=minus(j);
		end;
	     do j = 1 to 80;			/* upshift */
		k = index (lowercase, substr (buf, j, 1));
		if k ^= 0 then substr (buf, j, 1) = substr (uppercase, k, 1);
	     end;
	     call ioa_$ioa_stream (cards, "^80a", buf);
	     ncards = ncards + 1;

	end sub;

     end punch_MIT_deck;




		    write_acct_bill.pl1             09/18/84  1252.0rew 09/18/84  0802.8       71235



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1982 *
   *                                                         *
   * Copyright (c) 1972 by Massachusetts Institute of        *
   * Technology and Honeywell Information Systems, Inc.      *
   *                                                         *
   *********************************************************** */


write_acct_bill: proc;

/* This program writes a bill for each multics account.
   It is a print pass over "reqfile", and is run after "charge_accts".

   inputs:
   .	"reqfile"		per-account requisition info

   outputs:
   .	"bill"		one page per account, showing project and account status
   .	"mailing_copy"	same as bill, but with breaker page for mailing before each account
   THVV 11/69 */
/* Modified by C. Hornig June 1979 to center titles. */
/* Modified Feb 1980 by M. B. Armstrong to remove invalid (and useless) call to get prices. */
/* Modified 1984-08-01 BIM for some unaligned strings in the projfile. */

dcl  ec fixed bin (17),				/* file-system error code */
     subacct_exit fixed bin,
    (i, j, k) fixed bin (17),				/* counters */
     oproj char (12) aligned,				/* project names */
    (coxx, dpxx) char (4) aligned,			/* junk args to "system_info_" */
    (cods, dpds) char (120) aligned,			/* Comapny name & department name for header */
     dtemp char (8) aligned,				/* ... */
    (rv, rb) char (15) aligned,			/* ... */
    (yy (4), yz (4)) float bin (27),			/* totals for summary page */
     open char (15) aligned internal static init ("           open"),
     month (12) char (12) aligned int static init
    ("January", "February", "March", "April", "May", "June", "July",
     "August", "September", "October", "November", "December"),
    (mm, year) fixed bin (17),			/* converted args */
     qp ptr,					/* ptr to "reqfile" */
     bchr char (i) unal based (ap),			/* pickup args */
     ap ptr,
     dn char (168) aligned,
     user_count fixed bin (17) init (0);		/* number of users this proj */

dcl (divide, length, null, rtrim) builtin;

dcl  bill char (32) int static options (constant) aligned init ("bill"), /* Streamname on which bill is written */
     mc char (32) int static options (constant) init ("mailing_copy"); /* Streamname for mailing copy of bill */

/* format statements */

dcl  l3 char (48) aligned int static options (constant) init
    ("^-^-^-Multics ^a for the month of ^a, 19^d^/"),
     xl1 char (72) int static options (constant) aligned init
    ("^-^-^-The following charges have been billed to account no. ^a^/^/^/"),
     xl2a char (90) aligned int static options (constant) init
    ("^-^-^4xRequisition^8xCharge^10xRequisition^8xCharge^9xRequisition  Termination"),
     xl2b char (80) aligned int static options (constant) init
    ("^-^14a  or PO no.^8xthis month^6xAmount^13xthis req.^6xBalance^6xDate"),
     xl3 char (60) aligned int static options (constant) init
    ("^/^-^12a  ^12a  ^15a  ^15a  ^15a  ^15a  ^8a"),
     dashx char (120) aligned int static options (constant) init
    ("^/^-------------  ------------^3x--------------^3x--------------^3x--------------^3x--------------  --------");

/* procedures called by this program */

dcl  ioa_ entry options (variable),
     ioa_$rsnnl entry options (variable),
     get_wdir_ entry returns (char (168) aligned),
     ioa_$ioa_stream entry options (variable),
     system_info_$titles entry (char (*) aligned, char (*) aligned, char (*) aligned, char (*) aligned),
     cu_$arg_ptr ext entry (fixed bin, ptr, fixed bin, fixed bin),
     date_time_ ext entry (fixed bin (71), char (*) aligned),
     cv_$mwvf ext entry (float bin (27)) returns (char (15) aligned), /* dollar converter */
     cv_dec_check_ entry (char (*) unal, fixed bin) returns (fixed bin), /* ASCII to binary */
     hcs_$initiate entry (char (*) aligned, char (*) aligned, char (*) aligned,
     fixed bin (1), fixed bin (2), ptr, fixed bin),
     hcs_$terminate_noname entry (ptr, fixed bin),
     mailing_page_ entry (char (*), char (*), char (*)),
     com_err_ entry options (variable);

%include reqfile;

/* ====================================================================================================== */

	call system_info_$titles (coxx, dpxx, cods, dpds); /* Get installation ID */

	call cu_$arg_ptr (1, ap, i, ec);		/* get date */
	if ec ^= 0 then do;
aer:	     call com_err_ (0, "write_acct_bill", "argument error. mm yy");
	     return;
	end;
	mm = cv_dec_check_ (bchr, ec);		/* Convert month to binary. */
	if ec ^= 0 then go to aer;
	if mm > 12 then go to aer;			/* Check for legality. */
	call cu_$arg_ptr (2, ap, i, ec);		/* Get second argument. */
	if ec ^= 0 then go to aer;
	year = cv_dec_check_ (bchr, ec);		/* Convert year to binary */
	if ec ^= 0 then go to aer;
	if year < 69 then go to aer;			/* Check. */

	call hcs_$initiate ((get_wdir_ ()), "reqfile", "", 0, 1, qp, ec);
	if qp = null then do;
err:	     call com_err_ (ec, "write_acct_bill", "reqfile");
	     return;
	end;

	oproj = "";				/* force subtotal */
	k = 0;
	do i = 1 to reqfile.nacts;			/* loop through reqfile */
	     if qdf (i) ^= 0 then if chg_mo (i) = 0.0e0 then go to skipa;
	     if mitacct (i) = "nonbill" then go to skipa;
	     if acctid (i) = "" then go to skipa;	/* ... */
	     if oproj ^= mitacct (i) then do;		/* If account changed, subtotal & head. */
		if oproj ^= "" then if k > 1 then do;
			subacct_exit = 1;
			go to subacct;
		     end;
subacct_ret1:	yz (1), yz (2), yz (3), yz (4) = 0.0e0; /* Zero account totals. */
		call mailing_page_ (mc, billing_name (i), billing_addr (i));
		call ioa_$ioa_stream (bill, "^|^vx^a^/", 68 - divide (length (rtrim (cods)), 2, 17), cods); /* write headers */
		call ioa_$ioa_stream (bill, "^vx^a^/", 68 - divide (length (rtrim (dpds)), 2, 17), dpds); /* write headers */
		call ioa_$ioa_stream (bill, l3, "billing", month (mm), year);
		call ioa_$ioa_stream (bill, "^-^-^-To:     ^a; ^a^/", billing_name (i), billing_addr (i));
		call ioa_$ioa_stream (bill, xl1, mitacct (i));
		call ioa_$ioa_stream (bill, xl2a);
		call ioa_$ioa_stream (bill, xl2b, "Project ID");
		call ioa_$ioa_stream (bill, dashx);
		k = 0;				/* count of reqs on acct */
		oproj = mitacct (i);
	     end;
	     k = k + 1;				/* Count requisition. */
	     yy (1) = chg_mo (i);			/* Get charges this month. (just added this up) */
	     yy (2) = req_amt (i);			/* Get face amount of req. */
	     yy (3) = chg_tr (i) + yy (1);		/* Get charges this req. */
	     yy (4) = yy (2) - yy (3);		/* Compute balance. */
	     if yy (2) = 0.0e0 then do;		/* Check for OPEN balance. */
		yy (4) = 0.0e0;			/* Yes. */
		rv, rb = open;
	     end;
	     else do;				/* No. */
		rv = cv_$mwvf (yy (2));
		rb = cv_$mwvf (yy (4));
	     end;
	     call date_time_ (cutoff (i), dtemp);
	     do j = 1 to 4;				/* Add up account total. */
		yz (j) = yz (j) + yy (j);
	     end;
	     call ioa_$ioa_stream (bill, xl3, acctid (i), reqno (i), /* Write requisition line. */
		cv_$mwvf (yy (1)), rv, cv_$mwvf (yy (3)), rb, dtemp);
skipa:	end;
	subacct_exit = 2;
	if k > 1 then go to subacct;			/* last subtotal if necessary */
subacct_ret2:
	call ioa_ ("End of bill.");

	call hcs_$terminate_noname (qp, ec);		/* Terminate reqfile. */
	return;					/* FINAL EXIT */

/* - - - - - - - */

/* This internal procedure does a subtotal for bills */

subacct:	call ioa_$ioa_stream (bill, dashx);		/* Write dashes. */
	if yz (2) = 0.0e0 then rv, rb = open;		/* Check for OPEN */
	else do;
	     rv = cv_$mwvf (yz (2));
	     rb = cv_$mwvf (yz (4));
	end;
	call ioa_$rsnnl ("^d projects", dn, j, k);
	call ioa_$ioa_stream (bill, xl3, dn, "", cv_$mwvf (yz (1)), rv,
	     cv_$mwvf (yz (3)), rb, "");
	if subacct_exit = 1 then go to subacct_ret1;
	else go to subacct_ret2;
     end write_acct_bill;




		    write_billing_summary.pl1       09/18/84  1252.0rew 09/18/84  0802.8       66852



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1982 *
   *                                                         *
   * Copyright (c) 1972 by Massachusetts Institute of        *
   * Technology and Honeywell Information Systems, Inc.      *
   *                                                         *
   *********************************************************** */


write_billing_summary: proc;

/* This program writes a summary report, one line per requisition.
   It is a print pass over "reqfile" after "charge_accts" has been run.

   inputs:
   .	"reqfile"		per-account requisition info

   outputs:
   .	"sumry"		one line per requisition showing status & charges
   THVV 11/69 */
/* Modified Feb 1980 by M. B. Armstrong to remove invalid (and useless) call to get prices. */

dcl  ec fixed bin (17),				/* file-system error code */
     subacct1_exit fixed bin,
    (i, j) fixed bin (17),				/* counters */
     old_reqno char (12) aligned,			/* project names */
     old_acctno char (12) aligned,			/* temp account name */
     ocutoff fixed bin (71),
    (coxx, dpxx) char (4) aligned,			/* junk args to "system_info_" */
    (cods, dpds) char (120) aligned,			/* Comapny name & department name for header */
     dtemp char (8) aligned,				/* ... */
    (rv, rb) char (15) aligned,			/* ... */
    (account_total (4), grand_total (4)) float bin (27),	/* totals for summary page */
     open char (15) aligned internal static init ("           open"),
     month (12) char (12) aligned int static init
    ("January", "February", "March", "April", "May", "June", "July",
     "August", "September", "October", "November", "December"),
    (mm, dd, year) fixed bin (17),			/* converted args */
     pp ptr,					/* ptr to "projfile" */
     qp ptr,					/* ptr to "reqfile" */
     page fixed bin (17),				/* page number */
     bchr char (i) unal based (ap),			/* pickup args */
     ap ptr,
     user_count fixed bin (17) init (0);		/* number of users this proj */

dcl (null, substr) builtin;

dcl  sumry char (32) int static aligned init ("sumry");	/* Streamname on which output is written */


/* format statements */

dcl  l3 char (48) aligned int static init
    ("^-^-^-Multics ^a for the month of ^a, 19^d^/"),
     xl1 char (72) int static aligned init
    ("^-^-^-The following charges have been billed to account no. ^a^/^/^/"),
     xl2a char (90) aligned int static init
    ("^-^-^4xRequisition^8xCharge^10xRequisition^8xCharge^9xRequisition  Termination"),
     xl2b char (80) aligned int static init
    ("^-^14a  or PO no.^8xthis month^6xAmount^13xthis req.^6xBalance^6xDate"),
     xl3 char (60) aligned int static init
    ("^/^-^12a  ^12a  ^15a  ^15a  ^15a  ^15a  ^8a"),
     dashx char (120) aligned int static init
    ("^/^-------------  ------------^3x--------------^3x--------------^3x--------------^3x--------------  --------");

/* procedures called by this program */

dcl  get_wdir_ entry returns (char (168) aligned),
     ioa_ entry options (variable),
     ioa_$ioa_stream entry options (variable),
     system_info_$titles entry (char (*) aligned, char (*) aligned, char (*) aligned, char (*) aligned),
     cu_$arg_ptr ext entry (fixed bin, ptr, fixed bin, fixed bin),
     date_time_ ext entry (fixed bin (71), char (*) aligned),
     cv_$mwvf ext entry (float bin (27)) returns (char (15) aligned), /* dollar converter */
     cv_dec_check_ entry (char (*) unal, fixed bin) returns (fixed bin), /* ASCII to binary */
     hcs_$initiate entry (char (*) aligned, char (*) aligned, char (*) aligned,
     fixed bin (1), fixed bin (2), ptr, fixed bin),
     hcs_$terminate_noname entry (ptr, fixed bin),
     com_err_ entry options (variable);

%include reqfile;

/* ====================================================================================================== */

	call system_info_$titles (coxx, dpxx, cods, dpds); /* Get installation ID */

	call cu_$arg_ptr (1, ap, i, ec);		/* get date */
	if ec ^= 0 then do;
aer:	     call com_err_ (0, "write_billing_summary", "argument error. mm yy");
	     return;
	end;
	mm = cv_dec_check_ (bchr, ec);		/* Convert month to binary. */
	if ec ^= 0 then go to aer;
	if mm > 12 then go to aer;			/* Check for legality. */
	call cu_$arg_ptr (2, ap, i, ec);		/* Get second argument. */
	if ec ^= 0 then go to aer;
	year = cv_dec_check_ (bchr, ec);		/* Convert year to binary */
	if ec ^= 0 then go to aer;
	if year < 69 then go to aer;			/* Check. */

	call hcs_$initiate ((get_wdir_ ()), "reqfile", "", 0, 1, qp, ec);
	if qp = null then do;
err:	     call com_err_ (ec, "write_billing_summary", "reqfile");
	     return;
	end;

	account_total (1), account_total (2), account_total (3), account_total (4) = 0.0e0; /* zero counters */
	grand_total (1), grand_total (2), grand_total (3), grand_total (4) = 0.0e0; /* Clear grand total. */
	call ioa_$ioa_stream (sumry, "^|^-^-^a^/", cods); /* heading on summary */
	call ioa_$ioa_stream (sumry, "^-^-^-^a^/", dpds);
	call ioa_$ioa_stream (sumry, l3, "billing summary", month (mm), year);
	call ioa_$ioa_stream (sumry, xl2a);
	call ioa_$ioa_stream (sumry, xl2b, "Account");
	call ioa_$ioa_stream (sumry, dashx);

	old_reqno = "";
	old_acctno = "";
	do i = 1 to reqfile.nacts;
	     if qdf (i) ^= 0 then if chg_mo (i) = 0.0e0 then go to skipb;
	     if mitacct (i) = "nonbill" then go to skipb;
	     if acctid (i) = "" then go to skipb;	/* skip deleted acct */
	     if reqno (i) ^= old_reqno | mitacct (i) ^= old_acctno then do;
		subacct1_exit = 1;
		go to subacct1;			/* pseudocall */
subacct1_ret1:	account_total (1), account_total (2), account_total (3), account_total (4) = 0.0e0;
		old_reqno = reqno (i);
		old_acctno = mitacct (i);
		ocutoff = cutoff (i);
	     end;
	     account_total (1) = account_total (1) + chg_mo (i); /* Add up charges this month. */
	     account_total (2) = account_total (2) + req_amt (i); /* Add up face amount. */
	     account_total (3) = account_total (3) + chg_tr (i) + chg_mo (i); /* Calculate charges this req. */
	     if req_amt (i) > 0.0e0 then account_total (4) = account_total (4) + req_amt (i) - chg_tr (i) - chg_mo (i);
skipb:	end;
	subacct1_exit = 2;
	go to subacct1;
subacct1_ret2: call ioa_$ioa_stream (sumry, dashx);	/* Write final line of dashes. */
	call ioa_$ioa_stream (sumry, xl3, "", "", cv_$mwvf (grand_total (1)), cv_$mwvf (grand_total (2)),
	     cv_$mwvf (grand_total (3)), cv_$mwvf (grand_total (4)), "");



	call ioa_ ("End of billing summary. Grand total ^a", cv_$mwvf (grand_total (1)));

	call hcs_$terminate_noname (qp, ec);		/* Terminate reqfile. */
	return;					/* FINAL EXIT */

/* - - - - - - - */

subacct1:
	if old_reqno = "" then go to subx;
	if account_total (2) = 0.0e0 then do;		/* Check for OPEN */
	     rv, rb = open;
	end;
	else do;					/* ... no */
	     rv = cv_$mwvf (account_total (2));
	     rb = cv_$mwvf (account_total (4));
	end;
	call date_time_ (ocutoff, dtemp);
	call ioa_$ioa_stream (sumry, xl3, old_acctno, old_reqno, /* Write account line. */
	     cv_$mwvf (account_total (1)), rv, cv_$mwvf (account_total (3)), rb, dtemp);

skipp:	do j = 1 to 4;				/* Add up grand total, reset account total */
	     grand_total (j) = grand_total (j) + account_total (j);
	end;

subx:	if subacct1_exit = 1 then go to subacct1_ret1;
	else go to subacct1_ret2;

     end;




		    write_user_usage_report.pl1     08/29/88  0944.7rew 08/29/88  0858.7      514062



/****^  ***********************************************************
        *                                                         *
        * Copyright, (C) Honeywell Bull Inc., 1988                *
        *                                                         *
        * Copyright, (C) Honeywell Information Systems Inc., 1982 *
        *                                                         *
        * Copyright (c) 1972 by Massachusetts Institute of        *
        * Technology and Honeywell Information Systems, Inc.      *
        *                                                         *
        *********************************************************** */




/****^  HISTORY COMMENTS:
  1) change(87-11-03,GDixon), approve(88-08-15,MCR7969),
     audit(88-08-03,Lippard), install(88-08-29,MR12.2-1093):
     Update grand_total.devices(j) so grand total gets calculated/printed.
     (phx19300, Answering_Service 487)
                                                   END HISTORY COMMENTS */


write_user_usage_report: proc;

/* Usage report program. This program writes a pretty usage report for each proj.

   inputs:
   .	 sat                 list of valid projects, and projects deleted during the month
   .	 XXX.pdt             per-user cpu and console usage for each project XXX
   .	 "reqfile"           per-account requisition info
   .	 "projfile"          per-proj disk and misc charges and supervisor name
   .	 "miscfile"          misc charges detail info for the month
   .	 "billing_footnote"  constant text added to each summary page of the bill

   outputs:
   .	 "long_bill"         stream has one to five sections per proj...
   .	                     .         summary page
   .	                     .         interactive usage
   .	                     .         absentee usage
   .	                     .         io daemon usage
   .	                     .         device usage

   .	 "mailing_copy"      same as long_bill but with breaker page for mailing before each project.
   .	                     prices and footnotes on this copy only to save disk space.

   .	 "short_bill"        stream has summary page as above only (no footnotes)
   .	                     but does have fancy grand total page.

   .	 "both_bills"        stream goes on long_bill, mailing_copy, and short_bill

   .	 NOTE THAT ALL I/O ATTACHMENTS ARE RESPONSIBILITY OF THE CALLER.

   THVV 11/69
   . J. Phillipps -- modified 8/72 to remove translator daemon code and to upgrade to use PDTs instead of Hist.
   .	         -- modified 3/73 to upgrade for virtual page fault charging on the 6180.
   .	            modified 3/16/76 by TAC to fix bugs:
   .	                     sorting arrays (u,v,x,y) for projects and users
   .	                       are now allocated in begin blocks, after their size is known;
   .	                     computation of lodate is done correctly;
   .	                     message about inconsistent misc charge figures is correct.
   .	        -- modified 6/10/79 by CAH to print usage if charge was zero.
   .	         -- modified Feb 1980 by M. B. Armstrong to implement multiple rate structures.
   -- modified June 1980 by Ricarda McDonald to include page charging.
   Modified 1984-08-27 BIM for unaligned strings in projfile.
   */

dcl  abs_user_count fixed bin,			/* count of absentee users processed */
     ap ptr,					/* argument ptr */
     connect_tim (0:7) char (8) aligned,		/* connect time in ascii */
     memry_usge (0:7) float bin init ((8)0e0),		/* memory usage expressed as memory units *K */
     cpu_tim (0:7) char (8) aligned,			/* cpu time in ascii */
    (coxx, dpxx) char (4) aligned,			/* junk args to "system_info_" */
    (cods, dpds) char (120) aligned,			/* Comapny name & department name for header */
     device_count fixed bin,
     dmns fixed bin init (1),				/* index of proj start, if we need to go back */
     dmnx fixed bin init (0),				/* > 0 if proj has daemon usage */
     dn char (168) aligned,				/* directory name */
     ec fixed bin (17),				/* file-system error code */
     grand_absentee_chg float bin init (0e0),		/* grand-total absentee charge: all (users, queues) */
     grand_absentee_cpu fixed bin (71) init (0),		/* grand-total absentee cpu usage: all (users, queues) */
     grand_absentee_jobs fixed bin init (0),		/* grand-total number of absentee jobs: all (users, queues) */
     grand_absentee_memory fixed bin (71) init (0),	/* grand-total absentee memory usage: all (users, queues) */
     grand_device_chg float bin init (0e0),		/* grand-total device charge: all (users, projects) */
     grand_disk_chg float bin init (0e0),		/* grand-total disk charge: all (users, projects) */
     grand_disk_quota fixed bin init (0),
     grand_disk_usage fixed bin init (0),		/* grand-total disk usage: all (users, projects) */
     grand_interactive_chg float bin init (0e0),		/* grand-total interactive charge: all (users, shifts) */
     grand_interactive_connect fixed bin (71) init (0),	/* grand-total connect time: all (users, shifts) */
     grand_interactive_memory fixed bin (71) init (0),	/* grand-total memory usage: all (users, shifts) */
     grand_interactive_cpu fixed bin (71) init (0),	/* grand-total interactive cpu usage: all (users, shifts) */
     grand_interactive_ioops fixed bin (71) init (0),	/* grand-total interactive terminal I/O operations:
						   all users, all shifts */
     grand_iod_chg float bin init (0e0),		/* grand-total iod charge: all (users, queues) */
     grand_iod_lines fixed bin (71) init (0),		/* grand-total number of lines printed */
     grand_iod_pages fixed bin (71) init (0),		/* grand-total number of pages printed */
     grand_iod_pieces fixed bin init (0),		/* grand-total number of io requests: all (users, queues) */
     grand_misc_chg float bin init (0e0),		/* grand_total miscellaneous charge:all (users, items) */
     grand_pmonths float bin init (0e0),		/*  grand-total disk page-months */
     grand_total_chg float bin init (0e0),
     grand_registration_chg float bin init (0e0),		/* grand-total for registration on system */
     hidate char (8) aligned,				/* Last date in billing period. */
     hidate_bin fixed bin (71) init (0),		/* ... */
     iod_count fixed bin,				/* number of iod users */
    (i, ii, j, jj, k, kk, n, r) fixed bin,		/* counters */
     lin_incrm fixed bin init (0),			/* line counter increment */
     linct fixed bin (17),				/* line counter */
     linct_s fixed bin,				/* line count for short bill */
     lodate char (8) aligned,				/* First date in billing period. */
     lodate_bin fixed bin (71),			/* ... */
     m fixed bin,
     misc_chg float bin init (0e0),
     miscfilep ptr,					/* ptr to "miscfile" */
     miscfile_dir char (168) aligned,			/* path of dir where miscfile */
     miscfile_name char (32) aligned,			/* ename of miscfile */
     NL char (1) aligned int static init ("
"),						/* newline, for footnote scan */
     named bit (1),
     nonbill_total float bin init (0e0),		/* Total "overhead" charges */
     note char (1) aligned,				/* star if user deleted */
     noted fixed bin,				/* count deleted users on project */
     notel fixed bin,				/* char length of footnote */
     notep ptr,					/* ptr to "billing_footnote" */
    (numproj, numusers) fixed bin init (0),		/* total number of projects and users in system */
    (ix, oix) fixed bin,				/* indices used for formatting subtotal. */

     trmnl_ioops (0: 7) float bin init ((8)0e0),		/* no. of terminal I/O operations, ready for printing */
     page fixed bin (17),				/* page number */
     page_s fixed bin,				/* page number, short bill */
     pmonths float bin init (0e0),			/* disk page-months */
     pdt_dir char (168) aligned,			/* path of PDT's dir */
     pdt_name char (32) aligned,			/* ename for a PDT */
     pdtep ptr,
     pdtp ptr,
     pp ptr,					/* ptr to "projfile" */
     proj_absentee_chg float bin init (0e0),		/* total project absentee charge: all (users, queues) */
     proj_absentee_cpu fixed bin (71) init (0),		/* total absentee cpu usage for project: all (users, queues) */
     proj_absentee_jobs fixed bin init (0),		/* total number absentee jobs for project: all (users, queues) */
     proj_absentee_memory fixed bin (71) init (0),	/* total project absentee memory usage: all (users, queues) */
     proj_device_chg float bin init (0e0),		/* total project device charge */
     proj_disk_chg float bin init (0e0),		/* charge for project disk */
     proj_disk_quota fixed bin init (0),		/* disk temp */
     proj_disk_usage fixed bin init (0),		/* disk usage for a project */
     proj_interactive_chg float bin init (0e0),		/* total project interactive charge: all (users, shifts) */
     proj_interactive_connect fixed bin (71) init (0),	/* total project connect time: all (users, shifts) */
     proj_interactive_memory fixed bin (71) init (0),	/* total project memory usage: all (users, shifts) */
     proj_interactive_cpu fixed bin (71) init (0),	/* total project interactive cpu usage: all (users, shifts) */
     proj_interactive_ioops fixed bin (71) init (0),	/* total project interactive terminal I/O operations:
						   all users, all shifts */
     proj_iod_chg float bin init (0e0),			/* total project iod charge: all (users, queues) */
     proj_iod_lines fixed bin (71) init (0),		/* total number of lines printed for project */
     proj_iod_pages fixed bin (71) init (0),		/* total number of pages printed for project */
     proj_iod_pieces fixed bin init (0),		/* total project number of io requests: all (users, queues) */
     proj_registration_chg float bin init (0e0),		/* total registration charge for project */
     projfile_dir char (168) aligned,			/* path of dir where projfile */
     projfile_name char (32) aligned,			/* ename of projfile */
     proj_total_chg float bin init (0e0),		/* total dollars spent for a project */
     qp ptr,					/* ptr to "reqfile" */
     reqdir char (168) aligned,			/* path of dir where reqfile */
     reqname char (32) aligned,			/* ename of reqfile */
     rs_count fixed bin,				/* number of rate structures defined at this site */
     SIXTYMILLION fixed bin (35) internal static init (60000000),
     sat_dir char (168) aligned,			/* path of sat dir */
     sat_name char (32) aligned,			/* ename of sat */
     satep ptr,
     satp ptr,
     t1 fixed bin,					/* ... */
     temp fixed bin (71),
     tempf float bin,
     user_absentee_chg float bin init (0e0),
     user_absentee_cpu fixed bin (71) init (0),
     user_absentee_jobs fixed bin,
     user_absentee_memory fixed bin (71) init (0),
     user_device_chg float bin init (0e0),
     user_count fixed bin (17),			/* number of users in a project */
     user_interactive_chg float bin init (0),		/* interactive charge per user,all shifts  */
     user_interactive_connect fixed bin (71) init (0),	/* interactive connect time per user */
     user_interactive_memory fixed bin (71) init (0),	/* interactive memory usage per user */
     user_interactive_cpu fixed bin (71) init (0),	/* interactive cpu time per user */
     user_interactive_ioops fixed bin (71) init (0),	/* interactive terminal I/O operations per user */
     user_iod_chg float bin init (0e0),			/* daemon charge all queues for each user */
     user_iod_lines fixed bin (71),			/* total number of lines printed, each user, all queues */
     user_iod_pages fixed bin (71),			/* total number of pages printed, each user, all queues */
     user_iod_pieces fixed bin,			/* total number of pieces printed, each user, all queues */
     user_total_chg float bin init (0e0);		/* total dollar charge including reg fee for each user */

dcl (addr, divide, fixed, float, hbound, mod, null, substr) builtin;

dcl  lng char (32) int static aligned init ("long_bill");	/* long bill */
dcl  sht char (32) int static aligned init ("short_bill");
dcl  both char (32) int static aligned init ("both_bills");
dcl  mc char (32) int static aligned init ("mailing_copy");

dcl 1 notes based (notep) aligned,
    2 ch (131071) char (1) unal;

dcl  notestr char (131071) based (notep) aligned;



/* "format staements" -- control strings for ioa_ */

dcl  l3 char (48) aligned int static init
    ("^30xMultics ^a for the period ^a to ^a^/"),
     l4 char (80) aligned int static init
    ("^30xProject name: ""^a"", ^52a   page ^d^/^/^30xSupervisor:^4x^a; ^a^/^/^/"),
     dskfmt char (80) aligned int static init
    ("Disk Storage charge: ^10.2f page-months (quota ^d, current use ^d)"),
     ptlin char (19) int static aligned init ("^/^10x^99a ^5x^15a"),
     dash char (120) aligned int static init ((120)"-"),
     eqllin char (120) aligned int static init ((120)"=");

dcl  format char (50) aligned int static init		/* format for interactive shift usage */
    ("^10x^24a^8a^1x^8a^4x^8a^5x^11.1f^3x^11.1f^22x^15a"),
     format1 char (65) aligned int static init		/* format for interactive shift usage total */
    ("^/^8x^1a^1x^24a^8a^1x^8a^4x^8a^5x^11.1f^3x^11.1f^10d^10d^2x^15a^/"),
     formatz char (60) aligned int static init		/* Format for guy who never logged in. */
    ("^8x^1a^1x^24a^7x(no usage)^/"),
     fmt1 char (60) aligned int static init
    ("^8x^1a ^25a^15a ^15a ^15a ^15a ^15a ^15a^/"),
     dmnfmt char (60) aligned int static init
    ("^10x^24a ^8a^10d^16d^16d^8x^15a"),
     dmnfmt1 char (60) aligned int static init
    ("^/^10x^24a ^8a^10d^16d^16d^8x^15a^/"),
     absfmt char (60) aligned int static init
    ("^10x^24a ^8a^10d^4x^8a^4x^12.1f^8x^15a"),
     absfmt1 char (60) aligned int static init
    ("^/^10x^24a ^8a^10d^4x^8a^4x^12.1f^8x^15a^/"),
     formatA char (10) aligned int static init
    ("^/^10x^14a");

dcl  title1 char (24) aligned int static init ("charge summary"),
     title2 char (24) aligned int static init ("interactive usage"),
     title3 char (24) aligned int static init ("absentee usage"),
     title4 char (24) aligned int static init ("IO Daemon usage"),
     title5 char (24) aligned int static init ("other charges");

dcl  total char (8) aligned int static init ("  TOTAL:");

dcl  shift_label (0:7) char (8) aligned int static
     init ("Shift 0:", "Shift 1:", "Shift 2:", "Shift 3:", "Shift 4:", "Shift 5:", "Shift 6:", "Shift 7:");

dcl  queue_label (4) char (8) aligned int static
     init ("Queue 1:", "Queue 2:", "Queue 3:", "Queue 4:");

dcl  col1 char (120) aligned int static init
    ("^10xName^25xInteractive^8xAbsentee^7xIO Daemon^4xRegistration^11xOther^11xTotal"),
     col2 char (120) aligned int static init
    ("^10xName^34xCPU^5xConnect^4xTerminal I/O^6xMemory*K^4xLogins^3xCrashes^11xCharge"),
     col3 char (120) aligned int static init
    ("^10xName^31xRequests^9xCPU^8xMemory*K^17xCharge"),
     col4 char (120) aligned int static init
    ("^10xName^31xRequests^11xLines^11xPages^17xCharge"),
     col5 char (120) aligned int static init
    ("^10xName^20xDevice^12xCharge");

dcl  p_header char (14) aligned int static init
    ("PROJECT TOTALS");

dcl 1 prices (0:9),					/* array to hold all prices for each rate structure */
    2 rs_name char (32),
    2 abs_cpu_price (1: 4) float bin,			/* installation price for absentee cpu time */
    2 abs_memory_price (1: 4) float bin,		/* installation price for absentee memory usage */
    2 connect_price (0: 7) float bin,			/* installation price for terminal connect time */
    2 core_price (0: 7) float bin,			/* installation price for memory usage */
    2 devtab_copy (16) aligned,			/* device info not really needed as only device_id */
      3 device_id char (8),				/*     used. Put here to be consistent */
      3 device_price (0:7) float bin,
    2 disk_price float bin,				/* price for one page-second */
    2 interactive_cpu_price (0: 7) float bin,		/* installation price for interactive cpu time */
    2 ioops_price (0: 7) float bin,			/* installation price for I/O operations */
    2 lines_price (1: 4) float bin,
    2 reg_price float bin;				/* user registration charge */


/* procedures called by this procedure */


dcl  com_err_ entry options (variable),			/* system error procedure */
     cu_$arg_ptr ext entry (fixed bin, ptr, fixed bin, fixed bin),
     cv_$mwvf ext entry (float bin) returns (char (15) aligned), /* dollar converter */
     date_time_ entry (fixed bin (71), char (*) aligned),
     expand_path_ entry (ptr, fixed bin, ptr, ptr, fixed bin),
     get_wdir_ entry () returns (char (168) aligned),
     hcs_$initiate entry (char (*) aligned, char (*) aligned, char (*) aligned,
     fixed bin, fixed bin, ptr, fixed bin),
     hcs_$initiate_count entry (char (*) aligned, char (*) aligned, char (*) aligned,
     fixed bin, fixed bin, ptr, fixed bin),
     hcs_$terminate_noname entry (ptr, fixed bin),
     idsort_ entry ((*) char (32) aligned, (*) fixed bin, fixed bin),
    (ioa_, ioa_$rsnnl) entry options (variable),		/* output routines */
     ioa_$ioa_stream entry options (variable),		/* output on file */
     mailing_page_ entry (char (*) aligned, char (*) aligned, char (*) aligned),
     system_info_$titles entry (char (*) aligned, char (*) aligned, char (*) aligned, char (*) aligned),
     system_info_$rs_name entry (fixed bin, char (*), fixed bin),
     system_info_$prices_rs entry (fixed bin,
    (0: 7) float bin, (0: 7) float bin, (0: 7) float bin, (0: 7) float bin, float bin, float bin), /* Gets interactive installation prices */
     system_info_$device_prices_rs entry (fixed bin, fixed bin, ptr),
     system_info_$io_prices_rs entry (fixed bin, (4) float bin), /* gets daemon installation prices */
     system_info_$abs_prices_rs entry (fixed bin, (4) float bin, (4) float bin);

dcl  system_info_$max_rs_number entry (fixed bin);
						/* gets absentee installation prices */

%include grand_total;
%include miscfile;
%include pdt;
%include project_total;
%include projfile;
%include reqfile;
%include sat;
%include user_attributes;

/* ====================================================================================================== */

/* INITIALIZATION. Obtain prices, get and check arguments, initiate files. */

	call cu_$arg_ptr (1, ap, i, ec);		/* get pathname of SAT */
	if ec ^= 0 then do;
aer:	     call com_err_ (0, "write_user_usage_report",
		"Argument error. sat pdtdir reqfile projfile miscfile");
	     return;
	end;
	call expand_path_ (ap, i, addr (sat_dir), addr (sat_name), ec); /* dirname and ename for sat */
	if ec ^= 0 then go to aer;
	call hcs_$initiate (sat_dir, sat_name, "", 0, 0, satp, ec); /* make known and get ptr to sat */
	if satp = null then do;
err:	     call com_err_ (ec, "write_user_usage_report", "BILLING IS ABORTED");
	     go to exit;
	end;

	call cu_$arg_ptr (2, ap, i, ec);		/* path of dir where PDTs */
	if ec ^= 0 then go to err;
	call expand_path_ (ap, i, addr (pdt_dir), null, ec); /* get abs path of wh PDTs */
	if ec ^= 0 then go to err;

	call cu_$arg_ptr (3, ap, i, ec);		/* third arg, path of dir where reqfile */
	if ec ^= 0 then go to aer;
	call expand_path_ (ap, i, addr (reqdir), addr (reqname), ec);
	if ec ^= 0 then go to aer;
	call hcs_$initiate (reqdir, reqname, "", 0, 0, qp, ec); /* Initiate reqfile */
	if qp = null then go to err;

	call cu_$arg_ptr (4, ap, i, ec);		/* get fourth arg, path of projfile */
	if ec ^= 0 then go to aer;
	call expand_path_ (ap, i, addr (projfile_dir), addr (projfile_name), ec);
	if ec ^= 0 then go to aer;
	call hcs_$initiate (projfile_dir, projfile_name, "", 0, 0, pp, ec); /* Initiate projfile. */
	if pp = null then go to err;

	call cu_$arg_ptr (5, ap, i, ec);		/* fifth arg, path of miscfile */
	if ec ^= 0 then go to aer;
	call expand_path_ (ap, i, addr (miscfile_dir), addr (miscfile_name), ec);
	if ec ^= 0 then go to aer;
	call hcs_$initiate (miscfile_dir, miscfile_name, "", 0, 0, miscfilep, ec);
	if miscfilep = null then go to err;

	call hcs_$initiate_count ((get_wdir_ ()), "billing_footnote", "", notel, 1, notep, ec);
	if notep ^= null then do;			/* Will there be a footnote? */
	     notel = divide (notel, 9, 17, 0);
	     call ioa_ ("""billing_footnote"" will be added to long bill");
	end;

	call system_info_$titles (coxx, dpxx, cods, dpds); /* Get installation ID */
	call system_info_$max_rs_number (rs_count);	/* see how many rate structures site has defined */
	do r = 0 to hbound (prices, 1);
	     call system_info_$rs_name ((r), prices (r).rs_name, ec);
	     if ec ^= 0 then prices (r) = prices (0);	/* assume default prices if rate not defined */
	     else do;
		call system_info_$prices_rs ((r), prices (r).interactive_cpu_price (*), prices (r).connect_price (*),
		     prices (r).ioops_price (*), prices (r).core_price (*), prices (r).disk_price, prices (r).reg_price);
		call system_info_$abs_prices_rs ((r), prices (r).abs_cpu_price (*), prices (r).abs_memory_price (*));
		call system_info_$io_prices_rs ((r), prices (r).lines_price (*));
		call system_info_$device_prices_rs ((r), (0), addr (prices (r).devtab_copy (1)));
	     end;
	end;

/* Reset "processed" flags for reqfile and projfile */

	do i = 1 to reqfile.nacts;
	     reqfile.reqfiletab (i).procssd = 0;
	end;
	do i = 1 to projfile.nproj;
	     projfile.projfiletab (i).processed = 0;
	end;

/* ------------------------------------------------------- */

/* Main loop of this program is on the projects listed in the SAT. One report for each project. */

	begin;					/* get stack frame for u and v arrays, big enough to hold all projects */

dcl  u (sat.current_size) char (32) aligned;
dcl  v (sat.current_size) fixed bin;


	     n = 0;
	     do ii = 1 to sat.current_size;
		satep = addr (sat.project (ii));	/* pick out a project and get ptr */
		n = n + 1;
		u (n) = project.project_id;
		v (n) = ii;
	     end;
	     call idsort_ (u, v, n);			/* Make sorted list of all projects. */

/* Begin loop through projects. */

	     do ii = 1 to n;			/* loop thru sorted sat to bill all projects */
		satep = addr (sat.project (v (ii)));
		if project.state = 0 then go to endsatloop; /* skip dead entries */

/* Locate each project's PDT and its entries in reqfile and projfile */

		call ioa_$rsnnl ("^a.pdt", pdt_name, k, project.project_id);
		call hcs_$initiate (pdt_dir, pdt_name, "", 0, 0, pdtp, ec);
		if pdtp = null then do;		/* No bill if not found. */
nonfaterr:	     call com_err_ (ec, "write_user_usage_report", "Could not initiate ^a", pdt_name);
		     go to endsatloop;
		end;

		r = project.rs_number;		/* establish correct rate structure index */

		do k = 1 to projfile.nproj;		/* look thru projfile for proj title */
		     if project.project_id = projfile.projfiletab (k).id then go to fpj;
		end;
		call ioa_ ("write_user_usage_report: missing ""projfile"" entry for ""^a""", project.project_id);
		go to exitm1;

fpj:		if projfile.projfiletab (k).processed ^= 0 then do;
		     call ioa_ ("write_user_usage_report: project ^a has been processed twice", project.project_id);
		end;
		projfile.projfiletab (k).processed = 1;

		numproj = numproj + 1;		/* increase count of processed projects */
		do kk = 1 to reqfile.nacts;		/* look thru reqfile */
		     if project.project_id = reqfile.reqfiletab (kk).acctid then go to facc;
		end;
		call ioa_ ("write_user_usage_report: missing ""reqfile"" entry for ""^a""", project.project_id);
exitm1:		call ioa_ ("Billing cannot proceed. Attempting orderly cleanup.");
		go to exitm;

facc:		if reqfile.reqfiletab (kk).procssd ^= 0 then do;
		     call ioa_ ("write_user_usage_report: req for project ^a has been processed twice", project.project_id);
		end;
		reqfile.reqfiletab (kk).procssd = 1;

		if project.project_id ^= pdt.project_name then
		     call ioa_ ("write_user_usage_report: PDT.project_name for ^a is ^a. Proceeding.",
		     project.project_id, pdt.project_name);

/* initialize project total variables */

		proj_interactive_chg, proj_absentee_chg, proj_iod_chg, proj_registration_chg = 0e0;
		proj_device_chg = 0e0;
		proj_total_chg = 0e0;
		proj_interactive_cpu, proj_interactive_connect, proj_interactive_memory, proj_interactive_ioops = 0;
		proj_disk_chg = 0e0;
		proj_disk_quota, proj_disk_usage = 0;
		do j = 0 to 7;
		     project_total.interactive (j).charge = 0e0;
		     project_total.interactive (j).cpu = 0;
		     project_total.interactive (j).core = 0;
		     project_total.interactive (j).connect = 0;
		     project_total.interactive (j).io_ops = 0;
		end;
		project_total.logins, project_total.crashes = 0;
		proj_absentee_memory = 0;
		proj_absentee_jobs, proj_absentee_cpu = 0;
		abs_user_count = 0;
		iod_count = 0;
		noted = 0;
		user_count = 0;
		do j = 1 to 4;
		     project_total.absentee (j).charge = 0e0;
		     project_total.absentee (j).jobs = 0;
		     project_total.absentee (j).cpu = 0;
		     project_total.absentee (j).memory = 0e0;
		     project_total.iod (j).charge = 0e0;
		     project_total.iod (j).pieces = 0;
		     project_total.iod (j).lines = 0;
		     project_total.iod (j).pages = 0;
		end;
		do j = 1 to 16;
		     project_total.devices (j) = 0e0;
		end;
		proj_iod_pieces, proj_iod_lines = 0;
		proj_iod_pages = 0;

/* Now set up the "grade" array y, which orders the users in the project alphabetically. */

		begin;				/* get stack frame for x and y arrays, big enough to hold all users on this project */

dcl  x (pdt.current_size) char (32) aligned;
dcl  y (pdt.current_size) fixed bin;


		     m = 0;
		     lodate_bin = 0;		/* zero lodate before each project is processed */
		     do jj = 1 to pdt.current_size;	/* copy usage from each PDT */
			pdtep = addr (pdt.user (jj)); /* get pointer to user array */
			m = m + 1;
			if user.state = 0 then x (m) = ""; /* if user not active */
			else do;
			     if user.person_id = "*" then x (m) = "anonymous users";
			     else x (m) = user.person_id; /* array of user names in project */

			     if lodate_bin = 0 then	/* if we have no nonzero date yet */
				lodate_bin = user.time_last_reset; /* pick up this one */
			     else			/* however, if we already have a nonzero date */
			     if user.time_last_reset > 0 then /* only if this one is nonzero and */
				if user.time_last_reset < lodate_bin then /* less than the one we already have */
				     lodate_bin = user.time_last_reset; /* will we pick up this one */

			     if user.last_update > hidate_bin then hidate_bin = user.last_update;
			end;
			y (m) = jj;		/* index array of users in project */
skip1:		     end;
		     call date_time_ (hidate_bin, hidate); /* Set up dates for report. */
		     call date_time_ (lodate_bin, lodate); /* ... */
		     call idsort_ (x, y, m);

/* First page of bill for each project is summary of charges. Goes on long and short bills */

		     call mailing_page_ (mc, (projfile.sup (k)), (projfile.sup_addr (k)));
		     page, page_s = 1;
		     call projhead (lng, title1, col1, page, linct);
		     call projhead (sht, title1, col1, page_s, linct_s);

		     do jj = 1 to m;
			pdtep = addr (pdt.user (y (jj)));
			if x (y (jj)) = "" then go to endsloop;

			user_interactive_chg = 0e0;
			user_absentee_chg = 0e0;
			user_iod_chg = 0e0;
			user_device_chg = 0e0;

			if user.state = 2 then do;	/* User deleted during month? */
			     noted = noted + 1;
			     note = "*";
			end;
			else note = "";
			user_total_chg = 0e0;	/* initialize $charge for each user */
			do j = 0 to 7;
			     user_interactive_chg = user_interactive_chg + user.interactive (j).charge;
			     project_total.interactive (j).charge
				= project_total.interactive (j).charge + user.interactive (j).charge;
			     proj_interactive_chg = proj_interactive_chg + user.interactive (j).charge;
			     grand_total.interactive (j).charge
				= grand_total.interactive (j).charge + user.interactive (j).charge;
			     grand_interactive_chg = grand_interactive_chg + user.interactive (j).charge;
			end;
			do j = 1 to 4;
			     user_absentee_chg = user_absentee_chg + user.absentee (j).charge;
			     project_total.absentee (j).charge = project_total.absentee (j).charge + user.absentee (j).charge;
			     proj_absentee_chg = proj_absentee_chg + user.absentee (j).charge;
			     grand_total.absentee (j).charge = grand_total.absentee (j).charge + user.absentee (j).charge;
			     grand_absentee_chg = grand_absentee_chg + user.absentee (j).charge;
			     user_iod_chg = user_iod_chg + user.iod (j).charge;
			     project_total.iod (j).charge = project_total.iod (j).charge + user.iod (j).charge;
			     proj_iod_chg = proj_iod_chg + user.iod (j).charge;
			     grand_total.iod (j).charge = grand_total.iod (j).charge + user.iod (j).charge;
			     grand_iod_chg = grand_iod_chg + user.iod (j).charge;
			end;
			do j = 1 to 16;
			     proj_device_chg = proj_device_chg + user.devices (j);
			     grand_device_chg = grand_device_chg + user.devices (j);
			     user_device_chg = user_device_chg + user.devices (j);
			     project_total.devices (j) = project_total.devices (j) + user.devices (j);
			     grand_total.devices (j) = grand_total.devices (j) + user.devices(j);
			end;
			user_total_chg = prices (r).reg_price + user.dollar_charge; /* compute $charge each user */
			proj_total_chg = proj_total_chg + user_total_chg;
			grand_total_chg = grand_total_chg + user_total_chg;
			proj_registration_chg = proj_registration_chg + prices (r).reg_price;
			grand_registration_chg = grand_registration_chg + prices (r).reg_price;
			user_count = user_count + 1;	/* count number of users in the project */
			numusers = numusers + 1;	/* count number of users in the system */
			call ioa_$ioa_stream (both, fmt1, note, x (y (jj)),
			     cv_$mwvf (user_interactive_chg), cv_$mwvf (user_absentee_chg), cv_$mwvf (user_iod_chg),
			     cv_$mwvf (prices (r).reg_price), cv_$mwvf (user_device_chg), cv_$mwvf (user_total_chg));
			linct = linct + 2;
			linct_s = linct_s + 2;
			if linct > 50 then call projhead (lng, title1, col1, page, linct);
			if linct_s > 50 then call projhead (sht, title1, col1, page_s, linct_s);
endsloop:
		     end;


/* Now put out bottom lines of charge summary page. */

		     if linct > 46 then call projhead (lng, title1, col1, page, linct);
		     if linct_s > 46 then call projhead (sht, title1, col1, page_s, linct_s);
		     call ioa_$ioa_stream (both, "^10x^a^/", dash);
		     if user_count = 1 then dn = "1 user";
		     else call ioa_$rsnnl ("^d users", dn, t1, user_count);
		     call ioa_$ioa_stream (both, fmt1, "", dn,
			cv_$mwvf (proj_interactive_chg), cv_$mwvf (proj_absentee_chg), cv_$mwvf (proj_iod_chg),
			cv_$mwvf (proj_registration_chg), cv_$mwvf (proj_device_chg), cv_$mwvf (proj_total_chg));

		     call subtotal;

/* Interactive usage summary page. Long bill only */

		     if proj_interactive_chg > 0e0 then do; /* if proj active during month, bill */
						/* if no interactive charge, go to check absentee charge */
			call projhead (lng, title2, col2, page, linct);
			do jj = 1 to m;		/* Loop on all PDT entries for interactive use */
			     pdtep = addr (pdt.user (y (jj)));
			     if x (y (jj)) = "" then go to enduloop;

			     user_interactive_chg = 0e0;
			     user_interactive_cpu = 0;
			     user_interactive_memory = 0;
			     user_interactive_connect = 0;
			     user_interactive_ioops = 0;

			     note = "";
			     if user.state = 2 then note = "*";
			     do j = 0 to 7;		/* charge usage on all shifts */
				user_interactive_cpu = user_interactive_cpu + user.interactive (j).cpu;
				user_interactive_chg = user_interactive_chg + user.interactive (j).charge;
				cpu_tim (j) = cvt (user.interactive (j).cpu); /* convert time to print */
				user_interactive_memory = user_interactive_memory + user.interactive (j).core;
				memry_usge (j) = float ((user.interactive (j).core)/1e6); /* print format memry usage */
				user_interactive_connect = user_interactive_connect + user.interactive (j).connect;
				connect_tim (j) = cvt (user.interactive (j).connect);
				user_interactive_ioops = user_interactive_ioops + user.interactive (j).io_ops;
				trmnl_ioops (j) = float ((user.interactive (j).io_ops)/ 1e3); /* divide for printing */
						/* increase proj totals */
				project_total.interactive (j).cpu
				     = project_total.interactive (j).cpu + user.interactive (j).cpu;
				project_total.interactive (j).core
				     = project_total.interactive (j).core + user.interactive (j).core;
				project_total.interactive (j).connect
				     = project_total.interactive (j).connect + user.interactive (j).connect;
				project_total.interactive (j).io_ops
				     = project_total.interactive (j).io_ops + user.interactive (j).io_ops;
				proj_interactive_cpu = proj_interactive_cpu + user.interactive (j).cpu;
				proj_interactive_connect = proj_interactive_connect + user.interactive (j).connect;
				proj_interactive_ioops = proj_interactive_ioops + user.interactive (j).io_ops;
				proj_interactive_memory = proj_interactive_memory + user.interactive (j).core;
						/* increase grand totals */
				grand_total.interactive (j).cpu
				     = grand_total.interactive (j).cpu + user.interactive (j).cpu;
				grand_total.interactive (j).core
				     = grand_total.interactive (j).core + user.interactive (j).core;
				grand_total.interactive (j).connect
				     = grand_total.interactive (j).connect + user.interactive (j).connect;
				grand_total.interactive (j).io_ops
				     = grand_total.interactive (j).io_ops + user.interactive (j).io_ops;
				grand_interactive_cpu = grand_interactive_cpu + user.interactive (j).cpu;
				grand_interactive_connect = grand_interactive_connect + user.interactive (j).connect;
				grand_interactive_ioops = grand_interactive_ioops + user.interactive (j).io_ops;
				grand_interactive_memory = grand_interactive_memory + user.interactive (j).core;
			     end;
			     project_total.logins = project_total.logins + user.logins;
			     grand_total.logins = grand_total.logins + user.logins;
			     project_total.crashes = project_total.crashes + user.crashes;
			     grand_total.crashes = grand_total.crashes + user.crashes;

/* write one line on interactive charge page */

			     lin_incrm = 3;
			     do j = 0 to 7;
				if user.interactive (j).charge > 0e0
				| user.interactive (j).cpu > 0
				| user.interactive (j).connect > 0
				| user.interactive (j).io_ops > 0
				| user.interactive (j).core > 0
				then do;

				     call ioa_$ioa_stream (lng, format, x (y (jj)), shift_label (j),
					cpu_tim (j), connect_tim (j),
					trmnl_ioops (j), memry_usge (j),
					cv_$mwvf (user.interactive (j).charge));
				     lin_incrm = lin_incrm + 1;
				end;
			     end;
			     linct = linct + lin_incrm;

			     if user.logins = 0 then call ioa_$ioa_stream (lng, formatz, note, x (y (jj)));
			     else call ioa_$ioa_stream (lng, format1, note, x (y (jj)), total,
				cvt (user_interactive_cpu),
				cvt (user_interactive_connect),
				float (user_interactive_ioops/1e3), float (user_interactive_memory/1e6),
				user.logins, user.crashes, cv_$mwvf (user_interactive_chg));
			     if linct > 48 then call projhead (lng, title2, col2, page, linct);
enduloop:			end;

/* Total line for interactive usage page */

			if user_count > 1 then do;	/* omit total if one user */
			     do j = 0 to 7;		/* Convert project totals to ASCII. */
				cpu_tim (j) = cvt (project_total.interactive (j).cpu);
				connect_tim (j) = cvt (project_total.interactive (j).connect);
				trmnl_ioops (j) = float ((project_total.interactive (j).io_ops)/1e3);
						/* terminal i/o operations ready for printing */
				memry_usge (j) = float ((project_total.interactive (j).core)/1e6);
			     end;
			     call ioa_$ioa_stream (lng, "^10x^a^/", dash);

			     call ioa_$ioa_stream (lng, formatA, p_header);
			     linct = linct + 3;
			     if linct > 46 then call projhead (lng, title2, col2, page, linct);
			     do j = 0 to 7;
				if project_total.interactive (j).charge > 0e0 then do;
				     call ioa_$ioa_stream (lng, format, "", shift_label (j), cpu_tim (j), connect_tim (j),
					trmnl_ioops (j), memry_usge (j),
					cv_$mwvf (project_total.interactive (j).charge));
				end;
			     end;
			     call ioa_$rsnnl ("^d users", dn, j, user_count);
			     call ioa_$ioa_stream (lng, format1, "", dn, total, cvt (proj_interactive_cpu),
				cvt (proj_interactive_connect),
				float (proj_interactive_ioops/1e3), float (proj_interactive_memory/1e6), project_total.logins,
				project_total.crashes, cv_$mwvf (proj_interactive_chg));
			end;
		     end;

/* Absentee usage report page comes next. Long bill only */

		     if proj_absentee_chg > 0e0 then do; /* if proj had any absentee charge for month, bill */
						/* else go check io usage */
			call projhead (lng, title3, col3, page, linct);
			do jj = 1 to m;		/* Loop through PDT again, for absentee use */
			     pdtep = addr (pdt.user (y (jj)));
			     if x (y (jj)) = "" then go to endaloop;

			     user_absentee_chg = 0e0;
			     user_absentee_cpu = 0;
			     user_absentee_jobs = 0;
			     user_absentee_memory = 0;

			     do j = 1 to 4;
				user_absentee_chg = user_absentee_chg + user.absentee (j).charge;
				user_absentee_cpu = user_absentee_cpu + user.absentee (j).cpu;
				user_absentee_jobs = user_absentee_jobs + user.absentee (j).jobs;
				user_absentee_memory = user_absentee_memory + user.absentee (j).memory;
				project_total.absentee (j).jobs = project_total.absentee (j).jobs + user.absentee (j).jobs;
				project_total.absentee (j).cpu = project_total.absentee (j).cpu + user.absentee (j).cpu;
				project_total.absentee (j).memory = project_total.absentee (j).memory + user.absentee (j).memory;
				proj_absentee_cpu = proj_absentee_cpu + user.absentee (j).cpu;
				proj_absentee_memory = proj_absentee_memory + user.absentee (j).memory;
				proj_absentee_jobs = proj_absentee_jobs + user.absentee (j).jobs;
				grand_total.absentee (j).jobs = grand_total.absentee (j).jobs + user.absentee (j).jobs;
				grand_total.absentee (j).cpu = grand_total.absentee (j).cpu + user.absentee (j).cpu;
				grand_total.absentee (j).memory = grand_total.absentee (j).memory + user.absentee (j).memory;
				grand_absentee_cpu = grand_absentee_cpu + user.absentee (j).cpu;
				grand_absentee_memory = grand_absentee_memory + user.absentee (j).memory;
				grand_absentee_jobs = grand_absentee_jobs + user.absentee (j).jobs;
				cpu_tim (j) = cvt (user.absentee (j).cpu);
				memry_usge (j) = float ((user.absentee (j).memory)/1e6);
skip:			     end;
			     if user_absentee_cpu = 0 then go to endaloop;
			     abs_user_count = abs_user_count + 1; /* count of absentee users */
			     lin_incrm = 3;
			     do j = 1 to 4;
				if user.absentee (j).charge > 0e0 then do;
				     call ioa_$ioa_stream (lng, absfmt, x (y (jj)), queue_label (j), user.absentee (j).jobs,
					cpu_tim (j), memry_usge (j), cv_$mwvf (user.absentee (j).charge));
				     lin_incrm = lin_incrm + 1;
				end;
			     end;

			     linct = linct + lin_incrm;
			     call ioa_$ioa_stream (lng, absfmt1, x (y (jj)), total, user_absentee_jobs,
				cvt (user_absentee_cpu), float (user_absentee_memory/1e6), cv_$mwvf (user_absentee_chg));
			     if linct > 48 then call projhead (lng, title3, col3, page, linct);
endaloop:			end;
			if abs_user_count > 1 then do; /* if more than one absentee users per proj */
			     if linct > 46 then call projhead (lng, title3, col3, page, linct);
			     call ioa_$ioa_stream (lng, "^10x^a^/", dash);
			     call ioa_$ioa_stream (lng, formatA, p_header);
			     do j = 1 to 4;
				if project_total.absentee (j).charge > 0e0 then do;
				     call ioa_$ioa_stream (lng, absfmt, "", queue_label (j),
					project_total.absentee (j).jobs,
					cvt (project_total.absentee (j).cpu), float (project_total.absentee (j).memory/1e6),
					cv_$mwvf (project_total.absentee (j).charge));
				end;
			     end;
			     call ioa_$ioa_stream (lng, absfmt1, project.project_id, "Total", proj_absentee_jobs,
				cvt (proj_absentee_cpu), float (proj_absentee_memory/1e6), cv_$mwvf (proj_absentee_chg));
			end;
		     end;

/* IO Daemon usage page. Long bill only */

		     if proj_iod_chg > 0e0 then do;
			call projhead (lng, title4, col4, page, linct);
			do jj = 1 to m;		/* Final trip through PDT for daemon usage */
			     pdtep = addr (pdt.user (y (jj)));
			     if x (y (jj)) = "" then go to endiloop;

			     user_iod_chg = 0e0;
			     user_iod_pieces = 0;
			     user_iod_lines = 0;
			     user_iod_pages = 0;

			     do j = 1 to 4;
				user_iod_chg = user_iod_chg + user.iod (j).charge;
				user_iod_pieces = user_iod_pieces + user.iod (j).pieces;
				user_iod_lines = user_iod_lines + user.iod (j).lines;
				user_iod_pages = user_iod_pages + user.iod (j).pages;
				project_total.iod (j).pieces = project_total.iod (j).pieces + user.iod (j).pieces;
				project_total.iod (j).lines = project_total.iod (j).lines + user.iod (j).lines;
				project_total.iod (j).pages = project_total.iod (j).pages + user.iod (j).pages;
				proj_iod_pieces = proj_iod_pieces + user.iod (j).pieces;
				proj_iod_lines = proj_iod_lines + user.iod (j).lines;
				proj_iod_pages = proj_iod_pages + user.iod (j).pages;
				grand_total.iod (j).pieces = grand_total.iod (j).pieces + user.iod (j).pieces;
				grand_total.iod (j).lines = grand_total.iod (j).lines + user.iod (j).lines;
				grand_total.iod (j).pages = grand_total.iod (j).pages + user.iod (j).pages;
				grand_iod_pieces = grand_iod_pieces + user.iod (j).pieces;
				grand_iod_lines = grand_iod_lines + user.iod (j).lines;
				grand_iod_pages = grand_iod_pages + user.iod (j).pages;
			     end;
			     if user_iod_chg = 0e0 then go to endiloop;
			     iod_count = iod_count + 1;
			     lin_incrm = 3;
			     do j = 1 to 4;
				if user.iod (j).charge > 0e0 then do;
				     call ioa_$ioa_stream (lng, dmnfmt, x (y (jj)), queue_label (j), user.iod (j).pieces,
					fixed (user.iod (j).lines, 35),
					fixed (user.iod (j).pages, 35),
					cv_$mwvf (user.iod (j).charge));
				     lin_incrm = lin_incrm + 1;
				end;
			     end;
			     linct = linct + lin_incrm;
			     call ioa_$ioa_stream (lng, dmnfmt1, x (y (jj)), total, user_iod_pieces,
				fixed (user_iod_lines, 35), fixed (user_iod_pages, 35), cv_$mwvf (user_iod_chg));
			     if linct > 48 then call projhead (lng, title4, col4, page, linct);
endiloop:			end;
			if iod_count > 1 then do;
			     if linct > 46 then call projhead (lng, title4, col4, page, linct);
			     call ioa_$ioa_stream (lng, "^10x^a^/", dash);
			     call ioa_$ioa_stream (lng, formatA, p_header);
			     do j = 1 to 4;
				if project_total.iod (j).charge > 0e0 then do;
				     call ioa_$ioa_stream (lng, dmnfmt, "", queue_label (j), project_total.iod (j).pieces,
					fixed (project_total.iod (j).lines, 35),
					fixed (project_total.iod (j).pages, 35),
					cv_$mwvf (project_total.iod (j).charge));
				end;
			     end;
			     call ioa_$ioa_stream (lng, dmnfmt1, project.project_id, total,
				proj_iod_pieces, fixed (proj_iod_lines, 35), fixed (proj_iod_pages, 35),
				cv_$mwvf (proj_iod_chg));
			end;
		     end;

/* Device usage page. */

		     if proj_device_chg > 0e0 then do;
			call projhead (lng, title5, col5, page, linct);
			device_count = 0;
			do jj = 1 to m;
			     pdtep = addr (pdt.user (y (jj)));
			     if x (y (jj)) = "" then go to enddloop;
			     named = "0"b;
			     do j = 1 to 16;
				if user.devices (j) ^= 0e0 then do;
				     device_count = device_count + 1;
				     if ^named then do;
					named = "1"b;
					call ioa_$ioa_stream (lng, "^/^10x^22a  ^8a ^15a",
					     x (y (jj)), prices (r).devtab_copy.device_id (j), cv_$mwvf (user.devices (j)));
					linct = linct + 2;
				     end;
				     else do;
					call ioa_$ioa_stream (lng, "^34x^8a ^15a",
					     prices (r).devtab_copy.device_id (j), cv_$mwvf (user.devices (j)));
					linct = linct + 1;
				     end;
				     if linct > 55 then call projhead (lng, title5, col5, page, linct);
				end;
			     end;
enddloop:			end;
			if device_count > 1 then do;
			     if linct > 55 then call projhead (lng, title5, col5, page, linct);
			     call ioa_$ioa_stream (lng, "^/^10x^a^/", dash);
			     call ioa_$ioa_stream (lng, "^10x^9a^24x^15a", project.project_id, cv_$mwvf (proj_device_chg));
			end;
		     end;

		     call hcs_$terminate_noname (pdtp, ec); /* terminate each pdt as you finish billing project */

		end;				/* END BEGIN BLOCK for PDT size */

endsatloop:    end;					/* end of this project. */


/* End of main loop on projects. */

	end;					/* END BEGIN BLOCK for SAT size */


/* -------------------------------------------------------- */

/* Check for and process any projects which had no SAT entry but are active in reqfile or projfile. */

exitm:	noted = 0;
	r = 0;					/* establish default rate structure index */
	do k = 1 to projfile.nproj;
	     if projfile.projfiletab (k).processed = 0
	     then if projfile.projfiletab (k).n_misc > 0 | projfile.projfiletab (k).disk_psec > 0 then do;
		     call ioa_ ("write_user_usage_report: projfile entry ""^a"" had no users.", projfile.projfiletab (k).id);
		     projfile.projfiletab (k).processed = 1;
		     numproj = numproj + 1;
		     tempf = 0e0;
		     do kk = 1 to reqfile.nacts;
			if projfile.projfiletab (k).id = reqfile.reqfiletab (kk).acctid then do;
			     reqfile.reqfiletab (kk).procssd = 1;
			     tempf = reqfile.reqfiletab (kk).chg_mo;
			     go to fpj1;
			end;
		     end;
		     call ioa_ ("^25xreqfile entry missing");
fpj1:		     proj_total_chg = tempf - projfile.projfiletab (k).misc_charges
			- prices (r).disk_price * projfile.projfiletab (k).disk_psec; /* Subtract out because subtotal adds back in */
		     page, page_s = 1;
		     call projhead (lng, title1, col1, page, linct);
		     call projhead (sht, title1, col1, page_s, linct_s);
		     call subtotal;
		end;
	end;

	do kk = 1 to reqfile.nacts;
	     if reqfile.reqfiletab (kk).procssd = 0 then if reqfile.reqfiletab (kk).chg_mo > 0e0 then do;
		     call ioa_ ("write_user_usage_report: reqfile entry ""^a"" $^.2f, 0 PDT charge",
			reqfile.reqfiletab (kk).acctid, reqfile.reqfiletab (kk).chg_mo);
		     reqfile.reqfiletab (kk).procssd = 1;
		end;
	end;

/* All finished. Put out final grand total page. */

	call ioa_$ioa_stream (sht, "^|^20x^a^/", cods);	/* Put out heading for grand total page. */
	call ioa_$ioa_stream (sht, "^30x^a^/", dpds);
	call ioa_$ioa_stream (sht, l3, "Grand Total", lodate, hidate);
	call ioa_$ioa_stream (sht, "^/^10xInteractive usage^/");
	call ioa_$ioa_stream (sht, col2);
	do j = 0 to 7;
	     if grand_total.interactive (j).charge > 0e0 then
		call ioa_$ioa_stream (sht, format, "", shift_label (j),
		cvt (grand_total.interactive (j).cpu), cvt (grand_total.interactive (j).connect),
		float (grand_total.interactive (j).io_ops/1e3), float (grand_total.interactive (j).core/1e6),
		cv_$mwvf (grand_total.interactive (j).charge));
	end;
	call ioa_$ioa_stream (sht, format1, "", "", "Total", /* Write usage total line */
	     cvt (grand_interactive_cpu), cvt (grand_interactive_connect), float (grand_interactive_ioops/1e3),
	     float (grand_interactive_memory/1e6), grand_total.logins, grand_total.crashes, cv_$mwvf (grand_interactive_chg));
	call ioa_$ioa_stream (sht, "^10x^a^/", dash);
	call ioa_$ioa_stream (sht, "^/^10xAbsentee usage^/");
	call ioa_$ioa_stream (sht, col3);
	do j = 1 to 4;
	     call ioa_$ioa_stream (sht, absfmt, "", queue_label (j),
		grand_total.absentee (j).jobs, cvt (grand_total.absentee (j).cpu),
		float (grand_total.absentee (j).memory/1e6), cv_$mwvf (grand_total.absentee (j).charge));
	end;
	call ioa_$ioa_stream (sht, absfmt1, "", "Total",
	     grand_absentee_jobs, cvt (grand_absentee_cpu), (grand_absentee_memory)/1e6,
	     cv_$mwvf (grand_absentee_chg));
	call ioa_$ioa_stream (sht, "^10x^a^/", dash);
	call ioa_$ioa_stream (sht, "^/^10xIO Daemon^/");
	call ioa_$ioa_stream (sht, col4);
	do j = 1 to 4;
	     call ioa_$ioa_stream (sht, dmnfmt, "", queue_label (j),
		grand_total.iod (j).pieces,
		fixed (grand_total.iod (j).lines, 35),
		fixed (grand_total.iod (j).pages, 35),
		cv_$mwvf (grand_total.iod (j).charge));
	end;
	call ioa_$ioa_stream (sht, dmnfmt1, "", "Total",
	     grand_iod_pieces, fixed (grand_iod_lines, 35), fixed (grand_iod_pages, 35),
	     cv_$mwvf (grand_iod_chg));
	call ioa_$ioa_stream (sht, "^10x^a^/", dash);
	if grand_device_chg > 0e0 then do;
	     call ioa_$ioa_stream (sht, "^/^10xOther Usage^/");
	     call ioa_$ioa_stream (sht, col5);
	     do j = 1 to 16;
		if grand_total.devices (j) ^= 0e0 then
		     call ioa_$ioa_stream (sht, "^34x^8a ^15a", prices (r).devtab_copy.device_id (j), cv_$mwvf (grand_total.devices (j)));
	     end;
	     call ioa_$ioa_stream (sht, "^/^34xTotal^4x^15a^/", cv_$mwvf (grand_device_chg));
	     call ioa_$ioa_stream (sht, "^10x^a^/", dash);
	end;
	call ioa_$ioa_stream (sht, col1);
	call ioa_$rsnnl ("^d users, ^d projects", dn, i, numusers, numproj);
	call ioa_$ioa_stream (sht, fmt1, "", dn,
	     cv_$mwvf (grand_interactive_chg), cv_$mwvf (grand_absentee_chg), cv_$mwvf (grand_iod_chg),
	     cv_$mwvf (grand_registration_chg), cv_$mwvf (grand_device_chg), cv_$mwvf (grand_total_chg));
	call ioa_$rsnnl (dskfmt, dn, j, grand_pmonths, grand_disk_quota, grand_disk_usage);
	call ioa_$ioa_stream (sht, ptlin, dn, cv_$mwvf (grand_disk_chg)); /* write out disk line */
	grand_total_chg = grand_total_chg + grand_disk_chg; /* Get final charge. */
	call ioa_$ioa_stream (sht, ptlin, "Total miscellaneous", cv_$mwvf (grand_misc_chg));
	grand_total_chg = grand_total_chg + grand_misc_chg; /* increase by total misc charges */
	call ioa_$ioa_stream (sht, "^/^10x^a", eqllin);
	call ioa_$ioa_stream (sht, ptlin, "Total non-billable", cv_$mwvf (nonbill_total));
	call ioa_$rsnnl ("Total billable from ^a to ^a", dn, j, lodate, hidate);
	call ioa_$ioa_stream (sht, ptlin, dn, cv_$mwvf (grand_total_chg - nonbill_total));
	call ioa_ ("End of user usage report. Grand total ^a", cv_$mwvf (grand_total_chg - nonbill_total));

exit:	call hcs_$terminate_noname (satp, ec);		/* Terminate sat. */
	call hcs_$terminate_noname (pp, ec);		/* Terminate projfile. */
	call hcs_$terminate_noname (qp, ec);		/* Terminate reqfile. */
	call hcs_$terminate_noname (miscfilep, ec);	/* Terminate miscfile */

	return;					/* FINAL EXIT */

/* ================================================================================================ */

/* Internal procedures. */

/* Subtotal for each project in usage report. */

subtotal:	proc;
	     if linct > 35 then call projhead (lng, title1, col1, page, linct); /* Check page bottom */
	     if linct_s > 44 then call projhead (sht, title1, col1, page_s, linct_s);
	     temp = projfile.projfiletab (k).disk_psec;	/* compute proj disk in page-secs */
	     pmonths = temp / 2592e3;			/* compute page-months */
	     proj_disk_chg = prices (r).disk_price * temp; /* compute disk charge per-proj. */
	     grand_disk_chg = grand_disk_chg + proj_disk_chg; /* total disk charge for all projects. */
	     grand_pmonths = grand_pmonths + pmonths;	/* ... and total page-months for all projects. */
	     proj_disk_quota = projfile.projfiletab (k).disk_quota; /* get proj quota from projfile */
	     proj_disk_usage = projfile.projfiletab (k).disk_use; /* get proj disk use */
	     grand_disk_quota = grand_disk_quota + proj_disk_quota; /* total quota for all projects. */
	     grand_disk_usage = grand_disk_usage + proj_disk_usage; /* total disk usage for all projects */
	     call ioa_$rsnnl (dskfmt, dn, j, pmonths, proj_disk_quota, proj_disk_usage);
	     call ioa_$ioa_stream (both, ptlin, dn, cv_$mwvf (proj_disk_chg)); /* Write disk total line. */
	     proj_total_chg = proj_total_chg + proj_disk_chg; /* Increase proj use by disk charge */

process_misc_charges:
	     if projfile.projfiletab (k).n_misc > 0 then do; /* any misc charges? */
		misc_chg = 0e0;
		do j = 1 to misc_file.misc_ents;	/* search journal */
		     if misc_file.misctab (j).mproj = projfile.projfiletab (k).id then do;
			misc_chg = misc_chg + misc_file.misctab (j).mamt;
			call ioa_$ioa_stream
			     (both, ptlin, misc_file.misctab (j).mdesc, cv_$mwvf (misc_file.misctab (j).mamt));
		     end;
		end;
		if misc_chg ^= projfile.projfiletab (k).misc_charges then /* Check journal against summary */
		     call ioa_ ("write_user_usage_report: total for ""^a"" from ""miscfile"" is $^.2f, projfile has $^.2f",
		     projfile.projfiletab (k).id, misc_chg, projfile.projfiletab (k).misc_charges);
						/* We will use the number from projfile */
		proj_total_chg = proj_total_chg + projfile.projfiletab (k).misc_charges;
						/* increase proj total by misc chgs */
		grand_misc_chg = grand_misc_chg + projfile.projfiletab (k).misc_charges;
	     end;

	     call ioa_$ioa_stream (both, "^/^10xAccount number ^a, requsition ^a",
		reqfile.reqfiletab (kk).mitacct, reqfile.reqfiletab (kk).reqno);
	     if reqfile.reqfiletab (kk).mitacct = "nonbill" then do;
		nonbill_total = nonbill_total + proj_total_chg;
		tempf = 0e0;			/* avoid discrepancy comment */
	     end;
	     else tempf = proj_total_chg - reqfile.reqfiletab (kk).chg_mo;
						/* Calculate difference between pdt charge and reqfile */
	     if tempf < 0.005e0 then if tempf > -0.005e0 then go to ok; /* Check to make sure billing ok. */
	     call ioa_ ("write_user_usage_report: total for ""^a"" in ""reqfile"" is $^.2f, PDT total $^.2f",
		reqfile.reqfiletab (kk).acctid, reqfile.reqfiletab (kk).chg_mo, proj_total_chg); /* Gripe */
	     proj_total_chg = reqfile.reqfiletab (kk).chg_mo; /* But tell him what he was really charged */

ok:	     call ioa_$ioa_stream (both, "^/^10x^a", eqllin);

	     call ioa_$rsnnl ("Charge for ""^a""", dn, j, projfile.projfiletab (k).id);
	     call ioa_$ioa_stream (both, ptlin, dn, cv_$mwvf (proj_total_chg)); /* write proj total */

	     if noted > 0 then			/* Were any users deleted? */
		call ioa_$ioa_stream (both, "^/^8x* user deleted during the month");

/* list installation resource prices */

	     call ioa_$ioa_stream (mc, "^/^/^20xThe following prices are used: ");
	     if rs_count > 0 then			/* if site has multiple rate structures */
		call ioa_$ioa_stream (both, "^/^/^20xRate structure: ^a", prices (r).rs_name); /* print this one's name */
	     call ioa_$ioa_stream (mc, "^/^25xInteractive: ");
	     call ioa_$ioa_stream (mc, "^/^35xCPU^12xConnect^12xTerminal I/O^14xMemory");
	     do ix = 0 to 7;
		if prices (r).interactive_cpu_price (ix) + prices (r).connect_price (ix) > 0e0 then
		     call ioa_$ioa_stream (mc, "^12xshift ^1d ^15a/hr ^15a/hr ^15a/K lines ^15a/Kmu",
		     ix, cv_$mwvf (prices (r).interactive_cpu_price (ix)), cv_$mwvf (prices (r).connect_price (ix)), cv_$mwvf (prices (r).ioops_price (ix)),
		     cv_$mwvf (prices (r).core_price (ix)));
	     end;
	     call ioa_$ioa_stream (mc, "^/^28xAbsentee:^25xIO Daemon:");
	     call ioa_$ioa_stream (mc, "^/^35xCPU^14xMemory^18xPrint");
	     do ix = 1 to 4;
		call ioa_$ioa_stream (mc, "^12xqueue ^1d ^15a/hr ^15a/Kmu^15a/K lines",
		     ix, cv_$mwvf (prices (r).abs_cpu_price (ix)), cv_$mwvf (prices (r).abs_memory_price (ix)),
		     cv_$mwvf (prices (r).lines_price (ix)));
	     end;
	     call ioa_$ioa_stream (mc, "^/^20x^a/month registration fee per user", cv_$mwvf (prices (r).reg_price));
	     call ioa_$ioa_stream (mc, "^20x^a/disk page per month (^f per page-second)",
		cv_$mwvf (prices (r).disk_price*30*24*3600), prices (r).disk_price);
	     call ioa_$ioa_stream (mc, "^/^10xAll usage is shown truncated up to the next highest minute.");

/* Footnote processing */

	     if notep ^= null then do;
		call ioa_$ioa_stream (mc, "");	/* blank line before */
		oix = 1;
		do ix = 1 to notel;
		     if notes.ch (ix) = NL then do;
			dn = substr (notestr, oix, ix-oix);
			call ioa_$ioa_stream (mc, "^a", dn);
			oix = ix+1;
		     end;
		end;
	     end;

	     return;
	end subtotal;

/* ------------------------------- */

projhead:	proc (stream, ttitle, colhd, pagno, lct);

/* procedure for  making project headers */

dcl (stream, ttitle, colhd) char (*) aligned,
    (pagno, lct) fixed bin;

	     call ioa_$ioa_stream (stream, "^|^20x^a^/", cods); /* put out heading */
	     call ioa_$ioa_stream (stream, "^30x^a^/", dpds); /* ... */
	     call ioa_$ioa_stream (stream, l3, ttitle, lodate, hidate);
	     call ioa_$ioa_stream (stream, l4, projfile.projfiletab (k).id, projfile.projfiletab (k).title, pagno,
		sup (k), sup_addr (k));
	     call ioa_$ioa_stream (stream, colhd);
	     call ioa_$ioa_stream (stream, "^10x^a^/", dash);
	     pagno = pagno + 1;
	     lct = 18;
	end projhead;

/* ---------------------------------- */

cvt:	proc (time) returns (char (8) aligned);

/* procedure to convert time from fixed bin (71) to a nice formatted string of hrs: mins */

dcl  time fixed bin (71),
     j fixed bin,
     hours fixed bin,
     minutes fixed bin,
     answer char (8) aligned;

	     if time = 0 then return (" ");
	     minutes = divide ((time+SIXTYMILLION-1), SIXTYMILLION, 35, 0);
	     hours = divide (minutes, 60, 35, 0);
	     minutes = mod (minutes, 60);		/* get rid of the remainder */

	     call ioa_$rsnnl ("^5d:^2d", answer, j, hours, minutes);
	     if substr (answer, 7, 1) = " " then substr (answer, 7, 1) = "0";
						/* if less than 10 minutes, tidy up format */

	     return (answer);
	end;

     end write_user_usage_report;





		    bull_copyright_notice.txt       08/30/05  1008.4r   08/30/05  1007.3    00020025

                                          -----------------------------------------------------------


Historical Background

This edition of the Multics software materials and documentation is provided and donated
to Massachusetts Institute of Technology by Group Bull including Bull HN Information Systems Inc. 
as a contribution to computer science knowledge.  
This donation is made also to give evidence of the common contributions of Massachusetts Institute of Technology,
Bell Laboratories, General Electric, Honeywell Information Systems Inc., Honeywell Bull Inc., Groupe Bull
and Bull HN Information Systems Inc. to the development of this operating system. 
Multics development was initiated by Massachusetts Institute of Technology Project MAC (1963-1970),
renamed the MIT Laboratory for Computer Science and Artificial Intelligence in the mid 1970s, under the leadership
of Professor Fernando Jose Corbato.Users consider that Multics provided the best software architecture for 
managing computer hardware properly and for executing programs. Many subsequent operating systems
incorporated Multics principles.
Multics was distributed in 1975 to 2000 by Group Bull in Europe , and in the U.S. by Bull HN Information Systems Inc., 
as successor in interest by change in name only to Honeywell Bull Inc. and Honeywell Information Systems Inc. .

                                          -----------------------------------------------------------

Permission to use, copy, modify, and distribute these programs and their documentation for any purpose and without
fee is hereby granted,provided that the below copyright notice and historical background appear in all copies
and that both the copyright notice and historical background and this permission notice appear in supporting
documentation, and that the names of MIT, HIS, Bull or Bull HN not be used in advertising or publicity pertaining
to distribution of the programs without specific prior written permission.
    Copyright 1972 by Massachusetts Institute of Technology and Honeywell Information Systems Inc.
    Copyright 2006 by Bull HN Information Systems Inc.
    Copyright 2006 by Bull SAS
    All Rights Reserved
