parse Subroutine

private subroutine parse(self, args, ignore_unknown_clas, pref, error_unknown_clas)

Parse CLAsG arguments.

Type Bound

command_line_arguments_group

Arguments

Type IntentOptional Attributes Name
class(command_line_arguments_group), intent(inout) :: self

CLAsG data.

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

Command line arguments.

logical, intent(in) :: ignore_unknown_clas

Disable errors-raising for passed unknown CLAs.

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

Prefixing string.

integer(kind=I4P), intent(out) :: error_unknown_clas

Error flag for passed unknown CLAs.


Calls

proc~~parse~~CallsGraph proc~parse flap_command_line_arguments_group_t::command_line_arguments_group%parse cton cton proc~parse->cton proc~add flap_command_line_arguments_group_t::command_line_arguments_group%add proc~parse->proc~add proc~assign_object flap_object_t::object%assign_object proc~parse->proc~assign_object proc~check_m_exclusive flap_command_line_arguments_group_t::command_line_arguments_group%check_m_exclusive proc~parse->proc~check_m_exclusive proc~is_defined flap_command_line_arguments_group_t::command_line_arguments_group%is_defined proc~parse->proc~is_defined proc~raise_error_duplicated_clas flap_command_line_argument_t::command_line_argument%raise_error_duplicated_clas proc~parse->proc~raise_error_duplicated_clas proc~raise_error_nargs_insufficient flap_command_line_argument_t::command_line_argument%raise_error_nargs_insufficient proc~parse->proc~raise_error_nargs_insufficient proc~raise_error_switch_unknown flap_command_line_argument_t::command_line_argument%raise_error_switch_unknown proc~parse->proc~raise_error_switch_unknown proc~raise_error_value_missing flap_command_line_argument_t::command_line_argument%raise_error_value_missing proc~parse->proc~raise_error_value_missing proc~sanitize_defaults flap_command_line_arguments_group_t::command_line_arguments_group%sanitize_defaults proc~parse->proc~sanitize_defaults proc~check flap_command_line_arguments_group_t::command_line_arguments_group%check proc~add->proc~check proc~is_passed flap_command_line_arguments_group_t::command_line_arguments_group%is_passed proc~check_m_exclusive->proc~is_passed proc~raise_error_m_exclude~2 flap_command_line_argument_t::command_line_argument%raise_error_m_exclude proc~check_m_exclusive->proc~raise_error_m_exclude~2 proc~errored~2 flap_command_line_argument_t::command_line_argument%errored proc~raise_error_duplicated_clas->proc~errored~2 proc~raise_error_nargs_insufficient->proc~errored~2 proc~raise_error_switch_unknown->proc~errored~2 proc~raise_error_value_missing->proc~errored~2 proc~sanitize_defaults~2 flap_command_line_argument_t::command_line_argument%sanitize_defaults proc~sanitize_defaults->proc~sanitize_defaults~2 proc~check->proc~is_defined proc~errored flap_command_line_arguments_group_t::command_line_arguments_group%errored proc~check->proc~errored interface~colorize face::colorize proc~errored~2->interface~colorize proc~print_error_message flap_object_t::object%print_error_message proc~errored~2->proc~print_error_message str str proc~errored~2->str proc~raise_error_m_exclude~2->proc~errored~2 proc~replace_all flap_utils_m::replace_all proc~sanitize_defaults~2->proc~replace_all proc~unique flap_utils_m::unique proc~sanitize_defaults~2->proc~unique proc~wstrip flap_utils_m::wstrip proc~sanitize_defaults~2->proc~wstrip proc~colorize_default face::colorize_default interface~colorize->proc~colorize_default proc~errored->interface~colorize proc~errored->proc~print_error_message proc~errored->str proc~replace_all->proc~wstrip proc~replace flap_utils_m::replace proc~replace_all->proc~replace proc~color_index face::color_index proc~colorize_default->proc~color_index proc~style_index face::style_index proc~colorize_default->proc~style_index proc~upper face::upper proc~colorize_default->proc~upper

Called by

