;-------------------------------------------------------------------C
; show_file_macro.mar						    c
;								    c
;  FORMER NAME = SFFILER       January 1983                         c
;  Written by Denny Thury of Texas Instruments.  Stolen and added   C
;  Directory Managment (DM) by John C. Hayre, Texas Instruments.    C
;  Send suggestions and/or complaints to:                           C
;                                                                   C
;               Texas Instruments                                   C
;               P.O. Box 225012, MS 3618                            C
;               Dallas, Texas 75265                                 C
;               (Attention John Hayre)                              C
;                                                                   C
;  Phone: 214-995-3575                                              C
;-------------------------------------------------------------------C
	.TITLE	FILEMGR -- SHOWFILE FILE MANAGER
	.SUBTITLE MACRO DEFINITIONS
;
.MACRO	ON_ERROR DEST,?L
	BLBS	R0,L
	BRW	DEST
L:
.ENDM
	$DSCDEF
	.SUBTITLE DATA STRUCTURES
;
; THIS MODULE DEFINES ENTRY POINTS TO OPTIMIZE THE FILE OPERATIONS 
;  OF THE SHOWFILE PROGRAM.
;
; DATA STRUCTURES 
;
	.PSECT	FILEDATA,LONG,RD,WRT,NOSHR,PIC,NOEXE,REL,CON
;
REC_SIZE=132			; DEFAULT RECORD SIZE
;
SF_FAB:		$FAB	FAC=<GET>	; FAB - FILE NAME IS PASSED
;
SF_RAB:		$RAB	FAB=SF_FAB
;
OP_FAB:         $FAB    XAB=PR_XAB,SHR=<GET>
PR_XAB:         $XABPRO NXT=DA_XAB
DA_XAB:         $XABDAT NXT=SZ_XAB
SZ_XAB:         $XABFHC 
;
ER_FAB:         $FAB    FAC=<GET>
;
R1_FAB:         $FAB    FAC=<GET>
R2_FAB:         $FAB    FAC=<GET>
;
;--------------------------------------------------------------------
;
	.PSECT	RFABUFF,LONG,RD,WRT,NOSHR,PIC,NOEXE,REL,CON
;
; THIS SECTION RESERVES SPACE FOR A RECORD COUNT, WHICH WILL ACT AS
; AN INDEX INTO A "RECORD'S FILE ADDRESS" ARRAY.  THE ARRAY WILL SAVE
; THE RECORD'S FILE ADDRESS OF EACH RECORD READ, ALLOWING RANDOM 
; ACCESS AT A LATER TIME.  EACH TIME THE FILE IS READ SEQUENTIALLY, 
; THE RECORD COUNT WILL BE INCREMENTED.  IF AN END-OF-FILE IS 
; ENCOUNTERED, A FLAG WILL BE SET SO NO FURTHER ATTEMPTS WILL BE 
; MADE TO READ ANOTHER RECORD
;
RECCNT:		.BLKL	1		; RECORD COUNTER
CURRENT:	.BLKL	1		; CURRENT RECORD ACCESSED
END_OF_FILE:	.BLKB	1		; END_OF_FILE FLAG
;
; A 20,000 X 6 BYTE ARRAY FOR SAVING THE "RFA" OF EACH RECORD READ.
;  ( THE RFA IS 6 BYTES LONG).
;
RFABUFF:	.BLKB	20000*6
;
; THE FOLLOWING PSECT MAPS WITH A FORTRAN COMMON SECTION DEFINING THE
;  USER'S READ BUFFER.
;
;--------------------------------------------------------------------
;
	.PSECT	LINE_BUFF,PIC,OVR,REL,GBL,SHR,NOEXE,RD,WRT,LONG
LINE_BUFF:	.BLKB	REC_SIZE
;
        .PSECT  LDATE,PIC,OVR,REL,GBL,SHR,NOEXE,RD,WRT,LONG
LDATE:          .BLKB   8
        .PSECT  LPROT,PIC,OVR,REL,GBL,SHR,NOEXE,RD,WRT,LONG
LPROT:          .BLKB   4
        .PSECT  LUIC1,PIC,OVR,REL,GBL,SHR,NOEXE,RD,WRT,LONG
LUIC1:          .BLKB   2
        .PSECT  LUIC2,PIC,OVR,REL,GBL,SHR,NOEXE,RD,WRT,LONG
