From:	MERC::"uunet!CRVAX.SRI.COM!RELAY-INFO-VAX" 17-JUL-1992 20:33:25.91
To:	ucsu!psych.colorado.edu!barbour@boulder.colorado.edu
CC:	info-vax@sri.com
Subj:	RE: FAQ: how to do "a = f$file(file-name,"EOF") using RTL/SYS$/RMS

	Jim Barbour <ucsu!psych.colorado.edu!barbour@boulder.colorado.edu>
writes:
>
>I'm sure this has been talked about on this group before, but I have
>to get the amount of data in a file from within a program.  I have found
>nothing in TFM.  Can anyone help with this?
>

	The only way to get the *exact* amount of data in a "generic" file
is to read the file and count the records or bytes or whatever it is that
interests you.  There are possible shortcuts.

	One shortcut is to check how much of the file RMS thinks has been
used.  This should work reasonably well for sequential files.  The
following piece of code illustrates how this is done.  It might even work.
:-) 

      INTEGER FUNCTION SIZE_OPEN (FAB, RAB, LUN)
C
C         This is a useropen routine.  It is intended to be invoked
C     from the Fortran OPEN statement.  It will determine the address of
C     the first XAB connected to the FAB, pass the address of that XAB
C     to another integer function which in turn will return the address
C     of the next XAB in the XAB chain.  See the Record Management
C     Services (RMS) Manual for additional details as to the structures
C     used.
C
C     Arguments:
C         FAB    - Is the RMS File Access Block.  Passed by reference.
C         RAB    - Is the RMS Record Access Block.  Passed by reference.
C         LUN    - Is the Logical Unit Number.  Passed by reference.
C                  LUN is not used by this subroutine but is included
C                  because the USEROPEN keyword in the Fortran OPEN
C                  statement causes this routine to be called with
C                  the three arguments listed.
C
C     Richard B. Gilbert	Dragon@nscvax.Princeton.Edu
C     Princeton University	76702.1567@CompuServe.Com
C     M.A.E. Department		(609) 258-6217 (Tue-Fri) or
C     Princeton, NJ 08540	(609) 258-5130 (Mon)
C
      IMPLICIT INTEGER (A-Z)
      INCLUDE '($FABDEF)'		! File access block definitions.
      INCLUDE '($RABDEF)'		! Record access block definitions.
      RECORD  /FABDEF/ FAB
      RECORD  /RABDEF/ RAB
      SIZE_OPEN = SYS$OPEN(FAB)		! Open the file.
C     Should really check status here.  We are just assuming that the
C     file open was successful.
      SIZE_OPEN = SYS$CONNECT(RAB)	! Connect the RAB to the FAB.
C     Should really check this status as well.
C
C     Now, lets look at the XAB.  Since the FAB$L_XAB contains an
C     address, we must force pass by value in order to pass the XAB by
C     reference.  That is, we pass the value of the address rather than
C     the, useless to us, address of the address.  If the foregoing is
C     not clear to you, study the problem!  It's important to get it
C     right!
C
      STATUS = XABACCESS(%VAL(FAB.FAB$L_XAB), NEXT_XAB)
C
C     Pass the address of the first XAB to XABACCESS.
C
      DO WHILE(STATUS)
C         STATUS will be set when all XABs have been processed.
          THIS_XAB = NEXT_XAB
          STATUS = XABACCESS(%VAL(THIS_XAB), NEXT_XAB)
C         Pass the address of the next XAB to XABACCESS.
          END DO
      RETURN
      END
      INTEGER FUNCTION XABACCESS (FHCXAB, NEXT_XAB)
C
C         This function maps an XAB to a record defining a File Header
C     Characteristics XAB.  Because each XAB begins with XABDEF, the
C     type of XAB may be determined.  If this is the FHC XAB the
C     function stores the blocks used and the blocks allocated in COMMON
C     and returns zero as the function value.
C
      IMPLICIT INTEGER (A-Z)
      COMMON /SIZE/ FILESIZE, FILEALLO
      EXTERNAL SS$_CONTINUE
      INCLUDE  '($XABDEF)'	! XAB definitions common to all XABs.
      INCLUDE  '($XABFHCDEF)'	! XAB definitions for a FHC XAB.
      STRUCTURE /FHC_XAB/
         UNION
           MAP
             RECORD /XABDEF/    XABDEF_RECORD
           END MAP
           MAP
             RECORD /XABFHCDEF/ FHC_RECORD
           END MAP
         END UNION
      END STRUCTURE
      RECORD /FHC_XAB/ FHCXAB
      IF(FHCXAB.XABDEF_RECORD.XAB$B_COD .EQ. XAB$C_FHC) THEN
              FILESIZE = FHCXAB.FHC_RECORD.XAB$L_EBK
              FILEALLO = FHCXAB.FHC_RECORD.XAB$L_HBK
              XABACCESS = 0
          ELSE
              NEXT_XAB = FHCXAB.XABDEF_RECORD.XAB$L_NXT
C             Address of the next XAB in the XAB chain.
              XABACCESS = %LOC(SS$_CONTINUE)
          END IF
       RETURN
       END

*************************************************************************
*                                                                       *
*                        Here, there be dragons!                        *
*                      dragon@nscvax.princeton.edu                      *
*                                                                       *
*                                                Richard B. Gilbert     *
*************************************************************************

