Article 127955 of comp.os.vms:
Path: nntpd.lkg.dec.com!quark.enet.dec.com!lionel
From: lionel@quark.enet.dec.com (Steve Lionel)
Newsgroups: comp.lang.fortran,comp.os.vms
Subject: Re: Finding file size from DEC Fortran
Date: 25 Aug 1995 15:33:41 GMT
Organization: Digital Equipment Corporation, Nashua NH
Lines: 127
Distribution: world
Message-ID: <41kqgl$dve@nntpd.lkg.dec.com>
References: <41i6nm$bnv@trog.dra.hmg.gb>
Reply-To: lionel@quark.enet.dec.com (Steve Lionel)
NNTP-Posting-Host: quark.zko.dec.com
X-Newsreader: mxrn 6.18-32
Xref: nntpd.lkg.dec.com comp.lang.fortran:31592 comp.os.vms:127955


In article <41i6nm$bnv@trog.dra.hmg.gb>, alm@hep.phys.soton.ac.uk 
(Andrew McLean) writes:

|>I am opening a file for unformatted, direct access read using DEC
|>Fortran running under OpenVMS.  I want the Fortran program to find out
|>how big the file is, well I really want to know how many records it
|>contains but file size will do.  I am sure there is a system service
|>which can do this but I can't find it.  (This would be a really useful
|>extension to the INQUIRE function).

It would be useful only for sequential organization files of fixed length
records (or relative organization files, though you couldn't determine how
many records were deleted), otherwise INQUIRE would have to read through
the file and count.  We generally don't like to add extensions which have
limited usefulness.

Carl Lydick posted code which, though the principles are correct, contains
some usage errors which might cause problems down the road: 1) it uses
undocumented $$_FILL_n field names which are subject to change without
notice and 2) it fails to restore the XAB pointer after completion.  Also,
as a USEROPEN routine, it's perhaps more complicated than is necessary.

I've attached code for a function GET_NRECS which you can call for a file you
have open in Fortran and it will return as its function value the number of
records.  You should be able to see how to modify it if you want the file size
in bytes or blocks.  The argument is the unit number for the open file for
which you want the record count.   The file can be an existing one or one
you've created and are adding records to.  If the file doesn't have fixed
length records, or some other error occurs, it returns -1.

Enjoy.

	integer function get_nrecs(lun)
	implicit none

	integer lun		! Fortran logical unit number

	include '($FABDEF)'	! RMS File Access Block
	include '($RABDEF)'	! RMS Record Access Block
	include '($XABDEF)'	! RMS Common Extended Attributes Block
	include '($XABFHCDEF)'	! RMS File Header Characteristics XAB
	include '($SYSSRVNAM)'	! System Service declarations

	record /fabdef/ fab
	record /rabdef/ rab

! The following definition is the proper way to use RMS XAB declarations.
! This method is necessary due to the separate declaration for the header
! and body of the XAB.
!
	structure /xabfhc_type/
	  union
	   map
	   record /xabdef/ header
	   end map
	   map
	   record /xabfhcdef/ body
	   end map
	  end union
	end structure

	record /xabfhc_type/ xabfhc

	integer old_xab, old_nam

	pointer (p_fab, fab)
	pointer (p_rab, rab)

	integer for$rab, status, filesize

	get_nrecs = -1

! Get pointer to RAB and FAB
! FOR$RAB returns a pointer to the RAB for an open unit
!
	p_rab = for$rab(lun)
	if (p_rab .eq. 0) return    ! Unit not open
	p_fab = rab.rab$l_fab

! Verify that this file has fixed-length records
!
	if (fab.fab$b_rfm .ne. fab$c_fix) return  ! Not fixed-length

! Flush out any pending records
!
	status = sys$flush(rab)
	if (.not. status) return

! Set up for $display
!
	old_xab = fab.fab$l_xab
	old_nam = fab.fab$l_nam
	fab.fab$l_xab = %loc(xabfhc)
	fab.fab$l_nam = 0  ! Just so we don't confuse the RTL
	xabfhc.header.xab$b_cod = xab$c_fhc     ! Code for a FHC XAB
	xabfhc.header.xab$b_bln = xab$c_fhclen	! Length of a FHC XAB

! Ask RMS to fill in the XAB, then restore old XAB and NAM pointers
!
	status = sys$display(fab)
	fab.fab$l_xab = old_xab
	fab.fab$l_nam = old_nam
	if (.not. status) call lib$signal(%val(status))

! Calculate the size of the file in bytes
!    EBK=Ending Block number (blocks used in file)
!    FFB=First Free Byte (first unused byte in last block)
!
	filesize = ((xabfhc.body.xab$l_ebk - 1) * 512) +
	1   xabfhc.body.xab$w_ffb

! Number of records is filesize divided by record size
!
	get_nrecs = filesize / fab.fab$w_mrs
	return
	end

-- 

Steve Lionel                      Mail: lionel@quark.enet.dec.com
DEC Fortran Development           WWW:  http://www.digital.com/info/slionel.html
Digital Equipment Corporation     CompuServe: 75263,3001
110 Spit Brook Road, ZKO2-3/N30
Nashua, NH 03062-2698             "Free advice is worth every cent"

For information on DEC Fortran 90, see http://www.digital.com/info/hpc/f90/


