subroutine robs(obs,entry_num,error)
  use classcore_dependencies_interfaces
  use classcore_interfaces, except_this=>robs
  use class_common
  use class_index
  !----------------------------------------------------------------------
  ! @ private
  !  Read file header into internal buffer. Then fill into the
  ! observation header the presec section and part of the general
  ! sections, namely the elements coming from the Entry Index:
  !     obs%head%gen%num
  !     obs%head%gen%ver
  !     obs%head%pos%sourc
  !     obs%head%spe%line/obs%head%sky%line
  !     obs%head%gen%teles
  !     obs%head%gen%dobs
  !     obs%head%gen%dred
  !     obs%head%pos%lamof
  !     obs%head%pos%betof
  !     obs%head%pos%system
  !     obs%head%gen%kind
  !     obs%head%gen%qual
  !     obs%head%gen%scan
  !     obs%head%dri%apos
  !     obs%head%gen%subscan
  !----------------------------------------------------------------------
  type(observation),          intent(inout) :: obs        ! Observation header
  integer(kind=entry_length), intent(in)    :: entry_num  ! Index number of observation
  logical,                    intent(out)   :: error      !
  ! Local
  type(indx_t) :: ind
  !
  outobs_modify = .false.
  error = .false.
  !
  ! Read the Entry Title, transfer it in observation
  call rix(entry_num,ind,error)
  if (error) return
  call index_toobs(ind,obs%head,error)
  if (error)  return
  obs%head%gen%ver = abs(obs%head%gen%ver)
  !
  if (filein_isvlm) then
    ! Mimic the entry descriptor
    obs%desc%xnum = entry_num
    obs%desc%ldata = filein_vlmhead%gil%dim(1)
    !
    ! Fill obs%head%presec(:) for VLM
    obs%head%presec(:) = .false.
    obs%head%presec(class_sec_gen_id) = .true.
    obs%head%presec(class_sec_pos_id) = .true.
    obs%head%presec(class_sec_spe_id) = .true.
    obs%head%presec(class_sec_res_id) = filein_vlmhead%gil%reso_words.gt.0
    !
  else
    ! Read the Entry Descriptor
    call class_entrydesc_read('ROBS',filein,ix,entry_num,obs%desc,ibufobs,error)
    if (error)  return
    !
    ! Fill obs%head%presec(:)
    call classic_entrydesc_secfind_all(obs%desc,obs%head%presec,-mx_sec,error)
    if (error)  return
  endif
  !
end subroutine robs
!
subroutine class_entrydesc_read(rname,file,idx,entry_num,ed,bufobs,error)
  use gbl_message
  use classic_api
  use classcore_dependencies_interfaces
  use classcore_interfaces, except_this=>class_entrydesc_read
  use class_types
  !---------------------------------------------------------------------
  ! @ private
  !  Read the entry descriptor. Class overlay to the Classic subroutine
  !---------------------------------------------------------------------
  character(len=*),           intent(in)    :: rname      ! Calling routine name
  type(classic_file_t),       intent(in)    :: file       ! Class file
  type(optimize),             intent(in)    :: idx        ! Associated index
  integer(kind=entry_length), intent(in)    :: entry_num  ! Entry number
  type(classic_entrydesc_t),  intent(out)   :: ed         ! Entry descriptor
  type(classic_recordbuf_t),  intent(inout) :: bufobs     ! Working buffer
  logical,                    intent(inout) :: error      ! Logical error flag
  ! Local
  character(len=message_length) :: mess
  integer(kind=4) :: ier,vobs_allowed
  !
  if (entry_num.le.0 .or. entry_num.ge.file%desc%xnext) then
    error = .true.
    write(mess,'(A,I0)') 'Non-existant index entry ',entry_num
    call class_message(seve%e,rname,mess)
    return
  endif
  !
  call classic_recordbuf_open(file,idx%bloc(entry_num),idx%word(entry_num),  &
    bufobs,error)
  if (error)  return
  !
  call classic_entrydesc_read(file,bufobs,ed,error)
  if (error)  return
  !
  if (file%desc%version.ne.1 .and. ed%xnum.ne.entry_num) then
    ! Check that xnum in entry descriptor is consistant with the requested
    ! entry number. NB: this has never been checked in V1 files, avoid
    ! rejecting V1 files which were accepted before.
    ! Should we have a way to enforce reading?
    write(mess,'(A,I0,A,I0)')  'Entry number mismatch (malformed file): got ',  &
      ed%xnum,' in entry descriptor, expected ',entry_num
    call class_message(seve%e,rname,mess)
    error = .true.
    return
  endif
  !
  vobs_allowed = vobs_stable
  ier = sic_getlog('CLASS_OBS_VERSION',vobs_allowed)
  if (ed%version.gt.vobs_allowed) then
    write (mess,'(A,I0,A)')  &
      'Observation revision number #',ed%version,' not supported'
    call class_message(seve%e,rname,mess)
    call class_message(seve%e,rname,'Your CLASS version is too old to read this spectrum')
    call class_message(seve%e,rname,'Please update CLASS to the latest release')
    error = .true.
    return
  endif
  !
