Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Determining a running Fortran program's "residence directory" 2

Status
Not open for further replies.

Deniall

Technical User
May 15, 2011
250
4
18
Australia
rmniall.com
This is a repeat of a post I put on Eng-Tips about a fortnight ago.[ ] See
for that post and the replies it elicited.[ ][ ] It looks like I will not be able to achieve my aim in this matter, but I thought it worth trying this forum before I resign myself to this fate.

I am trying to get an old Fortran program to run on a modern Windows computer.[ ] Progress is slow but steady.[ ] However I have struck an "interesting" little problem.[ ] My program's *.EXE file will reside in a directory that will be chosen by the end user, with different users choosing to store it in different places.[ ] Users will run the program from a "Command Prompt" window, by typing its name and perhaps its residence directory.[ ] Thus they might type:
» ProgName[ ][ ] (if the program resides in the current working directory or in a directory that is on the system's "path")
» D:\MySoftware\etc\etc\ProgName[ ][ ] (an absolute address for the residence directory)
» ..\ProgName[ ][ ] (if the program resides in the directory above the current working directory)

I am looking for a way for the program to find out the full name of its residence directory.[ ] Gfortran has a subroutine GETCWD(cwd) that returns the full name of the directory the user is "sitting in", but I have been unable to find a way to obtain the program's residence directory.

Does anyone know of a way to achieve this?
 
While I was shoving thousands of walnuts into 10kg string bags my mind began to wander a bit.

Your get_exe_dir routine determines the program's "residence directory" and places the result on the screen.[ ] But where I want it is inside my main program, so (as per your post on 09Apr22@07:24) I can use a small separate program via a SYSTEM call to run your routine and redirect its output to a separate file, then read that file from my main program, then delete the file.

This is fine, but a bit convoluted and requires an extra .EXE file in what I eventually distribute to my miniscule clientele.[ ] Would it be possible to change get_exe_dir to make this a bit more straight forward.[ ] Possible approaches might be:
»[ ] Have get_exe_dir place the pathname directly into a file instead of shooting it to the screen. Any fixed file name would do.
»[ ] Convert get_exe_dir to a subroutine callable directly from within the main program via a line CALL GET_DIR_EXE(RESIDENCE) where RESIDENCE is an appropriately sized CHARACTER variable that would contain the required information.
»[ ] Convert get_exe_dir to a function which could be invoked via RESIDENCE=GET_DIR_EXE() or something similar.
 
Hi Deniall,
It's clear that you need a fortran function which returns the EXE path, e.g.:
RESIDENCE = GET_DIR_EXE()
or a subroutine which sets the EXE path to the string, e.g.:
CALL GET_DIR_EXE(RESIDENCE)

But for the first step - i.e. a proof-of-concept-example it was simplest for me when I called the C-Function getdir() which calls get_exe_dir() and prints the path.

Then I thought about the second step - to find out, how to convert C-string which is the pointer on character to the fortran string. IMO it's not well documented, how to do it. Although I could read in the classic book by Kernighan and Ritchie how the C-strings works, I couldn't find nothing similar about Fortran-strings.
And you were on the very edge of civilization during your walnut-gathering sojourn, so I thought about waiting for you, that you first write if you even need such functionality.

But then, quite coincidentally, I have found the pure fortran solution, which I posted here on 13 Apr 22 11:45. Then I thought this is the best solution, because the fortran programmer doesn't need to bother with C.
Have you tried the fortran solution, which I posted on 13 Apr 22 11:45?
 
It's "true confession" time.[ ] I did not try your 13Apr22 11:45 solution because I did not understand it.[ ] (I cut my teeth on Fortran 4, then stepped up to Fortran 77, but then never moved any further.[ ] So with that code you posted I did not even understand the syntax, let alone the logic.)

I will explore it when I get back to what we laughingly call "civilisation".[ ] I fully expect that with a bit of experimentation I will be able to get it working.

Apologies and further thanks.
 
Ok, try it, it's not so complicated.
Some years ago, I was also been a fan of Fortran77 only.
But then, to complete the tasks, I also recognized the merits of Forrtran 90 - namely, the modules. I'm sure you can handle it. It's not so [highlight #FCE94F][/highlight]difficult.
 
I am back in civilisation, and have successfully test-implemented an adaptation of your F95 solution.[ ] I am posting it here so that it will be available to anyone else who might have this weird urge to determine a program's residence directory.

(1)[ ] The F95 "subroutine":
Code:
module Win32
  use ISO_C_BINDING
  implicit none
  private
!
  public GetModuleFileName
  interface
    function GetModuleFileName(hModule, lpFileName, nSize) &
    bind(C,Name='GetModuleFileNameA')
      use ISO_C_BINDING
      implicit NONE
      !GCC$ ATTRIBUTES STDCALL :: GetModuleFileName
      integer(C_LONG) GetModuleFileName
      integer(C_INTPTR_T), value :: hModule
      character(kind=C_CHAR) lpFileName(*)
      integer(C_LONG), value :: nSize
    end function GetModuleFileName
  end interface
end module Win32
!
subroutine RESDIR(FilName,LenFilName)
  use Win32
  use ISO_C_BINDING
  implicit none
  integer(C_LONG) c
  character StringB*(255)
  integer(C_LONG) LenFilName
  character FilName*(255) 
  c = GetModuleFileName(0_C_INTPTR_T,StringB,len(StringB))
  FilName = StringB
  LenFilName = c
  return
end subroutine RESDIR

(2)[ ] The short F77 main program used to test the subroutine:
Code:
[ ] [ ] [ ] PROGRAM MAINPROG
C
C     Written to test the Fortran-95 code that returns the
C     calling program's "residence directory".
C
C     Deliberately written in and compiled as Fortran-77.
C
      INTEGER LenFilName, LenResPathName
      CHARACTER*255 FilName, ResPathName
      CHARACTER*1 Dummy
C
      CALL RESDIR(FilName,LenFilName)
      WRITE(*,920)LenFilName, FilName(1:LenFilName)
  920 FORMAT(/' RUNNING FILE'/
     +        '   Length  = ',I3/
     +        '   Address = ',A)
C
      ResPathName = FilName
      LenResPathName = LenFilName
      DO 100 I = LenResPathName,1,-1
          IF(ResPathName(I:I).EQ.'\')THEN
              J = I - 1
              GO TO 400
          ENDIF
  100 CONTINUE
      DO 200 I = LenResPathName,1,-1
          IF(ResPathName(I:I).EQ.':')THEN
              J = I
              GO TO 400
          ENDIF
  200 CONTINUE
C
  400 LenResPathName = J
      WRITE(*,940)LenResPathName, ResPathName(1:LenResPathName)
  940 FORMAT(' RESIDENCE DIRECTORY'/
     +       '   Length  = ',I3/
     +       '   Address = ',A)
C
      WRITE(*,960,advance='no')
  960 FORMAT(/' Hit <Enter> to finish: ')
      READ(*,'(A1)')Dummy
C
      CALL EXIT
      END

(3)[&nbsp;] The GFortran commands to compile and link it all.
[tt]GFortran -c MainProg.for
GFortran -c FortSub.f95
GFortran[&nbsp;] MainProg.o FortSub.o[&nbsp;] -o MainProg
[/tt]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top