subroutine exemac(line,error)
  use gildas_def
  use sic_structures
  use sic_dictionaries
  use gbl_message
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>exemac
  !---------------------------------------------------------------------
  ! @ private
  ! SIC   Internal routine
  !       Execute a macro
  !---------------------------------------------------------------------
  character(len=*), intent(in)  :: line   ! Command line
  logical,          intent(out) :: error  ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='MACRO'
  character(len=filename_length) :: name,fich
  integer :: i,n,ier,ipt,nc
  character(len=message_length) :: mess
  character(len=4) ::ans
  logical :: found
  !
  ! Increase execution level
  if (nlire.ge.maxlev-1) then
    call sic_message(seve%e,rname,'Input level too deep')
    error = .true.
    return
  endif
  !
  ! Find the macro name and setup the arguments
  error = .false.
  call sic_ch (line,0,1,name,nc,.true.,error)
  if (error) return
  call find_procedure(name,fich,found)
  if (.not.found) then
    call sic_message(seve%e,rname,'No such procedure '//name)
    error = .true.
    return
  endif
  !
  ! Check for recursive calls
  do i=1,nmacro
    if (macnam(i).eq.fich) then
      call sic_message(seve%e,rname,'Recursive call to macro '//fich)
      error = .true.
      return
    endif
  enddo
  !
  ! Get LUN
  call sic_lunmac_get(nmacro+1,error)
  if (error) return
  !
  ! Increment levels
  nlire   = nlire + 1
  nmacro  = nmacro + 1
  mlire(nlire) = nmacro
  !
  ! Open the file and proceed
  macnam(nmacro) = fich
  ier = sic_open(lunmac(nmacro),macnam(nmacro),'OLD',.true.)
  if (ier.ne.0) then
    call sic_message(seve%e,rname,'Unable to open macro '//fich)
    call putios('          ',ier)
    goto 70
  endif
  !
  ! Define the macro arguments
  ipt = 1
  macarg(nmacro) = ' '
  if (sic_present(0,maxmacarg+2)) then
    write (mess,'(A,I2,A)') 'Too many macro arguments. Only ',maxmacarg,  &
    ' will be used'
    call sic_message(seve%w,rname,mess)
  endif
  manarg(nmacro) = 0
  do i=1,maxmacarg
    if (sic_present(0,i+1)) then
      mac1(nmacro,i) = ipt
      call sic_ch (line,0,i+1,macarg(nmacro)(ipt:),nc,.true.,error)
      if (error) then
         close(unit=lunmac(nmacro))
         goto 70
      endif
      mac2(nmacro,i) = ipt + nc -1
      if (mac2(nmacro,i).lt.mac1(nmacro,i)) then
        mac2(nmacro,i) = mac1(nmacro,i)+sic_len(0,i+1)
      endif
      ipt = mac2(nmacro,i)+2
      manarg(nmacro) = i
    else
      mac1(nmacro,i) = 0
      mac2(nmacro,i) = 0
    endif
  enddo
  var_level = nmacro
  var_macro(var_level) = var_n
  jmac (nmacro) = 0
  nerr(var_level) = nerr(0)
  errcom(var_level) = errcom(0)
  !
  ! Define the arguments as SIC Variables
  call mac_variables
  !
  if (sic_stepin.ne.0) then
    if (.not.lverif) then
      print *,'---- Executing @ '//trim(macnam(nmacro))
      print *,'----',manarg(nmacro),' arguments'
      print *,'----'//trim(macarg(nmacro))
      if (sic_stepin.lt.0) call sic_wprn('Continue ? ',ans,n)
    endif
  endif
  error = .false.
  return
  !
  ! Error : reset the execution level and number of active macros
  !
70 call sic_lunmac_free(nmacro)
  nmacro = nmacro - 1
  nlire = nlire -1
  error = .true.
end subroutine exemac
!
subroutine endmac
  use sic_interfaces, except_this=>endmac
  use sic_structures
  !---------------------------------------------------------------------
  ! @ private
  ! End of macro execution
  !-----------------------------------------------------------------------
  !
  ! Close the unit and reset the active macro number
  close (unit=lunmac(nmacro))
  call sic_lunmac_free(nmacro)
  if (sic_stepin.ne.0) then
    print *,'---- Leaving @ '//trim(macnam(nmacro))
  endif
  errcom(nmacro) = ' '
  nerr  (nmacro) = 0
  nmacro = nmacro - 1
  !
  ! Delete all local variables :
  call erase_variables
  !
  ! Reset Arguments
  call mac_variables
end subroutine endmac
!
subroutine mac_variables
  use sic_interfaces, except_this=>mac_variables
  use sic_structures
  !---------------------------------------------------------------------
  ! @ private
  ! Define the current macro arguments as SIC Variables
  !---------------------------------------------------------------------
  logical :: error
  integer :: i
  !
  error = .false.
  call sic_delvariable ('PRO',.false.,error)
  if (nmacro.eq.0) return
  !
  ! This is a "Program Defined" structure
  error = .false.
  call sic_defstructure('PRO',.true.,error)
  !
  ! And now the associated program-defined variables.
  !
  call sic_def_char('PRO%NAME',macnam(nmacro),.true.,error)
  call sic_def_inte('PRO%NARG',manarg(nmacro),0,0,.true.,error)
  if (manarg(nmacro) .lt.1) return
  call sic_def_charn('PRO%ARG',macstr,1,manarg(nmacro),.true.,error)
  do i = 1,manarg(nmacro)
    macstr(i) = macarg(nmacro)(mac1(nmacro,i):mac2(nmacro,i))
  enddo
end subroutine mac_variables
!
subroutine macarg_parse(line,error)
  use gbl_message
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>macarg_parse
  use sic_structures
  !---------------------------------------------------------------------
  ! @ private
  ! Support routine for command:
  !  SIC\PARSE [/OPT1 [Nargmin [Nargmax]]] [/OPT2 ...] ... [/OPTN ...]
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line   ! Input command line
  logical,          intent(inout) :: error  ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='PARSE'
  character(len=varname_length) :: structname,varname1,varname2
  integer(kind=4) :: nc,nopt,iopt,iarg,narg,curr_opt
  character(len=command_length) :: imacstr,option
  character(len=command_length) :: optname(0:maxmacarg)
  integer(kind=4) :: nargmin(0:maxmacarg),nargmax(0:maxmacarg)
  integer(kind=4), save :: optnarg(0:maxmacarg)  ! Support for PRO%PARSE%<OPTNAME>%NARG
  integer(kind=4) :: optfirst(0:maxmacarg)
  logical, parameter :: global=.true.,ro=.true.
  character(len=32) :: mess1,mess2
  character(len=message_length) :: mess
  !
  ! --- The parent structure -------------------------------------------
  structname = 'PRO%PARSE'
  call sic_delvariable (structname,.false.,error)
  if (error)  return
  call sic_defstructure(structname,global,error)
  if (error)  return
  !
  ! --- The options list -----------------------------------------------
  nopt = 0
  optname(nopt) = '/COMMAND'
  nargmin(nopt) = -1  ! No minimum provided yet
  nargmax(nopt) = -1  ! No maximum provided yet
  !
  do iarg=1,sic_narg(0)
    call sic_ch(line,0,iarg,option,nc,.true.,error)
    if (error)  return
    if (option(1:1).eq."/") then
      ! This is a new option declaration
      ! Finish previous option declaring
      if (nargmax(nopt).eq.-1)  nargmax(nopt) = nargmin(nopt)
      ! Start new option declaration
      call sic_upper(option)
      nopt = nopt+1
      optname(nopt) = option
      nargmin(nopt) = -1  ! No minimum provided yet
      nargmax(nopt) = -1  ! No maximum provided yet
      !
    elseif (nargmin(nopt).eq.-1) then
      call sic_i4(line,0,iarg,nargmin(nopt),.true.,error)
      if (error)  return
      if (nargmin(nopt).le.-1) then
        call sic_message(seve%e,rname,'Invalid option declaration, should have 0 <= Nargmin <= Nargmax')
        error = .true.
        return
      endif
      !
    elseif (nargmax(nopt).eq.-1) then
      call sic_i4(line,0,iarg,nargmax(nopt),.true.,error)
      if (error)  return
      if (nargmax(nopt).lt.nargmin(nopt)) then
        call sic_message(seve%e,rname,'Invalid option declaration, should have 0 <= Nargmin <= Nargmax')
        error = .true.
        return
      endif
      !
    else
      call sic_message(seve%e,rname,'Invalid option declaration. Syntax is:')
      call sic_message(seve%e,rname,'SIC\PARSE [Nargmin [Nargmax]] /OPT1  [Nargmin [Nargmax]] /OPT2...')
      error = .true.
      return
    endif
  enddo
  !
  ! --- Parse PRO%ARG --------------------------------------------------
  !
  optnarg(:) = -1  ! i.e. none of the options is present
  optnarg(0) = 0   ! i.e. command is present, with 0 argument yet
  optfirst(:) = 0  !
  optfirst(0) = 1  ! 1st argument of command is 1st element of PRO%ARG[:]
  curr_opt = 0
  do iarg=1,manarg(nmacro)
    if (macstr(iarg)(1:1).eq.'/') then
      imacstr = macstr(iarg)
      call sic_upper(imacstr)
      call sic_ambigs(rname,imacstr,option,curr_opt,optname(1),nopt,error)
      if (error)  return
      optnarg(curr_opt) = 0
      optfirst(curr_opt) = iarg+1
    else
      optnarg(curr_opt) = optnarg(curr_opt)+1
    endif
  enddo
  !
  ! --- Check for correct number of arguments --------------------------
  !
  do iopt=0,nopt
    !
    if (optnarg(iopt).eq.-1)  cycle  ! Option is absent, nothing to check
    !
    if (nargmin(iopt).ne.-1 .and. nargmin(iopt).ne.nargmax(iopt)) then
      ! A minimum number is required
      if (optnarg(iopt).lt.nargmin(iopt)) then
        error = .true.
        mess2 = 'at least'
        narg = nargmin(iopt)
      endif
      !
    elseif (nargmax(iopt).ne.-1 .and. nargmin(iopt).ne.nargmax(iopt)) then
      ! A maximum number required
      if (optnarg(iopt).gt.nargmax(iopt)) then
        error = .true.
        mess2 = 'at most'
        narg = nargmax(iopt)
      endif
      !
    elseif (nargmin(iopt).ne.-1 .and. nargmin(iopt).eq.nargmax(iopt)) then
      ! An exact number is required
      if (optnarg(iopt).ne.nargmin(iopt)) then
        error = .true.
        mess2 = 'exactly'
        narg = nargmin(iopt)
      endif
    endif
    !
    if (error) then
      if (iopt.eq.0) then
        mess1 = 'Command'
      else
        mess1 = 'Option '//optname(iopt)
      endif
      write(mess,10)  trim(mess1),trim(mess2),narg
      call sic_message(seve%e,rname,mess)
      return
    endif
  enddo
  !
10 format(A,' takes ',A,1X,I0,' argument(s)')
  !
  ! --- Fill the PRO%PARSE% structure ----------------------------------
  !
  do iopt=0,nopt
    !
    ! PRO%PARSE%<OPTNAME>%
    write(varname1,'(A,A,A)')  trim(structname),'%',optname(iopt)(2:)  ! Strip the leading /
    call sic_defstructure(varname1,global,error)
    if (error)  return
    !
    ! PRO%PARSE%<OPTNAME>%NARG
    varname2 = trim(varname1)//'%NARG'
    call sic_def_inte(varname2,optnarg(iopt),0,0,ro,error)
    if (error)  return
    !
    ! PRO%PARSE%<OPTNAME>%ARG
    if (optnarg(iopt).gt.0) then
      varname2 = trim(varname1)//'%ARG'
      call sic_def_charn(varname2,macstr(optfirst(iopt)),1,optnarg(iopt),ro,error)
      if (error)  return
    endif
    !
  enddo
  !
end subroutine macarg_parse
