module yesnopi
  use gbl_format
  !---------------------------------------------------------------------
  ! Support module for SIC variables which are mapped on Fortran ones.
  !---------------------------------------------------------------------
  real(kind=8),    save :: pi=3.14159265358979323846d0
  logical,         save :: yes=.true.
  logical,         save :: no=.false.
  real(kind=4),    save :: nan
  integer(kind=4), save :: type_real=fmt_r4
  integer(kind=4), save :: type_inte=fmt_i4
  integer(kind=4), save :: type_long=fmt_i8
  integer(kind=4), save :: type_dble=fmt_r8
  integer(kind=4), save :: type_logi=fmt_l
  !
end module yesnopi
!
subroutine sic_opt(pr,log,mem)
  use sic_dependencies_interfaces
  use gpack_def
  use sic_interfaces, except_this=>sic_opt
  use sic_interactions
  !---------------------------------------------------------------------
  ! @ public (but obsolete in the context of new inits (at least since
  !   2008-04-11))
  ! Please use instead:
  !  - gprompt_set(pr): to set/modify the prompt
  !  - sic_open_log(log,error): to open the log file
  !  - no routine provided to turn ON|OFF the memory stack (default ON
  !    at startup, then user can call SIC\SIC MEMORY ON|OFF
  !---------------------------------------------------------------------
  ! SIC   External routine
  !       Modify the prompt and logfile logical name and status of stack
  !---------------------------------------------------------------------
  character(len=*), intent(in) :: pr   ! The prompt
  character(len=*), intent(in) :: log  ! The log file name
  logical,          intent(in) :: mem  ! Status of stack editor
  ! Local
  logical :: error
  !
  error = .false.
  !
  call gprompt_set(pr)
  logbuf = mem
  !
  if (loaded) return
  !
  ! Set default message filter for packages without specific message routine
  call gmessage_parse_and_set(gpack_global_id,'s=fewriu',error)
  !
  ! Check the gag environment is present
  call sic_build_environment
  !
  call sic_open_log(log,error)
  if (error) return
  !
  ! Initialize widget library
#if defined(GAG_USE_STATICLINK)
  call init_gui
#endif
  !
  call sense_inter_state  ! Selects the state (Interactive or not)
  call sic_build
  !
end subroutine sic_opt
!
subroutine sic_open_log(logf,error)
  use sic_interfaces, except_this=>sic_open_log
  use sic_structures
  use gbl_message
  use sic_dependencies_interfaces
  !---------------------------------------------------------------------
  ! @ private
  ! SIC   External routine
  !       Open the LOG file
  !---------------------------------------------------------------------
  character(len=*) :: logf       ! The log file name
  logical :: error               ! Logical error flag
  ! Local
  integer :: status
  character(len=filename_length) :: logfile
  !
  if (lunlog.ne.0)  return
  !
  if (logf.eq.' ')  return
  !
  status = sic_getlun(lunlog)
  if (mod(status,2).eq.0) call sysexi(status)
  call sic_parse_file(logf,'GAG_LOG:','.LOG',logfile)
  status = sic_open (lunlog,logfile,'NEW',.false.)
  if (status.ne.0) then
    call sic_message(seve%e,'SIC_OPEN_LOG','Error opening '//logf)
    call putios('E-SIC,  ',status)
    error = .true.
    call sic_frelun(lunlog)
    lunlog = 0
  endif
  !
end subroutine sic_open_log
!
subroutine sic_flush_log(error)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_flush_log
  use sic_structures
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! SIC   External routine
  !       Flush the LOG file buffer onto disk
  ! Arguments :
  !       ERROR   L       Error returned
  !---------------------------------------------------------------------
  logical :: error                  ! INTENT(INOUT)
  ! Local
  integer :: status
  !
  if (lunlog.eq.0) return
  status = sic_flush(lunlog)
  if (status.ne.0) then
    error = .true.
    call sic_message(seve%e,'SIC_FLUSH_LOG','Error flushing log file '//  &
    'buffer onto disk')
  endif
end subroutine sic_flush_log
!
subroutine sic_close_log(error)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_close_log
  use sic_structures
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  !  Close the LOG file and free its unit
  !---------------------------------------------------------------------
  logical, intent(inout) :: error  ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='SIC_CLOSE_LOG'
  integer(kind=4) :: status
  !
  if (lunlog.eq.0) return
  !
  status = sic_close(lunlog)
  if (status.ne.0)  error = .true.
  !
  call sic_frelun(lunlog)
  !
  lunlog = 0
  if (error) then
    call sic_message(seve%d,rname,"ERROR")
  else
    call sic_message(seve%d,rname,"SUCCESS")
  endif
  !
end subroutine sic_close_log
!
subroutine sic_build
  use ieee_arithmetic
  use gbl_message
  use sic_dependencies_interfaces
  use sic_dictionaries
  use sic_interactions
  use sic_interfaces
  use sic_structures
  use yesnopi
  !---------------------------------------------------------------------
  ! SIC   External routine
  !       Initialize SIC
  !---------------------------------------------------------------------
  ! Local
  character(len=*), parameter :: rname='SIC'
  integer :: i,code,timer,ier,stbl
  logical :: error
  character(len=12) :: command
  character(len=60) :: name
  character(len=1), parameter :: backslash=char(92)
  ! SIC language
  integer, parameter :: sic_commands=98
  character(len=12) :: sic_vocab(sic_commands)
  data sic_vocab/            &
    '-@',                    &  !  1
    ' BEGIN',                &  !  2
    ' BREAK',                &  !  3
    ' CONTINUE',             &  !  4
    ' EDIT',                 &  !  5
    ' ELSE',                 &  !  6
    ' EXIT', '/NOPROMPT',    &  !  7- 8
    ' END',                  &  !  9
    ' FOR', '/IN','/WHILE',  &  ! 10-12
    '-HELP',                 &  ! 13
    '-IF',                   &  ! 14
    ' NEXT',                 &  ! 15
    '-ON',                   &  ! 16
    ' PAUSE',                &  ! 17
    '-PYTHON',               &  ! 18
    '#QUIT',                 &  ! 19
    '#RECALL',               &  ! 20
    ' RETURN',               &  ! 21
    ' TYPE', '/OUTPUT',      &  ! 22-23=mbuilt_sic_inter (update if this changes)
    ! Beyond this point, elemental commands which can not alter the
    ! standard flow of commands in the SIC interpreter
    ' ACCEPT',   '/ARRAY','/BINARY','/COLUMN','/FORMAT','/LINE',        &  ! 24-29
    ' COMPUTE',  '/BLANKING',                                           &  ! 30-31
    ' DATETIME', '/FROM','/TO',                                         &  ! 32-34
    ' DEFINE',   '/GLOBAL','/LIKE','/TRIM',                             &  ! 35-38
    ' DELETE',   '/SYMBOL','/VARIABLE','/FUNCTION',                     &  ! 40-42
    ' DIFF',                                                            &  ! 43-
    ' EXAMINE',  '/GLOBAL','/FUNCTION','/HEADER','/ADDRESS','/ALIAS',   &  ! 44-
                 '/PAGE','/SAVE',                                       &  !   -51
    ' EXECUTE',                                                         &  ! 52
    ' IMPORT',   '/DEBUG',                                              &  ! 53-54
    ! The LET option order is alphabetic, and symbolic names are given in
    ! dedicated module 'let_options'
    ' LET',      '/CHOICE','/FILE','/FORMAT','/FORMULA','/INDEX',       &  ! 55-
                 '/LOWER','/NEW','/NOQUOTE','/PROMPT','/RANGE',         &  !
                 '/REPLACE','/RESIZE','/SEXAGESIMAL','/STATUS',         &
                 '/UPPER','/WHERE',                                     &  !   -71
    ' MESSAGE',  '/FORMAT',                                             &  ! 72-73
    ' MFIT',     '/START','/STEP','/WEIGHTS','/EPSILON','/METHOD',      &  ! 74-
                 '/ITERATIONS','/QUIET','/BOUNDS',                      &  !   -82
    ' MODIFY',   '/FREQUENCY','/VELOCITY','/SPECUNIT',                  &  ! 83-86
    '-PARSE',                                                           &  ! 87
    ' SAY',      '/FORMAT','/NOADVANCE',                                &  ! 88-90
    ' SIC',      '/COLOR',                                              &  ! 92
    ' SORT',                                                            &  ! 93
    ' SYMBOL',   '/INQUIRE',                                            &  ! 94-95
    ' SYSTEM',                                                          &  ! 96
    ' TIMER',    '/COMMAND' /                                              ! 97-98
  ! GUI language
  integer, parameter :: ngui=15
  character(len=12) :: cgui(ngui)
  data cgui/                              &
    ' BUTTON',                            &
    ' URI',                               &
    ' END',                               &
    ' ERASE',                             &
    ' GO',                                &
    ' PANEL', '/CLOSE','/DETACH','/LOG',  &
    ' MENU', '/CLOSE','/CHOICES',         &
    ' SUBMENU', '/CLOSE',                 &
    ' WAIT'/
  !
  error = .false.
  !
  ! Loaded : return
  if (loaded) return
  loaded = .true.
  !
  sicinteger = fmt_i4
  sicsystemerror = .true.  ! Error from command SIC\SYSTEM ignored or not?
  nan = ieee_value(0.,ieee_quiet_nan)
  !
  ! Initialize the stack
  call init_stack
  !
  ! Initialize the loops
  bulend = 1
  !
  ! Initialize error recovery
  nerr  (0) = e_pause
  errcom(0) = 'SIC'//backslash//'PAUSE'
  !
  ! Initialize the IF blocks
  do i=1,mcif
    if_finished(i) = .true.
    if_active(i) = .false.
    if_elsefound(i) = .false.
  enddo
  if_depth(1) = 1
  if_current = 0
  nlire = 0
  ! Initialize vocabulary and help
  nlang = 0
  klang(1) = 0
  call sic_load('SIC','GAG_HELP_SIC',sic_commands,sic_vocab,'9.3    10-Apr-2016')
  ! Take the associated name help_file in the files names dictionary
  ier = sic_getlog (languages(1)%help)
  !
  ! Action related to the inter_state mode (see sense_inter_state)
  if (edit_mode) then
    tt_edit = 'GAG_HELP_MODE'
    ier = sic_getlog (tt_edit)
    help_mode = help_page
    if (tt_edit.eq.'HTML') then
      help_mode = help_html
    elseif (tt_edit.eq.'SCROLL') then
      help_mode = help_scroll
    endif
  else
    help_mode = help_scroll
  endif
  call trap_ctrlc
  !
  ! Selects logical units for HELP and macros
  call sic_lunmac_init(error)
  if (error)  return
  sicext(1) = '.pro'
  lext(1) = 4
  do i=2,maxext
    lext(i) = 0
  enddo
  !
  ! Setup the symbol and variable tables
  call sic_inisymbol(error)
  if (error)  return
  call sic_inivariable
  call sic_inifunction
  ! Setup predefined symbols
  command = 'SIC'//backslash//'SYSTEM'
  call sic_setsymbol ('SHELL',command,error)
  command = 'SIC'//backslash//'end if'
  call sic_setsymbol ('ENDIF',command,error)
  call sic_setsymbol ('SIC'//backslash//'ENDIF',command,error)
  !
  i = 0
  cur_dir = ' '
  call sic_setdir(cur_dir,i,error)
  !
  sic_precis = 'DOUBLE'
  sicprecis = fmt_r8
  !
  ! Defines standard variables
  call sic_variables(error)
  if (error) call sic_message(seve%e,rname,'Error in variables definition')
  !
  ! Defines random functions
  call sic_def_func('GAUSSIAN1D',s_gaussian1d,d_gaussian1d,3,error,hlpfile='GAG_HELP_FUNC_SIC')
  call sic_def_func('NORMAL1D',s_normal1d,d_normal1d,3,error,hlpfile='GAG_HELP_FUNC_SIC')
  call sic_def_func('NOISE',s_noise,d_noise,1,error,hlpfile='GAG_HELP_FUNC_SIC')
  call sic_def_func('RANDOM',s_random,d_random,1,error,hlpfile='GAG_HELP_FUNC_SIC')
  if (error) call sic_message(seve%e,rname,'Error in function definition')
  !
  ! Define the default syntax
  name = 'FREE'
  ier = sic_getlog('GAG_SYNTAX',name)
  if (name.eq.'FIXED') then
    lsynt = 1
  else
    lsynt = 2
  endif
  !
  ! Define the default editor
  tt_edit = 'GAG_EDIT'
  ier = sic_getlog (tt_edit)
  !
  ! Activate X-Window mode if needed
  if (.not.inter_state)  sic_window = .false.
  !
  call search_clients(code)    ! Search for existing clients, launch keyboard
  if (code.eq.-1)  sic_window = .false.
  !
  ! These variables are already tested by gmaster. Just here for
  ! retrocompatibility with old programs.
  if (sic_window) then
    name = 'NONE'
    ier = sic_getlog('GAG_WIDGETS',name)
    sic_window = name.ne.'NONE'
  endif
  !
#ifndef WIN32
  if (sic_window) then
    name = ''
    ier = sic_getlog ('$DISPLAY',name)  ! sic_getenv???
    sic_window = ier.eq.0
  endif
#endif
  !
  if (sic_window) then
    ier = sic_getlog('SIC_TIMER',timer)  ! Hour units
    if (ier.eq.0)  call xgag_settimer(timer*3600)
  endif
  !
  if (edit_mode.and.inter_state .and. gmaster_get_ismaster().eq.1) then
    ! Start keyboard thread loop:
    !  - only if interactive mode (i.e. we need a prompt)
    !  - only if Gildas is master (if Gildas is slave, sic_python.c will
    !    start a keyboard by itself).
    call prompt_loop(code)
    if (code.eq.-1)  sic_window = .false.
  endif
  !
  if (sic_window) then
    call sic_message(seve%d,rname,'X-Window mode active')
    call sic_begin('GUI','GAG_HELP_GUI',-ngui,cgui,'1.2    10-Sep-2003',  &
      run_gui,err_gui)
  else
    call sic_message(seve%d,rname,'Normal keyboard mode')
  endif
  !
  call load_vector             ! Test
  call init_mfit
  call init_adjust
  !
  ! Remember the GAG_PROC: directory (to be sure to remove it, and not another one)
  ier = sic_getlog('GAG_PROC:',gag_proc)
  !
  ! Set default GILDAS Data format
  stbl = 2
  ier = sic_getlog('GILDAS_HEADERS',stbl)
  call gdf_stbl(stbl,error)
  !
end subroutine sic_build
!
subroutine make_gag_magic(gag_logical)
  use gildas_def
  use gbl_message
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>make_gag_magic
  use sic_structures
  !---------------------------------------------------------------------
  ! @ private
  ! Get a Gildas logical name and:
  !  1) append a magic (unique) number
  !  2) create the resulting directory
  !  3) update the value in the dictionnary
  ! Any error raised here is FATAL.
  !---------------------------------------------------------------------
  character(len=*), intent(in) :: gag_logical
  ! Local
  character(len=*), parameter :: rname='SIC'
  character(len=filename_length) :: message,file
  integer(kind=4) :: ier,ln,i,magicnum
  logical :: error
  character(len=message_length) :: mess
  !
  ! 1) Append a magic number
  call sic_parse_file(gag_logical,'','',message)
  ln = len_trim(message)+1
  if (ln.gt.len(message)-10) then
    write(mess,'(A,A,I0,A)')  &
      gag_logical,' translation longer than ',len(message),' characters'
    call sic_message(seve%f,rname,mess)
    call sysexi(fatale)
  endif
  magicnum = gag_getpid()
  write(message(ln:),'(I0)')  magicnum
  ln = len_trim(message)
  !
  ! 2) Create the directory, append a letter in case of error
  error = .false.
  call gag_mkdir(message(1:ln),error)
  i = 0
  do while (error)
    message(ln:ln) = char(i+ichar('A'))
    call gag_mkdir(message(1:ln),error)
    i = i+1
    if (i.gt.26) then
      call sic_message(seve%f,rname,'Cannot create '//gag_logical//' after 26 attempts')
      call sysexi(fatale)
    endif
  enddo
  !
  ! 3) Update the dictionnary value
  ln = ln+1
  message(ln:ln) = '/'
  ier = sic_setlog(gag_logical,message(1:ln))
  file = gag_logical
  ier = sic_getlog(file)
  !
