Skip to content
Hani Andreas Ibrahim edited this page Mar 17, 2023 · 9 revisions

In your project make use of f90getopt by adding use f90getopt in the head of your Fortran main file. Then decide if you want to use long options as "--alpha" (GNU extension) or just short options as "-a" (POSIX-compliant) or both.

Content

Just short options

Your development tree for a short option program is just:

  1. Add use f90getopt statement
  2. Handle no options
  3. Process options one by one in a do-loop with character function getopt()
  4. Done

No option

You have to specify what to do if no option was committed. Check for zero options and specify the action if true:

if (command_argument_count() .eq. 0) then
  print*, "ERROR: No options committed"
end if

Process options

2.) Then call the function getopt() in a do-loop and process the short options one by one by a select-cas-statement. Place just one character-array argument in getopt(). The character-array should contain all single-character option names in a line without space. If you want that some characters should ask for arguments, add a trailing colon (:) to the character.

If you want to have 3 options in your program, e.g. "-a", "-b" and "-h" and you want to commit an argument to the option "-b" your character array is "ab:h". The argument of "-b" (or others) is stored in the global character variable optarg. It is not an array, it pulls the argument of an option one by one. You do not need to declare optarg in your program. It is provided by f90getopt's module automatically.

The maximum sizes of the short option character string is 80 characters as well as optarg.

do
    short = getopt("ab:h") ! Separate variable for ifort compatibility
    select case(short)
        case(char(0)) ! if no arguments are left
            exit
        case("a")
            print*, "option -a"
        case("b")
            print*, "option -b=",  trim(optarg) ! "trim" is quite useful to avoid trailing spaces
        case("h")
            print*, "help-screen"
    end select
end do

Your done.

Sample program

program short_options
    ! Full working sample program for short options

    use f90getopt
    implicit none

    character(len=1) :: short ! getopt short variable

    ! If no options were committed
    ! ----------------------------
    if (command_argument_count() .eq. 0) then
      print*, "ERROR: Program has options: -a -b x -h"
    end if


    ! START Processing options
    ! ------------------------
    do
        short = getopt("ab:h") ! Separate variable for ifort compatibility
        select case(short)
            case(char(0))
                exit
            case("a")
                print*, "option alpha/a"
            case("b")
                print*, "option beta/b=",  trim(optarg)
            case("h")
                print*, "help-screen"
        end select
    end do

end program

You can run it by e.g.:

  • ./short_options -a -b 3.14
  • ./short_options -ab 3.14
  • ./short_options -b "Title"
  • ./short_options -h

Long options

First, you cannot use long options GNU extension without the POSIX-compliant short ones in f90getopt. The GNU-style is just an extension of the POSIX standard.

But if you want to use long options (GNU-style), e.g. "--alpha" in your program additionally, you just have to add their declaration by the derived type array variable option_s before you process the options one by one as done in the short option section. That means you program is constructed in the following order:

  1. Add use f90getopt statement
  2. Handle no options
  3. Declare option_s derived type array variable for long options (see below)
  4. Process options one by one in a do-loop with character function getopt(). Important: You have to add an additional argument to `getopt()' in comparison to the short option handling (see below). But everything else stay the same.

Declaration of long-options

For long options you need to declare option_s derived-type array variable before processing the options in the do-loop. option_s contains 3 values:

No. Description Type Size Example
1 Long option name character 2-80 "alpha"
2 Value required logical 1 .true.
3 Short option name character 1 "a"

A complete definition of option_s for the long option "--alpha", "--beta" and "--help" could look like:

type(option_s) :: opts(2)
opts(1) = option_s("alpha", .false., "a") ! has no argument
opts(2) = option_s("beta",  .true.,  "b") ! has an argument
opts(3) = option_s("help",  .false., "h") ! has no argument

getopt() for long options

For long option you have to add additionally to the short option character array a second argument to getopt(): The name of the long option declaration option_s, here opts. Your getopts-call looks for the examples above as:

getopts("ab:h", opts)

instead of `getopt("ab:h") for short options only.

IMPORTANT: The short option names declared in option_s have to match the ones in the short option character array!

Sample program

program f90getopt_sample
    ! Full working sample program for short and long options

    use f90getopt
    implicit none

    ! START for longopts only (optional)
    ! ----------------------------------
    type(option_s) :: opts(3)
    opts(1) = option_s("alpha", .false., "a")
    opts(2) = option_s("beta",  .true.,  "b")
    opts(3) = option_s("help",  .false., "h")

    ! If no options were committed
    ! ----------------------------
    if (command_argument_count() .eq. 0) then
      print*, "ERROR: Program has options: -a. --alpha -b x --beta=x --beta x -h --help"
    end if


    ! START Processing options
    do
        select case(getopt("ab:h", opts))
            case(char(0)) ! When all options are processed
                exit
            case("a")
                print*, "option alpha/a"
            case("b")
                print*, "option beta/b=",  trim(optarg)
            case("h")
                print*, "help-screen"
        end select
    end do

end program f90getopt_sample

Conversion of optarg to a number

If you commit a number by optarg and you want to do some calculations with it, you need to convert it by read(optarg,*) x. Where "x" is declared as the type you need, e.g.:

! Conversion of character variable "optarg" to double variable "x"
double precision :: x
read(optarg,*) x

Further information

  • A complete, documented and working example program for long (and short) options in the following wiki-page.
  • You find a table with all information regarding user functions and variable of f90getopt in the following wiki-page.