Last commit for src/ext/arglib.f90: 5874abaa643d4472a2aa9d1c5dbe454dadbd8d1f

Initial commit of the AENET code.

Bruno Mundim [2017-01-02 17:48:39]
Initial commit of the AENET code.
!-----------------------------------------------------------------------
!          arglib.f90 - Easy access to command line arguments
!-----------------------------------------------------------------------
!+ This file is part of the AENET package.
!+
!+ Copyright (C) 2012-2016 Nongnuch Artrith and Alexander Urban
!+
!+ This program is free software: you can redistribute it and/or modify
!+ it under the terms of the GNU General Public License as published by
!+ the Free Software Foundation, either version 3 of the License, or
!+ (at your option) any later version.
!+
!+ This program is distributed in the hope that it will be useful, but
!+ WITHOUT ANY WARRANTY; without even the implied warranty of
!+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
!+ General Public License for more details.
!+
!+ You should have received a copy of the GNU General Public License
!+ along with this program.  If not, see <http://www.gnu.org/licenses/>.
!-----------------------------------------------------------------------
! 2011-02-18 Alexander Urban (AU), Nongnuch Artrith (NA)
! 2011-03-19 -- new interface: args_env()
!-----------------------------------------------------------------------

module arglib

  implicit none

  public  :: args_init,     &
             args_final,    &
             args_switch,   &
             args_env,      &
             args_get,      &
             in_list

  private :: args_switch_c1, &
             args_switch_cn, &
             args_switch_l1, &
             args_switch_i1, &
             args_switch_in, &
             args_switch_d1, &
             args_switch_dn, &
             args_env_c,     &
             args_env_i,     &
             args_env_d,     &
             args_env_l


  integer, public :: nargs

  integer, parameter, private :: lenarg = 100

  !--------------------------------------------------------------------!
  !                      args_switch() interface                       !
  !                                                                    !
  ! Get the value(s) of a single command line switch.                  !
  !                                                                    !
  ! Examples:                                                          !
  !                                                                    !
  !    character(len=50) :: input                                      !
  !    call args_switch('--input', value=infile, default='INP')        !
  !    --> infile == 'INP' if the '--input' switch was not found       !
  !        otherwise the value from the command line will be returned  !
  !                                                                    !
  !    logical :: ishelp                                               !
  !    call args_switch('--help:-h', value=ishelp)                     !
  !    --> ishelp is .true., if either the '--help' or the '-h' switch !
  !        was found                                                   !
  !                                                                    !
  !    integer, dimension(3) :: vector                                 !
  !    call args_switch('-n', value=vector, n=3, default=(/ 0, 0, 0 /))!
  !                                                                    !
  ! Available implementations:                                         !
  !                                                                    !
  !    args_switch_c1 : single character string                        !
  !    args_switch_cn : n character strings                            !
  !    args_switch_l1 : logical (see above)                            !
  !    args_switch_i1 : single integer                                 !
  !    args_switch_in : n integers                                     !
  !    args_switch_d1 : singlle doublle precisions                     !
  !    args_switch_dn : n double precisions                            !
  !                                                                    !
  !--------------------------------------------------------------------!

  interface args_switch
     module procedure args_switch_c1, args_switch_cn, args_switch_l1, &
                      args_switch_i1, args_switch_in, args_switch_d1, &
                      args_switch_dn
  end interface

  !--------------------------------------------------------------------!
  !                        args_env() interface                        !
  !                                                                    !
  ! Get the value of an environment variable.                          !
  !                                                                    !
  ! Usage:                                                             !
  !                                                                    !
  !   call args_env(name=n, value=v, stat=s)                           !
  !   n : name of the environment variable (character string)          !
  !   v : value of the variable, if present (character, integer,       !
  !       double precision, or logical)                                !
  !   s : is the return status (optional);                             !
  !       the value of s is 0 if the env. variable was present         !
  !                                                                    !
  ! Available implementations:                                         !
  !                                                                    !
  !    args_env_c   : character string                                 !
  !    args_env_i   : integer value                                    !
  !    args_env_d   : double precision value                           !
  !    args_env_l   : logical value (.true. if the variable is set)    !
  !                                                                    !
  !--------------------------------------------------------------------!

  interface args_env
     module procedure args_env_c, args_env_i, args_env_d, args_env_l
  end interface

