C+ C NAME: C iFilePath C PURPOSE: C Platform-independent construction of file name C CATEGORY: C Portability C CALLING SEQUENCE: function iFilePath(cRootDir,nSub,cSub,cFile,cPathOut) C INPUTS: C cRootDir character*(*) The 'root' or 'device' part of the file name C If the string starts with cEnvi='$' then cRoot is interpreted C as a logical, e.g. cRoot=cEnvi//'dat'. If the logical does not C exist then the full cRoot (including cEnvi) is used. If cRoot C is set to the cHome and cTemp strings defined in dirspec.h, C then these also will be translated (even if they do not start C with cEnvi, as on VMS). To generate a machine independent file C name this almost always will be logical. C nSub integer # entries in cSub to be processed (can be zero) C cSub character(*)*(*)list of subdirectories to be appended to cRoot C usually this will list of string to copied literally. If an C entry in the cSub array starts with the cEnvi character then a C logical translation is attempted. If this is not succesfull C then the cEnvi is stripped off, and the remainder is used. C cFile character*(*) filename to be appended after the cSub entries. C OUTPUTS: C iFilePath integer # useful chars returned in cPath (=itrim(cPath)) C cPathOut character*(*) the (hopefully) machine-independent file name C EXAMPLE: C cSub(1) = 'sub1' C cSub(2) = 'sub2' C I = iFilePath(cEnvi//'dat',2,cSub,'file.txt',cFileSpec) C On VMS: C $DAT logical defined as UD1:[PHICK.SOFT.DAT] C cFileSpec = 'UD1:[PHICK.SOFT.DAT.SUB1.SUB2]FILE.TXT' C On NT: C $DAT logical defined as E:\DAT\ C cFileSpec = 'E:\DAT\SUB1\SUB2\FILE.TXT' C on Unix/Linux: C $dat logical defined as /mnt/dat/ C cFileSpec = '/mnt/dat/sub1/sub2/file.txt' C CALLS: C iGetLogical, Str2StrSet, Str2Str, uppercase C INCLUDE: include 'dirspec.h' include 'filparts.h' include 'str2str_inc.h' C PROCEDURE: C > The concept of a logical comes from VMS. Logical translation is done using a few C system calls. On NT, Unix and Linux the concept of a 'logical' does not really exist. C Instead the 'logical' definitions are maintained in the file LOGFIL.TXT in the users home C directory (in principle this would work on VMS also). C > The NT/Unix/Linux-style environment variable is the functional equivalent of C a logical, but I have had problems tracking down the appropriate system calls for setting, C deleting and translating environment variables. The approach with LOGFIL.TXT is the C workaround. It is ugly, but it works. C > For a non-casesensitive OS (as identified by the setting of C bOS__NotCaseSensitive in include file dirspec.h, the output is always C converted to uppercase (e.g. NT, VMS). C > On NT and Unix/Linux the logical does not have to be defined with a trailing C (back)slash, but for consistency it is better to add it: C a directory string ending with a (back)slash is always treated as a 'directory'. C If the (back)slash is not present it may be treated as a 'file'. C MODIFICATION HISTORY: C SEP-1998, Paul Hick (UCSD/CASS) C AUG-1999, Paul Hick (UCSD/CASS) C added option for cSub entries to be treated as logical if C preceeded by cEnvi character ($); added documentation. C AUG-1999, Paul Hick (UCSD; pphick@ucsd.edu) C modified to allow input arg cFile to be the same as output arg cPathOut C DEPENDENCY TREE: C C Str2Flt: C itrim C uppercase C Int2Str C Int2StrSet C Say C (see below) C C Say: (FORSTR.F LOGMODFILE.F OSCALLS.F) C uppercase C itrim C LocFirstLen C LocFirst C iGetLun C iFilePath C (see below) C iGetSymbol C itrim C LogModFile C itrim C bGetLun C iGetLun C iFreeLun C iOSRenameFile *(system call) C iOSDeleteFile *(system call) C OSExitCmd *(system call) C C iFilePath: (FORSTR.F LOGMODFILE.F OSCALLS.F) C Str2Str C itrim C Str2StrSet C iGetLogical C itrim C LogModFile C itrim C bGetLun C iGetLun C iFreeLun C iOSRenameFile *(system call) C iOSDeleteFile *(system call) C C- character cRootDir*(*) integer nSub character cSub(*) *(*) character cFile *(*) character cPathOut*(*) character cTmp *(FIL__LENGTH) character cPath*(FIL__LENGTH) integer Str2Str integer Str2StrSet iStr = Str2StrSet(STR__TRIM) iZero = 0 ! Needed by G77 !------- ! A leading $-sign on RootDir means it might be an logical ! (Note that the $-sign is part of the logical !------- ! On VMS the logical SYS$LOGIN (cHome) and SYS$SCRATCH (cTemp) may contain ! a device name that itself is a concealed logical. To avoid problems ! SYS$LOGIN and SYS$SCRATCH are translated first. if (cRootDir(:iEnvi) .eq. cEnvi .or. cRootDir .eq. cHome .or. cRootDir .eq. cTemp) then if (iGetLogical(cRootDir,cPath) .eq. 0) cPath = cRootDir else cPath = cRootDir end if !------- ! If cRootDir = ' ', assume cRootDir is current directory I = itrim(cPath) if (I .eq. 0) I = Str2Str(cFullDefault,cPath) if (cOpSys .eq. OS__VMS) then if (cPath(I-iTrail+1:I) .eq. cTrail(:iTrail)) then ! Remove ']' I = I-iTrail if (cPath(I-iDivide+1:I) .eq. cDivide(:iDivide)) I = I-iDivide ! Remove '.]' else ! Add colon if (cPath(I-iDevi+1:I) .ne. cDevi(:iDevi+iZero)) I = I+Str2Str(cDevi,cPath(I+1:)) J = iGetLogical(cPath(:I-iDevi),cTmp) ! Translate concealed logical on VMS if (J .ge. iDivide+iTrail) then ! Check for '.]' if (cTmp(J-iDivide-iTrail+1:J) .eq. cDivide(:iDivide)//cTrail(:iTrail)) & I = I+Str2Str(cLead(:iLead+iZero)//cRoot(:iRoot+iZero),cPath(I+1:))! Add '[000000' end if end if !------- ! cPath now ends with '[',':','000000','-', or alphabetic character if (nSub .ne. 0) then ! If sub dirs are to be added if (cPath(I-iDevi+1:I) .eq. cDevi(:iDevi+iZero)) then I = I+Str2Str(cLead,cPath(I+1:)) ! .. append '[' to ':' else I = I+Str2Str(cDivide,cPath(I+1:)) ! .. otherwise add '.' end if end if else if (cOpSys .eq. OS__DOS) then if (I .eq. 1) I = I+Str2Str(cDevi,cPath(I+1:)) ! Add colon to drive if (cPath(I-iTrail+1:I) .ne. cTrail(:iTrail)) I = I+Str2Str(cTrail,cPath(I+1:)) ! Add '\' if not there yet else if (cPath(I-iTrail+1:I) .ne. cTrail(:iTrail)) I = I+Str2Str(cTrail,cPath(I+1:)) ! Add '/' if not there yet end if do n=1,nSub ! Append subdirs if (cSub(n)(:iEnvi) .eq. cEnvi) then if (iGetLogical(cSub(n),cTmp) .eq. 0) cTmp = cSub(n)(iEnvi+1:) else cTmp = cSub(n) end if I = I+Str2Str(cTmp,cPath(I+1:)) !I = I+Str2Str(cSub(n),cPath(I+1:)) if (n .lt. nSub) I = I+Str2Str(cDivide,cPath(I+1:)) end do !------- ! Complete the directory by appending cTrail if it is not there yet. ! On VMS cTrail is not needed if cPath end with a colon (the 'device' would be ! a logical pointing to a directory. if (cOpSys .eq. OS__VMS) then if (cPath(I-iDevi +1:I) .ne. cDevi (:iDevi+iZero) .and. & cPath(I-iTrail+1:I) .ne. cTrail(:iTrail)) I = I+Str2Str(cTrail,cPath(I+1:)) else if (cPath(I-iTrail+1:I) .ne. cTrail(:iTrail)) I = I+Str2Str(cTrail,cPath(I+1:)) end if I = I+Str2Str(cFile,cPath(I+1:)) ! Append file name iStr = Str2StrSet(iStr) if (bOS__NotCaseSensitive) call uppercase(cPath) cPathOut = cPath iFilePath = I return end