#!/usr/bin/perl

use FindBin qw($RealBin);
use strict ;
use Getopt::Long;
use Pod::Usage;
use Pod::Text;
use lib "$RealBin/pm" ;
use ICG ;
use trick_print ;
use trick_version ;
use get_headers ;
use Cwd 'abs_path';

##############################################################################
# Main program 
##############################################################################

my $icg_operation ;
my @icg_h_files ;
my %sim ;
my $ret ;
my $help ;
my @defs ;
my ($valid_types_ref,$icg_depends_ref, $mis_entries_ref,$mis_depends_ref) ;
my ($head_depends_ref,$rcs_tags_ref) ;

# override the print format for help message
*Pod::Text::seq_i = sub { return "[04m" . $_[1] . "[00m" } ;

# set stdout to unbuffered so we see printout immediately.
$| = 1 ;

# set the default verbose level to 2
$sim{args}{v} = 2 ;
$sim{args}{force} = 0 ;

# default operation 
$icg_operation = "full" ;
$ICG::arg_lang = 0 ;

Getopt::Long::Configure ("bundling");
GetOptions ( "D=s" => sub { my $temp = join "" , @_ ; push @defs , "-$temp" ; } ,
             "U=s" => sub { my $temp = join "" , @_ ; push @defs , "-$temp" ; } ,
             "cpp|p" => sub { $ICG::arg_lang = "CPP" } ,
             "debug|d|g" => sub { $sim{args}{v} = 3 } ,
             "help|h|?" => \$help ,
             "force|f" => sub { $sim{args}{force} = 1} ,
             "outfile|o=s" => \$sim{args}{o} ,
             "sim_services|s" => sub { $icg_operation = "sim_services" } ,
             "single" => sub { $icg_operation = "single" } ,
             "s_source" => sub { $icg_operation = "s_source" } ,
             "tree|t" => sub { $icg_operation = "tree" } ,
             "unit_summary|u" => \&unit_summary ,
             "verbose|v=i" => \$sim{args}{v}
           ) or pod2usage(1) ;

pod2usage(1) if $help ;

#if ( -e "S_overrides.mk" ) {
#
#    open CFLAGS, "make -p -n -f S_overrides.mk fake_target 2>&1 |" ;
#
#    while ( <CFLAGS> ) {
#
#        if ( /^TRICK_CFLAGS\s*\:?=\s*(.*)/ ) {
#            $ENV{TRICK_CFLAGS} = $1 ;
#        }
#        elsif ( /^TRICK_ICG_EXCLUDE\s*\:?=\s*(.*)/ ) {
#            $ENV{TRICK_ICG_EXCLUDE} = $1 ;
#            $ENV{TRICK_ICG_EXCLUDE} =~ s/\$[{(]([^})]+)[})]/$ENV{$1}/ge ;
#        }
#    }
#    close CFLAGS ;
#}

$ENV{TRICK_CFLAGS} =~ s/\$[{(](\w+)[})]/$ENV{$1}/g ;
$ENV{TRICK_CFLAGS} =~ s/\"//g ;

# set and open the output file 
if ( $sim{args}{o} ne "" ) {
    my ($version, $thread) = get_trick_version() ;
    $thread =~ s/\d+\.// ;
    local *OUTFILE ;
    open OUTFILE , ">$sim{args}{o}" 
         or warn "ICG cannot open $sim{args}{o} for writing\n" ;
    $sim{fh} = *OUTFILE ;
    print OUTFILE "Output for $0 version $version-$thread at " .  localtime() . "\n\n" ;
}

push @icg_h_files , (grep !/(^-|(\.d|\.dd)$)/ , @ARGV) ;

#--------------------------------------------------------------
# Get all headers used by the sim and their modification dates
#if ( $icg_operation eq "s_source" ) {
#    get_headers(\%sim, abs_path("S_source.hh")) ;
#}

$ret = ICG(@icg_h_files, $icg_operation, \@defs, \%sim) ;