end subroutine class_entrydesc_read
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
subroutine mobs(obs,error)
  use gbl_message
  use classcore_dependencies_interfaces
  use classcore_interfaces, except_this=>mobs
  use class_types
  use class_common
  use class_index
  !---------------------------------------------------------------------
  ! @ private
  !  Open an observation of the output file to modify it. The length of
  ! each section modified must be smaller than the length of the
  ! corresponding section already present.
  !  Find the latest version of this obs. in this file
  !---------------------------------------------------------------------
  type(observation), intent(inout) :: obs    ! Observation header
  logical,           intent(out)   :: error  ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='MOBS'
  integer(kind=entry_length) :: ifind(10),nf
  !
  if (obs%head%gen%ver.lt.0) then
     call class_message(seve%e,'UPDATE','Can only update last versions')
     error = .true.
     return
  endif
  !
  error = .false.
  !
  call fox(obs%head%gen%num,ifind(1))
  nf = ifind(1)
  if (nf.eq.0) then
     error = .true.
     call class_message(seve%e,rname,'Observation to be modified was not found')
     return
  endif
  !
  ! Read the Entry Descriptor
  call class_entrydesc_read(rname,fileout,ox,ifind(1),obs%desc,obufobs,error)
  if (error)  return
  !
  outobs_modify = .true.
end subroutine mobs
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
subroutine cobs(set,obs,error)
  use gildas_def
  use gbl_constant
  use gbl_message
  use classcore_dependencies_interfaces
  use classcore_interfaces, except_this=>cobs
  use class_common
  use class_index
  use class_types
  !----------------------------------------------------------------------
  ! @ private
  !  Ends the writing of the output observation.
  !  Find the latest version of this observation in the file and
  ! decrease its version number by 32768
  !----------------------------------------------------------------------
  type(class_setup_t), intent(in)    :: set    !
  type(observation),   intent(inout) :: obs    ! Observation header
  logical,             intent(out)   :: error  ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='COBS'
  integer(kind=entry_length) :: ifind(10),nf
  integer(kind=4) :: hver
  character(len=80) :: mess
  type(indx_t) :: ind
  logical :: dupl
  !
  if (obufobs%lun.ne.fileout%lun) then
     error = .true.
     call class_message(seve%e,rname,'Observation not open for write nor modify')
     return
  endif
  !
  if (.not.outobs_modify) then
     if (obs%head%gen%num.lt.0) then
        write(mess,'(A,I0)')  'Invalid observation number ',obs%head%gen%num
        call class_message(seve%e,rname,mess)
        error = .true.
        return
        !
     elseif (obs%head%gen%num.eq.0) then
        ! No specified number, use automatic numbering. Find next one (unused
        ! yet) available.
        call fox_next(obs%head%gen%num)
        !
     elseif (fileout%desc%single) then
        ! ObsNumber must be unique. Find if it is already used
        call fox(obs%head%gen%num,ifind(1))
        if (ifind(1).ne.0) then
          write(mess,'(A,I0,A)') 'Observation #',obs%head%gen%num,' already exists'
          call class_message(seve%e,rname,mess)
          error = .true.
          return
        endif
        !
     else
        ! Multiple versions allowed
        call fox(obs%head%gen%num,ifind(1))
        nf = ifind(1)
        if (nf.ne.0) then
           ! Found a previous observation with the same number
           hver = ox%ver(ifind(1))
           if (hver.gt.0) ox%ver(ifind(1)) = -hver  ! Mark it as "old" if it exists
           call rox(ifind(1),ind,error)
           if (error) return
           ind%ver = ox%ver(ifind(1))
           call mox(ifind(1),ind,error)
           if (hver.lt.0) hver = -hver
           if (error) return
           obs%head%gen%ver = hver
        endif
     endif
     obs%head%gen%ver = abs(obs%head%gen%ver)+1  ! The version number must
       ! increase: each WRITE assumes a difference between the original spectrum
       ! and the one written. Do not reset the number to avoid losing history.
  endif
  !
  ! Set up the Index 'ind'
  call sic_gagdate(obs%head%gen%dred)
  !
  call index_fromobs(obs%head,ind,error)
  if (error)  return
  ind%bloc = obufobs%rstart
  ind%word = obufobs%wstart
  !
  ! Write the Index entry
  if (outobs_modify) then
     call mox(obs%desc%xnum,ind,error)
     ! if (error)... we should have ensured that obufobs is flushed to
     ! the file, else we would have an entry partially updated i.e.
     ! inconsistent. But how can we have an error in mox and not before?
     ! Should never happen.
     if (error)  &
       call class_message(seve%e,rname,'Observation may be incompletely updated')
  else
     call wox(ind,error)
     ! if (error)... not so dramatic since as long the entry index and
     ! the file descriptor are not written/updated, the entry has no
     ! real existence.
     if (.not.error) then
       ! Take care of the sorting arrays
       call ox_sort_add(set,obs,dupl,error)
       if (dupl) then
         ! Undo what WOX has done
         fileout%desc%xnext = fileout%desc%xnext-1
         ox%next = ox%next-1
         if (filein_is_fileout())  ix%next = ix%next-1
       endif
     endif
  endif
  if (error) return
  !
  ! Write the observation header. Must be last since it contains the
  ! observation description e.g. number of blocks.
  if (obs%desc%version.gt.vobs_stable) then
    write (mess,'(A,I0,A)')  &
      'Observation revision number #',obs%desc%version,' is experimental'
    call class_message(seve%w,rname,mess)
  endif
  call classic_entrydesc_write(fileout,obufobs,obs%desc,error)
  if (error)  return
  !
  call classic_entry_close(fileout,obufobs,error)
  if (error)  return
  !
  ! FILE BOTH case
  if (filein_is_fileout()) then
    ! Must force "forgetting" the record currently buffered in ibufobs,
    ! because the same record may have changed on disk
    call classic_recordbuf_nullify(ibufobs)
  endif
  !
  ! Update the file header
  call cox(error)
  !
end subroutine cobs
