module m_getopts
! Assume now a f2003 compliant compiler...
!use f2kcli
public :: getopts

CONTAINS

subroutine getopts(optionstring,name,optarg,optind,exitcode)
!$$$  Subprogram Documentation Block
!
! Subprogram:  Getopts    Process command line arguments for valid options
!   Prgmmr: Iredell       Org: W/NP23        Date: 2000-08-22
!
! Abstract: This subprogram processes command-line arguments for valid options.
!           It is the Fortran equivalent of the built-in shell command getopts.
!           Options on the command line come before the positional arguments.
!           Options are preceded by a - (minus sign) or a + (plus sign).
!           Options are single case-sensitive alphanumeric characters.
!           Options either do or do not have an expected argument.
!           Options without an argument may be immediately succeeded by
!           further options without the accompanying - or + prefix.
!           Options with an argument may be separated from their argument
!           by zero or more blanks.  The argument cannot end with a blank.
!           Options end when not preceded by a - or a + or after -- or ++.
!           This subprogram processes one option per invocation.
!           This subprogram is not thread-safe.
!
! Program History Log:
!   2007-05-05  Alberto Garcia: Use f2k-compliant f2kcli module
!   2000-08-22  Iredell
!
! Usage:    call getopts(optionstring,name,optarg,optind,exitcode)
!
!   Input Argument List:
!     optionstring
!       character string containing a list of all valid options;
!       options succeeded by a : require an argument
!
!   Input and Output Argument List:
!     optind
!       integer index of the next argument to be processed;
!       set to 0 before initial call or to restart processing
!
!   Output Argument List:
!     name
!       character string containing the name of the next option
!       or ? if no option or an unknown option is found
!       or : if an option had a missing required argument;
!       a + is prepended to the value in name if the option begins with a +
!     optarg
!       character string containing the option argument if required
!       or null if not required or not found;
!       optarg contains the option found if name is ? or :.
!     exitcode
!       integer return code (0 if an option was found, 1 if end of options)
!     
! Subprograms Called:
!   command_argument_count
!     Retrieve number of command-line arguments
!   get_command_argument
!     Retrieve a command-line argument
!   index 
!     Retrieve the starting position of a substring within a string
!     
! Remarks:
!   Here is an example of how to use this subprogram.
!     -----------------------------------------------------------
!     implicit none
!     character(len=20) copt,carg,cb,cpos
!     integer ia,ib,iopt,iret,narg,npos,ipos
!
!     ia=0     ! Programmer's flag for option a
!     ib=0     !  "                           b
!
!     iopt=0
!     do
!       call getopts('ab:',copt,carg,iopt,iret)
!       if(iret.ne.0) exit
!       select case(copt)
!       case('a','+a')
!         ia=1
!       case('b','+b')
!         ib=1
!         cb=carg
!       case('?',':')
!         print *,'invalid option ',carg(1:1)
!         stop 1
!       end select
!     enddo
!     if(ia.eq.1) print *,'option a selected'
!     if(ib.eq.1) print *,'option b selected; argument=',cb
!
!     Now process positional parameters
!     narg=command_argument_count()
!     npos=narg-iopt+1
!     do ipos=1,npos
!       call get_command_argument(number=ipos+iopt-1,value=cpos)
!       print *,'positional argument ',ipos,' is ',cpos
!     enddo
!     end
!     -----------------------------------------------------------
!
! Attributes:
!   Language: Fortran 90
!
!$$$
  implicit none

!  Passed data
  character(len=*),intent(in)      :: optionstring
  character(len=*),intent(out)     :: name
  character(len=*),intent(out)     :: optarg
  integer,         intent(inout)   :: optind
  integer,         intent(out)     :: exitcode

!  Saved data
  character(len=256), save  :: carg
  character(len=1) ,  save  :: cone
  integer,save              :: narg,larg,lcur

!  Local data
  character(len=1) ::  copt
  integer          ::  lname,lopt

! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!  Initially set saved data.
  if(optind.le.0) then
    optind=0
    narg=command_argument_count()
    carg=''
    cone=''
    larg=0
    lcur=1
  endif
! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!  Retrieve next command-line argument if necessary;
!  exit if at end of options
  if(lcur.gt.larg) then
    optind=optind+1
    if(optind.gt.narg) then
      name='?'
      optarg=''
      exitcode=1
      RETURN
    endif
    call get_command_argument(number=optind,value=carg)
    cone=carg(1:1)
    larg=len_trim(carg)
    lcur=2
    if(larg.eq.1.or.(cone.ne.'-'.and.cone.ne.'+')) then
      name='?'
      optarg=''
      exitcode=1
      RETURN
    elseif(larg.eq.2.and.carg(2:2).eq.cone) then
      optind=optind+1
      name='?'
      optarg=''
      exitcode=1
      RETURN
    endif
  endif
! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!  Find next option in the list; exit if option is unknown
  exitcode=0
  copt=carg(lcur:lcur)
  lcur=lcur+1
  lopt=index(optionstring,copt)
  if(lopt.eq.0) then
    name='?'
    optarg=copt
    RETURN
  endif
! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!  Option found; retrieve its argument if requested
    if(cone.eq.'-') then
      name=""
      lname=1
    else
      name="+"
      lname=2
    endif
  name(lname:lname)=copt
  optarg=''
  if(lopt.lt.len(optionstring)) then
     if (optionstring(lopt+1:lopt+1).eq.':') then
        if(lcur.gt.larg) then
           optind=optind+1
           if(optind.gt.narg) then
              name=':'
              optarg=copt
              RETURN
           endif
           call get_command_argument(number=optind,value=carg)
           larg=len_trim(carg)
           lcur=1
        endif
        optarg=carg(lcur:larg)
        lcur=larg+1
     endif
  endif
end subroutine
end module m_getopts