if ($ret eq -1)  {
    trick_print($sim{fh}, 
                "\nICG No files specified or found\n" , 
                "normal_yellow" , $sim{args}{v}) ;
}

sub unit_summary() {
        print "
                               Trick Measurement Units Summary
---------------------------------------------------------------------------------------------------
Standard Units                                  |Description
---------------------------------------------------------------------------------------------------
                Time:   s min  hr day           |second, minute, hour, day
Angular Displacement:   r   d  as  am rev       |radian, degree, arc-second, arc-minute, revolution
             Voltage:   v                       |volt
            Amperage: amp                       |ampere
          Resistance: ohm                       |ohm
               Sound:  dB                       |decibel
            Unitless:  -- cnt one mol           |no unit, count, one, mole
                                                |
---------------------------------------------------------------------------------------------------
English System Units                            |Description
---------------------------------------------------------------------------------------------------
 Linear Displacement:  ft kft  in  yd  mi  n.m. |foot, kilofoot, inch, yard, mile, nautical mile
                Mass:  sl lbm                   |slug, pound(mass)
               Force:  oz lbf                   |ounce, pound(force)
         Temperature:   R   F                   |Rankine, Fahrenheit
              Energy: BTU                       |British Thermal Unit
               Power:  hp                       |horsepower
            Pressure: psi                       |pound per square inch
              Volume: gal floz                  |gallon, fluid ounce
                                                |
---------------------------------------------------------------------------------------------------
Metric System Units                             |Description
---------------------------------------------------------------------------------------------------
 Linear Displacement:   m                       |meter
                Mass:   g  mt                   |gram, metric ton
               Force:   N                       |Newton
         Temperature:   C   K                   |Celsius, Kelvin
              Energy:   J TNT                   |Joule, ton of TNT
               Power:   W                       |Watt
            Pressure:  Pa atm mHg               |Pascal, atmosphere, meter of mercury
           Frequency:  Hz                       |Herz
              Volume:   l                       |liter

---------------------------------------------------------------------------------------------------

---------------------------------------------------------
You can use these prefixes for Multiples and Submultiples 
(Only valid for units: r v amp ohm m g N J W Pa mHg Hz)
---------------------------------------------------------
10**-1    d           10      da
10**-2    c           10**2    h
10**-3    m           10**3    k
10**-6    u           10**6    M
10**-9    n           10**9    G
10**-12   p           10**12   T
---------------------------------------------------------
\n\n" ;

        exit() ;
}

__END__

=head1 NAME

ICG - Trick Interface Code Generator

=head1 SYNOPSIS

ICG [-D B<label>] [-U B<label>] [--cpp] [--debug] [-d] [-g] [-h] [--help]
[-l] [--library] [-o I<outfile>] [--outfile=I<outfile>] [-p] [-s] [--sim_services]
[-t] [--tree] [-u] [--unit_summary] [-v I<level>] [--verbose=I<level>] [I<file> ...]

=head1 DESCRIPTION

See the Trick User's guide for B<ICG>.

=head1 OPTIONS

=over 8

=item B<-D> I<label>

Define a label

=item B<-U> I<label>

Undefine a label

=item B<-d> | B<-g> | B<--debug>

Set verbose level = 3

=item B<-h> | B<-?> | B<--help>

This help screen

=item B<-l> | B<--library>

Use this option in a SIM directory.  ICG will execute on all files listed in the
S_library_list file

=item B<-o> I<outfile> | B<--outfile>=I<outfile>

Direct output of ICG to outfile. ( Note: Does not affect screen output ).

=item B<-s> | B<--sim_services>

Run ICG on all required header files in the sim_services directory

=item B<-t> | B<--tree>

Print out a hierarchical tree of all header file dependcies for B<file>

=item B<-u> | B<--unit_summary>

Print out the list of known units to ICG

=item B<-v> I<level> | B<--verbose>=I<level>

Set the verbose level.  Valid entries are 0-3.

=item B<-DTRICK_VER=x.x>

Note: -DTRICK_VER=x.x is automatically used when parsing header files and the S_define file

=back

=cut

