Options and input processing for Fortran

options.f90 is a Fortran module for defining and parsing command-line options and input parameters for Fortran programs. Its design is inspired by Python's optparse module. Some features:

Download

Documentation

Basic usage

To begin using the library, first import the module and declare the options structure:

use options
! ...
type(options_t), save :: opts

To define options, use the define_option_<type> subroutines. For instance, to define an option "--Nt" with the default value 16:

call define_option_integer(opts,"Nt",16,description="Number of time slices")

A text description, lower and upper bounds, and an abbreviation can all be specified. E.g., to define a real-valued required parameter "--beta" with abbreviation "-b", and with valid values 1 <= beta <= 10:

call define_option_real(opts,"beta",0.d0,abbrev="b",min=1.d0,max=10.d0,&
        description="Inverse temperature (required)",required=.true.)

Once all the relevant options have been defined, you can process the command line arguments as follows:

call process_command_line(opts,ierr)
if (ierr .ne. 0) stop

Finally, get the value of the options as needed:

call get_option_integer(opts,"Nt",nt)
write (*,'(a,i0)') "Value of Nt: ", nt

If desired, a help message listing the available options and their descriptions can be printed with

call print_options(opts)

Realistic Example

The following program defines four command-line options: -h, --Nt, --beta (or -b), and --fast (or -f). If -h is passed, it prints a help message listing all the available options. The --beta option is defined with lower and upper bounds, and is set to be required by the user. If any of the option values are incorrect or out of bounds, or required parameters are missing, the program exits gracefully.

The define_option functions require default values, which helps ensure that by the time the main body of the program is executed, all paramaters are guaranteed to have reasonable values.

