Fortran Wiki

NAMELIST-based command line argument parsing

NAMELIST can be used to create a unprecedentedly simple method of passing keyword-value pairs via the command line. With a f2003-compliant compiler the following example program simply needs an initialized variable added to the NAMELIST and it automatically is available as a command line argument. Hard to imagine it getting much simpler.

You can call the example program with syntax like:

 testit r=200e3 i=200
 testit K=33333,J=22222,I=11111

Note that if you pass in strings you probably will have to use nested quotes or escape your quote characters. How you do that can vary with what shell and OS you are running in.

 # just quote the entire argument list with single quotes ...
 testit 'c="my character string" S=10,T=20.30,R=3e-2'

 or nest the quotes ...
 testit c='"string"' S=20.30

 or escape the quotes ...
 testit c=\"string\"

As you will see, there is no need to convert from strings to numeric values in the source code. Even arrays and user-defined types can be used, complex values can be input … just define the variable and add it to the NAMELIST definition.

And if you want to use a config file instead of command line arguments just create a NAMELIST input file and read it.

If your compiler does not support the f2003 ability to read a NAMELIST from an internal file, you will have to write the data to a file and then read it back. If it doesn’t support GET_COMMAND_ARGUMENT(3f), you can use the very common GETARGS(3f) extension or see the F2KCLI package from WINTERACTER.

program testit
   implicit none
   character(len=255)           :: message ! use for I/O error messages
   character(len=:),allocatable :: string  ! stores command line argument
   integer                      :: ios
   integer                      :: sum

! declare and initialize a namelist
   integer    :: i=1, j=2, k=3
   real       :: s=111.1, t=222.2, r=333.3
   character(len=255) :: c=' '
   namelist /cmd/ i,j,k,s,t,r,c            ! just add a variable here and it is a new parameter !!

   string=get_namelist()  ! return command line arguments as NAMELIST input
   read(string,nml=cmd,iostat=ios,iomsg=message) ! internal read of namelist
      write(*,'("ERROR:",i0,1x,a)')ios, trim(message)
      write(*,*)'COMMAND OPTIONS ARE'
      stop 1
   ! all done cracking the command line

   ! use the values in your program. For example ...
   function get_namelist() result (string)           
      character(len=:),allocatable :: string         ! stores command line argument
      integer :: command_line_length
      call get_command(length=command_line_length)   ! get length needed to hold command
      allocate(character(len=command_line_length) :: string)
      call get_command(string) 
      ! trim off command name and get command line arguments
      string=adjustl(string)//' '                    ! assuming command verb does not have spaces in it
      string=string(index(string,' '):)
      string="&cmd "//string//" /"                   ! add namelist prefix and terminator
   end function get_namelist
end program testit

category: code