C+ C NAME: C iOpenFile C PURPOSE: C (internal use only; called by bOpenFile) C Open statemenst for direct/sequential, formatted/unformatted files C CALLING SEQUENCE: function iOpenFile(iAct,cFile,nRecl) C INPUTS: (passed from bOpenFile) C iAct integer code passed from bOpenFile C cFile character*(*) fully qualified file name C nRecl integer record length in 4-byte longwords C (not always used; see PROCEDURE) C OUTPUTS: C iOpenFile integer logical unit number assigned by iGetLun C (=FIL__NOUNIT is open was unsuccessful) C nRecl integer on success, record length in longwords C on failure, input value is retained C INCLUDE: include 'dirspec.h' include 'openfile.h' C CALLS: C Say, HOSInquire, bGetLun, iFreeLun C PROCEDURE: C Isolates the Fortran open statements needed by bOpenFile. C C For HELIOS files the record length is determined by HOSInquire C C Binary files are best opened as direct access, unformatted files. If the C record length is not known or not fixed, then open with record length of C 1 byte (iRecl=1 and set the OPN__RECLBYTE bit). Then read each byte C separately with 'read(iU,rec=iR) ibyte'. C C In principle, a binary file can be opened as a sequential, unformatted C file, but apparently only if the file was written in a special way (at least C for g77; see http://gcc.gnu.org/onlinedocs/g77/index.html C Look under: Known causes of trouble with GNU Fortran/Missing Features/ C Portable unformatted files.) C C The open statements for sequential, formatted files (usually used to open C plain ascii files) cannot include the RECL= keyword. Absoft for Linux C will stop with error code 10025 (= RECL= only valid for direct acces files); C g77 just quietly ignores the keyword, I think. C C WARNING: C Do not add a call to iSearch to this function to check for the existence C of cFile. This may interfere with a wildcard search using iSearch in progress C in the calling procedure. C MODIFICATION HISTORY: C DEC-1995, Paul Hick (UCSD/CASS) C DEC-2001, Paul Hick (UCSD/CASS; pphick@ucsd.edu) C Removed 'recl=irecl' from open statements for sequential, formatted C files (Absoft chokes on it). C- integer iAct character cFile*(*) integer nRecl character cStatus*3 character cInt2Str*14 character cSay*9 /'iOpenFile'/ logical bRead logical bSeq logical bDir logical bFmt logical bUnfmt logical bNew logical bScratch logical bApp logical bGetLun logical bHOS logical bGetRecl logical bReclB logical bReturn if (cOpSys .ne. OS__LINUX) call Say(cSay,'E','version','for wrong OS') if (.not. bGetLun(iOpenFile,cFile)) return ! No unit number available bNew = iand(iAct,OPN__NEW ) .ne. 0 bScratch= iand(iAct,OPN__SCRATCH ) .ne. 0 bRead = iand(iAct,OPN__READONLY) .ne. 0 bHOS = iand(iAct,OPN__HOS ) .ne. 0 bReclB = iand(iAct,OPN__RECLBYTE) .ne. 0 !------- ! If bGetRecl is true just before returning, then an attempt is made to ! determine the record length by an inquire by logical unit on the ! succesfully opened file. bGetRecl= iand(iAct,OPN__RECLINQ) .ne. 0 cStatus = 'OLD' if (bNew ) cStatus = 'NEW' if (bScratch) cStatus = 'SCRATCH' !------- ! If any ways can be devised to obtain the record length from an ! existing file these can be inserted here. ! UNIX/LINUX: ! For a HELIOS file (set bHOS) the HOSInquire function may work. !------- ! iRecl will be used in the open statements to set the record length iRecl = 0 if (cStatus .eq. 'OLD') then if (bHOS) then call HOSInquire(cFile,iRecl) ! Determine record length for existing file if (bReclB) iRecl = 4*iRecl end if end if !------- ! If at this point still iRecl=0 then a positive input value of nRecl is ! assumed to be the record length in 4-byte longwords. If nRecl<=0 then ! iRecl remains zero !!!: this allows only open statements which do not ! require an explicit recordlength. if (iRecl .eq. 0 .and. nRecl .gt. 0) iRecl = nRecl ! Pick up input value if (.not. bReclB) iRecl = 4*iRecl bSeq = iand(iAct,OPN__SEQUENTIAL) .ne. 0 bApp = iand(iAct,OPN__APPEND ) .ne. 0 bDir = (iand(iAct,OPN__SEQUENTIAL) .eq. 0 .and. & iand(iAct,OPN__APPEND ) .eq. 0) .and. iRecl .gt. 0 bFmt = iand(iAct,OPN__FORMATTED ) .ne. 0 bUnfmt = iand(iAct,OPN__FORMATTED ) .eq. 0 ! Sanity checks if (bApp) then if (bNew .or. bScratch .or. bRead) then ! Append does not make much sense here bSeq = .TRUE. ! .. (for scratch files not even possible, I think) bApp = .FALSE. else bSeq = .FALSE. ! In case both OPN__SEQUENTIAL and OPN__APPEND are set end if end if !------- ! Sequential files: ! If form='FORMATTED' is NOT set and recl=4*iRecl is used than the file ! seems to default to an unformatted file, i.e. the open is succesfull ! but a subsequent formatted write will fail; if recl=iRecl is not used ! the file becomes a formatted file with recl=0 returned by the inquire ! by unit. Currently both form='FORMATTED' and recl=4*iRecl are used; ! the inquire by unit returns the proper record length (which is allowed ! to be zero). In general, if the recl keyword is not specified, then ! the inquire always seems to return a zero record length. bReturn = .FALSE. I = -1 iU = iOpenFile if (bRead) then ! Open 'readonly', only happens if cStatus='OLD' !------- ! The keyword "readonly" works in VAX and Absoft Fortran ! The keyword "mode='READ'" should work in MS-Fortran ! Neither works in G77 Fortran. Don't know what does. For the moment the readonly does not work in Linux if (bSeq) then if (bFmt) then ! Sequential access, formatted open (iU,iostat=I,file=cFile,status=cStatus,access='SEQUENTIAL',form='FORMATTED') bReturn = .TRUE. else if (bUnfmt) then ! Sequential access unformatted open (iU,iostat=I,file=cFile,status=cStatus,access='SEQUENTIAL',form='UNFORMATTED') end if else if (bDir) then if (bFmt) then ! Direct access, formatted open (iU,iostat=I,file=cFile,status=cStatus,access='DIRECT',form='FORMATTED' ,recl=iRecl) bReturn = .TRUE. else if (bUnfmt) then ! Direct access, unformatted open (iU,iostat=I,file=cFile,status=cStatus,access='DIRECT',form='UNFORMATTED',recl=iRecl) bReturn = .TRUE. end if end if else if (bNew .or. bScratch) then ! cStatus='NEW' or cStatus='SCRATCH' if (bSeq) then if (bFmt) then ! Linux seems to default to UNFORMATTED' if a recl is specified open (iU,iostat=I,file=cFile,status=cStatus,access='SEQUENTIAL',form='FORMATTED') bReturn = .TRUE. else if (bUnfmt) then open (iU,iostat=I,file=cFile,status=cStatus,access='SEQUENTIAL',form='UNFORMATTED',recl=iRecl) bReturn = .TRUE. end if else if (bDir) then if (bFmt) then open (iU,iostat=I,file=cFile,status=cStatus,access='DIRECT',form='FORMATTED' ,recl=iRecl) bReturn = .TRUE. else if (bUnfmt) then open (iU,iostat=I,file=cFile,status=cStatus,access='DIRECT',form='UNFORMATTED',recl=iRecl) bReturn = .TRUE. end if end if else ! cStatus='OLD' (but not readonly) if (bSeq) then if (bFmt) then open (iU,iostat=I,file=cFile,status=cStatus,access='SEQUENTIAL',form='FORMATTED') bReturn = .TRUE. else if (bUnfmt) then open (iU,iostat=I,file=cFile,status=cStatus,access='SEQUENTIAL',form='UNFORMATTED',recl=iRecl) bReturn = .TRUE. end if else if (bApp) then bGetRecl = .FALSE. ! Inquire would return zero !------ ! If the recl keyword is specified here the file pointer stays ! at the beginning of the file. if (bFmt) then open (iU,iostat=I,file=cFile,status=cStatus,access='APPEND',form='FORMATTED') else if (bUnfmt) then open (iU,iostat=I,file=cFile,status=cStatus,access='APPEND',form='UNFORMATTED') end if else if (bDir) then if (bFmt) then open (iU,iostat=I,file=cFile,status=cStatus,access='DIRECT',form='FORMATTED' ,recl=iRecl) bReturn = .TRUE. else if (bUnfmt) then open (iU,iostat=I,file=cFile,status=cStatus,access='DIRECT',form='UNFORMATTED',recl=iRecl) bReturn = .TRUE. end if end if end if if (I .ne. 0) then iOpenFile = iFreeLun(iOpenFile) ! Sets iOpenFile=FIL__NOUNIT call Say(cSay,'W',cFile,'error status '//cInt2Str(I)) nRecl = 0 else if (bGetRecl) then inquire (iOpenFile,recl=nRecl) nRecl = nRecl/4 ! Bytes -> words else if (bReturn) then nRecl = iRecl/4 end if return end