proc~~parse~~CalledByGraph proc~parse flap_command_line_arguments_group_t::command_line_arguments_group%parse proc~parse~2 flap_command_line_interface_t::command_line_interface%parse proc~parse~2->proc~parse proc~fake_call flap_test_group::fake_call proc~fake_call->proc~parse~2 none~get~2 flap_command_line_interface_t::command_line_interface%get proc~fake_call->none~get~2 proc~get_cla_list_varying_char~2 flap_command_line_interface_t::command_line_interface%get_cla_list_varying_char proc~get_cla_list_varying_char~2->proc~parse~2 proc~get_cla_list_varying_i1p~2 flap_command_line_interface_t::command_line_interface%get_cla_list_varying_I1P proc~get_cla_list_varying_i1p~2->proc~parse~2 proc~get_cla_list_varying_i2p~2 flap_command_line_interface_t::command_line_interface%get_cla_list_varying_I2P proc~get_cla_list_varying_i2p~2->proc~parse~2 proc~get_cla_list_varying_i4p~2 flap_command_line_interface_t::command_line_interface%get_cla_list_varying_I4P proc~get_cla_list_varying_i4p~2->proc~parse~2 proc~get_cla_list_varying_i8p~2 flap_command_line_interface_t::command_line_interface%get_cla_list_varying_I8P proc~get_cla_list_varying_i8p~2->proc~parse~2 proc~get_cla_list_varying_logical~2 flap_command_line_interface_t::command_line_interface%get_cla_list_varying_logical proc~get_cla_list_varying_logical~2->proc~parse~2 proc~get_cla_list_varying_r16p~2 flap_command_line_interface_t::command_line_interface%get_cla_list_varying_R16P proc~get_cla_list_varying_r16p~2->proc~parse~2 proc~get_cla_list_varying_r4p~2 flap_command_line_interface_t::command_line_interface%get_cla_list_varying_R4P proc~get_cla_list_varying_r4p~2->proc~parse~2 proc~get_cla_list_varying_r8p~2 flap_command_line_interface_t::command_line_interface%get_cla_list_varying_R8P proc~get_cla_list_varying_r8p~2->proc~parse~2 proc~get_cla_list~2 flap_command_line_interface_t::command_line_interface%get_cla_list proc~get_cla_list~2->proc~parse~2 proc~get_cla~2 flap_command_line_interface_t::command_line_interface%get_cla proc~get_cla~2->proc~parse~2 program~flap_save_bash_completion flap_save_bash_completion program~flap_save_bash_completion->proc~parse~2 program~flap_test_basic flap_test_basic program~flap_test_basic->proc~parse~2 none~get_varying~2 flap_command_line_interface_t::command_line_interface%get_varying program~flap_test_basic->none~get_varying~2 program~flap_test_basic->none~get~2 program~flap_test_choices_logical flap_test_choices_logical program~flap_test_choices_logical->proc~parse~2 program~flap_test_choices_logical->none~get~2 program~flap_test_nested flap_test_nested program~flap_test_nested->proc~parse~2 program~flap_test_nested->none~get~2 program~flap_test_string flap_test_string program~flap_test_string->proc~parse~2 program~flap_test_string->none~get~2 none~get_varying~2->proc~get_cla_list_varying_char~2 none~get_varying~2->proc~get_cla_list_varying_i1p~2 none~get_varying~2->proc~get_cla_list_varying_i2p~2 none~get_varying~2->proc~get_cla_list_varying_i4p~2 none~get_varying~2->proc~get_cla_list_varying_i8p~2 none~get_varying~2->proc~get_cla_list_varying_logical~2 none~get_varying~2->proc~get_cla_list_varying_r4p~2 none~get_varying~2->proc~get_cla_list_varying_r8p~2 none~get~2->proc~get_cla_list~2 none~get~2->proc~get_cla~2 program~flap_test_group flap_test_group program~flap_test_group->proc~fake_call program~flap_save_man_page flap_save_man_page program~flap_save_man_page->none~get~2 program~flap_save_usage_to_markdown flap_save_usage_to_markdown program~flap_save_usage_to_markdown->none~get~2 program~flap_test_action_store flap_test_action_store program~flap_test_action_store->none~get_varying~2 program~flap_test_action_store->none~get~2 program~flap_test_ansi_color_style flap_test_ansi_color_style program~flap_test_ansi_color_style->none~get~2 program~flap_test_duplicated_clas flap_test_duplicated_clas program~flap_test_duplicated_clas->none~get~2 program~flap_test_group_examples flap_test_group_examples program~flap_test_group_examples->none~get~2 program~flap_test_hidden flap_test_hidden program~flap_test_hidden->none~get~2 program~flap_test_ignore_unknown_clas flap_test_ignore_unknown_clas program~flap_test_ignore_unknown_clas->none~get~2 program~flap_test_minimal flap_test_minimal program~flap_test_minimal->none~get~2 program~flap_test_nargs_insufficient flap_test_nargs_insufficient program~flap_test_nargs_insufficient->none~get~2 program~flap_test_nargs_insufficient~2 flap_test_nargs_insufficient program~flap_test_nargs_insufficient~2->none~get~2