LUIC2:          .BLKB   2
        .PSECT  DERR,PIC,OVR,REL,GBL,SHR,NOEXE,RD,WRT,LONG
DERR:           .BLKB   4
        .PSECT  FILE_SIZE,PIC,OVR,REL,GBL,SHR,NOEXE,RD,WRT,LONG
FILE_SIZE:      .BLKB   4
        .PSECT  FRST_FREE,PIC,OVR,REL,GBL,SHR,NOEXE,RD,WRT,LONG
FRST_FREE:      .BLKB   2
        .PSECT  CHKSUM,PIC,OVR,REL,GBL,SHR,NOEXE,RD,WRT,LONG
CHKSUM:         .BLKB   4
        .PSECT  CHKSIZ,PIC,OVR,REL,GBL,SHR,NOEXE,RD,WRT,LONG
CHKSIZ:         .BLKB   4
;
	.PAGE
	.SUBTITLE OPENFILE -- INITIALIZE FILE MANAGER
;
	.PSECT	FILEMGR,PIC,EXE,SHR,NOWRT,RD,REL,CON,LONG
;
; DEFINE STACK DISPLACEMENT FOR FILE NAME DESCRIPTOR ADDRESS
;
FILENAME=4
;
	.ENTRY	OPENFILE,^M<R2>
;
	MOVL		FILENAME(AP),R2 ; GET ADDRESS OF FILE 
;                        DESCRIPTOR AND SET FILE NAME AND SIZE IN FAB
	MOVL		DSC$A_POINTER(R2),SF_FAB+FAB$L_FNA
	MOVB		DSC$W_LENGTH(R2),SF_FAB+FAB$B_FNS
;
	$OPEN		FAB=SF_FAB	; OPEN THE FILE
	ON_ERROR	EXIT		; TERMINATE IF ERROR
;
	$CONNECT	RAB=SF_RAB	; CONNECT RAB TO FAB
	ON_ERROR	EXIT		; TERMINATE IF ERROR
;
; INITIALIZE COUNTERS AND FLAGS
;
	CLRL		END_OF_FILE	; INITIALIZE TO FALSE
	CLRL		RECCNT
	CLRL		CURRENT
;
; SET ADDRESS AND SIZE OF USER BUFFER, IN COMMON DATA AREA
;
	MOVAL	LINE_BUFF,SF_RAB+RAB$L_UBF
	MOVW	#REC_SIZE,SF_RAB+RAB$W_USZ
;
	RET				; RETURN TO CALLER
;
	.SUBTITLE  READSEQ -- READ FILE SEQUENTIALLY
;
; THE FOLLOWING ROUTINE READS THE NEXT RECORD (SEQUENTIALLY) OF THE 
; FILE SAVING THE RFA OF THE FILE IN THE "RFA" ARRAY.
;
	.ENTRY	READSEQ,^M<R2,R3,R4,R5,R6,R7>
;
; DEFINE STACK DISPLACEMENTS FOR PARAMETERS
;
EOF=4				; ADDRESS TO RETURN EOF STATUS
;
	TSTB	END_OF_FILE	; HAS END OF FILE BEEN REACHED?
	BEQL	10$		; NO.. READ NEXT RECORD
	BRW	SFINI		; DO NOTHING
;
; FIND THE LAST RECORD THAT WAS SEQUENTIALLY READ, BEFORE PERFORMING
; ANOTHER SEQUENTIAL READ.
;
10$:
	CMPL	RECCNT,#20000	; 20,000 RECORD READ YET??
	BLSSU	15$		; NO.. CONTINUE
	BRW	25$		; YES.. MARK END OF FILE AND EXIT
15$:
	MOVB	#RAB$C_SEQ,SF_RAB+RAB$B_RAC ; SET SEQUENTIAL ACCESS
;
	CMPL	CURRENT,RECCNT	; IF CURRENTLY BEYOND HIGHEST RECORD
	BGTR	20$		; SKIP THIS CODE
	$FIND	RAB=SF_RAB	; SEARCH FOR LAST SEQUENTIAL RECORD
;
; CHECK IF END_OF_FILE HAS BEEN REACHED
;
	CMPL	R0,#RMS$_EOF
	BEQL	25$
;
	ON_ERROR EXIT
	INCL	CURRENT		; UPDATING CURRENT RECORD.
	BRB	10$
