	.TITLE	CNTRPRC_CSV
	.IDENT	/V1-001/
;++
;1 CNTRPRC_CSV	
; Programme to dump monitor data as comma seperated variables (CSV) to file. 
; All avaiable data is dumped in format:
;  variable name,sam1,sam2, ... samN
; Header (1st line) is:
; Variable,date1,date2,...,dateN
; Data is aligned such that dates run from oldest to newest.
; Note:
; The dates are taken from the 1st record and it is ASSUMED that all other
; records follow the same time pattern. In normal operation this is safe
; however, it is not guaranteed. Anomolies in the resulting data should
; be checked against this assumption.
; The resulting file name is fixed (CSVOUTP.DAT)
;2 Modifications:
; 001	Apr-2004	PB	Creation
;	
;--
	.library        /CNTPRC.MLB/
        $IODEF                          ;Define I/O functions and modifiers
	$SSDEF
	CNTRPRCDEF			; Counter processing
	

	.PSECT	CNTRPRC_CSV_D,WRT,NOEXE,PIC,SHR,QUAD

File:
CNTRPRCFAB:	$FAB  FAC = <DEL,UPD,GET,PUT>,- ; Access
		SHR = <DEL,UPD,GET,PUT>,- 	; Share with anyone
		FOP = CIF,-
		ORG = IDX,-			; Keyed file (Finally)
		FNM = <CNTRPRC>,-      		; Filename 
		DNM = <CNTRPRC.DAT.>,-      	; Filename 
		MRS = CTPRECSIZE,-
		XAB = CNTRPRCXAB
CNTRPRCRAB:	
		$RAB  FAB = CNTRPRCFAB,-        ; Record 
		ROP = NLK,-			; Do not lock
 		RBF = CNTRPRCREC,-
		UBF = CNTRPRCREC,-
		USZ = CTPRECSIZE,-
		RSZ = CTPRECSIZE,-
		RAC = KEY,-		 	; KEY access
		KBF = KEY_BUF,-
		KSZ = 112
CNTRPRCXAB:
	  	$XABKEY	REF = 0,-  		; Primary key
		DTP = STG,-            		; Key = 12 Bytes
		POS = 0,-               	; Key position
		SIZ = 112,-              	; Key len
                NXT = CNTRPRCXAB1
CNTRPRCXAB1:
	  	$XABKEY	REF = 1,-  	; Second key
		DTP = STG,-            	; Key = 8 Bytes(node name space padded)
		POS = 0,-               ; Key position
		SIZ = 8,-               ; Key len
                FLG = <DUP>,-           ; Duplicates, changes allowed
                NXT = CNTRPRCXAB2
CNTRPRCXAB2:
	  	$XABKEY	REF = 2,-  	; 
		DTP = BN4,-             ; FACILITY
		POS = 8,-               ; Key position
		SIZ = 4,-               ; Key len
                FLG = <DUP>,-           ; Duplicates, changes allowed
                NXT = CNTRPRCXAB3
CNTRPRCXAB3:
	  	$XABKEY	REF = 3,-  	; 
		DTP = BN4,-             ; Code
		POS = 12,-              ; Key position
		SIZ = 4,-               ; Key len
                FLG = <DUP>,-           ; Duplicates, changes allowed
                NXT = CNTRPRCXAB4
CNTRPRCXAB4:
	  	$XABKEY	REF = 4,-  	 ; 
		DTP = STG,-              ; Facility specific
		POS = 16,-               ; Key position
		SIZ = 96,-               ; Key len
                FLG = <DUP>              ; Duplicates, changes allowed

;
	.ALIGN	QUAD
KEY_BUF:		
CNTRPRCREC:             .BLKB	CTPRECSIZE
KEY_ARRAY:		.BLKB	CTP_C_KEYSIZ*400
;
CSVOUTPFAB:	$FAB  FAC = <DEL,UPD,GET,PUT>,- ; Access
		SHR = <DEL,UPD,GET,PUT>,- 	; Share with anyone
		RAT = CR,-
		FNM = <CSVOUTP>,-      		; Filename 
		DNM = <CSVOUTP.DAT.>      	; Filename 
CSVOUTPRAB:	
		$RAB  FAB = CSVOUTPFAB,-        ; Record 
 		RBF = FAOBUF,-
		UBF = FAOBUF

; FAO
FAOLST:		.BLKL	4000
FAOLST_LEN = .-FAOLST
FAOBUF:		.BLKL	5000
FAOBUF_LEN = .-FAOBUF
FAODESC:
FAOLEN:		.LONG	.-FAOBUF
		.ADDRESS  FAOBUF