Source Code

  subroutine parse(self, args, ignore_unknown_clas, pref, error_unknown_clas)
  !< Parse CLAsG arguments.
  class(command_line_arguments_group), intent(inout) :: self                !< CLAsG data.
  character(*),                        intent(in)    :: args(:)             !< Command line arguments.
  logical,                             intent(in)    :: ignore_unknown_clas !< Disable errors-raising for passed unknown CLAs.
  character(*), optional,              intent(in)    :: pref                !< Prefixing string.
  integer(I4P),                        intent(out)   :: error_unknown_clas  !< Error flag for passed unknown CLAs.
  type(command_line_argument)                        :: cla                 !< CLA data.
  character(500)                                     :: envvar              !< Environment variables buffer.
  integer(I4P)                                       :: arg                 !< Argument counter.
  integer(I4P)                                       :: a                   !< Counter.
  integer(I4P)                                       :: aa                  !< Counter.
  integer(I4P)                                       :: aaa                 !< Counter.
  integer(I4P)                                       :: nargs               !< Number of arguments consumed by a CLA.
  logical                                            :: found               !< Flag for checking if switch is a defined CLA.
  logical                                            :: found_val           !< Flag for checking if switch value is found.

  error_unknown_clas = 0
  if (self%is_called) then
     call self%sanitize_defaults
     arg = 0
     do while (arg < size(args, dim=1)) ! loop over CLAs group arguments passed
        arg = arg + 1
        found = .false.
        do a=1, self%Na ! loop over CLAs group clas named options
           if (.not.self%cla(a)%is_positional) then
              if (trim(adjustl(self%cla(a)%switch   ))==trim(adjustl(args(arg))).or.&
                  trim(adjustl(self%cla(a)%switch_ab))==trim(adjustl(args(arg)))) then
                 if (self%cla(a)%is_passed) then
                    ! current CLA has been already passed, raise an error
                    call self%cla(arg)%raise_error_duplicated_clas(pref=pref, switch=trim(adjustl(args(arg))))
                    self%error = self%cla(arg)%error
                 else
                    self%cla(a)%is_passed = .true.
                    found = .true.
                 endif
                 found_val = .false.

                 ! check action
                 if (self%cla(a)%act==action_store) then
                    ! flush default (if any) to value as starting point
                    if (allocated(self%cla(a)%def)) self%cla(a)%val = self%cla(a)%def

                    ! search for actual passed value if passed/required

                    ! check for envvar
                    if (allocated(self%cla(a)%envvar)) then
                       ! verify if the value has been passed directly to cli
                       if (arg + 1 <= size(args,dim=1)) then
                          ! there are still other arguments to check
                          if (.not.self%is_defined(switch=trim(adjustl(args(arg+1))))) then
                             ! argument seems good...
                             arg = arg + 1
                             self%cla(a)%val = trim(adjustl(args(arg)))
                             found_val = .true.
                          endif
                       endif
                       if (.not.found_val) then
                          ! value not found, try to take val from environment
                          call get_environment_variable(name=self%cla(a)%envvar, value=envvar, status=aa)
                          if (aa==0) then
                             self%cla(a)%val = trim(adjustl(envvar))
                             found_val = .true.
                          else
                             ! no found, raise value missing error
                             call self%cla(a)%raise_error_value_missing(pref=pref)
                             self%error = self%cla(a)%error
                             return
                          endif
                       endif

                    ! check for multiple argument values
                    elseif (allocated(self%cla(a)%nargs)) then
                       select case(self%cla(a)%nargs)
                       case('+')
                          aaa = n_next_undef_args(args=args, arg=arg)
                          if (aaa>=arg+1) then
                             self%cla(a)%val = ''
                             do aa=aaa, arg + 1, -1 ! decreasing loop due to gfortran bug
                                self%cla(a)%val = trim(adjustl(args(aa)))//args_sep//trim(self%cla(a)%val)
                                found_val = .true.
                             enddo
                             arg = aaa
                          elseif (self%cla(a)%is_val_required) then
                             call self%cla(a)%raise_error_nargs_insufficient(pref=pref)
                             self%error = self%cla(a)%error
                             return
                          endif
                       case('*')
                          aaa = n_next_undef_args(args=args, arg=arg)
                          if (aaa>=arg+1) then
                             self%cla(a)%val = ''
                             do aa=aaa, arg + 1, -1 ! decreasing loop due to gfortran bug
                                self%cla(a)%val = trim(adjustl(args(aa)))//args_sep//trim(self%cla(a)%val)
                                found_val = .true.
                             enddo
                             arg = aaa
                          endif
                       case default
                          nargs = cton(str=trim(adjustl(self%cla(a)%nargs)), knd=1_I4P)
                          if ((arg + nargs == n_next_undef_args(args=args, arg=arg))) then
                             self%cla(a)%val = ''
                             do aa=arg + nargs, arg + 1, -1 ! decreasing loop due to gfortran bug
                                self%cla(a)%val = trim(adjustl(args(aa)))//args_sep//trim(self%cla(a)%val)
                             enddo
                             found_val = .true.
                             arg = arg + nargs
                          elseif (self%cla(a)%is_val_required) then
                             call self%cla(a)%raise_error_nargs_insufficient(pref=pref)
                             self%error = self%cla(a)%error
                             return
                          endif
                       endselect

                    ! check for single argument value
                    else
                       if (self%cla(a)%is_val_required) then
                          ! value is required
                          if (arg+1>size(args)) then
                             ! no more arguments remaining, raise value missing error
                             call self%cla(a)%raise_error_value_missing(pref=pref)
                             self%error = self%cla(a)%error
                             return
                          elseif (self%is_defined(switch=trim(adjustl(args(arg+1))))) then
                             ! the next argument is a CLA switch, raise value missing error
                             call self%cla(a)%raise_error_value_missing(pref=pref)
                             self%error = self%cla(a)%error
                             return
                          else
                             ! value found
                             arg = arg + 1
                             self%cla(a)%val = trim(adjustl(args(arg)))
                             found_val = .true.
                          endif
                       else
                          ! value is not required, check if it is passed
                          if (arg + 1 <= size(args, dim=1)) then
                             ! there are arguments to check
                             if (.not.self%is_defined(switch=trim(adjustl(args(arg+1))))) then
                                ! value found
                                arg = arg + 1
                                self%cla(a)%val = trim(adjustl(args(arg)))
                                found_val = .true.
                             endif
                          endif
                       endif
                    endif

                 elseif (self%cla(a)%act==action_store_star) then
                    if (arg + 1 <= size(args, dim=1)) then ! verify if the value has been passed directly to cli
                       ! there are still other arguments to check
                       if (.not.self%is_defined(switch=trim(adjustl(args(arg+1))))) then
                          ! arguments seem good...
                          arg = arg + 1
                          self%cla(a)%val = trim(adjustl(args(arg)))
                          found = .true.
                          found_val = .true.
                       endif
                    endif
                    if (.not.found) then
                       ! flush default to val if default is set
                       if (allocated(self%cla(a)%def)) self%cla(a)%val = self%cla(a)%def
                    endif
                 elseif (self%cla(a)%act==action_print_help) then
                    self%error = STATUS_PRINT_H
                 elseif (self%cla(a)%act==action_print_mark) then
                    self%error = STATUS_PRINT_M
                 elseif (self%cla(a)%act==action_print_vers) then
                    self%error = STATUS_PRINT_V
                 endif

                 self%cla(a)%is_passed = .true.
                 found = .true.
                 exit
              endif
           endif
        enddo
        if (.not.found) then ! current argument (arg-th) does not correspond to a named option
           if (arg>self%Na) then ! has been passed too much CLAs
               ! place the error into a new positional dummy CLA
               call cla%assign_object(self)
               cla%is_passed = .true.
               cla%m_exclude = ''
               call self%add(pref=pref, cla=cla)
               call self%cla(self%Na)%raise_error_switch_unknown(pref=pref, switch=trim(adjustl(args(arg))))
               self%error = self%cla(self%Na)%error
               return
           endif
           if (.not.self%cla(arg)%is_positional) then ! current argument (arg-th) is not positional... there is a problem!
              call self%cla(arg)%raise_error_switch_unknown(pref=pref, switch=trim(adjustl(args(arg))))
              self%error = self%cla(arg)%error
              error_unknown_clas = self%error
              if (.not.ignore_unknown_clas) return
           else
              ! positional CLA always stores a value
              self%cla(arg)%val = trim(adjustl(args(arg)))
              self%cla(arg)%is_passed = .true.
           endif
        endif
     enddo
     call self%check_m_exclusive(pref=pref)
  endif
  contains
     function n_next_undef_args(args, arg)
     !< Return the number of the next undefined (not named switch) arguments.
     character(*), intent(in) :: args(:)           !< Command line arguments.
     integer(I4P), intent(in) :: arg               !< Current argument number.
     integer(I4P)             :: n_next_undef_args !< Number of the next undefined (not named switch) arguments.
     integer(I4P)             :: i                 !< Counter.

     n_next_undef_args = 0
     do i=arg + 1, size(args,dim=1)
        if (.not.self%is_defined(switch=trim(adjustl(args(i))))) then
           n_next_undef_args = i
        else
           exit
        endif
     enddo
     endfunction n_next_undef_args
  endsubroutine parse