#!/bin/sh
# the next line restarts using wish \
exec tclsh "$0" "$@"

source [ file join $env(TCLTOOLS_HOME) TclToolInits.tcl ]
TclToolInits UTILS UDF UDFDB
                                                                                
# RETURNS
#  1  OK
#  0  No data for this field
# -1  Bad field name
# -2  0 or less data values requested
# -3  beg offset larger than number of values
# -4  end offset larger than number of values

proc PreCheck { Tbl Blk } {
   global VFields  VSize VDeps VIDF GenOffsets TblOffsets ByTe_4 ByTe_2

   if { $Tbl == 0 } { 
      set Pos [lsearch -exact $VFields PADEFINED]
      binary scan $GenOffsets @[expr 4 * $Pos]$ByTe_4 Offset
      binary scan $VIDF @${Offset}c1 Var

      if { $Var > 0 } {
         set VDeps(PABXBYBZ) 3
         set VDeps(PATBLS) PAAPPS
         set VDeps(PAOPS) PAAPPS
      }
   } else {
      set TLoc [lsearch -exact $VFields TBLSCASZ]
      set CLoc [lsearch -exact $VFields CONSTID]
      set Loc [lsearch -exact $VFields CRITACTSZ]
      set InDx [expr ($CLoc - $TLoc) * $Blk + $Loc - $TLoc]
      binary scan $TblOffsets @[expr 4 * $InDx]$ByTe_4 Off
      set FmT @${Off}c1
      binary scan $VIDF $FmT Var
      if { $Var > 0 } {
         set VDeps(CRITSTATUS) SEN
         set VDeps(CRITOFF) SEN
      }
   }
}

proc VIDFField { Field Blk Beg End vN} {
   global VFields VSize VDeps VIDF GenOffsets TblOffsets ConOffsets \
          ByTe_4 ByTe_2

   upvar $vN Var
   set TLoc [lsearch -exact $VFields TBLSCASZ]
   set CLoc [lsearch -exact $VFields CONSTID]
   set Loc [lsearch -exact $VFields $Field]
   set ELoc [llength $VFields]
   if { $Loc < 0 } { return -1 }                      

   if {$Loc < $TLoc } {
      set Area 0
   } elseif {$Loc < $CLoc } {
      set Area 1
      PreCheck 1 $Blk
   } else { set Area 2 }

   set Dep $VDeps($Field)
   set Sz  $VSize($Field)

   if { [scan $Dep {%[0-9]} TmP] == 0 } {
      set NSz  $VSize($Dep)
      set NLoc [lsearch -exact $VFields $Dep]
      if {$NLoc < $TLoc } {
         binary scan $GenOffsets @[expr 4 * $NLoc]$ByTe_4 NOff
      } else {
         set InDx [expr ($CLoc - $TLoc) * $Blk + $NLoc - $TLoc]
         binary scan $TblOffsets @[expr 4 * $InDx]$ByTe_4 NOff
      }

      switch -exact -- $NSz {
         1        {  set NFmT @${NOff}c }
         2        {  set NFmT @${NOff}$ByTe_2 }
         4        {  set NFmT @${NOff}$ByTe_4 }
      }
      binary scan $VIDF $NFmT Dep

      if { $Dep <= 0 } { return 0 }                      
   }

   if { $End < 0 } { set End $Dep }
   set N [expr $End - $Beg + 1]

   if { $N <= 0 } { return -2 } 
   if { $Beg >= $Dep } { return -3 } 
   if { $End >= $Dep } { return -4 } 

   set InDx 0
   if { $Area == 0 } {
      binary scan $GenOffsets @[expr 4 * $Loc]$ByTe_4 Offset
      set Off [expr $Offset + $Sz * $Beg]
   }  elseif { $Area == 1 } {
      set InDx [expr ($CLoc - $TLoc) * $Blk + $Loc - $TLoc]
      binary scan $TblOffsets @[expr 4 * $InDx]$ByTe_4 Offset
      set Off [expr $Offset + $Sz * $Beg]
   }  elseif { $Area == 2 } {
      set InDx [expr ($ELoc - $CLoc) * $Blk + $Loc - $CLoc]
      binary scan $ConOffsets @[expr 4 * $InDx]$ByTe_4 Offset
      set Off [expr $Offset + $Sz * $Beg]
   }

   switch -exact -- $Sz {
      1        {  set FmT @${Off}c$N }
      2        {  set FmT @${Off}$ByTe_2$N }
      4        {  set FmT @${Off}$ByTe_2$N }
      default  {  set FmT @${Off}A$Sz }
   }

   binary scan $VIDF $FmT Var

   if { $Area == 1 } {
      set VDeps(CRITSTATUS) SEN
      set VDeps(CRITOFF)    SEN
   }
   return 1
}