contains

  subroutine args_init(check, status)

    implicit none

    character(len=*),  optional :: check
    integer,           optional :: status

    character(len=*), parameter :: figures = '0:1:2:3:4:5:6:7:8:9:.'

    integer                     :: istat, iarg
    character(len=100)          :: arg

    nargs = command_argument_count()

    istat = 0

    ! check if all occuring switches are recognized:
    if (present(check)) then
       chk : do iarg = 1, nargs
          call get_command_argument(iarg, value=arg)
          if ((arg(1:1)=='-') .and. (.not. in_list(figures,arg(2:2)))) then
             if (.not. in_list(check, arg)) then
                write(0,*) 'Warning: Unrecognized command line switch: ', trim(arg)
                istat = iarg
                exit chk
             end if
          end if
       end do chk
    end if

    if (present(status)) then
       status = istat
    end if

  end subroutine args_init

  !--------------------------------------------------------------------!

  subroutine args_final()

    implicit none

    continue
    return

  end subroutine args_final

  !--------------------------------------------------------------------!
  !          alias for the `get_command_aregument' subroutine          !
  !--------------------------------------------------------------------!

  subroutine args_get(iarg, value)

    implicit none

    integer,          intent(in)  :: iarg
    character(len=*), intent(out) :: value

    integer :: i

    if (iarg < 0) then
       i = nargs - iarg + 1
    else
       i = iargs
    end if

    if (i <= nargs) then
       call get_command_argument(iarg, value=value)
    end if

  end subroutine args_get



  !============================= PRIVATE ==============================!



  !--------------------------------------------------------------------!
  !                   args_switch_? implementations                    !
  !--------------------------------------------------------------------!

  subroutine args_switch_c1(switch, value, pos, default)

    implicit none

    character(len=*),           intent(in)    :: switch
    character(len=*), optional, intent(inout) :: value
    integer,          optional, intent(out)   :: pos
    character(len=*), optional, intent(in)    :: default

    integer               :: iarg
    character(len=lenarg) :: arg

    if (present(value) .and. present(default)) value = trim(default)
    if (present(pos)) pos = 0

    do iarg = 1, nargs
       call get_command_argument(iarg, value=arg)
       if (in_list(switch, arg)) then
          if (present(pos)) pos = iarg
          if (present(value)) then
             call get_command_argument(iarg+1, value=value)
          end if
       end if
    end do

  end subroutine args_switch_c1

  !--------------------------------------------------------------------!

  subroutine args_switch_cn(switch, value, n, default)

    implicit none

    integer,                                  intent(in)    :: n
    character(len=*),                         intent(in)    :: switch
    character(len=*), dimension(n),           intent(inout) :: value
    character(len=*), dimension(n), optional, intent(in)    :: default

    integer               :: iarg, i
    character(len=lenarg) :: arg

    if (present(default)) value(1:n) = default(1:n)

    do iarg = 1, nargs
       call get_command_argument(iarg, value=arg)
       if (in_list(switch, arg)) then
          do i = 1, n
             call get_command_argument(iarg+i, value=value(i))
          end do
       end if
    end do

  end subroutine args_switch_cn

  !--------------------------------------------------------------------!

  subroutine args_switch_l1(switch, value)

    implicit none

    character(len=*),           intent(in)    :: switch
    logical,                    intent(inout) :: value

    integer                                   :: ipos

    value = .false.

    call args_switch_c1(switch, pos=ipos)
    if (ipos > 0) then
       value = .true.
    end if

  end subroutine args_switch_l1

  !--------------------------------------------------------------------!

  subroutine args_switch_i1(switch, value, default)

    implicit none

    character(len=*),           intent(in)    :: switch
    integer,                    intent(inout) :: value
    integer,          optional, intent(in)    :: default

    integer                                   :: ipos
    character(len=lenarg)                     :: arg

    if (present(default)) value = default
    call args_switch_c1(switch, value=arg, pos=ipos)
    if (ipos > 0) then
       read(arg, *) value
    end if

  end subroutine args_switch_i1

  !--------------------------------------------------------------------!

  subroutine args_switch_in(switch, value, n, default)

    implicit none

    integer,                         intent(in)    :: n
    character(len=*),                intent(in)    :: switch
    integer, dimension(n),           intent(inout) :: value
    integer, dimension(n), optional, intent(in)    :: default

    integer                                        :: ipos, i
    character(len=lenarg), dimension(n)            :: arg

    if (present(default)) value(1:n) = default(1:n)
    call args_switch_c1(switch, pos=ipos)
    if (ipos > 0) then
       call args_switch_cn(switch, value=arg, n=n)
       do i = 1, n
          read(arg(i), *) value(i)
       end do
    end if

  end subroutine args_switch_in

  !--------------------------------------------------------------------!

  subroutine args_switch_d1(switch, value, default)

    implicit none

    character(len=*),           intent(in)    :: switch
    double precision,           intent(inout) :: value
    double precision, optional, intent(in)    :: default

    integer                                   :: ipos
    character(len=lenarg)                     :: arg

    if (present(default)) value = default
    call args_switch_c1(switch, value=arg, pos=ipos)
    if (ipos > 0) then
       read(arg, *) value
    end if

  end subroutine args_switch_d1

  !--------------------------------------------------------------------!

  subroutine args_switch_dn(switch, value, n, default)

    implicit none

    integer,                                  intent(in)    :: n
    character(len=*),                         intent(in)    :: switch
    double precision, dimension(n),           intent(inout) :: value
    double precision, dimension(n), optional, intent(in)    :: default

    integer                                                 :: ipos, i
    character(len=lenarg), dimension(n)                     :: arg

    if (present(default)) value(1:n) = default(1:n)
    call args_switch_c1(switch, pos=ipos)
    if (ipos > 0) then
       call args_switch_cn(switch, value=arg, n=n)
       do i = 1, n
          read(arg(i), *) value(i)
       end do
    end if

  end subroutine args_switch_dn

  !--------------------------------------------------------------------!
  !            implementations of the args_env_? interface             !
  !--------------------------------------------------------------------!

  subroutine args_env_c(name, value, stat)

    implicit none

    character(len=*),           intent(in)  :: name
    character(len=*),           intent(out) :: value
    integer,          optional, intent(out) :: stat

    integer :: status

    status = 0
    call get_environment_variable(name=trim(name), value=value, status=status)
    if (present(stat)) stat = status

  end subroutine args_env_c

  !--------------------------------------------------------------------!

  subroutine args_env_i(name, value, stat)

    implicit none

    character(len=*),           intent(in)  :: name
    integer,                    intent(out) :: value
    integer,          optional, intent(out) :: stat

    character(len=100) :: str
    integer            :: status

    call args_env_c(name=name, value=str, stat=status)
    if (status == 0) then
       read(str, *) value
    end if
    if (present(stat)) stat = status

  end subroutine args_env_i

  !--------------------------------------------------------------------!

  subroutine args_env_d(name, value, stat)

    implicit none

    character(len=*),           intent(in)  :: name
    double precision,           intent(out) :: value
    integer,          optional, intent(out) :: stat

    character(len=100) :: str
    integer            :: status

    call args_env_c(name=name, value=str, stat=status)
    if (status == 0) then
       read(str, *) value
    end if
    if (present(stat)) stat = status

  end subroutine args_env_d

  !--------------------------------------------------------------------!

  subroutine args_env_l(name, value)

    implicit none

    character(len=*),           intent(in)  :: name
    logical,                    intent(out) :: value

    character(len=100) :: str
    integer            :: status

    call args_env_c(name=name, value=str, stat=status)
    if (status == 0) then
       value = .true.
    else
       value = .false.
    end if

  end subroutine args_env_l

  !--------------------------------------------------------------------!
  ! Search input string `string' for a shorter string `search'.        !
  ! The input string contains records separated by the character       !
  ! `delim' (default = ':').                                           !
  !--------------------------------------------------------------------!

  function in_list(string, search, delim) result(found)

    implicit none

    character(len=*),    intent(in) :: string, search
    character, optional, intent(in) :: delim
    logical                         :: found

    character :: c
    integer   :: i1, i2
    integer   :: slen

    if (present(delim)) then
       c = delim
    else
       c = ':'
    end if

    slen = len_trim(string)

    found = .false.
    i1    = 1
    i2    = scan(string, c)

    do while(i2 >= i1)
       if (trim(adjustl(string(i1:i2-1))) == trim(adjustl(search))) then
          found = .true.
          exit
       end if
       i1 = i2 + 1
       i2 = i1 + scan(string(i1:slen), c) - 1
    end do

    if (trim(adjustl(string(i1:slen))) == trim(adjustl(search))) then
       found = .true.
    end if

  end function in_list

end module arglib
ViewGit