program example1
  use options
  implicit none

  type(options_t), save :: opts
  integer :: ierr, nt
  real(8) :: beta

  ! Define options
  call define_help_flag(opts,print_help)
  call define_option_integer(opts,"Nt",16,description="Number of time slices")
  call define_option_real(opts,"beta",0.d0,abbrev="b",min=1.d0,max=10.d0,&
          description="Inverse temperature",required=.true.)
  call define_flag(opts,"fast",abbrev="f",description="Do it the fast way! &
      &This option has a longer description in order to demonstrate line wrapping.")

  ! Process command line
  call process_command_line(opts,ierr)
  if (ierr .ne. 0) stop
  call check_required_options(opts,ierr)
  if (ierr .ne. 0) stop

  ! Do the work ...
  call get_option_integer(opts,"Nt",nt)
  call get_option_real(opts,"beta",beta)
  write (*,'(a,i0)') "Value of Nt: ", nt
  write (*,'(a,es10.3)') "Value of beta: ", beta

contains

  subroutine print_help(opts)
    type(options_t), intent(in) :: opts
    write (*,'(a)') "example1: Compute some useful things."
    write (*,'(a)') "Usage: example1 [options]"
    write (*,'(a)') ""
    write (*,'(a)') "Options:"
    call print_options(opts)
  end subroutine print_help

end program example1

Some examples of running this program:

$ ./example1 -h
example1: Compute some useful things.
Usage: example1 [options]

Options:
  -h, --help                 Print this help message.
  --Nt=NT                    Number of time slices
  -b BETA, --beta=BETA       Inverse temperature (required)
  -f, --fast                 Do it the fast way! This option has a longer description in
                             order to demonstrate line wrapping.
$ ./example1 --garble
Error: unknown option: --garble
Try using -h for more info.
$ ./example1
Error: missing required parameter: "--beta"
Try using -h for more info.
$ ./example1 --beta 1.x
Error: parameter 1.x is not a valid real number.
Try using -h for more info.
$ ./example1 --beta 11
Error: value for option "beta" out of range.
Value:  1.10000000E+01, min:  1.00000000E+00, max:  1.00000000E+01
Try using -h for more info.
$ ./example1 --beta 1.2
Value of Nt: 16
Value of beta:  1.200E+00

Advanced Example

This example, in addition to defining command-line options, also defines options to be read from an input file. It uses the group parameter to group options according to whether they should be read at the command line or from the file. Additionally, it uses the style argument to print_options to format the option descriptions appropriately for the two sources.

program example2
  use options
  implicit none

  type(options_t), save :: opts
  character(len=128) :: inputfile
  integer :: ierr, nt, nargs
  real(8) :: beta

  ! Define options
  call define_help_flag(opts,print_help,group="cmdline")
  call define_flag(opts,"fast",abbrev='f',&
         description="Do it the fast way!",group="cmdline")
  call define_option_integer(opts,"Nt",16,description="(integer) Number of time slices",&
         group="inputfile")
  call define_option_real(opts,"beta",0.d0,min=1.d0,max=10.d0,required=.true.,&
         description="(real) Inverse temperature",group="inputfile")

  ! Process command line
  call process_command_line(opts,ierr)
  if (ierr .ne. 0) stop
  call get_num_args(opts,nargs)
  if (nargs .ne. 1) then
     write (*,'(a)') "Error: expected exactly 1 argument for the input file."
     write (*,'(a)') "Try using -h for more info."
     stop
  end if

  ! Read input file
  call get_arg(opts,1,inputfile,ierr)
  if (ierr .ne. 0) stop
  call process_input_file(opts,inputfile,ierr,group='inputfile')
  if (ierr .ne. 0) stop

  ! Check options
  call check_required_options(opts,ierr)
  if (ierr .ne. 0) stop

  ! Do the work ...
  call get_option_integer(opts,"Nt",nt)
  call get_option_real(opts,"beta",beta)
  write (*,'(a,i0)') "Value of Nt: ", nt
  write (*,'(a,es10.3)') "Value of beta: ", beta

contains

  subroutine print_help(opts)
    implicit none
    type(options_t), intent(in) :: opts

    write (*,'(a)') "example2: Compute some useful things."
    write (*,'(a)') "Usage: example2 [options] <input file>"
    write (*,'(a)') ""
    write (*,'(a)') "Command line options:"
    call print_options(opts,group="cmdline")
    write (*,'(a)') ""
    write (*,'(a)') "Input file parameters:"
    call print_options(opts,group="inputfile",style="file")
  end subroutine print_help

end program example2

Some examples of running this program:

$ ./example2
Error: expected exactly 1 argument for the input file.
Try using -h for more info.
$ ./example2 -h
example2: Compute some useful things.
Usage: example2 [options] <input file>

Command line options:
  -h, --help                 Print this help message.
  -f, --fast                 Do it the fast way!

Input file parameters:
  Nt                         (integer) Number of time slices
  beta                       (real) Inverse temperature
$ cat input 
Nt: 3
beta: 2.2222
$
$ ./example2 input 
Value of Nt: 3
Value of beta:  2.222E+00

Reference guide

Defining options

define_option, define_flag

The subroutines define_option_<type> and define_flag define the options that will be recognized at the command line. An option is a named parameter which takes a value. A flag is a named logical parameter which, when specified, automatically assumes the value .true..

define_help_flag is a special case which creates a pre-defined flag and slightly alters the behavior of other routines. If this routine is called, a flag called "help" ("--help" or "-h") is defined, and a subroutine specified by the user is called to print a help message if this option is seen on the command line. If any of the options processing routines fail (e.g. due to an invalid option), the message "Try -h for more info" is printed.

subroutine define_help_flag(opts,help_routine,[group])
subroutine define_option_real(opts,name,default,[min,max,abbrev,required,description,group])
subroutine define_option_integer(opts,name,default,[min,max,abbrev,required,description,group])
subroutine define_option_logical(opts,name,default,[abbrev,required,description,group])
subroutine define_option_string(opts,name,default,[abbrev,required,description,group])
subroutine define_flag(opts,name,[abbrev,description,group])

Required arguments:

opts:(type(options_t)) The options structure.
name: (character(len=*)) A string representing the name of the option. The option can be indicated at the command line by --name.
default: (real, integer, logical, or string) Default value of the option.
help_routine: (subroutine) (For define_help_flag only.) A subroutine, taking a single parameter of type(options_t), intent(in), which prints a help message to the screen. This routine must be created by the user.

Optional arguments:

min, max: (real or integer) For real or integer options, specifys upper and lower bounds that the option may have. If the user tries to pass a value exceeding these bounds, an error is raised. The bounds are inclusive, i.e. min <= value <= max.
abbrev: (character(len=1)) A one-character abbreviation for the option which specifies its "short form". The option can be indicated at the command line by -abbrev.
required: (logical) If .true., an error will be raised if the option has not been set and check_required_opts is called.
description: (character(len=*)) A string specifying a description of the option to be printed when print_option or print_options is called. It may contain newlines. Long lines will be wrapped at max_column, specified in options.f90.
group: (character(len=*)) A string specifying the name of a group to which the option should be assigned. (This can be useful for differentiating between options which are to be read from the command line and options to be read from file, or for other means.)

Processing input options

process_command_line

The subroutine process_command_line reads option names and values from the command-line arguments and processes them accordingly.

subroutine process_command_line(opts,ierr,[group])

When process_command_line encounters an option it recognizes, it reads any value which has been supplied and, if it is valid and within bounds, saves it for later retrieval. If the value is invalid or out of bounds, or it encounters an undefined option, and error message is printed and a nonzero value of ierr is returned. Otherwise, upon success, ierr=0 is returned and the saved option values are stored in opts.

Required arguments:

opts: (type(options_t)) The options structure.
ierr: (integer) Error code. If an error occurs while processing the command-line arguments, e.g. an invalid or out-of-bounds parameter is encountered, ierr is set to a nonzero value. Upon success, ierr is set to 0.

Optional arguments:

group: (character(len=*)) Only allow options defined in this group. If not specified, or blank, allow all options.
process_input_file

The subroutine process_input_file reads option names and values from a text file and processes them accordingly.

subroutine process_input_file(opts,filename,ierr,[group,overwrite,delim_char,comment_chars])

When process_input_file encounters an option it recognizes, it reads any value which has been supplied and, if it is valid and within bounds, saves it for later retrieval. If the value is invalid or out of bounds, or it encounters an undefined option, and error message is printed and a nonzero value of ierr is returned. Otherwise, upon success, ierr=0 is returned and the saved option values are stored in opts.

Required arguments:

opts: (type(options_t)) The options structure.
filename: (character(len=*)) Name of file to read.
ierr: (integer) Error code. If an error occurs while processing the command-line arguments, e.g. an invalid or out-of-bounds parameter is incounted, ierr is set to a nonzero value. Upon success, ierr is set to 0.

Optional arguments:

group: (character(len=*)) Only allow options defined in this group. If not specified, or blank, allow all options.
overwrite: (character(len=*)) Overwrite policy. If "YES", options encountered that have already been set (either in a previous call to process_command_line or process_input_file, or in the current input file) will be overwritten with the newly read value. If "NO", the old value will be retained and the new value ignored. If "ERROR", an error message will be printed and a non-zero value of ierr will be returned.
delim_char: (character(len=1)) Delimiter character for the file. This indicates how options are specified in the file, e.g. by "opt: value" or "opt=value", where ':' and '=' are the delimiter characters. (Default ':')
comment_chars: (character(len=*)) Characters which can indicate comments in the file. (Default "#!", so both '#' and '!' indicate comments.)
check_required_options

The subroutine check_required_options, which can only be called after process_command_line or process_input_file, will verify that all required options have appeared on the command line.

subroutine check_required_options(opts,ierr)

Required arguments:

opts: (type(options_t)) The options structure.
ierr: (integer) Error code. If all required options are present, ierr is set to 0. Otherwise, ierr is set to a nonzero value and an error message is printed.

Retrieving option values

get_option, get_flag

The subroutines get_option_<type> and get_flag are used to retrieve the values of options.

subroutine get_option_real(opts,name,val)
subroutine get_option_integer(opts,name,val)
subroutine get_option_logical(opts,name,val)
subroutine get_option_string(opts,name,val)
subroutine get_flag(opts,name,val)

Required arguments:

opts: (type(options_t)) The options structure.
name: (character(len=*)) The name of the option to retrieve.
val: (real,integer,logical,string)  The value of the option. For flags, .true. if the flag was found, and .false. otherwise (unless the value was explicitly set via --flag=<value> or in an input file).
option_found

The function option_found will check to see if an option has been set, either via the command line or through an input file.

logical function option_found(opts,name,val)

Function arguments are the same as above. If the option was found, returns .true.; otherwise returns .false.

Retrieving arguments

The subroutines get_arg and get_num_args retrieve information about non-option command-line arguments.

get_arg

get_arg retrieves the nth non-option command-line argument:

subroutine get_arg(opts,index,str,ierr)

Required arguments:

opts: (type(options_t)) The options structure.
index: (integer) The index of the non-option argument to retrieve. E.g. if the command line is "myprogram --opt1 val1 arg" and the option "opt1" takes a parameter "val1", index=1 will retrieve "arg". (Options and their values are skipped.)
str: (character(len=*)) A buffer in which to store the argument.
ierr: (integer) Return code. Upon success, ierr=0; upon failure, ierr takes a non-zero value.b
get_num_args

get_num_args retrievs the number of non-option arguments that were found:

subroutine get_num_args(opts,num)

Required arguments:

opts: (type(options_t)) The options structure.
num: (integer) The number of non-option and non-value arguments found.

Printing options

print_option

The subroutine print_option will print the form and description of a specific option, suitable for a help message. To simply print all the options, or all options in a group, use print_options below.

subroutine print_option(opts,name,[unit,style])

Required arguments:

opts: (type(options_t)) The options structure.
name: (character(len=*)) The name of the option to print.

Optional arguments:

unit: (integer) Output file unit number to which to print the option.
style: (character(len=*)) Style in which to format the option. Two styles are defined: "cmdline", which formats options in a style appropriate for the command line (with dashes: "--name"), and "file", which formats in a style appropriate for input file options (without using dashes).
print_options

The subroutine print_options will print the form and description of all options.

subroutine print_options(opts,[unit,group,style])

Required arguments:

opts: (type(options_t)) The options structure.

Optional arguments:

unit: (integer) Output file unit number to which to print the option.
group: (character(len=*)) Print only options defined in this group.
style: (character(len=*)) Style in which to format the option (see print_option).
print_option_values

The subroutine print_option_values will print the values of all the defined options:

subroutine print_option_values(opts,unit)

Required arguments:

opts: (type(options_t)) The options structure.

Optional arguments:

unit: (integer) Output file unit number to which to print the option.

Printing arguments

print_args

The subroutine print_args will print the values of all non-option command-line arguments after process_command_line has been run:

subroutine print_args(opts,unit)

Required arguments:

opts: (type(options_t)) The options structure.

Optional arguments:

unit: (real,integer,logical,string) Output file unit number to which to print the option.

Internal Parameters

A number of parameters can be changed in options.f90, including the kind type parameters of integer and real values, columns for formatting descriptions, and maximum lengths for options/command-line arguments and descriptions. These are all listed at the top of the file.

The most important are perhaps the maxargs and maxopts parameters, which specify the size of static arrays used to store options. The default for both is 32, meaning that if you wish to define more than 32 options, or store more than 32 non-option command-line arguments, you will need to increase maxopts or maxargs, respectively. Memory usage can also be minimized by adjusting these parameters and the length parameters below.

Name Default Description
maxopts 32 The maximum number of options which can be defined (i.e. the size of the options array).
maxargs 32 The maximum number of non-option command line arguments which can be stored (i.e. the size of the arguments array).
name_column 3 Column at which to begin printing the names of options in print_option.
descr_column 30 Column at which to begin printing the descriptions of options in print_option.
max_column 90 Column at which to wrap long descriptions.
rk selected_real_kind(p=15) Kind parameter for real options.
ik kind(1) Kind parameter for integer options.
opt_len 256 Maximum length of an option passed at the command line (e.g. "--<name>=<value>")
descr_len 2048 Maximum length of an option description.