Parsing Command Line Arguments with Fortran
To evaluate the arguments your program got on the command line, there
are two runtime calls available:
- Get the number of arguments:
iargc
- Get the values of the arguments:
getarg
A small Fortran 90 program demonstrates their usage:
program getarg_example
implicit none
integer :: i, argc, iargc
character(len=80) :: arg
argc=iargc()
write(6,*) argc
do i=1, argc
call getarg(i, arg)
write(6,*) trim(arg)
! read(arg,'(i)') some_integer
! read(arg,'(f)') some_real_or_double
! etc...
end do
end program
This is somewhat clumsy in its usage. So I wrote a Fortran 90 module
which behaves like the C function
getopt.
getoptions.f90:
! This software is distributed under the following terms:
!
! Copyright (C) 2005 Dominik Epple
!
! Redistribution and use in source and binary forms, with or without
! modification, are permitted provided that the following conditions
! are met:
! 1. Redistributions of source code must retain the above copyright
! notice, this list of conditions and the following disclaimer.
! 2. Redistributions in binary form must reproduce the above copyright
! notice, this list of conditions and the following disclaimer in the
! documentation and/or other materials provided with the distribution.
!
! THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
! ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
! FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! SUCH DAMAGE.
module getoptions
implicit none
save
character(len=80) :: optarg
integer :: optind=1
! this variable should be module private - no plan how to do that
integer :: optstr_ind
contains
character function getopt(optstr)
character(len=*),intent(IN) :: optstr
integer :: argc
character(len=80) :: arg
character :: okey
integer :: found
integer :: iargc
argc=iargc()
if(optind.gt.argc) then
getopt='>'
return
end if
call getarg(optind, arg)
if(arg(1:1).eq.'-') then
okey=arg(2:2)
found=0
optstr_ind=1
do while(optstr_ind.le.6)
if(optstr(optstr_ind:optstr_ind).eq.okey) then
found=1
if(optstr(optstr_ind+1:optstr_ind+1).eq.':') then
optstr_ind=optstr_ind+1
optind=optind+1
call getarg(optind, optarg)
end if
exit
end if
optstr_ind=optstr_ind+1
end do
if(found.gt.0) then
getopt=okey
else
getopt='!'
optarg=arg
end if
else
getopt='.'
optarg=arg
end if
optind=optind+1
return
end function
end module
This module implements only a small subset of standard C getopt. The following
forms of arguments are allowed:
- Switches:
-o
- Arguments with values:
-o value
- Parameters:
parameter
Thus, the following command line can be parsed with the module (given the correct
optstr):
% ./a.out -b -d 2.3d0 -i 15 -r 1.2 -o file.out file.in
Grouping of arguments is not allowed.
A sample program follows:
use_getoptions.f90
! This software is distributed under the following terms:
!
! Copyright (C) 2005 Dominik Epple
!
! Redistribution and use in source and binary forms, with or without
! modification, are permitted provided that the following conditions
! are met:
! 1. Redistributions of source code must retain the above copyright
! notice, this list of conditions and the following disclaimer.
! 2. Redistributions in binary form must reproduce the above copyright
! notice, this list of conditions and the following disclaimer in the
! documentation and/or other materials provided with the distribution.
!
! THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
! ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
! FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! SUCH DAMAGE.
program use_getoptions
use getoptions
implicit none
character :: okey
character(len=80) :: filename='def.in', ofilename='def.out'
integer :: i=1
integer :: binary=0
double precision :: d=0
real :: r=0
write(6,*)
write(6,*) 'Parsing arguments and parameters:'
write(6,*) '---------------------------------'
write(6,*)
do
okey=getopt('i:br:d:o:')
if(okey.eq.'>') exit
if(okey.eq.'!') then
write(6,*) 'unknown option: ', trim(optarg)
stop
end if
if(okey.eq.'b') then
binary=1
write(6,*) 'Found argument: -',okey
end if
if(okey.eq.'i') then
read(optarg,'(i)') i
write(6,*) 'Found argument: -',okey,' with value ',trim(optarg)
end if
if(okey.eq.'d') then
read(optarg,'(f)') d
write(6,*) 'Found argument: -',okey,' with value ',trim(optarg)
end if
if(okey.eq.'o') then
ofilename=optarg
write(6,*) 'Found argument: -',okey,' with value ',trim(optarg)
end if
if(okey.eq.'r') then
read(optarg,'(f)') r
write(6,*) 'Found argument: -',okey,' with value ',trim(optarg)
end if
if(okey.eq.'.') then
filename=optarg
write(6,*) 'Found parameter: ',trim(filename)
end if
end do
write(6,*)
write(6,*) 'Got these arguments and parameters:'
write(6,*) '-----------------------------------'
write(6,*)
write(6,*) 'binary:',binary
write(6,*) 'integer:',i
write(6,*) 'double:',d
write(6,*) 'real:', r
write(6,*) 'filename:',trim(filename)
write(6,*) 'ofilename:',trim(ofilename)
end program
This program demonstrates the usage of
getopt: It is being
called repeatedly until it returns '
>' to indicate all arguments
have been processed.
The argument to
getopt is the
optstr, which
contains the valid options, followed by a colon if the options takes an
argument.
getopt returns
> if all options have been parsed,
! if an unexpected option has been found (i.e. one that has not been given in optstr),
. if it found a parameter,
- or the letter of the option.
After calling
getopt the module variable
optarg (a string)
contains the value of the argument, or the parameter, or the option itself if an invalid
option has been found, in the form
-x.
You can convert the string
optarg to a real value with
read(optarg,'(f)') r,
and analogously to
integer,
double precision etc.
Impressum
Contact the
author.