SAMSTRI:	.ASCID	/ !#(UL),/
SAMSTRF:	.ASCID	/ !AC,!#(AD)/
TIMESTR:	.ASCID	/ !%D,!#(AD)/
INTFMT:		.ASCID	/!UL,/


	.ALIGN quad

; Misc
OUTP:           .BLKL	2000		; Strings here
OUTP_SIZ = .-OUTP
TEMPBUF:	.BLKB	24
TEMPDESC:	.LONG	.-TEMPBUF
		.ADDRESS  TEMPBUF
TEMPBUF2:	.BLKB	24
TEMPDESC2:	.LONG	.-TEMPBUF2
		.ADDRESS  TEMPBUF2
TEMPDESC3:	.QUAD

CNTR:		.LONG	0
LASTSEEN:	.LONG	0
FLTLEN:		.LONG	0
RECCNT:		.LONG	0
CDXLT:		.LONG	0
TABPNT:		.LONG	0
       
	.PSECT CNTRPRC_CSV_C,EXE,NOWRT,LONG

	.CALL_ENTRY	MAX_ARGS=12, HOME_ARGS=TRUE, -
			INPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>, -
			PRESERVE=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>, -
			LABEL=CNTRPRC_CSV
; 
	$OPEN	FAB=CNTRPRCFAB
	BSBW	ERROR_CHK		; Any error fatal
	$CONNECT RAB=CNTRPRCRAB
	BSBW	ERROR_CHK
        MOVB    #RAB$C_SEQ,CNTRPRCRAB+RAB$B_RAC
        CLRL	TABPNT
10$:					; 1ST CALL
        MOVW    #CTPRECSIZE,CNTRPRCRAB+RAB$W_USZ
        MOVW    #CTPRECSIZE,CNTRPRCRAB+RAB$W_RSZ
 
	$GET	RAB=CNTRPRCRAB
	BLBS	R0,20$
	RET
20$:
	MOVAL	CNTRPRCREC,R6
	MOVL	CTP_L_TBLPNT(R6),TABPNT
	PUSHAL	TABPNT
	PUSHAL	CNTRPRCREC
	CALLS	#2,G^CSV_COUNTERS
	BLBS	R0,30$
	RET
30$:
        MOVW    #CTPRECSIZE,CNTRPRCRAB+RAB$W_USZ
        MOVW    #CTPRECSIZE,CNTRPRCRAB+RAB$W_RSZ
 
	$GET	RAB=CNTRPRCRAB
	BLBS	R0,40$
	RET
40$:
	PUSHAL	TABPNT
	PUSHAL	CNTRPRCREC
	CALLS	#2,G^CSV_COUNTERS
	BLBS	R0,30$
	RET


; Subroutines
;
ERROR_CHK:
	.JSB_ENTRY	INPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>, -
			OUTPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>

	BLBC	R0,10$
	RSB
10$:
	$EXIT_S	R0				; Die

	.CALL_ENTRY	MAX_ARGS=12, HOME_ARGS=TRUE, -
			INPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>, -
			PRESERVE=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>, -
			LABEL=CSV_COUNTERS
; Routine to format SAMTBL within CNTRPRC rec as CSV. 
;
; Input = .address of CNTRREC to display
;	  .address of table pointer. on 1st call (=TBLPNT) pointer to 1st 
;		(oldest)
;		rec in array is returned. On subsequent call (.ne. TBLPNT) this
;		pointer is used as array number to start display at.
; Translate code to name and display this with samtbl in CSV format:
; Name, oldest sample, ..., newest sample. 
	MOVL	4(AP),R6
	MOVL	@8(AP),R7
	CMPL	R7,CTP_L_TBLPNT(R6)
	BNEQ	400$			; Br if not 1st call
                
; On 1st call:
; Determine start point (oldest time), create outp file, write header.
; TBLPNT is pointing to newest sample. If STCNT = MAXSAMPL , oldest
; sample is TBLPNT+1. If not (table not full), oldest sample = begin of 
; table.
	
	MOVL	CTP_X_STCNT(R6),R8
	BBC	#CTP_V_FLT,CTP_L_DTYP(R6),20$	; Br if not Floating data
	CVTFL	R8,R8				; Make int
20$:
	CMPL	R8,#CTP_C_MAXSMPL		; Table full?
	BEQL	30$  				; Br if so
	CLRL	@8(AP)				; Return oldest entry pos
	BRW	40$
