#!/usr/bin/perl
# *********************************************************************
#  Original code: subtotal,v 2.7 1994/11/08 09:01:53 hobbs
#
#  Adapted to NoSQL by Carlo Strozzi <carlos@linux.it>.
#
#  subtotal: compute subtotals on selected table columns.
#  Copyright (C) 1998-2003 Carlo Strozzi <carlos@linux.it>
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# *********************************************************************
#  $Id: subtotal,v 1.2 2003/03/17 10:10:46 carlo Exp $

$NOSQL_INSTALL = $ENV{'NOSQL_INSTALL'};
$NOSQL_INSTALL = "/usr/local/nosql" if not $NOSQL_INSTALL;

$0 =~ s-.*/-- ;
while ( $ARGV[0] =~ /^-/ ){             # Get args
    $_ = shift ;
    if( /-s.*/ || /^--subtotal$/ ){ $xsum++ ; last ; }
    if( /-t.*/ || /^--total$/ ){ $TOT++ ; next ; }
    if( /-T.*/ || /^--total-only$/ ){ $TOT++ ; $TONLY++; $xsum++ ; next ; }
    if( /-h.*/ || /^--help$/ ){
	$HelpInfo = `grep -v '^#' $NOSQL_INSTALL/help/subtotal.txt`;
	print "$HelpInfo" ;
	exit 1;
    }
    die "\n$0: bad arg: $_\n", "For help type \"$0 --help\".\n" ; }
while(<STDIN>){                     # get header info
    #if( /^\s*#/ ){          # comment
    #push( @savcom, $_ ) ;
    #next ; }
    chop ;
    if( ++$lln == 1 ){
    $_ =~ s/\001//g;		# remove SOH markers
    @H = split( /\t/, $_ ) ; }  # col names
    #elsif( $lln == 2 ){
    #@F = split( /\t/, $_ ) ; last ; } } # definitions
    last ; }
while( $arg = shift ){                  # build brk, sum arrays
    if( $arg =~ /^-/ ){
    $xsum++ ;
    next ; }
    for( $ok=$f=0 ; $f <= $#H ; $f++ ){
    if( $arg eq $H[$f] ){   # match existing column
        $ok++ ;
        push( @nh, $f ) ;
        if( ! $xsum ){
        push( @Bx, $f ) ; } # break index
        else{
        push( @Sx, $f ) ; } # subtot index
        last ;
    }
    }
    die "\n$0: bad column name: $arg\n" if ! $ok ;
}
if( ! @Bx && ! $TONLY ){ # no break columns given
    unshift( @nh, 0 ) ;
    push( @Bx, 0 ) ; }
if( ! @Sx ){        # no sub-tot columns given
    for( $f=0 ; $f <= $#H ; $f++ ){
    if( $F[$f] =~ /(\S+)/ && $1 =~ /N/i ){  # numeric column
        push( @nh, $f ) ;
        push( @Sx, $f ) ; } } }
@n = @nh ;
#print @savcom ;     # print comments
@D = @H ; &printem ;    # print new col names
#@D = @F ; &printem ;    # print new definitions
while(<STDIN>){                 # read body
    chop ;
    @F = split( /\t/, $_ );
    $dif = 0 ;
    $x = 0 ;
    for (@Bx){      # check break columns for diff
    $F[$_] = ' ' if $F[$_] eq '' ;  # for null case
    if( $G[$x++] ne $F[$_] ){
        $dif++ ;
        last ; }
    }
    if( $dif && $notfst++ ){
    print join( "\t", @G ), "\n" ;  # print output array
    &chk_bl ;
    for (@G){
        $_  = "" ; }    # clear output array
    if( $bl ){
        print join( "\t", @G2 ), "\n" ;
        print join( "\t", @G ), "\n" ; # blank line
        for (@G2){
        $_  = "" ; }    # clear 2nd output array
    }
    }
    $x = 0 ;
    for (@Bx){          # save break columns
    $G2[$x]    = "" ;   # (preallocate for perl5)
    $G[$x++]   = $F[$_] ; }
    for (@Sx){          # sum subtot columns
    $G[$x]     += $F[$_] ;
    $T[$x]     += $F[$_] ;  # totals
    $G2[$x++]  += $F[$_] ; }
}
unless( $TONLY ){
    print join( "\t", @G ), "\n" ;
    print join( "\t", @G2 ), "\n" if @Bx > 1 ;
}
if( $TOT ){
    $x = @G -1 ;
    print "\t" x $x, "\n" unless $TONLY ;
    $T[0] = "Totals" unless $TONLY ;
    print join( "\t", @T ), "\n" ;
}
sub printem {
    $c = 0 ;
    print "\001" ;
    for $x (@n) {
    print "\t\001" if $c++ > 0 ;
    print $D[$x] ; }
    print "\n" if @n ;
}
sub chk_bl {            # set $bl if blank line needed
    $bl = 0 ;
    if( @Bx > 1 && $G[0] ne $F[$Bx[0]] ){ $bl++ ; }
}

########################################################################
# End of program.
########################################################################