; 
; READ NEXT SEQUENTIAL RECORD AND INCREMENT THE HIGH RECORD COUNTER
; CLEAR USER'S BUFFER TO FIRST 
;
20$:
	MOVC5	#0,(R6),#^A/ /,#REC_SIZE,LINE_BUFF
	$GET	RAB=SF_RAB	; READ NEXT RECORD
;
; CHECK IF END_OF_FILE HAS BEEN REACHED
;
	CMPL	R0,#RMS$_EOF
	BNEQ	30$
25$:
	INCL	END_OF_FILE
	BRW	SFINI
30$:
	CMPL	R0,#RMS$_RTB
	BEQLU	40$
	ON_ERROR  EXIT,40$
	INCL	RECCNT		; INCREMENT THE RECORD COUNTER
	INCL	CURRENT		; ALSO BUMP CURRENT RECORD COUNTER
;
; CALCULATE INDEX INTO RFA BUFFER AND STORE RFA
;
	MOVAL	RFABUFF,R6	; GET ADDRESS OF RFABUFF
	MOVL	RECCNT,R7	;
	DECL	R7
	MULL2	#6,R7
	MOVC3	#6,SF_RAB+RAB$W_RFA,(R6)[R7]
SFINI:				; RETURN END_OF_FILE STATUS
	MOVB	END_OF_FILE,@EOF(AP)
	MOVL	#SS$_NORMAL,R0
	RET			; RETURN TO CALLER
;
	.SUBTITLE  READRAN -- READ FILE RANDOMLY
;
; THE FOLLOWING ROUTINE READS ANY SPECIFIED RECORD OF THE FILE, 
; EXTRACTING THE RFA OF THE DESIRED RECORD FROM THE "RFA" ARRAY.
;
	.ENTRY READRAN,^M<R2,R3,R4,R5,R6,R7>
;
; DEFINE STACK DISPLACEMENTS FOR PARAMETERS
;
RECNUM=4			; RECORD NUMBER TO READ
SIZE=8				; RETURN NUMBER OF BYTES READ 
DONE=12				; RETURN TRUE IF ATTEMPTED TO EXCEED
;				  FILE LIMITS ((RECNUM < 0) OR 
;				               (RECNUM > MAX_REC))
; VERIFY VALID VALUE FOR RECNUM
;
	MOVL	#1,@DONE(AP)	; DEFAULT IS NOTHING CAN BE READ
;
	TSTL	@RECNUM(AP)	; RECNUM SHOULD BE GT 0
	BGTR	10$		; CONTINUE CHECK IF SO
	BRW	RFINI		; ELSE THIS ROUTINE IS FINISHED
10$:
	CMPL	@RECNUM(AP),RECCNT ; REQUESTED RECORD GT HIGHEST 
;                                        READ??
	BLEQ	20$		; NO.. CONTINUE
	BRW	RFINI		; YES.. SIGNAL COMPLETION
;
; READ DESIRED RECORD 
;
20$:
	CLRL	@DONE(AP)
	MOVB	#RAB$C_RFA,SF_RAB+RAB$B_RAC	; SET RFA ACCESS MODE
;
; FIND THE RFA VALUE AND PLACE IT INTO THE RAB
;
	MOVAL	RFABUFF,R6	; GET ADDRESS OF RFABUFF
	MOVL	@RECNUM(AP),R7	; GET RECORD NUMBER DESIRED
	MOVL	R7,CURRENT	; SAVE CURRENT RECORD NUMBER READ
	DECL	R7
	MULL2	#6,R7		; SET INDEX INTO RFABUFF
	MOVC3	#6,(R6)[R7],SF_RAB+RAB$W_RFA
;
; "BLANK" OUT USER BUFFER AREA, AND READ RECORD 
;
	MOVC5	#0,(R6),#^A/ /,#REC_SIZE,LINE_BUFF
	$GET	RAB=SF_RAB	; READ NEXT RECORD
	CMPL	R0,#RMS$_RTB
	BEQLU	40$
	ON_ERROR EXIT,40$
;
; RETURN SIZE (NUMBER OF BYTES READ) TO USER
;
	MOVZWL	SF_RAB+RAB$W_RSZ,@SIZE(AP)
RFINI:
	MOVL	#SS$_NORMAL,R0
	RET
