M_CLI2
M_CLI2 module (Fortran)
Data Types | Functions/Subroutines | Variables
m_cli2 Module Reference

Data Types

interface  cgets
 
interface  dgets
 
interface  get_args
 
interface  get_args_fixed_length
 
interface  get_args_fixed_size
 
interface  igets
 
interface  insert
 
interface  lgets
 
interface  locate
 
type  option
 
interface  remove
 
interface  replace
 
interface  rgets
 
interface  sgets
 
interface  str
 

Functions/Subroutines

subroutine, private check_commandline (help_text, version_text)
 
subroutine, public set_args (prototype, help_text, version_text, string, ierr, errmsg)
 
character(len=:) function, allocatable, public get_subcommand ()
 
subroutine set_usage (keyword, description, value)
 
recursive subroutine, private prototype_to_dictionary (string)
 
elemental impure logical function, public specified (key)
 
subroutine, private update (key, val)
 
subroutine, private wipe_dictionary ()
 
character(len=:) function, allocatable, private get (key)
 
subroutine, private prototype_and_cmd_args_to_nlist (prototype, string)
 
subroutine expand_response (name)
 
subroutine get_prototype (name, prototype)
 
integer function fileopen (filename, message)
 
character(len=:) function, allocatable get_env (NAME, DEFAULT)
 
character(len=:) function, allocatable join_path (a1, a2, a3, a4, a5)
 
character(len=:) function, allocatable get_name ()
 
character(:) function, allocatable basename (path, suffix)
 
character(len=1) function separator2 ()
 
character(len=1) function separator ()
 
subroutine cmd_args_to_dictionary ()
 
subroutine, public print_dictionary (header, stop)
 
logical function strtok (source_string, itoken, token_start, token_end, delimiters)
 
subroutine get_fixedarray_class (keyword, generic, delimiters)
 
subroutine get_anyarray_l (keyword, larray, delimiters)
 
subroutine get_anyarray_d (keyword, darray, delimiters)
 
subroutine get_anyarray_i (keyword, iarray, delimiters)
 
subroutine get_anyarray_r (keyword, rarray, delimiters)
 
subroutine get_anyarray_x (keyword, xarray, delimiters)
 
subroutine get_anyarray_c (keyword, strings, delimiters)
 
subroutine get_args_fixed_length_a_array (keyword, strings, delimiters)
 
subroutine get_fixedarray_i (keyword, iarray, delimiters)
 
subroutine get_fixedarray_r (keyword, rarray, delimiters)
 
subroutine get_fixed_size_complex (keyword, xarray, delimiters)
 
subroutine get_fixedarray_d (keyword, darr, delimiters)
 
subroutine get_fixedarray_l (keyword, larray, delimiters)
 
subroutine get_fixedarray_fixed_length_c (keyword, strings, delimiters)
 
subroutine get_scalar_d (keyword, d)
 
subroutine get_scalar_real (keyword, r)
 
subroutine get_scalar_i (keyword, i)
 
subroutine get_scalar_anylength_c (keyword, string)
 
elemental impure subroutine get_args_fixed_length_scalar_c (keyword, string)
 
subroutine get_scalar_complex (keyword, x)
 
subroutine get_scalar_logical (keyword, l)
 
integer function longest_command_argument ()
 
subroutine journal (where, g0, g1, g2, g3, g4, g5, g6, g7, g8, g9, ga, gb, gc, gd, ge, gf, gg, gh, gi, gj, sep)
 
character(len=:) function, allocatable msg_scalar (generic0, generic1, generic2, generic3, generic4, generic5, generic6, generic7, generic8, generic9, generica, genericb, genericc, genericd, generice, genericf, genericg, generich, generici, genericj, sep)
 
character(len=:) function, allocatable msg_one (generic0, generic1, generic2, generic3, generic4, generic5, generic6, generic7, generic8, generic9, sep)
 
character(:) function, allocatable upper (str)
 
character(:) function, allocatable lower (str)
 
subroutine a2i (chars, valu, ierr)
 
subroutine a2d (chars, valu, ierr, onerr)
 
subroutine split (input_line, array, delimiters, order, nulls)
 
subroutine crack_cmd (cmd, old, new, ierr)
 
character(len=:) function, allocatable replace_str (targetline, old, new, ierr, cmd, range)
 
character(len=:) function, allocatable quote (str, mode, clip)
 
pure character(len=:) function, allocatable unquote (quoted_str, esc)
 
character(len=:) function, allocatable i2s (ivalue, fmt)
 
character(len=:) function, allocatable merge_str (str1, str2, expr)
 
logical function decodebase (string, basein, out_baseten)
 
character(len=length) function lenset (line, length)
 
subroutine value_to_string (gval, chars, length, err, fmt, trimz)
 
subroutine trimzeros_ (string)
 
subroutine substitute (targetline, old, new, ierr, start, end)
 
subroutine, private locate_c (list, value, place, ier, errmsg)
 
subroutine, private remove_c (list, place)
 
subroutine, private remove_l (list, place)
 
subroutine, private remove_i (list, place)
 
subroutine, private replace_c (list, value, place)
 
subroutine, private replace_l (list, value, place)
 
subroutine, private replace_i (list, value, place)
 
subroutine, private insert_c (list, value, place)
 
subroutine, private insert_l (list, value, place)
 
subroutine, private insert_i (list, value, place)
 
subroutine many_args (n0, g0, n1, g1, n2, g2, n3, g3, n4, g4, n5, g5, n6, g6, n7, g7, n8, g8, n9, g9, na, ga, nb, gb, nc, gc, nd, gd, ne, ge, nf, gf, ng, gg, nh, gh, ni, gi, nj, gj)
 
integer function, public iget (n)
 
real function, public rget (n)
 
real(kind=dp) function, public dget (n)
 
character(len=:) function, allocatable, public sget (n)
 
complex function, public cget (n)
 
logical function, public lget (n)
 
integer function, dimension(:), allocatable igs (n)
 
real function, dimension(:), allocatable rgs (n)
 
real(kind=dp) function, dimension(:), allocatable dgs (n)
 
character(len=:) function, dimension(:), allocatable sgs (n, delims)
 
complex function, dimension(:), allocatable cgs (n)
 
logical function, dimension(:), allocatable lgs (n)
 
integer function, dimension(:), allocatable ig ()
 
real function, dimension(:), allocatable rg ()
 
real(kind=dp) function, dimension(:), allocatable dg ()
 
logical function, dimension(:), allocatable lg ()
 
complex function, dimension(:), allocatable cg ()
 
character(len=:) function, dimension(:), allocatable sg ()
 
subroutine mystop (sig, msg)
 
function atleast (line, length, pattern)
 
subroutine locate_key (value, place)
 

Variables

integer, parameter, private dp =kind(0.0d0)
 
integer, parameter, private sp =kind(0.0)
 
logical, save, public debug_m_cli2 =.false.
 
character(len= *), parameter gen ='(*(g0))'
 
character(len=:), dimension(:), allocatable, public unnamed
 
character(len=:), dimension(:), allocatable, public args
 
character(len=:), allocatable, public remaining
 
character(len=:), dimension(:), allocatable, save keywords
 
character(len=:), dimension(:), allocatable, save shorts
 
character(len=:), dimension(:), allocatable, save values
 
integer, dimension(:), allocatable, save counts
 
logical, dimension(:), allocatable, save present_in
 
logical, dimension(:), allocatable, save mandatory
 
logical, save g_keyword_single_letter =.true.
 
character(len=:), allocatable, save g_passed_in
 
logical, save g_remaining_on
 
logical, save g_remaining_option_allowed
 
character(len=:), allocatable, save g_remaining
 
character(len=:), allocatable, save g_subcommand
 
character(len=:), allocatable, save g_stop_message
 
integer, save g_stop
 
logical, save g_quiet
 
logical, save g_strict
 
logical, save, public cli_response_file =.false.
 
logical, save g_append
 
logical, save g_options_only
 
logical, save g_response
 
character(len=:), allocatable, save g_response_ignored
 

Detailed Description

NAME

M_CLI2(3fm) - [ARGUMENTS::M_CLI2::INTRO] - command line argument parsing using a prototype command (LICENSE:PD)

SYNOPSIS

Available procedures and variables:

use M_CLI2, only : set_args, get_args, unnamed, remaining, args use M_CLI2, only : get_args_fixed_length, get_args_fixed_size use M_CLI2, only : specified ! convenience functions use M_CLI2, only : dget, iget, lget, rget, sget, cget use M_CLI2, only : dgets, igets, lgets, rgets, sgets, cgets

DESCRIPTION

Allow for command line parsing much like standard Unix command line parsing using a simple prototype.

Typically one call to SET_ARGS(3f) is made to define the command arguments, set default values and parse the command line. Then a call is made to the convenience commands based on GET_ARGS(3f) for each command keyword to obtain the argument values.

The documentation for SET_ARGS(3f) and GET_ARGS(3f) provides further details.

EXAMPLE

Sample program using type conversion routines