30$:
	ADDL3	#1,R8,@8(AP)			; Return oldest entry pos
40$:
; Open outp file
	$CREATE	FAB=CSVOUTPFAB
	BSBW	ERROR_CHK		; Any error fatal
	$CONNECT RAB=CSVOUTPRAB
	BSBW	ERROR_CHK


	MOVL	@8(AP),R3			; Index oldest time
	MOVL	CTP_X_STCNT(R6),R4		; Sample count
	BBC	#CTP_V_FLT,CTP_L_DTYP(R6),360$	; Br if not Floating data
	CVTFL	R4,R4				; Make int

; 
360$:	
; Display times
	ADDL3	#CTP_TQ_TIMTBL,R6,R7		; Time origin
	MOVAL	OUTP,R9	     			; Strings
	MOVAL	FAOLST,R8      			; Descriptors (4000)
	MOVL    #OUTP_SIZ,R10   			; Str len
370$:
	MOVAQ	(R7)[R3],(R8)			; Addr of 1st date/time
	ADDL	#4,R8                           ; Next list item
	INCL	R3				; Next index
	CMPL	#CTP_C_MAXTBL,R3	        ; If past end ...
	BGEQ	380$                     	; 
	CLRL	R3	                        ; ... Wrap to begin 
380$:
	DECL	R4   
; Insert param count as next param
	MOVL	CTP_X_STCNT(R6),(R8)		; Sample count
	BBC	#CTP_V_FLT,CTP_L_DTYP(R6),382$	; Br if not Floating data
	CVTFL	(R8),(R8)				; Make int
382$:
	DECL	(R8)+
385$:
; Extract time from each date string for remainder of display
; Set up out desc
	MOVL	R10,TEMPDESC3		; Make desc
	MOVL	R9,TEMPDESC3+4
	PUSHL	#2			; TIME
	PUSHAL	TEMPDESC3			; 
	PUSHAQ	(R7)[R3]
	CALLS	#3,G^EXTRACT_DATE

	INCL	R3				; Next index
	CMPL	#CTP_C_MAXTBL,R3	        ; If past end ...
	BGEQ	386$                     	; 
	CLRL	R3	                        ; ... Wrap to begin 
386$:
	ADDL	TEMPDESC3,R9 			; Adjust pointers
	SUBL	TEMPDESC3,R10
	MOVQ	TEMPDESC3,(R8)                  ; Add desc to list
	ADDL	#8,R8                           ; Next desc
	SOBGTR	R4,385$

	MOVL	#FAOBUF_LEN,FAODESC
	PUSHAL	FAOLST
	PUSHAL	FAODESC
	PUSHAL	FAODESC
	PUSHAL	TIMESTR
	CALLS	#4,G^SYS$FAOL
	BLBS	R0,390$
	RET
390$:

	MOVW	FAODESC,CSVOUTPRAB+RAB$W_RSZ
	MOVW	FAODESC,CSVOUTPRAB+RAB$W_USZ
	$PUT	RAB=CSVOUTPRAB
	BLBS	R0,400$
	RET	
400$:
 ; Display Corresponding 8 samples
	BBS	#CTP_V_FLT,CTP_L_DTYP(R6),1000$	; Br if Floating data
	MOVL	@8(AP),R3
	MOVL	CTP_X_STCNT(R6),R4		; Sample count
	BBC	#CTP_V_FLT,CTP_L_DTYP(R6),401$	; Br if not Floating data
	CVTFL	R4,R4				; Make int
401$:
	ADDL3	#CTP_TF_SAMTBL,R6,R7		; SAM origin
	MOVAL	OUTP,R9	     			; Strings
	MOVAL	FAOLST,R8      			; Descriptors (512)
	MOVL    #OUTP_SIZ,R10   		; Str len
; Insert name as 1st param
	PUSHL	R8			; Addr here
	PUSHL	CTP_L_CODE(R6)		; (TEMP)
	CALLS	#2,G^XLATE_RMI
        ADDL	#4,R8
	SUBL	#4,R10
; Insert param count as next param
	MOVL	R4,(R8)+		; Sample count

; Set up out desc
405$:
	MOVL	R10,TEMPDESC3		; Make desc
	MOVL	R9,TEMPDESC3+4
	PUSHL	(R7)[R3]                ; Value
	PUSHAL	TEMPDESC3			; Len
	PUSHAL	TEMPDESC3		; 
	PUSHAL	INTFMT
	CALLS	#4,G^SYS$FAO
        BLBS	R0,410$
	RET
