eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
    & eval 'exec perl -S $0 $argv:q'
    if 0;

# -*- perl -*-
# $Id$
#

use File::Basename;

$cmd= basename($0);

if ($#ARGV < 0) {
    die "Usage: $cmd module...\n";
}

@match_order = ();
%typeRE = ();

&initfiletypes;

foreach $module (@ARGV) {
    if ( ! -d $module ) {
        warn "$cmd: no such directory $module\n";
        next;
    }

    open(DIRS, "find $module -type d|");
    @dirs = grep {if(!/CVS/) {chop;}} <DIRS>;
    close(DIRS);

    open(FIND, "find $module -type f|");
    @files = grep {if (!/build/
                       && !/CVS/
                       && !/rpc\+\+/
                       && !/\.bpr$/
                       && !/\.mdp$/
                       && !/\.MDP$/
                       && !/\.dsp$/
                       && !/\.DSP$/
                       && !/\.dsw$/
                       && !/\.DSW$/
                       && !/\.mak$/
                       && !/\.MAK$/
                       && !/\.o$/
                       && !/\.sl$/
                       && !/\.a$/) {chop;}} <FIND>;
    close(FIND);

    $totdirs = $#dirs;
    $totfiles = $#files;
    $totlines = 0;
    %lines = ();

    foreach $file (@files) {
        $n = 0;
        if (!open(IN, $file)) {
            warn "$cmd: cannot open '$file' for reading\n";
            next;
        }
        while(<IN>) {
            $n++;
        }
        close(IN);
        $lines{$file} = $n;
        $totlines += $n;
    }


    # Define two associative arrays to keep the results for each kind
    # of file.
    %linespertype = ();
    %filespertype = ();
    foreach $type (keys %typeRE) {
        $linespertype{$type} = 0;
        $filespertype{$type} = 0;
    }
    # The file is classified and added to the corresponding variable.
    FILE: while (($file, $l) = each %lines) {
        foreach $type (@match_order) {
            $re = $typeRE{$type};
            if($file =~ m/$re/) {
                $linespertype{$type} += $l;
                $filespertype{$type}++;
                next FILE;
            }
        }
        print STDERR "Unmatched file: $file\n";
    }

    format STDOUT_TOP=
                                      @|||
                                       $%

                Lines of code in module @<<<<<<<<<<<<<<<<<<<<
                                              $module

Files:                 @>>>>>>>>
                       $totfiles
Directories:           @>>>>>>>>
                       $totdirs
Lines:                 @>>>>>>>>
                       $totlines

File type                    lines              files
---------------------------- ------------------ -----------------
.
    format STDOUT=
@<<<<<<<<<<<<<<<<<<<<<<<<<<< @>>>>>>>>>>>>>>>>> @>>>>>>>>>>>>>>>>
$type,                       $typelines,        $typefiles
.


    foreach $type (@match_order) {
        $typelines = $linespertype{$type};
        $typefiles = $filespertype{$type};
        if ($typefiles != 0) {
            write;
        }
    }
    # Forzamos un newpage para cada modulo.
    $- = 0;
}

sub updateRE {
    local $desc = shift;
    local $re = shift;

    if (exists $typeRE{$desc}) {
        local $mix = $typeRE{$desc} . '|(' . $re . ')';
        $typeRE{$desc} = $mix;
    } else {
        $typeRE{$desc} = '(' . $re . ')';
        push @match_order, $desc;
    }
}

sub initfiletypes {
    # Here we define the regular expressions for each kind of file.
    # This RE must be mutually exclusive, a file will not be counted
    # twice, but it could be unproperly classified.

    local %filenames =
        ('GNUmakefile'     => 'Makefile',
         'Makefile.*'   => 'Makefile',
         'README'       => 'README files',
         'COPYING'      => 'Licenses',
         'LICENSE.*'    => 'Licenses',
         'ChangeLog.*'  => 'ChangeLog',
         'ChangeLog-.*' => 'ChangeLog',
         '.cvsignore'   => 'Control CVS',
         'run_test.pl'  => 'Test driver',
         'run_test'     => 'Test driver',
         'run_tests'    => 'Test driver',
         'run_test.sh'  => 'Test driver');
    local %fileexts =
        ('cc'    => 'C++ sources',
         'cpp'   => 'C++ sources',
         'inl'   => 'C++ sources',
         'i'     => 'C++ sources',
         'h'     => 'Headers',
         'hh'    => 'Headers',
         'c'     => 'C/C++ sources',
         'idl'   => 'IDL sources',
         'IDL'   => 'IDL sources',
         'pidl'  => 'IDL sources',
         'y'     => 'yacc source',
         'yy'    => 'yacc source',
         'l'     => 'lex source',
         'll'    => 'lex source',
         'php'   => 'php script',
         'pm'    => 'perl script',
         'pl'    => 'perl script',
         'perl'  => 'perl script',
         'py'    => 'python script',
         'GNU'   => 'GNU make config',
         'tex'   => '(La)TeX',
         'txt'   => 'Text files',
         '1'     => 'man pages',
         '3'     => 'man pages',
         'html'  => 'HTML',
         'bib'   => 'BibTeX',
         'sty'   => 'TeX styles',
         'bld'   => 'VxWorks build file',
         'am'    => 'Automake file',
         'icc'   => 'VisualAge project files',
         'icp'   => 'VisualAge project files',
         'vac'   => 'VisualAge project files',
         'vcp'   => 'Microsof eMbedded Visual Tools project files',
         'vcw'   => 'Microsof eMbedded Visual Tools project files',
         'bpr'   => 'Borland project files',
         'bor'   => 'Borland project files',
         'dsp'   => 'DevStudio project files',
         'DSP'   => 'DevStudio project files',
         'mdp'   => 'MSVC project files',
         'MDP'   => 'MSVC project files',
         'dsw'   => 'MSVC workspaces',
         'DSW'   => 'MSVC workspaces',
         'mak'   => 'MSVC MAK files',
         'MAK'   => 'MSVC MAK files',
         'java'  => 'JAVA source',
         'class' => 'JAVA class',
         'cccc'  => 'codecount output',
         'gif'   => 'GIF images',
         'conf'  => 'Svc_Config files',
         'diff'  => 'patches',
         'zip'   => 'Compressed files',
         'gz'    => 'Compressed files',
         'EXE'   => 'Win32 executable',
         'shar'  => 'Shar archive',
         'mib'   => 'MIB definition files',
         'gperf' => 'GPERF input',
         'phil.*'=> 'Test driver'
         );
    local %paths = ();

    local ($desc, $reseed);
    while (($reseed, $desc) = each %filenames) {
        local $re = '/' . $reseed . '$';
        updateRE($desc, $re);
    }
    while (($reseed, $desc) = each %fileexts) {
        local $re = '/[^/]*\.' . $reseed . '$';
        updateRE($desc, $re);
    }
    while (($reseed, $desc) = each %paths) {
        local $re = $reseed;
        updateRE($desc, $re);
    }

     updateRE('Others', '.*');

#    while (($desc, $reseed) = each %typeRE) {
#       print STDERR $desc, " ==> ", $reseed, "\n";
#    }
}