program demo_M_CLI2
use M_CLI2,  only : set_args, get_args
use M_CLI2,  only : filenames=>unnamed
use M_CLI2,  only : get_args_fixed_length, get_args_fixed_size
implicit none
integer                      :: i
integer,parameter            :: dp=kind(0.0d0)
!
! DEFINE ARGS
real                         :: x, y, z
real(kind=dp),allocatable    :: point(:)
logical                      :: l, lbig
logical,allocatable          :: logicals(:)
character(len=:),allocatable :: title    ! VARIABLE LENGTH
character(len=40)            :: label    ! FIXED LENGTH
real                         :: p(3)     ! FIXED SIZE
logical                      :: logi(3)  ! FIXED SIZE
!
! DEFINE AND PARSE (TO SET INITIAL VALUES) COMMAND LINE
!   o set a value for all keywords.
!   o double-quote strings
!   o set all logical values to F or T.
!   o value delimiter is comma, colon, or space
call set_args('                         &
        & -x 1 -y 2 -z 3                &
        & -p -1 -2 -3                   &
        & --point 11.11, 22.22, 33.33e0 &
        & --title "my title" -l F -L F  &
        & --logicals  F F F F F         &
        & -logi F T F                   &
        & --label " " &
        ! note space between quotes is required
        & ')
! ASSIGN VALUES TO ELEMENTS
call get_args('x',x)         ! SCALARS
call get_args('y',y)
call get_args('z',z)
call get_args('l',l)
call get_args('L',lbig)
call get_args('title',title) ! ALLOCATABLE STRING
call get_args('point',point) ! ALLOCATABLE ARRAYS
call get_args('logicals',logicals)
!
! for NON-ALLOCATABLE VARIABLES

! for non-allocatable string
call get_args_fixed_length('label',label)

! for non-allocatable arrays
call get_args_fixed_size('p',p)
call get_args_fixed_size('logi',logi)
!
! USE VALUES
write(*,*)'x=',x, 'y=',y, 'z=',z, x+y+z
write(*,*)'p=',p
write(*,*)'point=',point
write(*,*)'title=',title
write(*,*)'label=',label
write(*,*)'l=',l
write(*,*)'L=',lbig
write(*,*)'logicals=',logicals
write(*,*)'logi=',logi
!
! unnamed strings
!
if(size(filenames).gt.0)then
   write(*,'(i6.6,3a)')(i,'[',filenames(i),']',i=1,size(filenames))
endif
!
end program demo_M_CLI2

AUTHOR

John S. Urban, 2019

LICENSE

Public Domain

Function/Subroutine Documentation

◆ a2d()

subroutine m_cli2::a2d ( character(len=*), intent(in)  chars,
doubleprecision, intent(out)  valu,
integer, intent(out)  ierr,
class(*), intent(in), optional  onerr 
)
private

References decodebase(), i2s(), journal(), substitute(), and unquote().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ a2i()

subroutine m_cli2::a2i ( character(len=*), intent(in)  chars,
integer, intent(out)  valu,
integer, intent(out)  ierr 
)
private

References a2d(), and journal().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ atleast()

function m_cli2::atleast ( character(len=*), intent(in)  line,
integer, intent(in)  length,
character(len=*), intent(in), optional  pattern 
)
private
Here is the caller graph for this function:

◆ basename()

character(:) function, allocatable m_cli2::basename ( character(*), intent(in)  path,
logical, intent(in), optional  suffix 
)
private

References split().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cg()

complex function, dimension(:), allocatable m_cli2::cg
private

References a2d(), sp, and unnamed.

Here is the call graph for this function:

◆ cget()

complex function, public m_cli2::cget ( character(len=*), intent(in)  n)

◆ cgs()

complex function, dimension(:), allocatable m_cli2::cgs ( character(len=*), intent(in)  n)
private

◆ check_commandline()

subroutine, private m_cli2::check_commandline ( character(len=:), dimension(:), intent(in), optional, allocatable  help_text,
character(len=:), dimension(:), intent(in), optional, allocatable  version_text 
)
private

NAME

check_commandline(3f) - [ARGUMENTS:M_CLI2]check command and process pre-defined options

SYNOPSIS

  subroutine check_commandline(help_text,version_text,ierr,errmsg)

   character(len=:),allocatable,intent(in),optional :: help_text(:)
   character(len=:),allocatable,intent(in),optional :: version_text(:)

DESCRIPTION

Checks the commandline and processes the implicit –help, –version, –verbose, and –usage parameters.

If the optional text values are supplied they will be displayed by –help and –version command-line options, respectively.

OPTIONS

 HELP_TEXT     if present, will be displayed if program is called with
               --help switch, and then the program will terminate. If
               not supplied, the command line initialized string will be
               shown when --help is used on the commandline.

 VERSION_TEXT  if present, will be displayed if program is called with
               --version switch, and then the program will terminate.

    If the first four characters of each line are "@(#)" this prefix
    will not be displayed and the last non-blank letter will be
    removed from each line. This if for support of the SCCS what(1)
    command. If you do not have the what(1) command on GNU/Linux and
    Unix platforms you can probably see how it can be used to place
    metadata in a binary by entering:

     strings demo_commandline|grep '@(#)'|tr '>' '\n'|sed -e 's/  */ /g'

EXAMPLE

Typical usage:

 program check_commandline
 use M_CLI2,  only : unnamed, set_args, get_args
 implicit none
 integer                      :: i
 character(len=:),allocatable :: version_text(:), help_text(:)
 real               :: x, y, z
 character(len=*),parameter :: cmd='-x 1 -y 2 -z 3'
    version_text=[character(len=80) :: "version 1.0","author: me"]
    help_text=[character(len=80) :: "wish I put instructions","here","I suppose?"]
    call set_args(cmd,help_text,version_text)
    call get_args('x',x,'y',y,'z',z)
    ! All done cracking the command line. Use the values in your program.
    write (*,*)x,y,z
    ! the optional unnamed values on the command line are
    ! accumulated in the character array "UNNAMED"
    if(size(unnamed).gt.0)then
       write (*,'(a)')'files:'
       write (*,'(i6.6,3a)') (i,'[',unnamed(i),']',i=1,size(unnamed))
    endif
 end program check_commandline

References debug_m_cli2, default_help(), g_quiet, g_stop_message, gen, get(), journal(), mystop(), and print_dictionary().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cmd_args_to_dictionary()

subroutine m_cli2::cmd_args_to_dictionary
private

◆ crack_cmd()

subroutine m_cli2::crack_cmd ( character(len=*), intent(in)  cmd,
character(len=:), intent(out), allocatable  old,
character(len=:), intent(out), allocatable  new,
integer  ierr 
)
private

NAME

replace_str(3f) - [M_CLI2:EDITING] function globally replaces one substring for another in string (LICENSE:PD)

SYNOPSIS

function replace_str(targetline[,old,new|cmd],range,ierr) result (newline)

 character(len=*)                       :: targetline
 character(len=*),intent(in),optional   :: old
 character(len=*),intent(in),optional   :: new
 character(len=*),intent(in),optional   :: cmd
 integer,intent(in),optional            :: range(2)
 integer,intent(out),optional           :: ierr
 logical,intent(in),optional            :: clip
 character(len=:),allocatable           :: newline

DESCRIPTION

Globally replace one substring for another in string. Either CMD or OLD and NEW must be specified.

OPTIONS

targetline input line to be changed old old substring to replace new new substring cmd alternate way to specify old and new string, in the form c/old/new/; where "/" can be any character not in "old" or "new" range if present, only change range(1) to range(2) of occurrences of old string ierr error code. iF ier = -1 bad directive, >= 0 then count of changes made clip whether to return trailing spaces or not. Defaults to .false.

RETURNS

newline allocatable string returned

EXAMPLES

Sample Program:

  program demo_replace_str
  use M_CLI2, only : replace_str
  implicit none
  character(len=:),allocatable :: targetline

  targetline='this is the input string'

  call testit('th','TH','THis is THe input string')

  ! a null old substring means "at beginning of line"
  call testit('','BEFORE:', 'BEFORE:THis is THe input string')

  ! a null new string deletes occurrences of the old substring
  call testit('i','', 'BEFORE:THs s THe nput strng')

  write(*,*)'Examples of the use of RANGE='

  targetline=replace_str('a b ab baaa aaaa','a','A')
  write(*,*)'replace a with A ['//targetline//']'

  targetline=replace_str('a b ab baaa aaaa','a','A',range=[3,5])
  write(*,*)'replace a with A instances 3 to 5 ['//targetline//']'

  targetline=replace_str('a b ab baaa aaaa','a','',range=[3,5])
  write(*,*)'replace a with null instances 3 to 5 ['//targetline//']'

  targetline=replace_str('a b ab baaa aaaa aa aa a a a aa aaaaaa','aa','CCCC',range=[3,5])
  write(*,*)'replace aa with CCCC instances 3 to 5 ['//targetline//']'

  contains
  subroutine testit(old,new,expected)
  character(len=*),intent(in) :: old,new,expected
  write(*,*)repeat('=',79)
  write(*,*)':STARTED ['//targetline//']'
  write(*,*)':OLD['//old//']', ' NEW['//new//']'
  targetline=replace_str(targetline,old,new)
  write(*,*)':GOT     ['//targetline//']'
  write(*,*)':EXPECTED['//expected//']'
  write(*,*)':TEST    [',targetline.eq.expected,']'
  end subroutine testit

  end program demo_replace_str

Expected output


STARTED [this is the input string] OLD[th] NEW[TH] GOT [THis is THe input string] EXPECTED[THis is THe input string]

TEST [ T ]

STARTED [THis is THe input string] OLD[] NEW[BEFORE:] GOT [BEFORE:THis is THe input string] EXPECTED[BEFORE:THis is THe input string]

TEST [ T ]

STARTED [BEFORE:THis is THe input string] OLD[i] NEW[] GOT [BEFORE:THs s THe nput strng] EXPECTED[BEFORE:THs s THe nput strng] TEST [ T ] Examples of the use of RANGE= replace a with A [A b Ab bAAA AAAA] replace a with A instances 3 to 5 [a b ab bAAA aaaa] replace a with null instances 3 to 5 [a b ab b aaaa] replace aa with CCCC instances 3 to 5 [a b ab baaa aaCCCC CCCC CCCC a a a aa aaaaaa]

AUTHOR

John S. Urban

LICENSE

Public Domain

References journal(), and strtok().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ decodebase()

logical function m_cli2::decodebase ( character(len=*), intent(in)  string,
integer, intent(in)  basein,
integer, intent(out)  out_baseten 
)
private

NAME

decodebase(3f) - [M_CLI2:BASE] convert whole number string in base [2-36] to base 10 number
(LICENSE:PD)

SYNOPSIS

logical function decodebase(string,basein,out10)

character(len=*),intent(in) :: string integer,intent(in) :: basein integer,intent(out) :: out10

DESCRIPTION

Convert a numeric string representing a whole number in base BASEIN
to base 10. The function returns FALSE if BASEIN is not in the range
[2..36] or if string STRING contains invalid characters in base BASEIN
or if result OUT10 is too big

The letters A,B,...,Z represent 10,11,...,36 in the base > 10.

OPTIONS

string input string. It represents a whole number in the base specified by BASEIN unless BASEIN is set to zero. When BASEIN is zero STRING is assumed to be of the form BASE::VALUE where BASE represents the function normally provided by BASEIN. basein base of input string; either 0 or from 2 to 36. out10 output value in base 10

EXAMPLE

Sample program:

 program demo_decodebase
 use M_CLI2, only : codebase, decodebase
 implicit none
 integer           :: ba,bd
 character(len=40) :: x,y
 integer           :: r

 print *,' BASE CONVERSION'
 write(*,'("Start   Base (2 to 36): ")',advance='no'); read *, bd
 write(*,'("Arrival Base (2 to 36): ")',advance='no'); read *, ba
 INFINITE: do
    print *,''
    write(*,'("Enter number in start base: ")',advance='no'); read *, x
    if(x.eq.'0') exit INFINITE
    if(decodebase(x,bd,r)) then
       if(codebase(r,ba,y)) then
         write(*,'("In base ",I2,": ",A20)')  ba, y
       else
         print *,'Error in coding number.'
       endif
    else
       print *,'Error in decoding number.'
    endif
 enddo INFINITE

 end program demo_decodebase

AUTHOR

John S. Urban

Ref.: "Math matiques en Turbo-Pascal by M. Ducamp and A. Reverchon (2), Eyrolles, Paris, 1988".

based on a F90 Version By J-P Moreau (www.jpmoreau.fr)

LICENSE

Public Domain

References a2i(), and upper().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ dg()

real(kind=dp) function, dimension(:), allocatable m_cli2::dg
private

References a2d(), and unnamed.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ dget()

real(kind=dp) function, public m_cli2::dget ( character(len=*), intent(in)  n)

◆ dgs()

real(kind=dp) function, dimension(:), allocatable m_cli2::dgs ( character(len=*), intent(in)  n)
private

◆ expand_response()

subroutine m_cli2::expand_response ( character(len=*), intent(in)  name)
private

References debug_m_cli2, g_append, gen, get_prototype(), and prototype_to_dictionary().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fileopen()

integer function m_cli2::fileopen ( character(len=*), intent(in)  filename,
character(len=*), intent(out), optional  message 
)
private

References debug_m_cli2, and gen.

Here is the caller graph for this function:

◆ get()

character(len=:) function, allocatable, private m_cli2::get ( character(len=*), intent(in)  key)
private

NAME

get(3f) - [ARGUMENTS:M_CLI2] get dictionary value associated with key name in private M_CLI2(3fm) dictionary

SYNOPSIS

DESCRIPTION

Get dictionary value associated with key name in private M_CLI2(3fm) dictionary.

OPTIONS

RETURNS

EXAMPLE

References counts, locate_key(), and values.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_anyarray_c()

subroutine m_cli2::get_anyarray_c ( character(len=*), intent(in)  keyword,
character(len=:), dimension(:), allocatable  strings,
character(len=*), intent(in), optional  delimiters 
)
private

References counts, journal(), locate_key(), mystop(), split(), unquote(), and values.

Here is the call graph for this function:

◆ get_anyarray_d()

subroutine m_cli2::get_anyarray_d ( character(len=*), intent(in)  keyword,
real(kind=dp), dimension(:), intent(out), allocatable  darray,
character(len=*), intent(in), optional  delimiters 
)
private

References a2d(), counts, journal(), locate_key(), mystop(), replace_str(), split(), and values.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_anyarray_i()

subroutine m_cli2::get_anyarray_i ( character(len=*), intent(in)  keyword,
integer, dimension(:), allocatable  iarray,
character(len=*), intent(in), optional  delimiters 
)
private

References get_anyarray_d().

Here is the call graph for this function:

◆ get_anyarray_l()

subroutine m_cli2::get_anyarray_l ( character(len=*), intent(in)  keyword,
logical, dimension(:), allocatable  larray,
character(len=*), intent(in), optional  delimiters 
)
private

References counts, journal(), locate_key(), mystop(), split(), upper(), and values.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_anyarray_r()

subroutine m_cli2::get_anyarray_r ( character(len=*), intent(in)  keyword,
real, dimension(:), allocatable  rarray,
character(len=*), intent(in), optional  delimiters 
)
private

References get_anyarray_d().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_anyarray_x()

subroutine m_cli2::get_anyarray_x ( character(len=*), intent(in)  keyword,
complex, dimension(:), allocatable  xarray,
character(len=*), intent(in), optional  delimiters 
)
private

References get_anyarray_d(), journal(), and mystop().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_args_fixed_length_a_array()

subroutine m_cli2::get_args_fixed_length_a_array ( character(len=*), intent(in)  keyword,
character(len=*), dimension(:), allocatable  strings,
character(len=*), intent(in), optional  delimiters 
)
private

References counts, journal(), locate_key(), mystop(), split(), unquote(), and values.

Here is the call graph for this function:

◆ get_args_fixed_length_scalar_c()

elemental impure subroutine m_cli2::get_args_fixed_length_scalar_c ( character(len=*), intent(in)  keyword,
character(len=*), intent(out)  string 
)
private

References counts, journal(), locate_key(), mystop(), unquote(), and values.

Here is the call graph for this function:

◆ get_env()

character(len=:) function, allocatable m_cli2::get_env ( character(len=*), intent(in)  NAME,
character(len=*), intent(in), optional  DEFAULT 
)
private
Here is the caller graph for this function:

◆ get_fixed_size_complex()

subroutine m_cli2::get_fixed_size_complex ( character(len=*), intent(in)  keyword,
complex, dimension(:)  xarray,
character(len=*), intent(in), optional  delimiters 
)
private

References get_anyarray_x(), journal(), mystop(), and print_dictionary().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_fixedarray_class()

subroutine m_cli2::get_fixedarray_class ( character(len=*), intent(in)  keyword,
class(*), dimension(:)  generic,
character(len=*), intent(in), optional  delimiters 
)
private

NAME

get_args(3f) - [ARGUMENTS:M_CLI2] return keyword values when parsing command line arguments (LICENSE:PD)

SYNOPSIS

 use M_CLI2, only : get_args
 ! convenience functions
 use M_CLI2, only : dget, iget, lget, rget, sget, cget
 use M_CLI2, only : dgets, igets, lgets, rgets, sgets, cgets

 subroutine get_args(name,value,delimiters)

  character(len=*),intent(in) :: name

  character(len=:),allocatable :: value
  ! or
  character(len=:),allocatable :: value(:)
  ! or
  [real|doubleprecision|integer|logical|complex] :: value
  ! or
  [real|doubleprecision|integer|logical|complex],allocatable :: value(:)

  character(len=*),intent(in),optional :: delimiters

DESCRIPTION

GET_ARGS(3f) returns the value of keywords after SET_ARGS(3f)
has been called. For fixed-length CHARACTER variables
see GET_ARGS_FIXED_LENGTH(3f). For fixed-size arrays see
GET_ARGS_FIXED_SIZE(3f).

As a convenience multiple pairs of keywords and variables may be
specified if and only if all the values are scalars and the CHARACTER
variables are fixed-length or pre-allocated.

OPTIONS

 NAME        name of commandline argument to obtain the value of
 VALUE       variable to hold returned value. The kind of the value
             is used to determine the type of returned value. May
             be a scalar or allocatable array. If type is CHARACTER
             the scalar must have an allocatable length.
 DELIMITERS  By default the delimiter for array values are comma,
             colon, and whitespace. A string containing an alternate
             list of delimiter characters may be supplied.

CONVENIENCE FUNCTIONS

There are convenience functions that are replacements for calls to
get_args(3f) for each supported default intrinsic type

  o scalars -- dget(3f), iget(3f), lget(3f), rget(3f), sget(3f),
               cget(3f)
  o vectors -- dgets(3f), igets(3f), lgets(3f), rgets(3f),
               sgets(3f), cgets(3f)

D is for DOUBLEPRECISION, I for INTEGER, L for LOGICAL, R for REAL,
S for string (CHARACTER), and C for COMPLEX.

If the functions are called with no argument they will return the
UNNAMED array converted to the specified type.

EXAMPLE

Sample program:

program demo_get_args
use M_CLI2,  only : filenames=>unnamed, set_args, get_args
implicit none
integer                      :: i
! DEFINE ARGS
real                         :: x, y, z
real,allocatable             :: p(:)
character(len=:),allocatable :: title
logical                      :: l, lbig
! DEFINE AND PARSE (TO SET INITIAL VALUES) COMMAND LINE
!   o only quote strings and use double-quotes
!   o set all logical values to F or T.
call set_args(' &
   &-x 1 -y 2 -z 3 &
   &-p -1,-2,-3 &
   &--title "my title" &
   & -l F -L F  &
   & --label " " &
   & ')
! ASSIGN VALUES TO ELEMENTS
! SCALARS
call get_args('x',x,'y',y,'z',z)
call get_args('l',l)
call get_args('L',lbig)
! ALLOCATABLE STRING
call get_args('title',title)
! NON-ALLOCATABLE ARRAYS
call get_args('p',p)
! USE VALUES
write(*,'(1x,g0,"=",g0)')'x',x, 'y',y, 'z',z
write(*,*)'p=',p
write(*,*)'title=',title
write(*,*)'l=',l
write(*,*)'L=',lbig
if(size(filenames).gt.0)then
   write(*,'(i6.6,3a)')(i,'[',filenames(i),']',i=1,size(filenames))
endif
end program demo_get_args

AUTHOR

John S. Urban, 2019

LICENSE

Public Domain

NAME

get_args_fixed_length(3f) - [ARGUMENTS:M_CLI2] return keyword values for fixed-length string when parsing command line (LICENSE:PD)

SYNOPSIS

subroutine get_args_fixed_length(name,value)

 character(len=:),allocatable :: value
 character(len=*),intent(in),optional :: delimiters

DESCRIPTION

GET_ARGS_fixed_length(3f) returns the value of a string
keyword when the string value is a fixed-length CHARACTER
variable.

OPTIONS

NAME   name of commandline argument to obtain the value of

VALUE  variable to hold returned value.
       Must be a fixed-length CHARACTER variable.

DELIMITERS  By default the delimiter for array values are comma,
            colon, and whitespace. A string containing an alternate
            list of delimiter characters may be supplied.

EXAMPLE

Sample program:

program demo_get_args_fixed_length
use M_CLI2,  only : set_args, get_args_fixed_length
implicit none
! DEFINE ARGS
character(len=80)   :: title
call set_args(' &
   & -title "my title" &
   & ')
! ASSIGN VALUES TO ELEMENTS
   call get_args_fixed_length('title',title)
! USE VALUES
   write(*,*)'title=',title
end program demo_get_args_fixed_length

AUTHOR

John S. Urban, 2019

LICENSE

Public Domain

NAME

get_args_fixed_size(3f) - [ARGUMENTS:M_CLI2] return keyword values for fixed-size array when parsing command line arguments (LICENSE:PD)

SYNOPSIS

subroutine get_args_fixed_size(name,value)

 [real|doubleprecision|integer|logical|complex] :: value(NNN)
    or
 character(len=MMM) :: value(NNN)

 character(len=*),intent(in),optional :: delimiters

DESCRIPTION

GET_ARGS_FIXED_SIZE(3f) returns the value of keywords for
fixed-size arrays after SET_ARGS(3f) has been called.
On input on the command line all values of the array must
be specified.

OPTIONS

NAME name of commandline argument to obtain the value of

VALUE variable to hold returned values. The kind of the value is used to determine the type of returned value. Must be a fixed-size array. If type is CHARACTER the length must also be fixed.

DELIMITERS By default the delimiter for array values are comma, colon, and whitespace. A string containing an alternate list of delimiter characters may be supplied.

EXAMPLE

Sample program:

program demo_get_args_fixed_size
use M_CLI2,  only : set_args, get_args_fixed_size
implicit none
integer,parameter   :: dp=kind(0.0d0)
! DEFINE ARGS
real                :: x(2)
real(kind=dp)       :: y(2)
integer             :: p(3)
character(len=80)   :: title(1)
logical             :: l(4), lbig(4)
complex             :: cmp(2)
! DEFINE AND PARSE (TO SET INITIAL VALUES) COMMAND LINE
!   o only quote strings
!   o set all logical values to F or T.
call set_args(' &
   & -x 10.0,20.0 &
   & -y 11.0,22.0 &
   & -p -1,-2,-3 &
   & -title "my title" &
   & -l F,T,F,T -L T,F,T,F  &
   & --cmp 111,222.0,333.0e0,4444 &
   & ')
! ASSIGN VALUES TO ELEMENTS
   call get_args_fixed_size('x',x)
   call get_args_fixed_size('y',y)
   call get_args_fixed_size('p',p)
   call get_args_fixed_size('title',title)
   call get_args_fixed_size('l',l)
   call get_args_fixed_size('L',lbig)
   call get_args_fixed_size('cmp',cmp)
! USE VALUES
   write(*,*)'x=',x
   write(*,*)'p=',p
   write(*,*)'title=',title
   write(*,*)'l=',l
   write(*,*)'L=',lbig
   write(*,*)'cmp=',cmp
end program demo_get_args_fixed_size

Results:

AUTHOR

John S. Urban, 2019

LICENSE

Public Domain

References dp, get_fixed_size_complex(), get_fixedarray_d(), get_fixedarray_fixed_length_c(), get_fixedarray_i(), get_fixedarray_l(), get_fixedarray_r(), and mystop().

Here is the call graph for this function:

◆ get_fixedarray_d()

subroutine m_cli2::get_fixedarray_d ( character(len=*), intent(in)  keyword,
real(kind=dp), dimension(:)  darr,
character(len=*), intent(in), optional  delimiters 
)
private

References get_anyarray_d(), journal(), mystop(), and print_dictionary().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_fixedarray_fixed_length_c()

subroutine m_cli2::get_fixedarray_fixed_length_c ( character(len=*), intent(in)  keyword,
character(len=*), dimension(:)  strings,
character(len=*), intent(in), optional  delimiters 
)
private

References counts, journal(), locate_key(), mystop(), print_dictionary(), split(), unquote(), and values.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_fixedarray_i()

subroutine m_cli2::get_fixedarray_i ( character(len=*), intent(in)  keyword,
integer, dimension(:)  iarray,
character(len=*), intent(in), optional  delimiters 
)
private

References get_anyarray_d(), journal(), mystop(), and print_dictionary().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_fixedarray_l()

subroutine m_cli2::get_fixedarray_l ( character(len=*), intent(in)  keyword,
logical, dimension(:)  larray,
character(len=*), intent(in), optional  delimiters 
)
private

References get_anyarray_l(), journal(), mystop(), and print_dictionary().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_fixedarray_r()

subroutine m_cli2::get_fixedarray_r ( character(len=*), intent(in)  keyword,
real, dimension(:)  rarray,
character(len=*), intent(in), optional  delimiters 
)
private

References get_anyarray_r(), journal(), mystop(), and print_dictionary().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_name()

character(len=:) function, allocatable m_cli2::get_name
private
Here is the caller graph for this function:

◆ get_prototype()

subroutine m_cli2::get_prototype ( character(len=*), intent(in)  name,
character(len=:), intent(out), allocatable  prototype 
)
private

References basename(), debug_m_cli2, find_and_read_response_file(), gen, get_env(), and get_name().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_scalar_anylength_c()

subroutine m_cli2::get_scalar_anylength_c ( character(len=*), intent(in)  keyword,
character(len=:), intent(out), allocatable  string 
)
private

References counts, journal(), locate_key(), mystop(), unquote(), and values.

Here is the call graph for this function:

◆ get_scalar_complex()

subroutine m_cli2::get_scalar_complex ( character(len=*), intent(in)  keyword,
complex, intent(out)  x 
)
private

References get_fixedarray_d(), journal(), mystop(), and sp.

Here is the call graph for this function:

◆ get_scalar_d()

subroutine m_cli2::get_scalar_d ( character(len=*), intent(in)  keyword,
real(kind=dp d 
)
private

References get_anyarray_d(), journal(), mystop(), and print_dictionary().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_scalar_i()

subroutine m_cli2::get_scalar_i ( character(len=*), intent(in)  keyword,
integer, intent(out)  i 
)
private

References get_scalar_d().

Here is the call graph for this function:

◆ get_scalar_logical()

subroutine m_cli2::get_scalar_logical ( character(len=*), intent(in)  keyword,
logical  l 
)
private

References get_anyarray_l(), journal(), and mystop().

Here is the call graph for this function:

◆ get_scalar_real()

subroutine m_cli2::get_scalar_real ( character(len=*), intent(in)  keyword,
real, intent(out)  r 
)
private

References get_scalar_d().

Here is the call graph for this function:

◆ get_subcommand()

character(len=:) function, allocatable, public m_cli2::get_subcommand

NAME

get_subcommand(3f) - [ARGUMENTS:M_CLI2] special-case routine for handling subcommands on a command line (LICENSE:PD)

SYNOPSIS

function get_subcommand()

 character(len=:),allocatable :: get_subcommand

DESCRIPTION

In the special case when creating a program with subcommands it is assumed the first word on the command line is the subcommand. A routine is required to handle response file processing, therefore this routine (optionally processing response files) returns that first word as the subcommand name.

It should not be used by programs not building a more elaborate command with subcommands.

RETURNS

NAME name of subcommand

EXAMPLE

Sample program:

program demo_get_subcommand !x! SUBCOMMANDS !x! For a command with subcommands like git(1) !x! you can make separate namelists for each subcommand. !x! You can call this program which has two subcommands (run, test), !x! like this: !x! demo_get_subcommand –help !x! demo_get_subcommand run -x -y -z -title -l -L !x! demo_get_subcommand test -title -l -L -testname !x! demo_get_subcommand run –help implicit none !x! DEFINE VALUES TO USE AS ARGUMENTS WITH INITIAL VALUES real :: x=-999.0,y=-999.0,z=-999.0 character(len=80) :: title="not set" logical :: l=.false. logical :: l_=.false. character(len=80) :: testname="not set" character(len=20) :: name call parse(name) !x! DEFINE AND PARSE COMMAND LINE !x! ALL DONE CRACKING THE COMMAND LINE. !x! USE THE VALUES IN YOUR PROGRAM. write(*,*)'command was ',name write(*,*)'x,y,z .... ',x,y,z write(*,*)'title .... ',title write(*,*)'l,l_ ..... ',l,l_ write(*,*)'testname . ',testname contains subroutine parse(name) !x! PUT EVERYTHING TO DO WITH COMMAND PARSING HERE FOR CLARITY use M_CLI2, only : set_args, get_args, get_args_fixed_length use M_CLI2, only : get_subcommand use M_CLI2, only : CLI_RESPONSE_FILE character(len=*) :: name ! the subcommand name character(len=:),allocatable :: help_text(:), version_text(:) CLI_RESPONSE_FILE=.true. ! define version text version_text=[character(len=80) :: & '@(#)PROGRAM: demo_get_subcommand >', & '@(#)DESCRIPTION: My demo program >', & '@(#)VERSION: 1.0 20200715 >', & '@(#)AUTHOR: me, myself, and I>', & '@(#)LICENSE: Public Domain >', & '' ] ! general help for "demo_get_subcommand --help" help_text=[character(len=80) :: & ' allowed subcommands are ', & ' * run -l -L -title -x -y -z ', & ' * test -l -L -title ', & '' ] ! find the subcommand name by looking for first word on command ! not starting with dash name = get_subcommand() select case(name) case('run') help_text=[character(len=80) :: & ' ', & ' Help for subcommand "run" ', & ' ', & '' ] call set_args( & & '-x 1 -y 2 -z 3 –title "my title" -l F -L F',& & help_text,version_text) call get_args('x',x) call get_args('y',y) call get_args('z',z) call get_args_fixed_length('title',title) call get_args('l',l) call get_args('L',l_) case('test') help_text=[character(len=80) :: & ' ', & ' Help for subcommand "test" ', & ' ', & '' ] call set_args(& & '–title "my title" -l F -L F –testname "Test"',& & help_text,version_text) call get_args_fixed_length('title',title) call get_args('l',l) call get_args('L',l_) call get_args_fixed_length('testname',testname) case default ! process help and version call set_args(' ',help_text,version_text) write(*,'(*(a))')'unknown or missing subcommand [',trim(name),']' write(*,'(a)')[character(len=80) :: & ' allowed subcommands are ', & ' * run -l -L -title -x -y -z ', & ' * test -l -L -title ', & '' ] stop end select end subroutine parse end program demo_get_subcommand

AUTHOR

John S. Urban, 2019

LICENSE

Public Domain

References g_options_only, g_subcommand, get_prototype(), longest_command_argument(), split(), and unnamed.

Here is the call graph for this function:

◆ i2s()

character(len=:) function, allocatable m_cli2::i2s ( integer, intent(in)  ivalue,
character(len=*), intent(in), optional  fmt 
)
private

References value_to_string().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ig()

integer function, dimension(:), allocatable m_cli2::ig
private

References a2i(), and unnamed.

Here is the call graph for this function:

◆ iget()

integer function, public m_cli2::iget ( character(len=*), intent(in)  n)

◆ igs()

integer function, dimension(:), allocatable m_cli2::igs ( character(len=*), intent(in)  n)
private

◆ insert_c()

subroutine, private m_cli2::insert_c ( character(len=:), dimension(:), allocatable  list,
character(len=*), intent(in)  value,
integer, intent(in)  place 
)
private

NAME

insert(3f) - [M_CLI2] insert entry into a string array at specified position (LICENSE:PD)

SYNOPSIS

subroutine insert(list,value,place)

character(len=*)|doubleprecision|real|integer,intent(in) :: value character(len=:)|doubleprecision|real|integer,intent(in) :: list(:) integer,intent(in) :: place

DESCRIPTION

Insert a value into an allocatable array at the specified index.
The list and value must be of the same type (CHARACTER, DOUBLEPRECISION,
REAL, or INTEGER)

OPTIONS

list    is the list array. Must be sorted in descending order.
value   the value to place in the array
PLACE   is the subscript that the entry should be placed at

EXAMPLES

Find if a string is in a sorted array, and insert the string into the list if it is not present ...

program demo_insert
use M_sort, only : sort_shell
use M_CLI2, only : locate, insert
implicit none
character(len=:),allocatable :: arr(:)
integer                       :: i

arr=[character(len=20) :: '', 'ZZZ', 'aaa', 'b', 'xxx' ]
! make sure sorted in descending order
call sort_shell(arr,order='d')
! add or replace values
call update(arr,'b')
call update(arr,'[')
call update(arr,'c')
call update(arr,'ZZ')
call update(arr,'ZZZ')
call update(arr,'ZZZZ')
call update(arr,'')
call update(arr,'z')

contains
subroutine update(arr,string)
character(len=:),allocatable :: arr(:)
character(len=*)             :: string
integer                      :: place, end

end=size(arr)
! find where string is or should be
call locate(arr,string,place)
! if string was not found insert it
if(place.lt.1)then
   call insert(arr,string,abs(place))
endif
! show array
end=size(arr)
write(*,'("array is now SIZE=",i0,1x,*(a,","))')end,(trim(arr(i)),i=1,end)

end subroutine update
end program demo_insert

Results:

array is now SIZE=5 xxx,b,aaa,ZZZ,, array is now SIZE=6 xxx,b,aaa,[,ZZZ,, array is now SIZE=7 xxx,c,b,aaa,[,ZZZ,, array is now SIZE=8 xxx,c,b,aaa,[,ZZZ,ZZ,, array is now SIZE=9 xxx,c,b,aaa,[,ZZZZ,ZZZ,ZZ,, array is now SIZE=10 z,xxx,c,b,aaa,[,ZZZZ,ZZZ,ZZ,,

AUTHOR

1989,2017 John S. Urban

LICENSE

Public Domain

◆ insert_i()

subroutine, private m_cli2::insert_i ( integer, dimension(:), allocatable  list,
integer, intent(in)  value,
integer, intent(in)  place 
)
private

◆ insert_l()

subroutine, private m_cli2::insert_l ( logical, dimension(:), allocatable  list,
logical, intent(in)  value,
integer, intent(in)  place 
)
private

◆ join_path()

character(len=:) function, allocatable m_cli2::join_path ( character(len=*), intent(in)  a1,
character(len=*), intent(in)  a2,
character(len=*), intent(in), optional  a3,
character(len=*), intent(in), optional  a4,
character(len=*), intent(in), optional  a5 
)
private

References separator(), and substitute().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ journal()

subroutine m_cli2::journal ( character(len=*), intent(in)  where,
class(*), intent(in)  g0,
class(*), intent(in), optional  g1,
class(*), intent(in), optional  g2,
class(*), intent(in), optional  g3,
class(*), intent(in), optional  g4,
class(*), intent(in), optional  g5,
class(*), intent(in), optional  g6,
class(*), intent(in), optional  g7,
class(*), intent(in), optional  g8,
class(*), intent(in), optional  g9,
class(*), intent(in), optional  ga,
class(*), intent(in), optional  gb,
class(*), intent(in), optional  gc,
class(*), intent(in), optional  gd,
class(*), intent(in), optional  ge,
class(*), intent(in), optional  gf,
class(*), intent(in), optional  gg,
class(*), intent(in), optional  gh,
class(*), intent(in), optional  gi,
class(*), intent(in), optional  gj,
character(len=*), intent(in), optional  sep 
)
private

References debug_m_cli2.

Here is the caller graph for this function:

◆ lenset()

character(len=length) function m_cli2::lenset ( character(len=*), intent(in)  line,
integer, intent(in)  length 
)
private

NAME

lenset(3f) - [M_CLI2:LENGTH] return string trimmed or padded to specified length (LICENSE:PD)

SYNOPSIS

function lenset(str,length) result(strout)

 character(len=*)                     :: str
 character(len=length)                :: strout
 integer,intent(in)                   :: length

DESCRIPTION

lenset(3f) truncates a string or pads it with spaces to the specified length.

OPTIONS

str input string length output string length

RESULTS

strout output string

EXAMPLE

Sample Program:

program demo_lenset
 use M_CLI2, only : lenset
 implicit none
 character(len=10)            :: string='abcdefghij'
 character(len=:),allocatable :: answer
    answer=lenset(string,5)
    write(*,'("[",a,"]")') answer
    answer=lenset(string,20)
    write(*,'("[",a,"]")') answer
end program demo_lenset

Expected output:

[abcde] [abcdefghij ]

AUTHOR

John S. Urban

LICENSE

Public Domain

Here is the caller graph for this function:

◆ lg()

logical function, dimension(:), allocatable m_cli2::lg
private

References journal(), unnamed, and upper().

Here is the call graph for this function:

◆ lget()

logical function, public m_cli2::lget ( character(len=*), intent(in)  n)

◆ lgs()

logical function, dimension(:), allocatable m_cli2::lgs ( character(len=*), intent(in)  n)
private

◆ locate_c()

subroutine, private m_cli2::locate_c ( character(len=:), dimension(:), allocatable  list,
character(len=*), intent(in)  value,
integer, intent(out)  place,
integer, intent(out), optional  ier,
character(len=*), intent(out), optional  errmsg 
)
private

NAME

locate(3f) - [M_CLI2] finds the index where a string is found or should be in a sorted array (LICENSE:PD)

SYNOPSIS

subroutine locate(list,value,place,ier,errmsg)

character(len=:)|doubleprecision|real|integer,allocatable :: list(:) character(len=*)|doubleprecision|real|integer,intent(in) :: value integer, intent(out) :: PLACE

integer, intent(out),optional :: IER character(len=*),intent(out),optional :: ERRMSG

DESCRIPTION

LOCATE(3f) finds the index where the VALUE is found or should
be found in an array. The array must be sorted in descending
order (highest at top). If VALUE is not found it returns the index
where the name should be placed at with a negative sign.

The array and list must be of the same type (CHARACTER, DOUBLEPRECISION,
REAL,INTEGER)

OPTIONS

VALUE         the value to locate in the list.
LIST          is the list array.

RETURNS

PLACE is the subscript that the entry was found at if it is greater than zero(0).

If PLACE is negative, the absolute value of PLACE indicates the subscript value where the new entry should be placed in order to keep the list alphabetized.

IER is zero(0) if no error occurs. If an error occurs and IER is not present, the program is stopped.

ERRMSG description of any error

EXAMPLES

Find if a string is in a sorted array, and insert the string into the list if it is not present ...

program demo_locate
use M_sort, only : sort_shell
use M_CLI2, only : locate
implicit none
character(len=:),allocatable  :: arr(:)
integer                       :: i

arr=[character(len=20) :: '', 'ZZZ', 'aaa', 'b', 'xxx' ]
! make sure sorted in descending order
call sort_shell(arr,order='d')

call update(arr,'b')
call update(arr,'[')
call update(arr,'c')
call update(arr,'ZZ')
call update(arr,'ZZZZ')
call update(arr,'z')

contains
subroutine update(arr,string)
character(len=:),allocatable :: arr(:)
character(len=*)             :: string
integer                      :: place, plus, ii, end
! find where string is or should be
call locate(arr,string,place)
write(*,*)'for "'//string//'" index is ',place, size(arr)
! if string was not found insert it
if(place.lt.1)then
   plus=abs(place)
   ii=len(arr)
   end=size(arr)
   ! empty array
   if(end.eq.0)then
      arr=[character(len=ii) :: string ]
   ! put in front of array
   elseif(plus.eq.1)then
      arr=[character(len=ii) :: string, arr]
   ! put at end of array
   elseif(plus.eq.end)then
      arr=[character(len=ii) :: arr, string ]
   ! put in middle of array
   else
      arr=[character(len=ii) :: arr(:plus-1), string,arr(plus:) ]
   endif
   ! show array
   write(*,'("SIZE=",i0,1x,*(a,","))')end,(trim(arr(i)),i=1,end)
endif
end subroutine update
end program demo_locate

Results:

for "b" index is 2 5 for "[" index is -4 5 SIZE=5 xxx,b,aaa,[,ZZZ, for "c" index is -2 6 SIZE=6 xxx,c,b,aaa,[,ZZZ, for "ZZ" index is -7 7 SIZE=7 xxx,c,b,aaa,[,ZZZ,, for "ZZZZ" index is -6 8 SIZE=8 xxx,c,b,aaa,[,ZZZZ,ZZZ,, for "z" index is -1 9 SIZE=9 z,xxx,c,b,aaa,[,ZZZZ,ZZZ,,

AUTHOR

1989,2017 John S. Urban

LICENSE

Public Domain

References mystop().

Here is the call graph for this function:

◆ locate_key()

subroutine m_cli2::locate_key ( character(len=*), intent(in)  value,
integer, intent(out)  place 
)
private

References keywords, and shorts.

Here is the caller graph for this function:

◆ longest_command_argument()

integer function m_cli2::longest_command_argument
private

NAME

longest_command_argument(3f) - [ARGUMENTS:M_args] length of longest argument on command line (LICENSE:PD)

SYNOPSIS

function longest_command_argument() result(ilongest)

 integer :: ilongest

DESCRIPTION

length of longest argument on command line. Useful when allocating storage for holding arguments.

RESULT

longest_command_argument length of longest command argument

EXAMPLE

Sample program

 program demo_longest_command_argument
 use M_args, only : longest_command_argument
    write(*,*)'longest argument is ',longest_command_argument()
 end program demo_longest_command_argument

AUTHOR

John S. Urban, 2019

LICENSE

Public Domain

Here is the caller graph for this function:

◆ lower()

character(:) function, allocatable m_cli2::lower ( character(*), intent(in)  str)
private
Here is the caller graph for this function:

◆ many_args()

subroutine m_cli2::many_args ( character(len=*), intent(in)  n0,
class(*), intent(out)  g0,
character(len=*), intent(in)  n1,
class(*), intent(out)  g1,
character(len=*), intent(in), optional  n2,
class(*), intent(out), optional  g2,
character(len=*), intent(in), optional  n3,
class(*), intent(out), optional  g3,
character(len=*), intent(in), optional  n4,
class(*), intent(out), optional  g4,
character(len=*), intent(in), optional  n5,
class(*), intent(out), optional  g5,
character(len=*), intent(in), optional  n6,
class(*), intent(out), optional  g6,
character(len=*), intent(in), optional  n7,
class(*), intent(out), optional  g7,
character(len=*), intent(in), optional  n8,
class(*), intent(out), optional  g8,
character(len=*), intent(in), optional  n9,
class(*), intent(out), optional  g9,
character(len=*), intent(in), optional  na,
class(*), intent(out), optional  ga,
character(len=*), intent(in), optional  nb,
class(*), intent(out), optional  gb,
character(len=*), intent(in), optional  nc,
class(*), intent(out), optional  gc,
character(len=*), intent(in), optional  nd,
class(*), intent(out), optional  gd,
character(len=*), intent(in), optional  ne,
class(*), intent(out), optional  ge,
character(len=*), intent(in), optional  nf,
class(*), intent(out), optional  gf,
character(len=*), intent(in), optional  ng,
class(*), intent(out), optional  gg,
character(len=*), intent(in), optional  nh,
class(*), intent(out), optional  gh,
character(len=*), intent(in), optional  ni,
class(*), intent(out), optional  gi,
character(len=*), intent(in), optional  nj,
class(*), intent(out), optional  gj 
)
private

References get_generic().

Here is the call graph for this function:

◆ merge_str()

character(len=:) function, allocatable m_cli2::merge_str ( character(len=*), intent(in), optional  str1,
character(len=*), intent(in), optional  str2,
logical, intent(in)  expr 
)
private

NAME

merge_str(3f) - [M_CLI2:LENGTH] pads strings to same length and then calls MERGE(3f) (LICENSE:PD)

SYNOPSIS

function merge_str(str1,str2,expr) result(strout)

 character(len=*),intent(in),optional :: str1
 character(len=*),intent(in),optional :: str2
 logical,intent(in)              :: expr
 character(len=:),allocatable    :: strout

DESCRIPTION

merge_str(3f) pads the shorter of str1 and str2 to the longest length of str1 and str2 and then calls MERGE(padded_str1,padded_str2,expr). It trims trailing spaces off the result and returns the trimmed string. This makes it easier to call MERGE(3f) with strings, as MERGE(3f) requires the strings to be the same length.

NOTE: STR1 and STR2 are always required even though declared optional. this is so the call "STR_MERGE(A,B,present(A))" is a valid call. The parameters STR1 and STR2 when they are optional parameters can be passed to a procedure if the options are optional on the called procedure.

OPTIONS

STR1 string to return if the logical expression EXPR is true STR2 string to return if the logical expression EXPR is false EXPR logical expression to evaluate to determine whether to return STR1 when true, and STR2 when false.

RESULT

MERGE_STR a trimmed string is returned that is otherwise the value of STR1 or STR2, depending on the logical expression EXPR.

EXAMPLES

Sample Program:

program demo_merge_str
use M_CLI2, only : merge_str
implicit none
character(len=:), allocatable :: answer
   answer=merge_str('first string', 'second string is longer',10.eq.10)
   write(*,'("[",a,"]")') answer
   answer=merge_str('first string', 'second string is longer',10.ne.10)
   write(*,'("[",a,"]")') answer
end program demo_merge_str

Expected output

[first string] [second string is longer]

AUTHOR

John S. Urban

LICENSE

Public Domain

References lenset().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ msg_one()

character(len=:) function, allocatable m_cli2::msg_one ( class(*), dimension(:), intent(in)  generic0,
class(*), dimension(:), intent(in), optional  generic1,
class(*), dimension(:), intent(in), optional  generic2,
class(*), dimension(:), intent(in), optional  generic3,
class(*), dimension(:), intent(in), optional  generic4,
class(*), dimension(:), intent(in), optional  generic5,
class(*), dimension(:), intent(in), optional  generic6,
class(*), dimension(:), intent(in), optional  generic7,
class(*), dimension(:), intent(in), optional  generic8,
class(*), dimension(:), intent(in), optional  generic9,
character(len=*), intent(in), optional  sep 
)
private

References print_generic().

Here is the call graph for this function:

◆ msg_scalar()

character(len=:) function, allocatable m_cli2::msg_scalar ( class(*), intent(in), optional  generic0,
class(*), intent(in), optional  generic1,
class(*), intent(in), optional  generic2,
class(*), intent(in), optional  generic3,
class(*), intent(in), optional  generic4,
class(*), intent(in), optional  generic5,
class(*), intent(in), optional  generic6,
class(*), intent(in), optional  generic7,
class(*), intent(in), optional  generic8,
class(*), intent(in), optional  generic9,
class(*), intent(in), optional  generica,
class(*), intent(in), optional  genericb,
class(*), intent(in), optional  genericc,
class(*), intent(in), optional  genericd,
class(*), intent(in), optional  generice,
class(*), intent(in), optional  genericf,
class(*), intent(in), optional  genericg,
class(*), intent(in), optional  generich,
class(*), intent(in), optional  generici,
class(*), intent(in), optional  genericj,
character(len=*), intent(in), optional  sep 
)
private

NAME

str(3f) - [M_CLI2] converts any standard scalar type to a string (LICENSE:PD)

SYNOPSIS

function str(g0,g1,g2,g3,g4,g5,g6,g7,g8,g9,ga,gb,gc,gd,ge,gf,gg,gh,gi,gj,sep)

 class(*),intent(in),optional  :: g0,g1,g2,g3,g4,g5,g6,g7,g8,g9
 class(*),intent(in),optional  :: ga,gb,gc,gd,ge,gf,gg,gh,gi,gj
 character(len=*),intent(in),optional :: sep
 character,len=(:),allocatable :: str

DESCRIPTION

str(3f) builds a space-separated string from up to twenty scalar values.

OPTIONS

g[0-9a-j] optional value to print the value of after the message. May be of type INTEGER, LOGICAL, REAL, DOUBLEPRECISION, COMPLEX, or CHARACTER.

Optionally, all the generic values can be single-dimensioned arrays. Currently, mixing scalar arguments and array arguments is not supported.

sep separator to place between values. Defaults to a space.

RETURNS

str description to print

EXAMPLES

Sample program:

  program demo_msg
  use M_CLI2, only : str
  implicit none
  character(len=:),allocatable :: pr
  character(len=:),allocatable :: frmt
  integer                      :: biggest

  pr=str('HUGE(3f) integers',huge(0),'and real',huge(0.0),'and double',huge(0.0d0))
  write(*,'(a)')pr
  pr=str('real            :',huge(0.0),0.0,12345.6789,tiny(0.0) )
  write(*,'(a)')pr
  pr=str('doubleprecision :',huge(0.0d0),0.0d0,12345.6789d0,tiny(0.0d0) )
  write(*,'(a)')pr
  pr=str('complex         :',cmplx(huge(0.0),tiny(0.0)) )
  write(*,'(a)')pr

  ! create a format on the fly
  biggest=huge(0)
  frmt=str('(*(i',int(log10(real(biggest))),':,1x))',sep=' ')
  write(*,*)'format=',frmt

  ! although it will often work, using str(3f) in an I/O statement is not recommended
  ! because if an error occurs str(3f) will try to write while part of an I/O statement
  ! which not all compilers can handle and is currently non-standard
  write(*,*)str('program will now stop')

  end program demo_msg

Output

HUGE(3f) integers 2147483647 and real 3.40282347E+38 and double 1.7976931348623157E+308 real : 3.40282347E+38 0.00000000 12345.6787 1.17549435E-38 doubleprecision : 1.7976931348623157E+308 0.0000000000000000 12345.678900000001 2.2250738585072014E-308 complex : (3.40282347E+38,1.17549435E-38) format=(*(i9:,1x)) program will now stop

AUTHOR

John S. Urban

LICENSE

Public Domain

References debug_m_cli2, gen, and print_generic().

Here is the call graph for this function:

◆ mystop()

subroutine m_cli2::mystop ( integer, intent(in)  sig,
character(len=*), intent(in), optional  msg 
)
private

References g_quiet, g_stop, g_stop_message, and journal().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ print_dictionary()

subroutine, public m_cli2::print_dictionary ( character(len=*), intent(in), optional  header,
logical, intent(in), optional  stop 
)

NAME

print_dictionary(3f) - [ARGUMENTS:M_CLI2] print internal dictionary created by calls to set_args(3f) (LICENSE:PD)

SYNOPSIS

 subroutine print_dictionary(header,stop)

  character(len=*),intent(in),optional :: header
  logical,intent(in),optional          :: stop

DESCRIPTION

Print the internal dictionary created by calls to set_args(3f). This routine is intended to print the state of the argument list if an error occurs in using the set_args(3f) procedure.

OPTIONS

HEADER label to print before printing the state of the command argument list. STOP logical value that if true stops the program after displaying the dictionary.

EXAMPLE

Typical usage:

  program demo_print_dictionary
  use M_CLI2,  only : set_args, get_args
  implicit none
  real :: x, y, z
     call set_args('-x 10 -y 20 -z 30')
     call get_args('x',x,'y',y,'z',z)
     ! all done cracking the command line; use the values in your program.
     write(*,*)x,y,z
  end program demo_print_dictionary

 Sample output

 Calling the sample program with an unknown parameter or the --usage
 switch produces the following:

    $ ./demo_print_dictionary -A
    UNKNOWN SHORT KEYWORD: -A
    KEYWORD             PRESENT  VALUE
    z                   F        [3]
    y                   F        [2]
    x                   F        [1]
    help                F        [F]
    version             F        [F]
    usage               F        [F]

AUTHOR

John S. Urban, 2019

LICENSE

Public Domain

References args, atleast(), counts, g_quiet, g_remaining, keywords, mystop(), present_in, shorts, unnamed, and values.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ prototype_and_cmd_args_to_nlist()

subroutine, private m_cli2::prototype_and_cmd_args_to_nlist ( character(len=*), intent(in)  prototype,
character(len=*), intent(in), optional  string 
)
private

NAME

prototype_and_cmd_args_to_nlist(3f) - [ARGUMENTS:M_CLI2] convert Unix-like command arguments to table (LICENSE:PD)

SYNOPSIS

 subroutine prototype_and_cmd_args_to_nlist(prototype)

  character(len=*)             :: prototype

DESCRIPTION

create dictionary with character keywords, values, and value lengths using the routines for maintaining a list from command line arguments.

OPTIONS

prototype

EXAMPLE

Sample program

 program demo_prototype_and_cmd_args_to_nlist
 use M_CLI2,  only : prototype_and_cmd_args_to_nlist, unnamed
 implicit none
 character(len=:),allocatable :: readme
 character(len=256)           :: message
 integer                      :: ios
 integer                      :: i
 doubleprecision              :: something

 ! define arguments
 logical            :: l,h,v
 real               :: p(2)
 complex            :: c
 doubleprecision    :: x,y,z

 ! uppercase keywords get an underscore to make it easier o remember
 logical            :: l_,h_,v_
 character(len=256) :: a_,b_                  ! character variables must be long enough to hold returned value
 integer            :: c_(3)

    ! give command template with default values
    ! all values except logicals get a value.
    ! strings must be delimited with double quotes
    ! A string has to have at least one character as for -A
    ! lists of numbers should be comma-delimited. No spaces are allowed in lists of numbers
    call prototype_and_cmd_args_to_nlist('&
    & -l -v -h -LVH -x 0 -y 0.0 -z 0.0d0 -p 0,0 &
    & -A " " -B "Value B" -C 10,20,30 -c (-123,-456)',readme)

    call get_args('x',x,'y',y,'z',z)
       something=sqrt(x**2+y**2+z**2)
       write (*,*)something,x,y,z
       if(size(unnamed).gt.0)then
          write (*,'(a)')'files:'
          write (*,'(i6.6,3a)')(i,'[',unnamed(i),']',i=1,size(unnamed))
       endif
 end program demo_prototype_and_cmd_args_to_nlist

AUTHOR

John S. Urban, 2019

LICENSE

Public Domain

References args, cmd_args_to_dictionary(), debug_m_cli2, g_passed_in, g_remaining, g_remaining_on, g_remaining_option_allowed, g_strict, gen, locate_key(), longest_command_argument(), present_in, prototype_to_dictionary(), remaining, unnamed, and update().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ prototype_to_dictionary()

recursive subroutine, private m_cli2::prototype_to_dictionary ( character(len=*), intent(in)  string)
private

NAME

prototype_to_dictionary(3f) - [ARGUMENTS:M_CLI2] parse user command and store tokens into dictionary (LICENSE:PD)

SYNOPSIS

 recursive subroutine prototype_to_dictionary(string)

  character(len=*),intent(in)     ::  string

DESCRIPTION

given a string of form

-var value -var value

define dictionary of form

keyword(i), value(i)

o string values

o must be delimited with double quotes.
o adjacent double quotes put one double quote into value
o must not be null. A blank is specified as " ", not "".

o logical values

o logical values must have a value

o leading and trailing blanks are removed from unquoted values

OPTIONS

STRING string is character input string to define command

RETURNS

EXAMPLE

sample program:

Results:

AUTHOR

John S. Urban, 2019

LICENSE

Public Domain

References debug_m_cli2, g_keyword_single_letter, g_remaining_option_allowed, g_response_ignored, gen, locate_key(), and update().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ quote()

character(len=:) function, allocatable m_cli2::quote ( character(len=*), intent(in)  str,
character(len=*), intent(in), optional  mode,
logical, intent(in), optional  clip 
)
private

NAME

quote(3f) - [M_CLI2:QUOTES] add quotes to string as if written with list-directed input (LICENSE:PD)

SYNOPSIS

function quote(str,mode,clip) result (quoted_str)

character(len=*),intent(in) :: str character(len=*),optional,intent(in) :: mode logical,optional,intent(in) :: clip character(len=:),allocatable :: quoted_str

DESCRIPTION

Add quotes to a CHARACTER variable as if it was written using list-directed input. This is particularly useful for processing strings to add to CSV files.

OPTIONS

str input string to add quotes to, using the rules of list-directed input (single quotes are replaced by two adjacent quotes) mode alternate quoting methods are supported:

           DOUBLE   default. replace quote with double quotes
           ESCAPE   replace quotes with backslash-quote instead of double quotes

clip default is to trim leading and trailing spaces from the string. If CLIP is .FALSE. spaces are not trimmed

RESULT

quoted_str The output string, which is based on adding quotes to STR.

EXAMPLE

Sample program:

program demo_quote
use M_CLI2, only : quote
implicit none
character(len=:),allocatable :: str
character(len=1024)          :: msg
integer                      :: ios
character(len=80)            :: inline
   do
      write(*,'(a)',advance='no')'Enter test string:'
      read(*,'(a)',iostat=ios,iomsg=msg)inline
      if(ios.ne.0)then
         write(*,*)trim(inline)
         exit
      endif

      ! the original string
      write(*,'(a)')'ORIGINAL     ['//trim(inline)//']'

      ! the string processed by quote(3f)
      str=quote(inline)
      write(*,'(a)')'QUOTED     ['//str//']'

      ! write the string list-directed to compare the results
      write(*,'(a)',iostat=ios,iomsg=msg) 'LIST DIRECTED:'
      write(*,*,iostat=ios,iomsg=msg,delim='none') inline
      write(*,*,iostat=ios,iomsg=msg,delim='quote') inline
      write(*,*,iostat=ios,iomsg=msg,delim='apostrophe') inline
   enddo
end program demo_quote

AUTHOR

John S. Urban

LICENSE

Public Domain

References journal(), lower(), merge_str(), and replace_str().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ remove_c()

subroutine, private m_cli2::remove_c ( character(len=:), dimension(:), allocatable  list,
integer, intent(in)  place 
)
private

NAME

remove(3f) - [M_CLI2] remove entry from an allocatable array at specified position (LICENSE:PD)

SYNOPSIS

subroutine remove(list,place)

character(len=:)|doubleprecision|real|integer,intent(inout) :: list(:) integer, intent(out) :: PLACE

DESCRIPTION

Remove a value from an allocatable array at the specified index.
The array is assumed to be sorted in descending order. It may be of
type CHARACTER, DOUBLEPRECISION, REAL, or INTEGER.

OPTIONS

list    is the list array.
PLACE   is the subscript for the entry that should be removed

EXAMPLES

Sample program

program demo_remove
use M_sort, only : sort_shell
use M_CLI2, only : locate, remove
implicit none
character(len=:),allocatable :: arr(:)
integer                       :: i
integer                       :: end

arr=[character(len=20) :: '', 'ZZZ', 'Z', 'aaa', 'b', 'b', 'ab', 'bb', 'xxx' ]
! make sure sorted in descending order
call sort_shell(arr,order='d')

end=size(arr)
write(*,'("SIZE=",i0,1x,*(a,","))')end,(trim(arr(i)),i=1,end)
call remove(arr,1)
end=size(arr)
write(*,'("SIZE=",i0,1x,*(a,","))')end,(trim(arr(i)),i=1,end)
call remove(arr,4)
end=size(arr)
write(*,'("SIZE=",i0,1x,*(a,","))')end,(trim(arr(i)),i=1,end)

end program demo_remove

Results:

Expected output

SIZE=9 xxx,bb,b,b,ab,aaa,ZZZ,Z,, SIZE=8 bb,b,b,ab,aaa,ZZZ,Z,, SIZE=7 bb,b,b,aaa,ZZZ,Z,,

AUTHOR

1989,2017 John S. Urban

LICENSE

Public Domain

◆ remove_i()

subroutine, private m_cli2::remove_i ( integer, dimension(:), allocatable  list,
integer, intent(in)  place 
)
private

◆ remove_l()

subroutine, private m_cli2::remove_l ( logical, dimension(:), allocatable  list,
integer, intent(in)  place 
)
private

◆ replace_c()

subroutine, private m_cli2::replace_c ( character(len=:), dimension(:), allocatable  list,
character(len=*), intent(in)  value,
integer, intent(in)  place 
)
private

NAME

replace(3f) - [M_CLI2] replace entry in a string array at specified position (LICENSE:PD)

SYNOPSIS

subroutine replace(list,value,place)

character(len=*)|doubleprecision|real|integer,intent(in) :: value character(len=:)|doubleprecision|real|integer,intent(in) :: list(:) integer, intent(out) :: PLACE

DESCRIPTION

replace a value in an allocatable array at the specified index. Unless the
array needs the string length to increase this is merely an assign of a value
to an array element.

The array may be of type CHARACTER, DOUBLEPRECISION, REAL, or INTEGER>
It is assumed to be sorted in descending order without duplicate values.

The value and list must be of the same type.

OPTIONS

VALUE         the value to place in the array
LIST          is the array.
PLACE         is the subscript that the entry should be placed at

EXAMPLES

Replace key-value pairs in a dictionary

program demo_replace
use M_CLI2, only  : insert, locate, replace
! Find if a key is in a list and insert it
! into the key list and value list if it is not present
! or replace the associated value if the key existed
implicit none
character(len=20)            :: key
character(len=100)           :: val
character(len=:),allocatable :: keywords(:)
character(len=:),allocatable :: values(:)
integer                      :: i
integer                      :: place
call update('b','value of b')
call update('a','value of a')
call update('c','value of c')
call update('c','value of c again')
call update('d','value of d')
call update('a','value of a again')
! show array
write(*,'(*(a,"==>",a,/))')(trim(keywords(i)),trim(values(i)),i=1,size(keywords))

call locate_key('a',place)
if(place.gt.0)then
   write(*,*)'The value of "a" is',trim(values(place))
else
   write(*,*)'"a" not found'
endif

contains
subroutine update(key,val)
character(len=*),intent(in)  :: key
character(len=*),intent(in)  :: val
integer                      :: place

! find where string is or should be
call locate_key(key,place)
! if string was not found insert it
if(place.lt.1)then
   call insert(keywords,key,abs(place))
   call insert(values,val,abs(place))
else ! replace
   call replace(values,val,place)
endif

end subroutine update

end program demo_replace

Expected output

d==>value of d c==>value of c again b==>value of b a==>value of a again

AUTHOR

1989,2017 John S. Urban

LICENSE

Public Domain

◆ replace_i()

subroutine, private m_cli2::replace_i ( integer, dimension(:), allocatable  list,
integer, intent(in)  value,
integer, intent(in)  place 
)
private

◆ replace_l()

subroutine, private m_cli2::replace_l ( logical, dimension(:), allocatable  list,
logical, intent(in)  value,
integer, intent(in)  place 
)
private

◆ replace_str()

character(len=:) function, allocatable m_cli2::replace_str ( character(len=*), intent(in)  targetline,
character(len=*), intent(in), optional  old,
character(len=*), intent(in), optional  new,
integer, intent(out), optional  ierr,
character(len=*), intent(in), optional  cmd,
integer, dimension(2), intent(in), optional  range 
)
private

References crack_cmd(), and journal().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ rg()

real function, dimension(:), allocatable m_cli2::rg
private

References dg().

Here is the call graph for this function:

◆ rget()

real function, public m_cli2::rget ( character(len=*), intent(in)  n)

◆ rgs()

real function, dimension(:), allocatable m_cli2::rgs ( character(len=*), intent(in)  n)
private

◆ separator()

character(len=1) function m_cli2::separator
private

NAME

separator(3f) - [M_io:ENVIRONMENT] try to determine pathname directory separator character (LICENSE:PD)

SYNOPSIS

function separator() result(sep)

 character(len=1) :: sep

DESCRIPTION

First testing for the existence of "/.", then if that fails a list of variable names assumed to contain directory paths {PATH|HOME} are examined first for a backslash, then a slash. Assuming basically the choice is a ULS or MSWindows system, and users can do weird things like put a backslash in a ULS path and break it.

Therefore can be very system dependent. If the queries fail the default returned is "/".

EXAMPLE

sample usage

program demo_separator use M_io, only : separator implicit none write(*,*)'separator=',separator() end program demo_separator

References get_env().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ separator2()

character(len=1) function m_cli2::separator2
private

◆ set_args()

subroutine, public m_cli2::set_args ( character(len=*), intent(in)  prototype,
character(len=:), dimension(:), intent(in), optional, allocatable  help_text,
character(len=:), dimension(:), intent(in), optional, allocatable  version_text,
character(len=*), intent(in), optional  string,
integer, intent(out), optional  ierr,
character(len=:), intent(out), optional, allocatable  errmsg 
)

NAME

set_args(3f) - [ARGUMENTS:M_CLI2] command line argument parsing (LICENSE:PD)

SYNOPSIS

 subroutine set_args(definition,help_text,version_text,ierr,errmsg)

  character(len=*),intent(in),optional              :: definition
  character(len=:),intent(in),allocatable,optional  :: help_text
  character(len=:),intent(in),allocatable,optional  :: version_text
  integer,intent(out),optional                      :: ierr
  character(len=:),intent(out),allocatable,optional :: errmsg

DESCRIPTION

 SET_ARGS(3f) requires a unix-like command prototype for defining
 arguments and default command-line options. Argument values are then
 read using GET_ARGS(3f).

 The --help and --version options require the optional
 help_text and version_text values to be provided.

OPTIONS

  DESCRIPTION   composed of all command arguments concatenated
                into a Unix-like command prototype string. For
                example:

                  call set_args('-L F -ints 10,20,30 -title "my title" -R 10.3')

                DESCRIPTION is pre-defined to act as if started with
                the reserved options '--verbose F --usage F --help
                F --version F'. The --usage option is processed when
                the set_args(3f) routine is called. The same is true
                for --help and --version if the optional help_text
                and version_text options are provided.

                see "DEFINING THE PROTOTYPE" in the next section for
                further details.

  HELP_TEXT     if present, will be displayed if program is called with
                --help switch, and then the program will terminate. If
                not supplied, the command line initialization string
                will be shown when --help is used on the commandline.

  VERSION_TEXT  if present, will be displayed if program is called with
                --version switch, and then the program will terminate.
  IERR          if present a non-zero option is returned when an
                error occurs instead of program execution being
                terminated
  ERRMSG        a description of the error if ierr is present

DEFINING THE PROTOTYPE

o all keywords on the prototype MUST get a value.

o logicals MUST be set to F or T.

o strings MUST be delimited with double-quotes and must be at least one space. Internal double-quotes are represented with two double-quotes.

o numeric keywords are not allowed; but this allows negative numbers to be used as values.

o lists of values should be comma-delimited unless a user-specified delimiter is used. The prototype must use the same array delimiters as the call to the family of get_args*(3f) called.

o long names (–keyword) should be all lowercase

o The simplest way to have short names is to suffix the long name with :LETTER If this syntax is used then logical shorts may be combined on the command line and – and - prefixes are strictly enforced.

mapping of short names to long names not using the –LONGNAME:SHORTNAME syntax is demonstrated in the manpage for SPECIFIED(3f).

o A very special behavior occurs if the keyword name ends in ::. The next parameter is taken as a value even if it starts with -. This is not generally recommended but is noted here for completeness.

o to define a zero-length allocatable array make the value a delimiter (usually a comma).

o all unused values go into the character array UNNAMED

o If the prototype ends with "--" a special mode is turned on where anything after "--" on input goes into the variable REMAINING and the array ARGS instead of becoming elements in the UNNAMED array. This is not needed for normal processing.

USAGE

When invoking the program line note that (subject to change) the following variations from other common command-line parsers:

o Long names should be all lowercase and always more than one character.

o values for duplicate keywords are appended together with a space separator when a command line is executed.

o numeric keywords are not allowed; but this allows negative numbers to be used as values.

o Although not generally recommended you can equivalence keywords (usually for multi-lingual support). Be aware that specifying both names of an equivalenced keyword on a command line will have undefined results (currently, their ASCII alphabetical order will define what the Fortran variable values become).

The second of the names should only be called with a GET_ARGS*(3f) routine if the SPECIFIED(3f) function is .TRUE. for that name.

Note that allocatable arrays cannot be EQUIVALENCEd in Fortran.

o short keywords cannot be combined unless they were defined using the –LONGNAME:SHORTNAME syntax. Even then -a -b -c is required not -abc unless all the keywords are logicals (Boolean keys).

o shuffling is not supported. Values should follow their keywords.

o if a parameter value of just "-" is supplied it is converted to the string "stdin".

o values not matching a keyword go into the character array "UNUSED".

o if the keyword "--" is encountered the rest of the command arguments go into the character array "UNUSED".

EXAMPLE

Sample program:

program demo_set_args
use M_CLI2,  only : filenames=>unnamed, set_args, get_args
use M_CLI2,  only : get_args_fixed_size
implicit none
integer                      :: i
! DEFINE ARGS
real                         :: x, y, z
real                         :: p(3)
character(len=:),allocatable :: title
logical                      :: l, lbig
integer,allocatable          :: ints(:)
!
!  DEFINE COMMAND (TO SET INITIAL VALUES AND ALLOWED KEYWORDS)
!  AND READ COMMAND LINE
call set_args(' &
   ! reals
   & -x 1 -y 2.3 -z 3.4e2 &
   ! integer array
   & -p -1,-2,-3 &
   ! always double-quote strings
   & --title "my title" &
   ! set all logical values to F or T.
   & -l F -L F &
   ! set allocatable size to zero if you like by using a delimiter
   & -ints , &
   ! string should be a single character at a minimum
   & --label " " &
   & ')
! ASSIGN VALUES TO ELEMENTS
!     SCALARS
call get_args('x',x)
call get_args('y',y)
call get_args('z',z)
call get_args('l',l)
call get_args('L',lbig)
call get_args('ints',ints)      ! ALLOCATABLE ARRAY
call get_args('title',title)    ! ALLOCATABLE STRING
call get_args_fixed_size('p',p) ! NON-ALLOCATABLE ARRAY
! USE VALUES
write(*,*)'x=',x
write(*,*)'y=',y
write(*,*)'z=',z
write(*,*)'p=',p
write(*,*)'title=',title
write(*,*)'ints=',ints
write(*,*)'l=',l
write(*,*)'L=',lbig
! UNNAMED VALUES
if(size(filenames).gt.0)then
   write(*,'(i6.6,3a)')(i,'[',filenames(i),']',i=1,size(filenames))
endif
end program demo_set_args

RESPONSE FILES

If you have no interest in using external files as abbreviations you can ignore this section. Otherwise, before calling set_args(3f) add:

use M_CLI2, only : CLI_response_file CLI_response_file=.true.

M_CLI2 Response files are small files containing CLI (Command Line Interface) arguments that end with ".rsp" that can be used when command lines are so long that they would exceed line length limits or so complex that it is useful to have a platform-independent method of creating an abbreviation.

Shell aliases and scripts are often used for similar purposes (and allow for much more complex conditional execution, of course), but they generally cannot be used to overcome line length limits and are typically platform-specific.

Examples of commands that support similar response files are the Clang and Intel compilers, although there is no standard format for the files.

They are read if you add options of the syntax "@NAME" as the FIRST parameters on your program command line calls. They are not recursive – that is, an option in a response file cannot be given the value "@NAME2" to call another response file.

Note that more than one response name may appear on a command line.

They are case-sensitive names.

LOCATING RESPONSE FILES

A search for the response file always starts with the current directory. The search then proceeds to look in any additional directories specified with the colon-delimited environment variable CLI_RESPONSE_PATH.

The first resource file found that results in lines being processed will be used and processing stops after that first match is found. If no match is found an error occurs and the program is stopped.

RESPONSE FILE SECTIONS

A simple response file just has options for calling the program in it prefixed with the word "options". But they can also contain section headers to denote selections that are only executed when a specific OS is being used, print messages, and execute system commands.

SEARCHING FOR OSTYPE IN REGULAR FILES

So assuming the name @NAME was specified on the command line a file named NAME.rsp will be searched for in all the search directories and then in that file a string that starts with the string @OSTYPE (if the environment variables $OS and $OSTYPE are not blank. $OSTYPE takes precedence over $OS).

SEARCHING FOR UNLABELED DIRECTIVES IN REGULAR FILES

Then, the same files will be searched for lines above any line starting with "@". That is, if there is no special section for the current OS it just looks at the top of the file for unlabeled options.

SEARCHING FOR OSTYPE AND NAME IN THE COMPOUND FILE

In addition or instead of files with the same name as the @NAME option on the command line, you can have one file named after the executable name that contains multiple abbreviation names.

So if your program executable is named EXEC you create a single file called EXEC.rsp and can append all the simple files described above separating them with lines of the form @OSTYPE@NAME or just @NAME.

So if no specific file for the abbreviation is found a file called "EXEC.rsp" is searched for where "EXEC" is the name of the executable. This file is always a "compound" response file that uses the following format:

Any compound EXEC.rsp file found in the current or searched directories will be searched for the string @OSTYPE@NAME first.

Then if nothing is found, the less specific line @NAME is searched for.

THE SEARCH IS OVER

Sounds complicated but actually works quite intuitively. Make a file in the current directory and put options in it and it will be used. If that file ends up needing different cases for different platforms add a line like "@Linux" to the file and some more lines and that will only be executed if the environment variable OSTYPE or OS is "Linux". If no match is found for named sections the lines at the top before any "@" lines will be used as a default if no match is found.

If you end up using a lot of files like this you can combine them all together and put them into a file called "program_name".rsp and just put lines like @NAME or @OSTYPE@NAME at that top of each selection.

Now, back to the details on just what you can put in the files.

SPECIFICATION FOR RESPONSE FILES

SIMPLE RESPONSE FILES

The first word of a line is special and has the following meanings:

options|- Command options following the rules of the SET_ARGS(3f) prototype. So o It is preferred to specify a value for all options. o double-quote strings. o give a blank string value as " ". o use F|T for lists of logicals, o lists of numbers should be comma-delimited. comment|# Line is a comment line system|! System command. System commands are executed as a simple call to system (so a cd(1) or setting a shell variable would not effect subsequent lines, for example) print|> Message to screen stop display message and stop program.

So if a program that does nothing but echos its parameters

program testit use M_CLI2, only : set_args, rget, sget, lget use M_CLI2, only : CLI_response_file implicit none real :: x,y ; namelist/args/ x,y character(len=:),allocatable :: title ; namelist/args/ title logical :: big ; namelist/args/ big CLI_response_file=.true. call set_args('-x 10.0 -y 20.0 –title "my title" –big F') x=rget('x') y=rget('y') title=sget('title') big=lget('big') write(*,nml=args) end program testit

And a file in the current directory called "a.rsp" contains

defaults for project A

options -x 1000 -y 9999 options –title " " options –big T

The program could be called with

$myprog # normal call X=10.0 Y=20.0 TITLE="my title"

$myprog # change defaults as specified in "a.rsp" X=1000.0 Y=9999.0 TITLE=" "

change defaults but use any option as normal to override defaults

$myprog -y 1234 X=1000.0 Y=1234.0 TITLE=" "

COMPOUND RESPONSE FILES

A compound response file has the same basename as the executable with a ".rsp" suffix added. So if your program is named "myprg" the filename must be "myprg.rsp".

Note that here basename means the last leaf of the name of the program as returned by the Fortran intrinsic GET_COMMAND_ARGUMENT(0,...) trimmed of anything after a period ("."), so it is a good idea not to use hidden files.

Unlike simple response files compound response files can contain multiple setting names.

Specifically in a compound file if the environment variable $OSTYPE (first) or $OS is set the first search will be for a line of the form (no leading spaces should be used):

@OSTYPE@alias_name

If no match or if the environment variables $OSTYPE and $OS were not set or a match is not found then a line of the form

@alias_name

is searched for in simple or compound files. If found subsequent lines will be ignored that start with "@" until a line not starting with "@" is encountered. Lines will then be processed until another line starting with "@" is found or end-of-file is encountered.

COMPOUND RESPONSE FILE EXAMPLE An example compound file

> RUNNING TESTS USING RELEASE VERSION AND ifort options test –release –compiler ifort

@gf > RUNNING TESTS USING RELEASE VERSION AND gfortran options test –release –compiler gfortran

@nv > RUNNING TESTS USING RELEASE VERSION AND nvfortran options test –release –compiler nvfortran

@nag > RUNNING TESTS USING RELEASE VERSION AND nagfor options test –release –compiler nagfor #

OS-specific example:

@Linux@install #

install executables in directory (assuming install(1) exists)

# system mkdir -p ~/.local/bin options run –release T –compiler gfortran –runner "install -vbp -m 0711 -t ~/.local/bin" @install STOP INSTALL NOT SUPPORTED ON THIS PLATFORM OR $OSTYPE NOT SET #

@fpm@testall # !fpm test –compiler nvfortran !fpm test –compiler ifort !fpm test –compiler gfortran !fpm test –compiler nagfor STOP tests complete. Any additional parameters were ignored

Would be used like

fpm @install fpm @nag – fpm @testall

NOTES

The intel Fortran compiler now calls the response files "indirect files" and does not add the implied suffix ".rsp" to the files anymore. It also allows the @NAME syntax anywhere on the command line, not just at the beginning. – 20201212

AUTHOR

John S. Urban, 2019

LICENSE

Public Domain

References args, check_commandline(), cli_response_file, debug_m_cli2, g_append, g_options_only, g_passed_in, g_quiet, g_response, g_response_ignored, g_stop, g_stop_message, gen, longest_command_argument(), prototype_and_cmd_args_to_nlist(), split(), unnamed, and wipe_dictionary().

Here is the call graph for this function:

◆ set_usage()

subroutine m_cli2::set_usage ( character(len=*), intent(in)  keyword,
character(len=*), intent(in)  description,
character(len=*), intent(in)  value 
)
private

◆ sg()

character(len=:) function, dimension(:), allocatable m_cli2::sg
private

References unnamed.

◆ sget()

character(len=:) function, allocatable, public m_cli2::sget ( character(len=*), intent(in)  n)

◆ sgs()

character(len=:) function, dimension(:), allocatable m_cli2::sgs ( character(len=*), intent(in)  n,
character(len=*), intent(in), optional  delims 
)
private

◆ specified()

elemental impure logical function, public m_cli2::specified ( character(len=*), intent(in)  key)

NAME

specified(3f) - [ARGUMENTS:M_CLI2] return true if keyword was present on command line (LICENSE:PD)

SYNOPSIS

elemental impure function specified(name)

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

DESCRIPTION

specified(3f) returns .true. if the specified keyword was present on
the command line.

OPTIONS

NAME   name of commandline argument to query the presence of

RETURNS

SPECIFIED returns .TRUE. if specified NAME was present on the command line when the program was invoked.

EXAMPLE

Sample program:

program demo_specified use M_CLI2, only : set_args, get_args, specified implicit none ! DEFINE ARGS integer :: flag integer,allocatable :: ints(:) real,allocatable :: twonames(:)

! IT IS A BAD IDEA TO NOT HAVE THE SAME DEFAULT VALUE FOR ALIASED ! NAMES BUT CURRENTLY YOU STILL SPECIFY THEM call set_args(' -flag 1 -f 1 -ints 1,2,3 -i 1,2,3 -twonames 11.3 -T 11.3')

! ASSIGN VALUES TO ELEMENTS CONDITIONALLY CALLING WITH SHORT NAME call get_args('flag',flag) if(specified('f'))call get_args('f',flag) call get_args('ints',ints) if(specified('i'))call get_args('i',ints) call get_args('twonames',twonames) if(specified('T'))call get_args('T',twonames)

! IF YOU WANT TO KNOW IF GROUPS OF PARAMETERS WERE SPECIFIED USE ! ANY(3f) and ALL(3f) write(*,*)specified(['twonames','T ']) write(*,*)'ANY:',any(specified(['twonames','T '])) write(*,*)'ALL:',all(specified(['twonames','T ']))

! FOR MUTUALLY EXCLUSIVE if (all(specified(['twonames','T '])))then write(*,*)'You specified both names -T and -twonames' endif

! FOR REQUIRED PARAMETER if (.not.any(specified(['twonames','T '])))then write(*,*)'You must specify -T or -twonames' endif

! USE VALUES write(*,*)'flag=',flag write(*,*)'ints=',ints write(*,*)'twonames=',twonames end program demo_specified

AUTHOR

John S. Urban, 2019

LICENSE

Public Domain

References locate_key(), and present_in.

Here is the call graph for this function:

◆ split()

subroutine m_cli2::split ( character(len=*), intent(in)  input_line,
character(len=:), dimension(:), intent(out), allocatable  array,
character(len=*), intent(in), optional  delimiters,
character(len=*), intent(in), optional  order,
character(len=*), intent(in), optional  nulls 
)
private

NAME

split(3f) - [M_CLI2:TOKENS] parse string into an array using specified delimiters (LICENSE:PD)

SYNOPSIS

subroutine split(input_line,array,delimiters,order,nulls)

 character(len=*),intent(in)              :: input_line
 character(len=:),allocatable,intent(out) :: array(:)
 character(len=*),optional,intent(in)     :: delimiters
 character(len=*),optional,intent(in)     :: order
 character(len=*),optional,intent(in)     :: nulls

DESCRIPTION

SPLIT(3f) parses a string using specified delimiter characters and store tokens into an allocatable array

OPTIONS

INPUT_LINE  Input string to tokenize

ARRAY       Output array of tokens

DELIMITERS  List of delimiter characters.
            The default delimiters are the "whitespace" characters
            (space, tab,new line, vertical tab, formfeed, carriage
            return, and null). You may specify an alternate set of
            delimiter characters.

            Multi-character delimiters are not supported (Each
            character in the DELIMITERS list is considered to be
            a delimiter).

            Quoting of delimiter characters is not supported.

ORDER SEQUENTIAL|REVERSE|RIGHT  Order of output array.
            By default ARRAY contains the tokens having parsed
            the INPUT_LINE from left to right. If ORDER='RIGHT'
            or ORDER='REVERSE' the parsing goes from right to left.

NULLS IGNORE|RETURN|IGNOREEND  Treatment of null fields.
            By default adjacent delimiters in the input string
            do not create an empty string in the output array. if
            NULLS='return' adjacent delimiters create an empty element
            in the output ARRAY. If NULLS='ignoreend' then only
            trailing delimiters at the right of the string are ignored.

EXAMPLES

Sample program:

program demo_split
use M_CLI2, only: split
character(len=*),parameter     :: &
& line='  aBcdef   ghijklmnop qrstuvwxyz  1:|:2     333|333 a B cc    '
character(len=:),allocatable :: array(:) ! output array of tokens
   write(*,*)'INPUT LINE:['//LINE//']'
   write(*,'(80("="))')
   write(*,*)'typical call:'
   CALL split(line,array)
   write(*,'(i0," ==> ",a)')(i,trim(array(i)),i=1,size(array))
   write(*,*)'SIZE:',SIZE(array)
   write(*,'(80("-"))')
   write(*,*)'custom list of delimiters (colon and vertical line):'
   CALL split(line,array,delimiters=':|',order='sequential',nulls='ignore')
   write(*,'(i0," ==> ",a)')(i,trim(array(i)),i=1,size(array))
   write(*,*)'SIZE:',SIZE(array)
   write(*,'(80("-"))')
   write(*,*)&
 &'custom list of delimiters, reverse array order and count null fields:'
   CALL split(line,array,delimiters=':|',order='reverse',nulls='return')
   write(*,'(i0," ==> ",a)')(i,trim(array(i)),i=1,size(array))
   write(*,*)'SIZE:',SIZE(array)
   write(*,'(80("-"))')
   write(*,*)'INPUT LINE:['//LINE//']'
   write(*,*)&
   &'default delimiters and reverse array order and return null fields:'
   CALL split(line,array,delimiters='',order='reverse',nulls='return')
   write(*,'(i0," ==> ",a)')(i,trim(array(i)),i=1,size(array))
   write(*,*)'SIZE:',SIZE(array)
end program demo_split

Output

> INPUT LINE:[ aBcdef ghijklmnop qrstuvwxyz 1:|:2 333|333 a B cc ] > =========================================================================== > typical call: > 1 ==> aBcdef > 2 ==> ghijklmnop > 3 ==> qrstuvwxyz > 4 ==> 1:|:2 > 5 ==> 333|333 > 6 ==> a > 7 ==> B > 8 ==> cc > SIZE: 8 > -----------------------------------------------------------------------— > custom list of delimiters (colon and vertical line): > 1 ==> aBcdef ghijklmnop qrstuvwxyz 1 > 2 ==> 2 333 > 3 ==> 333 a B cc > SIZE: 3 > -----------------------------------------------------------------------— > custom list of delimiters, reverse array order and return null fields: > 1 ==> 333 a B cc > 2 ==> 2 333 > 3 ==> > 4 ==> > 5 ==> aBcdef ghijklmnop qrstuvwxyz 1 > SIZE: 5 > -----------------------------------------------------------------------— > INPUT LINE:[ aBcdef ghijklmnop qrstuvwxyz 1:|:2 333|333 a B cc ] > default delimiters and reverse array order and count null fields: > 1 ==> > 2 ==> > 3 ==> > 4 ==> cc > 5 ==> B > 6 ==> a > 7 ==> 333|333 > 8 ==> > 9 ==> > 10 ==> > 11 ==> > 12 ==> 1:|:2 > 13 ==> > 14 ==> qrstuvwxyz > 15 ==> ghijklmnop > 16 ==> > 17 ==> > 18 ==> aBcdef > 19 ==> > 20 ==> > SIZE: 20

AUTHOR

John S. Urban

LICENSE

Public Domain

References lower().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ strtok()

logical function m_cli2::strtok ( character(len=*), intent(in)  source_string,
integer, intent(inout)  itoken,
integer, intent(out)  token_start,
integer, intent(inout)  token_end,
character(len=*), intent(in)  delimiters 
)
private
Here is the caller graph for this function:

◆ substitute()

subroutine m_cli2::substitute ( character(len=*)  targetline,
character(len=*), intent(in)  old,
character(len=*), intent(in)  new,
integer, intent(out), optional  ierr,
integer, intent(in), optional  start,
integer, intent(in), optional  end 
)
private

NAME

substitute(3f) - [M_CLI2:EDITING] subroutine globally substitutes one substring for another in string (LICENSE:PD)

SYNOPSIS

subroutine substitute(targetline,old,new,ierr,start,end)

 character(len=*)              :: targetline
 character(len=*),intent(in)   :: old
 character(len=*),intent(in)   :: new
 integer,intent(out),optional  :: ierr
 integer,intent(in),optional   :: start
 integer,intent(in),optional   :: end

DESCRIPTION

Globally substitute one substring for another in string.

OPTIONS

TARGETLINE input line to be changed. Must be long enough to hold altered output. OLD substring to find and replace NEW replacement for OLD substring IERR error code. If IER = -1 bad directive, >= 0 then count of changes made. START sets the left margin to be scanned for OLD in TARGETLINE. END sets the right margin to be scanned for OLD in TARGETLINE.

EXAMPLES

Sample Program:

program demo_substitute
use M_CLI2, only : substitute
implicit none
! must be long enough to hold changed line
character(len=80) :: targetline

targetline='this is the input string'
write(*,*)'ORIGINAL    : '//trim(targetline)

! changes the input to 'THis is THe input string'
call substitute(targetline,'th','TH')
write(*,*)'th => TH    : '//trim(targetline)

! a null old substring means "at beginning of line"
! changes the input to 'BEFORE:this is the input string'
call substitute(targetline,'','BEFORE:')
write(*,*)'"" => BEFORE: '//trim(targetline)

! a null new string deletes occurrences of the old substring
! changes the input to 'ths s the nput strng'
call substitute(targetline,'i','')
write(*,*)'i => ""     : '//trim(targetline)

end program demo_substitute

Expected output

ORIGINAL : this is the input string th => TH : THis is THe input string "" => BEFORE: BEFORE:THis is THe input string i => "" : BEFORE:THs s THe nput strng

AUTHOR

John S. Urban

LICENSE

Public Domain

References journal().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ trimzeros_()

subroutine m_cli2::trimzeros_ ( character(len=*)  string)
private

NAME

trimzeros_(3fp) - [M_CLI2:NUMERIC] Delete trailing zeros from numeric decimal string (LICENSE:PD)

SYNOPSIS

subroutine trimzeros_(str)

 character(len=*)  :: str

DESCRIPTION

TRIMZEROS_(3f) deletes trailing zeros from a string representing a number. If the resulting string would end in a decimal point, one trailing zero is added.

OPTIONS

str input string will be assumed to be a numeric value and have trailing zeros removed

EXAMPLES

Sample program:

  program demo_trimzeros_
  use M_CLI2, only : trimzeros_
  character(len=:),allocatable :: string
     write(*,*)trimzeros_('123.450000000000')
     write(*,*)trimzeros_('12345')
     write(*,*)trimzeros_('12345.')
     write(*,*)trimzeros_('12345.00e3')
  end program demo_trimzeros_

AUTHOR

John S. Urban

LICENSE

Public Domain

Here is the caller graph for this function:

◆ unquote()

pure character(len=:) function, allocatable m_cli2::unquote ( character(len=*), intent(in)  quoted_str,
character(len=1), intent(in), optional  esc 
)
private

NAME

unquote(3f) - [M_CLI2:QUOTES] remove quotes from string as if read with list-directed input (LICENSE:PD)

SYNOPSIS

pure function unquote(quoted_str,esc) result (unquoted_str)

character(len=*),intent(in) :: quoted_str character(len=1),optional,intent(in) :: esc character(len=:),allocatable :: unquoted_str

DESCRIPTION

Remove quotes from a CHARACTER variable as if it was read using list-directed input. This is particularly useful for processing tokens read from input such as CSV files.

Fortran can now read using list-directed input from an internal file, which should handle quoted strings, but list-directed input does not support escape characters, which UNQUOTE(3f) does.

OPTIONS

quoted_str input string to remove quotes from, using the rules of list-directed input (two adjacent quotes inside a quoted region are replaced by a single quote, a single quote or double quote is selected as the delimiter based on which is encountered first going from left to right, ...) esc optional character used to protect the next quote character from being processed as a quote, but simply as a plain character.

RESULT

unquoted_str The output string, which is based on removing quotes from quoted_str.

EXAMPLE

Sample program:

  program demo_unquote
  use M_CLI2, only : unquote
  implicit none
  character(len=128)           :: quoted_str
  character(len=:),allocatable :: unquoted_str
  character(len=1),parameter   :: esc='\'
  character(len=1024)          :: msg
  integer                      :: ios
  character(len=1024)          :: dummy
  do
     write(*,'(a)',advance='no')'Enter test string:'
     read(*,'(a)',iostat=ios,iomsg=msg)quoted_str
     if(ios.ne.0)then
        write(*,*)trim(msg)
        exit
     endif

     ! the original string
     write(*,'(a)')'QUOTED       ['//trim(quoted_str)//']'

     ! the string processed by unquote(3f)
     unquoted_str=unquote(trim(quoted_str),esc)
     write(*,'(a)')'UNQUOTED     ['//unquoted_str//']'

     ! read the string list-directed to compare the results
     read(quoted_str,*,iostat=ios,iomsg=msg)dummy
     if(ios.ne.0)then
        write(*,*)trim(msg)
     else
        write(*,'(a)')'LIST DIRECTED['//trim(dummy)//']'
     endif
  enddo
  end program demo_unquote

AUTHOR

John S. Urban

LICENSE

Public Domain

References quote().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update()

subroutine, private m_cli2::update ( character(len=*), intent(in)  key,
character(len=*), intent(in), optional  val 
)
private

NAME

update(3f) - [ARGUMENTS:M_CLI2] update internal dictionary given keyword and value (LICENSE:PD)

SYNOPSIS

 subroutine update(key,val)

  character(len=*),intent(in)           :: key
  character(len=*),intent(in),optional  :: val

DESCRIPTION

Update internal dictionary in M_CLI2(3fm) module.

OPTIONS

key name of keyword to add, replace, or delete from dictionary val if present add or replace value associated with keyword. If not present remove keyword entry from dictionary.

If "present" is true, a value will be appended

EXAMPLE

AUTHOR

John S. Urban, 2019

LICENSE

Public Domain

References counts, g_append, g_strict, keywords, locate_key(), mandatory, present_in, shorts, split(), unquote(), and values.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ upper()

character(:) function, allocatable m_cli2::upper ( character(*), intent(in)  str)
private
Here is the caller graph for this function:

◆ value_to_string()

subroutine m_cli2::value_to_string ( class(*), intent(in)  gval,
character(len=*), intent(out)  chars,
integer, intent(out), optional  length,
integer, optional  err,
character(len=*), intent(in), optional  fmt,
logical, intent(in), optional  trimz 
)
private

NAME

value_to_string(3f) - [M_CLI2:NUMERIC] return numeric string from a numeric value (LICENSE:PD)

SYNOPSIS

subroutine value_to_string(value,chars[,iilen,ierr,fmt,trimz])

 character(len=*) :: chars  ! minimum of 23 characters required
 !--------
 ! VALUE may be any <em>one</em> of the following types:
 doubleprecision,intent(in)               :: value
 real,intent(in)                          :: value
 integer,intent(in)                       :: value
 logical,intent(in)                       :: value
 !--------
 character(len=*),intent(out)             :: chars
 integer,intent(out),optional             :: iilen
 integer,optional                         :: ierr
 character(len=*),intent(in),optional     :: fmt
 logical,intent(in)                       :: trimz

DESCRIPTION

value_to_string(3f) returns a numeric representation of a numeric value in a string given a numeric value of type REAL, DOUBLEPRECISION, INTEGER or LOGICAL. It creates the string using internal writes. It then removes trailing zeros from non-zero values, and left-justifies the string.

OPTIONS

VALUE input value to be converted to a string FMT You may specify a specific format that produces a string up to the length of CHARS; optional. TRIMZ If a format is supplied the default is not to try to trim trailing zeros. Set TRIMZ to .true. to trim zeros from a string assumed to represent a simple numeric value.

RETURNS

CHARS returned string representing input value, must be at least 23 characters long; or what is required by optional FMT if longer. IILEN position of last non-blank character in returned string; optional. IERR If not zero, error occurred; optional.

EXAMPLE

Sample program:

 program demo_value_to_string
 use M_CLI2, only: value_to_string
 implicit none
 character(len=80) :: string
 integer           :: iilen
    call value_to_string(3.0/4.0,string,iilen)
    write(*,*) 'The value is [',string(:iilen),']'

    call value_to_string(3.0/4.0,string,iilen,fmt='')
    write(*,*) 'The value is [',string(:iilen),']'

    call value_to_string(3.0/4.0,string,iilen,fmt='("THE VALUE IS ",g0)')
    write(*,*) 'The value is [',string(:iilen),']'

    call value_to_string(1234,string,iilen)
    write(*,*) 'The value is [',string(:iilen),']'

    call value_to_string(1.0d0/3.0d0,string,iilen)
    write(*,*) 'The value is [',string(:iilen),']'

 end program demo_value_to_string

Expected output

The value is [0.75] The value is [ 0.7500000000] The value is [THE VALUE IS .750000000] The value is [1234] The value is [0.33333333333333331]

AUTHOR

John S. Urban

LICENSE

Public Domain

References journal(), and trimzeros_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ wipe_dictionary()

subroutine, private m_cli2::wipe_dictionary
private

NAME

wipe_dictionary(3fp) - [ARGUMENTS:M_CLI2] reset private M_CLI2(3fm) dictionary to empty (LICENSE:PD)

SYNOPSIS

  subroutine wipe_dictionary()

DESCRIPTION

reset private M_CLI2(3fm) dictionary to empty

EXAMPLE

Sample program:

 program demo_wipe_dictionary
 use M_CLI2, only : dictionary
    call wipe_dictionary()
 end program demo_wipe_dictionary

AUTHOR

John S. Urban, 2019

LICENSE

Public Domain

References counts, keywords, mandatory, present_in, shorts, and values.

Here is the caller graph for this function:

Variable Documentation

◆ args

character(len=:), dimension(:), allocatable, public m_cli2::args

◆ cli_response_file

logical, save, public m_cli2::cli_response_file =.false.

◆ counts

integer, dimension(:), allocatable, save m_cli2::counts
private

◆ debug_m_cli2

logical, save, public m_cli2::debug_m_cli2 =.false.

◆ dp

integer, parameter, private m_cli2::dp =kind(0.0d0)
private

◆ g_append

logical, save m_cli2::g_append
private

◆ g_keyword_single_letter

logical, save m_cli2::g_keyword_single_letter =.true.
private

◆ g_options_only

logical, save m_cli2::g_options_only
private

◆ g_passed_in

character(len=:), allocatable, save m_cli2::g_passed_in
private

◆ g_quiet

logical, save m_cli2::g_quiet
private

◆ g_remaining

character(len=:), allocatable, save m_cli2::g_remaining
private

◆ g_remaining_on

logical, save m_cli2::g_remaining_on
private

◆ g_remaining_option_allowed

logical, save m_cli2::g_remaining_option_allowed
private

◆ g_response

logical, save m_cli2::g_response
private

◆ g_response_ignored

character(len=:), allocatable, save m_cli2::g_response_ignored
private

◆ g_stop

integer, save m_cli2::g_stop
private

◆ g_stop_message

character(len=:), allocatable, save m_cli2::g_stop_message
private

◆ g_strict

logical, save m_cli2::g_strict
private

◆ g_subcommand

character(len=:), allocatable, save m_cli2::g_subcommand
private

◆ gen

character(len=*), parameter m_cli2::gen ='(*(g0))'
private

◆ keywords

character(len=:), dimension(:), allocatable, save m_cli2::keywords
private

◆ mandatory

logical, dimension(:), allocatable, save m_cli2::mandatory
private

◆ present_in

logical, dimension(:), allocatable, save m_cli2::present_in
private

◆ remaining

character(len=:), allocatable, public m_cli2::remaining

◆ shorts

character(len=:), dimension(:), allocatable, save m_cli2::shorts
private

◆ sp

integer, parameter, private m_cli2::sp =kind(0.0)
private

◆ unnamed

character(len=:), dimension(:), allocatable, public m_cli2::unnamed

◆ values

character(len=:), dimension(:), allocatable, save m_cli2::values
private