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

# -*- perl -*-
# count_lines,v 4.4 2001/07/26 18:49:04 coryan Exp
#

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 =
	('Makefile'     => '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',
	 'pm'    => 'perl script',
	 'pl'    => 'perl script',
	 'perl'  => 'perl 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";
#    }
}