410$:
	INCL	R3				; Next index
	CMPL	#CTP_C_MAXTBL,R3	        ; If past end ...
	BGEQ	415$                     	; 
	CLRL	R3	                        ; ... Wrap to begin 
415$:
	MOVL	TEMPDESC3,(R8)+                  ; Add desc to list
	MOVL	R9,(R8)+
	ADDL	TEMPDESC3,R9 			; Adjust pointers
	SUBL	TEMPDESC3,R10
	SOBGTR	R4,405$

	MOVL	#FAOBUF_LEN,FAODESC
	PUSHAL	FAOLST
	PUSHAL	FAODESC
	PUSHAL	FAODESC
	PUSHAL	SAMSTRF
	CALLS	#4,G^SYS$FAOL
	BLBS	R0,420$
	RET
420$:
	MOVW	FAODESC,CSVOUTPRAB+RAB$W_RSZ
	MOVW	FAODESC,CSVOUTPRAB+RAB$W_USZ
	$PUT	RAB=CSVOUTPRAB
	RET	
	
1000$:
; Display floating data                                              \
	MOVL	@8(AP),R3
	MOVL	CTP_X_STCNT(R6),R4		; Sample count
        CVTFL	R4,R4
	ADDL3	#CTP_TF_SAMTBL,R6,R7		; Time origin
	MOVAL	OUTP,R9	     			; Strings
	MOVAL	FAOLST,R8      			; Descriptors (512)
	MOVL    #OUTP_SIZ,R10   			; Str len

1010$:
; Set up out desc
	MOVL	R10,TEMPDESC3		; Make desc
	MOVL	R9,TEMPDESC3+4
	PUSHAL	FLTLEN			; Len
	PUSHAL	TEMPDESC3		; 
	PUSHL	(R7)[R3]                ; Value
	CALLS	#3,G^FAO_FFLOAT
        BLBS	R0,1020$
	RET
1020$:
	INCL	R3				; Next index
	CMPL	#CTP_C_MAXTBL,R3	        ; If past end ...
	BGEQ	1030$                     	; 
	CLRL	R3	                        ; ... Wrap to begin 
1030$:
	MOVL	FLTLEN,(R8)+                  ; Add desc to list
	MOVL	R9,(R8)+
	ADDL	FLTLEN,R9 			; Adjust pointers
	SUBL	FLTLEN,R10
	SOBGTR	R4,1010$

	MOVL	#FAOBUF_LEN,FAODESC
	PUSHAL	FAOLST
	PUSHAL	FAODESC
	PUSHAL	FAODESC
	PUSHAL	SAMSTRF
	CALLS	#4,G^SYS$FAOL
	BLBS	R0,420$
	RET

        
	.CALL_ENTRY	MAX_ARGS=12, HOME_ARGS=TRUE, -
			INPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>, -
			PRESERVE=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>, -
			LABEL=EXTRACT_DATE
;++
;2 EXTRACT_DATE
; Routine to take binary time, convert it to ascii and return the date
; or time portion. The routine writes the entire date string to the outp desc
; then adjusts the len to include the selected field only. Thus the outp desc 
; must be at least 23 bytes though the len returned is always 11(date) or 
; 8 (time). To facilitate CSV construction, a , is added to the end of the
; field when time is requested. Thus time is retuned as 9 bytes.
;3 Inputs
; .address of .quad VMS binary time to convert
; .address of desc pointing to outp area. Must be at least 23 bytes long
; .long flag - 2 = time. any other param defaults to date. 
;3 Outputs
;  The entire date string is produced in the outp area and then 
; manipulated to return the desired field.
;3 Returns
;	SS$_NORMAL	OK
; any from $ASCTIM
;--

	CLRL	-(SP)			; cvtflg
	PUSHL	4(AP)
	PUSHL	8(AP)
	PUSHL	8(AP)
	CALLS	#4,G^SYS$ASCTIM
        BLBS	R0,10$
	RET
10$:
	CMPL	12(AP),#2
	BEQL	20$
; Date
	MOVL	#11,@8(AP)
	MOVL	#SS$_NORMAL,R0
	RET
; Time
20$:
	MOVQ	@8(AP),R6
	MOVL	#8,R6
	ADDL3	#12,R7,R8
	MOVC3	R6,(R8),(R7)
; ADD ','
	MOVB	#^A/,/,(R7)[R6]
	INCL	R6
	MOVQ	R6,@8(AP)
	MOVL	#SS$_NORMAL,R0
	RET

	.END	CNTRPRC_CSV