;---------------------------------------------------------;
; CLOSE THE FILE AFTER ALL ELSE IS DONE                   ;
;---------------------------------------------------------;
	.ENTRY	CLOSEFIL,^M<R2>
;
	$CLOSE		FAB=SF_FAB	; OPEN THE FILE
	ON_ERROR	EXIT		; TERMINATE IF ERROR
;
	RET				; RETURN TO CALLER
;---------------------------------------------------------;
; RENAME THE FILE:                                        ;
;---------------------------------------------------------;
	.ENTRY	RENAM1,^M<R2,R3,R4,R5,R6,R7,R8>
	MOVL		FILENAME(AP),R2 ; GET ADDRESS OF FILE 
;                        DESCRIPTOR AND SET FILE NAME AND SIZE IN FAB
	MOVL		DSC$A_POINTER(R2),R1_FAB+FAB$L_FNA
	MOVB		DSC$W_LENGTH(R2),R1_FAB+FAB$B_FNS
        RET
;--------------------------------------------------------;
	.ENTRY	RENAM2,^M<R2,R3,R4,R5,R6,R7,R8>
	MOVL		FILENAME(AP),R2 ; GET ADDRESS OF FILE 
;                        DESCRIPTOR AND SET FILE NAME AND SIZE IN FAB
	MOVL		DSC$A_POINTER(R2),R2_FAB+FAB$L_FNA
	MOVB		DSC$W_LENGTH(R2),R2_FAB+FAB$B_FNS
        $RENAME         OLDFAB=R1_FAB,NEWFAB=R2_FAB 
;	ON_ERROR	EXIT ;	CALLER MUST DETERMINE IF DID IT!
	RET				; RETURN TO CALLER
;---------------------------------------------------------;
; FORTRAN LOOK:  GET SOME OF THE FILE CHARACTERISTICS     ;
;---------------------------------------------------------;
	.ENTRY	FLOOK,^M<R2,R3,R4,R5,R6,R7,R8>
;
        CLRL            DERR ;ASSUME NO ERROR
	MOVL		FILENAME(AP),R2 ; GET ADDRESS OF FILE 
;                        DESCRIPTOR AND SET FILE NAME AND SIZE IN FAB
	MOVL		DSC$A_POINTER(R2),OP_FAB+FAB$L_FNA
	MOVB		DSC$W_LENGTH(R2),OP_FAB+FAB$B_FNS
;
        $OPEN           FAB=OP_FAB      ; OPEN SO CAN CLOSE
 	ON_ERROR	BADX            ; DERR = 0 FOR NO ERROR
        MOVQ            DA_XAB+XAB$Q_CDT,LDATE ; DATE
        MOVW            PR_XAB+XAB$W_PRO,LPROT
        CLRW            LPROT+2                ; FILE PROTECTION
        MOVW            PR_XAB+XAB$W_GRP,LUIC1 ; GROUP
        MOVW            PR_XAB+XAB$W_MBM,LUIC2 ; MEMBER
        MOVL            SZ_XAB+XAB$L_EBK,FILE_SIZE ;FILE SIZE
        MOVW            SZ_XAB+XAB$W_FFB,FRST_FREE ;1ST FREE BYTE
        $CLOSE          FAB=OP_FAB      ; CLOSE 
	ON_ERROR	EXIT		; TERMINATE IF ERROR
;
	RET				; RETURN TO CALLER
;---------------------------------------------------------;
; DELETE THE FILE                                         ;
;---------------------------------------------------------;
	.ENTRY	DELFILE,^M<R2>
;
        CLRL            DERR ;ASSUME NO ERROR
	MOVL		FILENAME(AP),R2 ; GET ADDRESS OF FILE 
;                        DESCRIPTOR AND SET FILE NAME AND SIZE IN FAB
	MOVL		DSC$A_POINTER(R2),ER_FAB+FAB$L_FNA
	MOVB		DSC$W_LENGTH(R2),ER_FAB+FAB$B_FNS
;
        $ERASE          FAB=ER_FAB      ; DELETE FILE
 	ON_ERROR	BADX            ; DERR = 0 FOR NO ERROR
	RET		         	; NORMAL RETURN TO CALLER
;
BADX:   MOVL            R2,DERR
        RET                     ; ERROR RETURN
;
EXIT:	$EXIT_S	R0		; ERROR -- TERMINATE IMAGE
	.END