proc PrField { Field Title Blk Fmt OnLine } {
   global VFields  VSize VDeps VIDF errorInfo ByTe_4 ByTe_2

   set TLoc [lsearch -exact $VFields TBLSCASZ]
   set CLoc [lsearch -exact $VFields CONSTID]
   set Loc [lsearch -exact $VFields $Field]
   if { ($Loc >= $TLoc) && ($Loc < $CLoc) } { PreCheck 1 $Blk }

   set Dep $VDeps($Field)
   if { [scan $Dep {%[0-9]} TmP] == 0 } {
       VIDFField $Dep $Blk 0 0 Dep
   } 

   if { $Loc >= $TLoc } {
      set VDeps(CRITSTATUS) CRITACTSZ
      set VDeps(CRITOFF) CRITACTSZ
   }

   for { set I 0 } { $I < $Dep } { incr I } {
      catch { VIDFField $Field $Blk $I $I Var} Res
      if { $Res == 1 } {
          if {[expr $I % $OnLine] == 0} {
             if {$I != 0} { puts stderr "" }
             puts -nonewline stderr "$Title [format $Fmt $Var]"
          } else {
             puts -nonewline stderr [format $Fmt $Var]
          }
      } 
   }
   if { $Dep > 0 } { puts stderr "" }
}

# ...........................................................................
#
#                                THE MAIN EVENT
#
#  Here starts the VIDF read and regurgitate
#
# ...........................................................................


set ALen [llength $argv]
if { $ALen == 1 } {
   set VFile [lindex $argv 0]
} else {
   set P [lindex $argv 0]
   set M [lindex $argv 1]
   set E [lindex $argv 2]
   set I [lindex $argv 3]
   set V [lindex $argv 4]
   if { $ALen > 5 } {
     set bY [lindex $argv 5]
     set eY $bY
     set bD [lindex $argv 6]
     set eD $bD
     if { $ALen == 10 } {
        set Ms [expr 3600000 * [lindex $argv 7] + \
                          60000 * [lindex $argv 8] + 1000 *  [lindex $argv 9]]
     } else { set Ms [ expr [lindex $argv 7]] }

     set dMs [expr $Ms + 2000]  
     if { $dMs > 86400000 } {
         set bMs [expr $Ms - 2000] ; set eMs $Ms
     } else { set bMs $Ms ; set eMs $dMs }
   } else {
     set bY 1900 ; set eY 3000
     set bD 1 ; set eD 1
     set bMs 0 ; set eMs 0
   }


   set KeY [GetDataKey $P $M $E $I $V]
   set vList [DBgetEntries $KeY $bY $bD $bMs $eY $eD $eMs I]
   set VFile [file join $UDFPaths(2) [lindex [lindex $vList 0] 0]I]
}

set CurOffset 0
set GenOffsets 0
set TblOffsets 0
set ConOffsets 0

UDFvidfInfo
if [string match littleEndian $tcl_platform(byteOrder)] {
   set ByTe_2 s
   set ByTe_4 i
} else {
   set ByTe_2 S
   set ByTe_4 I
}

set fd [open $VFile]

fconfigure $fd -translation binary
set VIDF [read $fd 8]
set Version [string trimright $VIDF \0]
set VIDF [read $fd 4]
binary scan $VIDF $ByTe_4 GLen
set GenOffsets [read $fd $GLen]
set VIDF [read $fd 8]
binary scan $VIDF $ByTe_4$ByTe_4 NTbl TLen
set TblOffsets [read $fd $TLen]
set VIDF [read $fd 8]
binary scan $VIDF $ByTe_4$ByTe_4 NConst CLen
set ConOffsets [read $fd $CLen]
set VIDF [read $fd 4]
binary scan $VIDF $ByTe_4 Fsize
set VIDF [read $fd]

PreCheck 0 0