end subroutine make_gag_magic
!
subroutine make_gag(logdir)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>make_gag
  use gildas_def
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! SIC   External routine
  !       Creates input directory if it does not exist. Input must be a
  !       symbolic name.
  ! Arguments :
  !       LOGDIR     C*(*)       Symbolic name      Input
  !---------------------------------------------------------------------
  character(len=*) :: logdir        !
  ! Local
  character(len=*), parameter :: rname='SIC'
  character(len=1), parameter :: backslash=char(92)
  character(len=filename_length) :: dir
  integer :: nl,nd
  logical :: exist,error
  !
  ! First, check if input in a symbolic name for a path (i.e. it ends
  ! with a ":")
  nl = len_trim(logdir)
  if (logdir(nl:nl).ne.':') then
    call sic_message(seve%e,rname,'"'//logdir(1:nl)//'" is not a symbolic '//  &
    'name')
    goto 100
  endif
  !
  ! Parse symbolic name
  call sic_parse_file(logdir,'','',dir)
  nd = len_trim(dir)
  if (dir(nd:nd).eq.'/'.or.dir(nd:nd).eq.backslash) nd=nd-1   ! Strip last slash as inquire does not like it!
  !
  ! Check if symbolic name was successfully parsed
  if (logdir(nl:nl).eq.dir(nd:nd)) then
    call sic_message(seve%e,rname,'Could not parse "'//logdir(1:nl)//'"')
    goto 100
  endif
  !
  ! Check if translation is empty
  if (dir(1:nd).eq.'') then
    call sic_message(seve%e,rname,'"'//logdir(1:nl)//'" is defined but provides empty translation')
    goto 100
  endif
  !
  ! Check if directory already exists
  inquire(file=dir(1:nd),exist=exist)
  if (.not.exist) then
    error = .false.
    call gag_mkpath(dir(1:nd),error)
    if (error) then
      call sic_message(seve%e,rname,'Cannot create directory "'//dir(1:nd)//'"')
      goto 100
    endif
  endif
  !
  ! Success
  return
  !
  ! Fatal error
100 call sic_message(seve%f,rname,'Cannot create "'//logdir(1:nl)//  &
        '" directory')
  call sysexi(fatale)
  !
end subroutine make_gag
!
subroutine sic_build_environment
  use sic_interfaces, except_this=>sic_build_environment
  !---------------------------------------------------------------------
  ! @ private
  ! SIC   External routine
  !       Set the log file
  !---------------------------------------------------------------------
  call make_gag("gag_gag:")
  call make_gag("gag_log:")
  call make_gag("gag_scratch:")
  call make_gag("gag_init:")
  call make_gag("gag_tmp:")
  call make_gag("gag_proc:")
  !
  ! Magic ones (unique per session)
  call make_gag_magic('GAG_SCRATCH:')
  call make_gag_magic('GAG_PROC:')
  !
end subroutine sic_build_environment
!
subroutine sic_variables(error)
  use sic_dependencies_interfaces
  use sic_interfaces
  use sic_define_status
  use sic_interactions
  use sic_python
  use sic_structures
  use yesnopi
  !$ use omp_lib
  !---------------------------------------------------------------------
  ! @ no-interface (problem with private module sic_define_status)
  !  Define SIC variables (i.e. Sic variables owned by the SIC package)
  !---------------------------------------------------------------------
  logical, intent(inout) :: error
  ! Local
  integer(kind=index_length) :: dims(sic_maxdims)
  character(len=12), save :: prognam
  character(len=20), save :: version,usernam,hostnam  ! Support variables
  integer :: ier, nt, ns
  !
  call sic_def_dble ('PI',pi,0,0,.true.,error)
  call sic_def_logi ('YES',yes,.true.,error)
  call sic_def_logi ('NO',no,.true.,error)
  call sic_def_real ('NAN',nan,0,0,.true.,error)
  call sic_def_inte ('TYPE_INTE',type_inte,0,0,.true.,error)
  call sic_def_inte ('TYPE_LONG',type_long,0,0,.true.,error)
  call sic_def_inte ('TYPE_REAL',type_real,0,0,.true.,error)
  call sic_def_inte ('TYPE_DBLE',type_dble,0,0,.true.,error)
  call sic_def_inte ('TYPE_LOGI',type_logi,0,0,.true.,error)
  !
  call sic_defstructure('SIC',.true.,error)
  call sic_def_logi ('SIC%VERIFY',lverif,.false.,error)
  call sic_def_logi ('SIC%EXIST',lexist,.true.,error)
  call sic_def_logi ('SIC%INTERACTIVE',inter_state,.true.,error)
  call sic_def_inte ('SIC%CHECK_MACRO',sic_stepin,0,0,.false.,error)
  call sic_def_logi ('SIC%DEFINE_STRICT',strict_define,.false.,error)
  call sic_def_char ('SIC%EDITOR',tt_edit,.true.,error)
  call sic_def_char ('SIC%DIRECTORY',cur_dir,.true.,error)
  call sic_def_char ('SIC%PRECISION',sic_precis,.true.,error)
  call sic_def_logi ('SIC%INITWINDOW',sic_initwindow,.false.,error)
  call sic_def_logi ('SIC%ERROR',sicvar_error,.true.,error)
  call sic_def_logi ('SIC%SYSTEMERROR',sicsystemerror,.false.,error)
  !
#if defined(WIN32)
  version = 'MS-Windows'
#else
  version = 'Generic-Unix'
#endif
  call sic_def_char ('SIC%VERSION',version,.true.,error)
  !
  ! Program name
  prognam = gprompt_master
  call sic_lower (prognam)
  call sic_def_char ('SIC%PROGRAM',prognam,.true.,error)
  !
  call sic_username(usernam)
  call sic_def_char ('SIC%USER',usernam,.true.,error)
  call sic_hostname(hostnam)
  call sic_def_char ('SIC%HOST',hostnam,.true.,error)
  !
  ! Define SIC%WINDOW in a protected mode if it could not be activated
  ! automatically. Allow the User to change the mode otherwise.
  if (sic_window) then
    call sic_def_logi ('SIC%WINDOW',sic_window,.false.,error)
  else
    call sic_def_logi ('SIC%WINDOW',sic_window,.true.,error)
  endif
  !
  ! Total RAM size (MB)
  call gag_ramsize(sic_ramsize)
  call sic_def_long ('SIC%RAMSIZE',sic_ramsize,0,0,.true.,error)
  !
  ! CPU caches size (kiB)
  dims(:) = 0
  dims(1) = 4
  call gag_cachesize(sic_cachel(1),sic_cachel(2),sic_cachel(3),sic_cachel(4))
  call sic_def_long ('SIC%CACHEL',sic_cachel,1,dims,.true.,error)
  if (error)  return
  !
  ! OpenMP
  call sic_defstructure('SIC%OPENMP',.true.,error)
  if (error) return
  sic_omp_compiled = .false.
  !$ sic_omp_compiled = .true.
  call sic_def_logi ('SIC%OPENMP%ACTIVE',sic_omp_compiled,.true.,error)
  if (error)  return
  sic_omp_ncores = 1
  call sic_def_inte ('SIC%OPENMP%NCORES',sic_omp_ncores,0,0,.true.,error)
  if (error)  return
  sic_omp_mthreads = 1
  call sic_def_inte ('SIC%OPENMP%MTHREADS',sic_omp_mthreads,0,0,.true.,error)
  if (error)  return
  sic_omp_nthreads = 1
  call sic_def_inte ('SIC%OPENMP%NTHREADS',sic_omp_nthreads,0,0,.true.,error)
  if (error)  return
  !
  !$ sic_omp_ncores = omp_get_num_procs()       ! Logical Cores in general
  !$ nt = 0
  !$ ier = sic_getlog('$OMP_NUM_THREADS',nt)
  !$ if (nt.ne.0) then
  !$    sic_omp_mthreads = min(nt,sic_omp_ncores)  ! Maximum reasonable number...
  !$ else
  !$    sic_omp_mthreads = sic_omp_ncores          ! Maximum 1 per logical core
  !$ endif
  !$ sic_omp_ncores = sic_omp_ncores/2             ! Assume Hyper Threading
  !$ ns = 0
  !$ ier = sic_getlog('$SLURM_CPUS_PER_TASK',ns)
  !$ if (ns.ne.0) sic_omp_mthreads = min(ns,sic_omp_mthreads)
  !$
  !$ sic_omp_nthreads = sic_omp_ncores             ! Default 1 per physical core
  !$ call omp_set_num_threads(sic_omp_nthreads)
  !
  ! Gildas-Python binding
  call sic_def_logi ('SIC%MASTER',gildas_ismaster,.true.,error)
  if (error)  return
  !
  call sic_variables_codes('SIC',error)
  if (error)  return
  !
  call sic_ansi_termcodes(error)
  if (error)  return
  !
end subroutine sic_variables
!
subroutine sic_variables_codes(parent,error)
  use gbl_constant
  use sic_interfaces, except_this=>sic_variables_codes
  !---------------------------------------------------------------------
  ! @ private
  !  Define SIC variables providing various codes
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: parent  ! Parent structure name
  logical,          intent(inout) :: error   ! Logical error flag
  ! Local
  character(len=32) :: str
  ! PROJECTION
  integer(kind=4), save :: sic_p_none=p_none
  integer(kind=4), save :: sic_p_gnomonic=p_gnomonic
  integer(kind=4), save :: sic_p_ortho=p_ortho
  integer(kind=4), save :: sic_p_azimuthal=p_azimuthal
  integer(kind=4), save :: sic_p_stereo=p_stereo
  integer(kind=4), save :: sic_p_lambert=p_lambert
  integer(kind=4), save :: sic_p_aitoff=p_aitoff
  integer(kind=4), save :: sic_p_radio=p_radio
  integer(kind=4), save :: sic_p_sfl=p_sfl
  integer(kind=4), save :: sic_p_mollweide=p_mollweide
  integer(kind=4), save :: sic_p_ncp=p_ncp
  integer(kind=4), save :: sic_p_cartesian=p_cartesian
  ! COORDINATES
  integer(kind=4), save :: sic_coord_un=type_un
  integer(kind=4), save :: sic_coord_eq=type_eq
  integer(kind=4), save :: sic_coord_ga=type_ga
  integer(kind=4), save :: sic_coord_ho=type_ho
  integer(kind=4), save :: sic_coord_ic=type_ic
  ! VELOCITY TYPES
  integer(kind=4), save :: sic_vel_unk=vel_unk
  integer(kind=4), save :: sic_vel_lsr=vel_lsr
  integer(kind=4), save :: sic_vel_hel=vel_hel
  integer(kind=4), save :: sic_vel_obs=vel_obs
  integer(kind=4), save :: sic_vel_ear=vel_ear
  integer(kind=4), save :: sic_vel_aut=vel_aut
  ! VELOCITY CONVENTIONS
  integer(kind=4), save :: sic_vconv_unk=vconv_unk
  integer(kind=4), save :: sic_vconv_rad=vconv_rad
  integer(kind=4), save :: sic_vconv_opt=vconv_opt
  integer(kind=4), save :: sic_vconv_30m=vconv_30m
  ! DATA KIND
  integer(kind=4), save :: sic_kind_spec=kind_spec
  integer(kind=4), save :: sic_kind_cont=kind_cont
  integer(kind=4), save :: sic_kind_sky=kind_sky
  integer(kind=4), save :: sic_kind_onoff=kind_onoff
  integer(kind=4), save :: sic_kind_focus=kind_focus
  ! X UNIT
  integer(kind=4), save :: sic_a_velo=a_velo
  integer(kind=4), save :: sic_a_freq=a_freq
  integer(kind=4), save :: sic_a_wave=a_wave
  ! SWITCH
  integer(kind=4), save :: sic_mod_unkn=mod_unk
  integer(kind=4), save :: sic_mod_freq=mod_freq
  integer(kind=4), save :: sic_mod_posi=mod_pos
  integer(kind=4), save :: sic_mod_fold=mod_fold
  integer(kind=4), save :: sic_mod_wobb=mod_wob
  integer(kind=4), save :: sic_mod_mixe=mod_mix
  !
  str = trim(parent)//'%CODE'
  call sic_defstructure(str,.true.,error)
  if (error) return
  !
  ! PROJECTION
  call sic_defstructure(trim(str)//'%PROJ',.true.,error)
  if (error) return
  call sic_def_inte(trim(str)//'%PROJ%NONE',     sic_p_none,     0,0,.true.,error)
  call sic_def_inte(trim(str)//'%PROJ%GNOMONIC', sic_p_gnomonic, 0,0,.true.,error)
  call sic_def_inte(trim(str)//'%PROJ%ORTHO',    sic_p_ortho,    0,0,.true.,error)
  call sic_def_inte(trim(str)//'%PROJ%AZIMUTHAL',sic_p_azimuthal,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%PROJ%STEREO',   sic_p_stereo,   0,0,.true.,error)
  call sic_def_inte(trim(str)//'%PROJ%LAMBERT',  sic_p_lambert,  0,0,.true.,error)
  call sic_def_inte(trim(str)//'%PROJ%AITOFF',   sic_p_aitoff,   0,0,.true.,error)
  call sic_def_inte(trim(str)//'%PROJ%RADIO',    sic_p_radio,    0,0,.true.,error)
  call sic_def_inte(trim(str)//'%PROJ%SFL',      sic_p_sfl,      0,0,.true.,error)
  call sic_def_inte(trim(str)//'%PROJ%MOLLWEIDE',sic_p_mollweide,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%PROJ%NCP',      sic_p_ncp,      0,0,.true.,error)
  call sic_def_inte(trim(str)//'%PROJ%CARTESIAN',sic_p_cartesian,0,0,.true.,error)
  if (error)  return
  !
  ! COORDINATES
  call sic_defstructure(trim(str)//'%COORD',.true.,error)
  if (error) return
  call sic_def_inte(trim(str)//'%COORD%UNK', sic_coord_un,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%COORD%EQU', sic_coord_eq,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%COORD%GAL', sic_coord_ga,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%COORD%HOR', sic_coord_ho,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%COORD%ICRS',sic_coord_ic,0,0,.true.,error)
  if (error)  return
  !
  ! VELOCITY TYPES
  call sic_defstructure(trim(str)//'%VELO',.true.,error)
  if (error) return
  call sic_def_inte(trim(str)//'%VELO%UNK',  sic_vel_unk,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%VELO%LSR',  sic_vel_lsr,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%VELO%HELIO',sic_vel_hel,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%VELO%OBS',  sic_vel_obs,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%VELO%EARTH',sic_vel_ear,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%VELO%AUTO', sic_vel_aut,0,0,.true.,error)
  if (error)  return
  !
  ! VELOCITY CONVENTION
  call sic_defstructure(trim(str)//'%CONV',.true.,error)
  if (error) return
  call sic_def_inte(trim(str)//'%CONV%UNK',sic_vconv_unk,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%CONV%RAD',sic_vconv_rad,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%CONV%OPT',sic_vconv_opt,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%CONV%30M',sic_vconv_30m,0,0,.true.,error)
  !
  ! DATA KIND
  call sic_defstructure(trim(str)//'%KIND',.true.,error)
  if (error) return
  call sic_def_inte(trim(str)//'%KIND%SPEC', sic_kind_spec, 0,0,.true.,error)
  call sic_def_inte(trim(str)//'%KIND%CONT', sic_kind_cont, 0,0,.true.,error)
  call sic_def_inte(trim(str)//'%KIND%SKY',  sic_kind_sky,  0,0,.true.,error)
  call sic_def_inte(trim(str)//'%KIND%ONOFF',sic_kind_onoff,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%KIND%FOCUS',sic_kind_focus,0,0,.true.,error)
  if (error)  return
  !
  ! X UNIT
  call sic_defstructure(trim(str)//'%XUNIT',.true.,error)
  if (error) return
  call sic_def_inte(trim(str)//'%XUNIT%VELO',sic_a_velo,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%XUNIT%FREQ',sic_a_freq,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%XUNIT%WAVE',sic_a_wave,0,0,.true.,error)
  if (error)  return
  !
  ! SWITCH
  call sic_defstructure(trim(str)//'%SWITCH',.true.,error)
  if (error) return
  call sic_def_inte(trim(str)//'%SWITCH%UNKNOWN',sic_mod_unkn,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%SWITCH%FREQ',   sic_mod_freq,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%SWITCH%POSI',   sic_mod_posi,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%SWITCH%FOLD',   sic_mod_fold,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%SWITCH%WOBBLER',sic_mod_wobb,0,0,.true.,error)
  call sic_def_inte(trim(str)//'%SWITCH%MIXED',  sic_mod_mixe,0,0,.true.,error)
  if (error)  return
  !
end subroutine sic_variables_codes
!
subroutine sic_ansi_termcodes(error)
  use sic_interfaces, except_this=>sic_ansi_termcodes
  use gbl_ansicodes
  !---------------------------------------------------------------------
  ! @ private
  ! Define and populate the ANSI% structure
  !---------------------------------------------------------------------
  logical, intent(inout) :: error
  ! Support variables for the ANSI% variables
  character(len=5), save :: sic_ansi_black=c_black
  character(len=5), save :: sic_ansi_red=c_red
  character(len=5), save :: sic_ansi_green=c_green
  character(len=5), save :: sic_ansi_yellow=c_yellow
  character(len=11), save :: sic_ansi_orange=c_orange
  character(len=5), save :: sic_ansi_blue=c_blue
  character(len=5), save :: sic_ansi_magenta=c_magenta
  character(len=5), save :: sic_ansi_cyan=c_cyan
  character(len=5), save :: sic_ansi_white=c_white
  character(len=4), save :: sic_ansi_clear=c_clear
  character(len=4), save :: sic_ansi_bold=c_bold
  character(len=4), save :: sic_ansi_under=c_under
  character(len=4), save :: sic_ansi_reverse=c_reverse
  character(len=4), save :: sic_ansi_blink=c_blink
  !
  call sic_defstructure('ANSI',.true.,error)
  if (error)  return
  call sic_def_char('ANSI%RED',sic_ansi_red,.true.,error)
  call sic_def_char('ANSI%GREEN',sic_ansi_green,.true.,error)
  call sic_def_char('ANSI%YELLOW',sic_ansi_yellow,.true.,error)
  call sic_def_char('ANSI%ORANGE',sic_ansi_orange,.true.,error)
  call sic_def_char('ANSI%BLUE',sic_ansi_blue,.true.,error)
  call sic_def_char('ANSI%MAGENTA',sic_ansi_magenta,.true.,error)
  call sic_def_char('ANSI%CYAN',sic_ansi_cyan,.true.,error)
  call sic_def_char('ANSI%WHITE',sic_ansi_white,.true.,error)
  call sic_def_char('ANSI%BLACK',sic_ansi_black,.true.,error)
  call sic_def_char('ANSI%NONE',sic_ansi_clear,.true.,error)
  call sic_def_char('ANSI%BOLD',sic_ansi_bold,.true.,error)
  call sic_def_char('ANSI%UNDERLINE',sic_ansi_under,.true.,error)
  call sic_def_char('ANSI%REVERSE',sic_ansi_reverse,.true.,error)
  call sic_def_char('ANSI%BLINK',sic_ansi_blink,.true.,error)
  ! Clear is duplicated under %ZERO so that it comes last when
  ! typing EXA ANSI. This leaves the terminal in default mode.
  call sic_def_char('ANSI%ZERO',sic_ansi_clear,.true.,error)
  if (error)  return
  !
end subroutine sic_ansi_termcodes
