#!/bin/sh
# -*- tcl -*- \
exec tclsh "$0" ${1+"$@"}
# Collect Size STATisticS for all known builds into a single report
# ========================================================================
package require struct
package require report
cd [file join [file dirname [info script]] ..]
set origin [pwd]
::report::defstyle html {} {
    set c  [columns]
    set cl $c ; incr cl -1
    data set "
 [split [string repeat " " $cl] ""] 
"
    for {set col 0} {$col < $c} {incr col} {
	pad $col left  ""
	pad $col right ""
    }
    return
}
proc showmat {m} {
    puts   m/c=[set ::struct::matrix::matrix${m}::columns]
    puts   m/r=[set ::struct::matrix::matrix${m}::rows]
    parray ::struct::matrix::matrix${m}::data
}
proc percent {m idx} {
    set vec [$m get column $idx]
    #puts $vec
    set res [list "[lindex $vec 0] %"]
    set base [lindex $vec 1]
    foreach v [lrange $vec 1 end] {
	lappend res [format %.2f [expr {($v*100.0)/$base}]]
	
    }
    $m add column $res
}
proc dpercent {m idx} {
    set vec [$m get column $idx]
    #puts $vec
    set res [list "[lindex $vec 0] d%"]
    set base [lindex $vec 1]
    foreach v [lrange $vec 1 end] {
	lappend res [format %.2f [expr {100.0 - ($v*100.0)/$base}]]
    }
    return $res
}
proc percentage {title vect} {
    set res [list $title]
    set base [lindex $vect 1]
    foreach v [lrange $vect 1 end] {
	lappend res [format %.2f [expr {($v*100.0)/$base}]]
    }
    return $res
}
# ========================================================================
cd work/data
puts stderr "$argv0 ... Collecting work /libraries"
set here [pwd]
array set stats {}
array set objs  {}
array set dirs  {}
foreach dir [glob -nocomplain *] {
    if {![file exists [file join $dir static.size]]} {
	continue
    }
    puts stderr "* $dir ..."
    cd $dir
    set config [exec grep config= [file join .. .. build $dir cdrive.cfg] | sed -e {s/config=//}]
    #set data [file join [pwd] ../../data/$dir]
    #cd $data
    set dirs($dir)    $config
    set s [open static.size r]
    set data [read $s]
    close $s
    foreach line [split $data \n] {
	foreach {size object} [split [string trim $line]] break
	if {[string match *stub* $object]} {continue}
	set stats($dir,$object)	 $size
	set objs($object) .
	#puts "\t$dir,$object	 $size"
    }
    cd $here
}
# Transform stats into a nice matrix.
# Rows:    Configurations
# Columns: Objects
set on [array size objs]    ; incr on
set cn [array size dirs]    ; incr cn
set objlist [lsort [array names objs]]
set cfglist [lsort [array names dirs]]
set speclist [list {ENV_FLAGS}]
foreach cfg $cfglist {
    lappend speclist $dirs($cfg)
}
## puts "#objects = $on ($objlist)"
## puts "#configs = $cn ($cfglist)"
set ctitle [linsert $objlist 0 {}]
set rtitle [linsert $cfglist 0 {}]
struct::matrix lib
lib add columns $on
lib add rows    $cn
lib set row    0 $ctitle
lib set column 0 $rtitle
set r 1
foreach cfg $cfglist {
    set c 1
    foreach obj $objlist {
	lib set cell $c $r $stats($cfg,$obj)
	incr c
    }
    incr r
}
lib delete column 1 ; # bin/tclsh not relevant
lib add column [percent  lib 1]
lib add column [dpercent lib 1]
lib add column $speclist
lib set rect 0 1 [lsort -decr -index 1 [lib get rect 0 1 end end]]
# ========================================================================
unset stats ; unset objs ; unset dirs
cd $origin
cd work/build
puts stderr "$argv0 ... Collecting work /object files"
set here [pwd]
array set stats {}
array set objs  {}
array set dirs  {}
foreach dir [glob -nocomplain *] {
    if {![file exists [file join $dir cdrive.cfg]]} {
	continue
    }
    puts  stderr "* $dir ..."
    cd $dir
    set config [exec grep config= cdrive.cfg | sed -e {s/config=//}]
    set dirs($dir)    $config
    foreach o [glob -nocomplain *.o] {
	exec strip $o
	set size [file size $o]
	set stats($dir,$o)	 $size
	set objs($o) .
    }
    cd $here
}
puts stderr "Calculating report ..."
# Transform stats into a nice matrix.
# Rows:    Objects
# Columns: Configurations
set on [array size objs]    ; incr on
set cn [array size dirs]    ; incr cn
set objlist [lsort [array names objs]]
set cfglist [lsort [array names dirs]]
set speclist [list {ENV_FLAGS}]
foreach cfg $cfglist {
    lappend speclist $dirs($cfg)
}
## puts "#objects = $on ($objlist)"
## puts "#configs = $cn ($cfglist)"
set rtitle [linsert $objlist 0 {}]
set ctitle [linsert $cfglist 0 {}]
struct::matrix osize
osize add columns $cn
osize add rows    $on
osize set row    0 $ctitle
osize set column 0 $rtitle
# Move the information from the array into the matrix.
set r 1
set delrow [list]
foreach obj $objlist {
    set c 1
    set basesize $stats(baseline,$obj)
    set changes 0
    foreach cfg $cfglist {
	osize set cell $c $r $stats($cfg,$obj)
	incr c
	if {$stats($cfg,$obj) != $basesize} {
	    set changes 1
	}
    }
    if {!$changes} {lappend delrow $r}
    incr r
}
# Remove all object files which were not changed at all ...
if {1} {
    while {[llength $delrow] > 0} {
	set idx [lindex $delrow end]
	set delrow [lrange $delrow 0 end-1]
	osize delete row $idx
    }
}
# Sum the columns up.
set svect [list Sigma]
set c 1
foreach cfg $cfglist {
    lappend svect [expr [join [osize get rect $c 1 $c end] +]]
    incr c
}
osize add row $svect
osize add row [percentage % $svect]
# ========================================================================
puts stdout "Static sizes"
report::report r [lib columns] style html
puts stdout " | Library sizes
"
puts stdout ""
r printmatrix2channel lib stdout
puts stdout "
"
r destroy
report::report r [osize columns] style html
puts stdout "Object file sizes
"
puts stdout ""
r printmatrix2channel osize stdout
puts stdout "
"
r destroy
puts stdout ""
lib   destroy
osize destroy
exit