puts stderr "VIDF $VFile (version $Version)" 
puts stderr "" 
PrField PROJECT     "PROJECT   :" 0 "%s"  1 
PrField MISSION     "MISSION   :" 0 "%s"  1 
PrField EXPDESC     "EXPDESC   :" 0 "%s"  1 
PrField INSTDESC    "INSTDESC  :" 0 "%s"  1 
PrField COMMENTS    "COMMENT   :" 0 "%s"  1 
PrField DSYEAR      "DSYEAR    :" 0 "%7d" 1 
PrField DSDAY       "DSDAY     :" 0 "%7d" 1
PrField DSMSEC      "DSMSEC    :" 0 "%7d" 1
PrField DSUSEC      "DSUSEC    :" 0 "%7d" 1
PrField DEYEAR      "DEYEAR    :" 0 "%7d" 1
PrField DEDAY       "DEDAY     :" 0 "%7d" 1
PrField DEMSEC      "DEMSEC    :" 0 "%7d" 1
PrField DEUSEC      "DEUSEC    :" 0 "%7d" 1
PrField SMPID       "SMPID     :" 0 "%7d" 1
PrField SENMODE     "SENMODE   :" 0 "%7d" 1
PrField NUMQUAL     "NUMQUAL   :" 0 "%7d" 1
PrField CALSETS     "CALSETS   :" 0 "%7d" 1
PrField NUMTBLS     "NUMTBLS   :" 0 "%7d" 1
PrField NUMCONSTS   "NUMCONSTS :" 0 "%7d" 1
PrField STATUS      "NUM STATUS:" 0 "%7d" 1
PrField PADEFINED   "PADEFINED :" 0 "%7d" 1
PrField SEN         "NUM SEN   :" 0 "%7d" 1
PrField SWPLEN      "SWPLEN    :" 0 "%7d" 1
PrField MAXNSS      "MAXNSS    :" 0 "%7d" 1
PrField DATALEN     "DATALEN   :" 0 "%7d" 1
PrField FILLFLAG    "FILLFLAG  :" 0 "%7d" 1
PrField FILL        "FILL      :" 0 "%7d" 1
PrField DAMETHOD    "DAMETHOD  :" 0 "%7d" 1
PrField STATUSNAME  "STATUS NM :" 0 "%s"  1
PrField STATES      "STATUS LEN:" 0 "%7d" 10
PrField SENNAME     "SEN NAME  :" 0 "%s" 1
PrField CALNAMES    "ANC NAME  :" 0 "%s" 1
PrField QUALNAME    "QUAL NAME :" 0 "%s" 1
PrField PAFORMAT    "PAFORMAT  :" 0 "%7d" 1
PrField PAPROJECT   "PAPROJECT :" 0 "%s" 1
PrField PAMISSION   "PAMISSION :" 0 "%s" 1
PrField PAEXPER     "PAEXPER   :" 0 "%s" 1
PrField PAINST      "PAINST    :" 0 "%s" 1
PrField PAVINST     "PAVINST   :" 0 "%s" 1
PrField PABXBYBZ    "PABXBYBZ  :" 0 "%7d" 3
PrField PATBLS      "PATBLS    :" 0 "%7d" 10
PrField PAOPS       "PAOPS     :" 0 "%7d" 10
PrField DATATYPE    "DATATYPE  :" 0 "%7d" 10
PrField TDWLEN      "TDWLEN    :" 0 "%7d" 10
PrField SENSTATUS   "SENSTATUS :" 0 "%7d" 10
PrField TIMEOFF     "TIMEOFF   :" 0 "%7d" 10
PrField CALUSE      "CAL_USE   :" 0 "%7d" 10
PrField CALWLEN     "CAL_WLEN  :" 0 "%7d" 10
PrField CALTARGET   "CALTARGET :" 0 "%7d" 10 

VIDFField NUMTBLS 0 0 0 nT
for { set I 0 } { $I < $nT} { incr I } {
   puts stderr ""
   puts stderr "INFORMATION FOR TABLE $I"
   puts stderr ""
   PrField TBLSCASZ    "TBLSCASZ  :" $I "%7d" 1 
   PrField TBLELESZ    "TBLELESZ  :" $I "%7d" 1 
   PrField TBLTYPE     "TBLTYPE   :" $I "%7d" 1 
   PrField TBLDESC     "TBLDESC   :" $I "%s"  1 
   PrField TBLVAR      "TBLVAR    :" $I "%7d" 1 
   PrField TBLEXPAND   "TBLEXPAND :" $I "%7d" 1 
   PrField CRITACTSZ   "CRITACTSZ :" $I "%7d" 1 
   PrField CRITSTATUS  "CRITSTATUS:" $I "%7d" 8
   PrField CRITOFF     "CRITOFF   :" $I "%7d" 8
   PrField CRITACTION  "CRITACTION:" $I "%7d" 8
   PrField TBLFMT      "TBLFMT    :" $I "%7d" 8
   PrField TBLOFF      "TBLOFF    :" $I "%7d" 8
   PrField TBLSCA      "TBLSCA    :" $I "%13d" 5
   PrField TBL         "TBL       :" $I "%13d" 5
}

VIDFField NUMCONSTS 0 0 0 nC
for { set I 0 } { $I < $nC} { incr I } {
   puts stderr ""
   puts stderr "INFORMATION FOR CONSTANT $I"
   puts stderr ""
   PrField CONSTID     "CONSTID   :" $I "%7d" 1 
   PrField CONSTDESC   "CONSTDESC :" $I "%s"  1 
   PrField CONSTSCA    "CONSTSCA  :" $I "%13d" 5
   PrField CONST       "CONST     :" $I "%13d" 5
}

