use File::Path;
use IO::Handle;
use File::Glob;
use Time::Local;
use Config;
use Cwd;

# File build_exe.pl
$Version = "6.3";

# authors: Jan Galema      (JG)
#        : Peter Kazakov   (PK)
#        : Lee Boekelheide (LB)
#        : Bhaskar G       (BG)
#        : Roopa Mahishi   (RM)
#
# support: Peter Kazakov
#
# Revision history:
# -----------|---------|------------------------------------------
# date       | version | Description
# -----------|---------|------------------------------------------
# 2001-02-12 | 0.1, JG | As specified in c06s02_applicationbuildscript.doc
# -----------|---------|------------------------------------------
# 2001-02-14 | 0.2, JG | implement $(SOME_LIBS) in Iibspec
#            |         | (in function InterpretLine)
# -----------|---------|------------------------------------------
# 2001-02-16 | 0.3, JG | 1. No check for _TMBSL
#            |         | 2. _TMDIVERSITY - adapt EvalLibs
#            |         |    (other way of finding parameters)
#            |         | 3. Treat DLLS as LIBS
#            |         | 4. $(SOME_LIBS) should be any environment variable
# -----------|---------|------------------------------------------
# 2001-04-06 | 0.4, PK | 1. Remove LOADED section for DLLS
#------------|---------|---------------------------------------------------------
# 2001-05-23 | 0.5, PK | 1. Based on PR119, the implementation is offered by M. 
#                       Selten
# -----------|---------|----------------------------------------------------------
# 2001-07-23 | 0.6, PK | PR166  - script output is confusing
# -----------|---------|----------------------------------------------------------
# 2001-07-24 | 0.7, PK | PR192 - build_exe.pl does not work properly if there is
#            |         |         more than 1 level of DLLS+LIBS components
#            |         |   Major restructuring: Building all transitive required components, generating .l files optionally, not changing diversity
#            |         |   Algorithm for the order - Build the graph and build the leaves first. Remove the leaves and again.
#            |         |   The order is important for DLLS. As far as we do not know whether the component is DLL in advance,
#            |         |   we do this order for all components.
# -----------|---------|----------------------------------------------------------
# 2001-09-25 | 0.8, PK | Integration of the changes proposed from Sunnyvale (see PR )
#            |         | ReadMakefile is replaced by FindDependentLibraries
# -----------|---------|----------------------------------------------------------
# 2001-10-01 | 0.9, PK | Script output to STDOUT and STDERR
#            |         | Option for generating only .l files
# -----------|---------|----------------------------------------------------------
# 2001-10-04 | 1.0, PK | PR301: Use of binary release included
# -----------|---------|----------------------------------------------------------
# 2001-10-12 | 1.1, PK | PR302: Second synchronisation with Sunnyvale
#            |      LB |        InterpretLine is rewritten
# -----------|---------|----------------------------------------------------------
# 2001-10-15 | 1.2, LB | PR305: Third synchronisation with Sunnyvale
#            |         |        Changes to allow mixing diversities
# -----------|---------|----------------------------------------------------------
# 2001-12-04 | 1.3, PK | PR324: _TMREQPRJ shpould be reintroduced - support for Unix shell env.variables added
# -----------|---------|----------------------------------------------------------
# 2001-12-13 | 1.5, PK | PR364: Circular dependencies are still present
# -----------|---------|----------------------------------------------------------
# 2001-12-19 | 1.6, PK | PR349: build_exe.pl halts late if _TMREPORTS directory does not exist
# -----------|---------|----------------------------------------------------------
# 2001-12-19 | 1.7, PK | PR346: Separate reports directories
# -----------|---------|----------------------------------------------------------
# 2001-12-20 | 1.8, PK | CR 353: build.pl/build_exe.pl/  always reports compiling warnings for mips_psos
# -----------|---------|----------------------------------------------------------
# 2001-01-21 | 1.9, PK | CR 402: Changes in *.l mechanism
# -----------|---------|----------------------------------------------------------
# 2001-01-21 | 2.1, PK | CR 433: Clarification of recursive LIBS approach
# -----------|---------|----------------------------------------------------------
# 2001-03-11 | 2.2, PK | PR 463: Build process fails if _TMREPORTS directory does not exists; Improved messages.
# -----------|---------|----------------------------------------------------------
# 2001-03-18 | 2.21,PK | PR 474: build_exe.pl should handle multiple drives and drive letters in pathnames
# 2001-03-18 | 2.3, PK | PR 475: build_exe.pl should handle multiple drives and drive letters in pathnames
# -----------|---------|----------------------------------------------------------
# 2002-05-10 | 2.4, SP | CR 509: Add -target option to explicitly mention the makefile target
# -----------|---------|----------------------------------------------------------
# 2002-05-29 | 2.5, PK | CR 413: Add debug option
# -----------|---------|----------------------------------------------------------
# 2002-06-12 | 2.6, BG | PR 516: Fix for cannot generate <o/p>/reports
# -----------|---------|----------------------------------------------------------
# 2002-06-24 | 2.7, BG | CR 413: Add debug option
# -----------|---------|----------------------------------------------------------
# 2002-07-01 | 2.8, SP | CR 499/509: Fix Add _target:<empty> check
# -----------|---------|----------------------------------------------------------
# 2002-07-01 | 2.9, BG | CR 542: build_exe.pl does not take into account JAVA_REQUIRES when building an application
#            |      PK |                                                           
# -----------|---------|----------------------------------------------------------
# 2002-07-01 | 3.0, BG | CR 499/509: Update Usage info. with -target option.
#            |      PK |                                                           
# -----------|---------|----------------------------------------------------------
# 2002-07-05 | 3.1, BG | build_exe.pl will still try to build if no component is 
#            |         | specified
# -----------|---------|----------------------------------------------------------
# 2002-07-08 | 3.2, BG | build_exe.pl doesnot display environment variables properly
#            |          | set in the prjlist.txt file
# -----------|---------|----------------------------------------------------------
# 2002-07-11 | 3.2.1,  | build_exe.pl doesnot display environment variables properly
#            | BG      | set in the prjlist.txt file
#            |          |
#            |          | build_exe.pl with a clean target will not perform clean if
#           |         |  Binary release of the component is available
# -----------|---------|----------------------------------------------------------
# 2002-07-15 | 3.3, PK | PR 571: build_exe.pl is not consistent in a case that there is more then one comps with the same name in the tree
# -----------|---------|----------------------------------------------------------
# 2002-07-17 | 3.4, PK | PR 582: SDE2 fails if component is used as interface
# -----------|---------|----------------------------------------------------------
# 2002-07-30 | 3.5, PK | PR 586: build_exe.pl does not generate tmFlags.* files before start recursing
# -----------|---------|----------------------------------------------------------
# 2002-07-31 | 3.6, BG | PR 585: build_exe.pl does not work properly with Java binary release
# -----------|---------|----------------------------------------------------------
# 2002-07-31 | 3.7, SP | Corrections -target: option with multiple targets specified.
# -----------|---------|----------------------------------------------------------
# 2002-08-02 | 3.8, PK | CR 578: Add "Trace" mode
# -----------|---------|----------------------------------------------------------
# 2002-08-12 | 3.9, BG | build_exe.pl with some directory entry doesnot give error message
# -----------|---------|----------------------------------------------------------
# 2002-08-21 | 4.0, BG | build_exe.pl with -target clean_all will not clean if the 
#            |          | component exists outside $_TMROOT
# -----------|---------|----------------------------------------------------------
# 2002-08-21 | 4.1, BG | PR 1 build_exe.pl should log more information
# -----------|---------|----------------------------------------------------------
# 2002-11-28 | 4.2, BG | Changes made for clean_all target PR 509.
# -----------|---------|----------------------------------------------------------
# 2003-02-03 | 4.3, BG | PR 630: optional: -g:<filename>: create dependency graph definition   
#        |         | file in 'dot' format provided by Jan Galema
# -----------|---------|----------------------------------------------------------
# 2003-03-31 | 4.4, SP | PR 19489: Improve build_exe.pl output with accurate msg of what is being built 
# -----------|---------|----------------------------------------------------------
# 2003-04-10 | 4.5, BG | CR18279/18479: Logging should be optimised with more options.
# -----------|---------|----------------------------------------------------------
# 2003-05-30 | 4.6, BG | build_exe.pl doesnot consider comps/<compname> if comp is not it _TMROOT
# -----------|---------|----------------------------------------------------------
# 2003-10-13 | 4.7, BG | SDE 2 ver. 1.7 log file is not chronological 
# -----------|---------|----------------------------------------------------------
# 2003-10-13 | 4.8, BG | SDE2, v1.7 -- Cancelling a build doesn't always clean-up temp directories 
# -----------|---------|----------------------------------------------------------
# 2004-02-09 | 4.9, RM | PR 24379:  Output message modified to include the component name 
# -----------|---------|----------------------------------------------------------
# 2004-02-09 | 5.0, SP | Correct TMP directory selection
# -----------|---------|----------------------------------------------------------
# 2004-03-25 | 5.1, SP | Include generation of loc_list files
# -----------|---------|----------------------------------------------------------
# 2004-05-14 | 5.2, RM | PR 29607: Changing the -z to -f filetest operator
#            |         | Sorting the TMDIVERSITY value alphabetically 
#            |         | Setting in the proper file search path in generating loc_list file
#            |         | (module name findComps)
# -----------|---------|----------------------------------------------------------
# 2004-10-11 | 5.3, RM | PR 29477: Removing the circualar dependency hangup. 
#            |         | Adding up more of comments
#            |         | use FILE::glob changed to use File::Glob
# -----------|---------|----------------------------------------------------------
# 2004-10-12 | 5.4, RM | PR 34815: Make changes in the readDomains module
#            |         | so that the spaces are recognised while building the
#            |         | domains array
# -----------|---------|----------------------------------------------------------
# 2004-12-13 | 5.5, RM | PR 36449: Change all the output direction to default STDOUT.
# -----------|---------|----------------------------------------------------------
# 2004-12-15 | 5.5, RM | PR 36581: Use the format function to print out the output values
# -----------|---------|----------------------------------------------------------
# 2004-12-17 | 5.5, RM | PR 36623: Display of elapsed time and total time taken for execution
#            |         | Format of some regular expressions and change in CheckParamters function    
# -----------|---------|----------------------------------------------------------
# 2004-12-17 | 5.6, BG | PR 40104: SDE2 build_exe.pl fails due to dependecy on TMP/TEMP variable 
# -----------|---------|----------------------------------------------------------
# 2005-06-02 | 5.7, RM | PR 41707: build_exe.pl fails when pathname contains '-' 
# -----------|---------|----------------------------------------------------------
# 2005-06-03 | 5.8, RM | PR 41931: build_exe.pl does not expand for ~(tilde) specified in prjlist.txt
# -----------|---------|----------------------------------------------------------
# 2005-06-06 |5.8.1,RM | PR 41931: Do not call expand_tilde function for windows
# -----------|---------|----------------------------------------------------------
# 2005-08-02 | 5.9, RM | PR 44284: errors printed two times during links edition 
# -----------|---------|----------------------------------------------------------
# 2005-09-06 | 5.10, RM| PR 45668: dependency graph not printed to file at option -g  
#------------|---------|----------------------------------------------------------
# 2005-05-17 | 5.11, BG| Remove perl warnings 
#------------|---------|----------------------------------------------------------
# 2005-05-17 | 5.12, BG| CR 46315: Build multiple applications in one go 
#------------|---------|----------------------------------------------------------
# 2006-06-05 | 5.13, BG| PR 55921:Generated loc_list.* incomplete when using the 
#            |         |           Build_exe.pl script  
#------------|---------|----------------------------------------------------------
# 2006-08-22 | 6.0, BG | CR 54884:Better support for dynamic loading and linking
#------------|---------|----------------------------------------------------------
# 2007-02-22 | 6.1, BG | Check for absolute path first
#------------|---------|----------------------------------------------------------
# 2007-02-28 | 6.2, BG | Check for dll binaries
#------------|---------|----------------------------------------------------------
# 2007-04-11 | 6.3, BG | Consolidation of env variables
#------------|---------|----------------------------------------------------------

format STDOUT

=
@*
$string
~~
.
# Globals Constants
$Fail               = "stop";

#$Fail = "go";                                # debug statement (continue after failing make)

$LOG             = 0;
$QUIET           = 0;
$NameMakefile    = "makefile";
$ReportLogfile   = "build_exe_report.log";
$format          = '-' x80;
$format1         = '*' x80;
$format2         = '=' x80;
$TargetSpecified = "";
$MAKE="";

#
# Globals Variables

$CompsDirName    = "comps";

my $ExtraGoal_target="";
my $ShowTime;
my $BuildEntry;
my $Rel="";
my $MakeSDE2List = 0;
my $OldNrLibs = 0;
$Exit_value         = 0;
$Exit_value_summary = 0;
$OnlyLFiles         = 0;
$SkipBinary         = 0;
$PrintGraph         = 0;
$PrintGraphFile     = ''; # 4.3
$DBG                = 0;
$java_is_required   = 0;

my $startTime = "";
my $MyRootLocations = "";
my $RootLocations="";
my $LoadType="immediate";
$BLACKHOLE = $^O eq "MSWin32" ? "NUL" : "/dev/null";

#
#
###############################################################################################
#Possible environment variables (not changed by this script, only checked for existance)
$ENDIAN              = "_TMTGTENDIAN";
$HOST                = "_TMTCSHOST";
$OS                  = "_TMTGTOS";
$CPUTYPE             = "_TMTGTCPUTYPE";
$BSL                 = "_TMBSL";

#This environment variables should not be changed during the build process
$RELTYPE             = "_TMTGTREL";
$DIVERSITY           = "_TMDIVERSITY"; # (optional environment variable)

@parameters          = ($OS, $ENDIAN, $CPUTYPE, $RELTYPE, $HOST, $BSL, $DIVERSITY);

#Variables used to create loc_list files
$_TMROOT             = $ENV {"_TMROOT"};
$_TMROOT             =~ s/\\/\//g; 
$_TMTGTBUILDROOT     = $ENV {"_TMTGTBUILDROOT"};
$_TMTGTBUILDROOT     =~ s/\\/\//g; 

    if( exists $ENV {'_TMTGTBUILDROOT'} ) 
	{ $_TMTGTBUILDPROJECT  = "$_TMTGTBUILDROOT/project"; }
	else
	{ $_TMTGTBUILDPROJECT  = "$_TMROOT/project"; }

if(exists $ENV{'_TMPROJECT'} && -d $ENV{'_TMPROJECT'}){
if (-f "$ENV{'_TMPROJECT'}/prjlist.txt") {
$TM_PRJLIST          = "$ENV{'_TMPROJECT'}/prjlist.txt";
} 
else {
   print ("File not found: $ENV{'_TMPROJECT'}/prjlist.txt\n");
   exit 1;
}
}
else {
$TM_PRJLIST          = "$ENV{'_TMROOT'}/project/prjlist.txt";
}

$LOC_LIST_FILENAME   = "$_TMTGTBUILDPROJECT/loc_list.txt";
$LOC_LIST_MKFILENAME = "$_TMTGTBUILDPROJECT/loc_list.mk";

#-------------------------------------------------------------------
# void PrintLog() Print a string to LOGFILE and REPORTLOGFILE
sub PrintLog
{
    my ($string) = @_;
    print $string;
    print REPORTLOGFILE $string if ($LOG == 1);
}
#---------------------------------------------------------------------------------------------
sub DisplayUsage
{
    $string
        = qq (\nUsage :\n\n\tbuild_exe.pl \t[-b] [-c] [-dbg] [-showtime] [-g[:<filename>]] [-h] [-l] [-log]
    \t\t\ [-quiet] [-list:<file name>] [-target:<target name>]\n\t\t\<Locations of makefile of Component/Executable\>\n$format\n
    \t-b\t\t:\tDo not use binary release, if any.
    \t-c\t\t:\tContinue with the compilation if there is an error.
    \t-dbg\t\t:\tPrint debug info during the execution.
    \t-g[|:<filename>]:\tPrint the dependency graph, optional file in\n\t\t\t\t'dot'format. 
    \t-h\t\t:\tPrint current help and exit.
    \t-l\t\t:\tGenerate only *.l files.
    \t-showtime\t:\tDisplay each component's Build Time.
    \t-log\t\t:\tPrint all the information onto a report logfile
    \t-quiet\t\t:\tPrint only a brief information
    -list:<file name>\t:\tFile that contains the list of applications to be built
    -target:<target name>\t:\tTo specify makefile targets explicitly
    \t\t\t\tUser can specify multiple targets with \n\t\t\t\tmore -target: options.
    \t\t\t\teg: build_exe.pl -target:t1 -target:t2\n$format\n);
    write();
}
#---------------------------------------------------------------------------------------------
sub CheckParameters
{
    # GetOptions (  "c:i"   => \$contCompilation,
    #                 "b:i"   => \$buildBinary,
    #                 "dbg:i" => \$printDebug,
    #               "l:i"   => \$rptfile,
    #                 "log:i" => \$logFile,
    #               "h:i"=>  \$help,
    #                 "quiet:i"=> \$quietInfo,
    #                 "target:s" => \@targetName, 
    #                 "g\[*\]:s"  => \$PrintGraphFile  );

    $error = "";
    my $i     = 0;
    if( @ARGV < 1 )
    {
        print "ERROR:\tInvalid number of parameters\n\n";
        DisplayUsage();
        exit 1;
    }
    $MakeSDE2List = 1;
    for( @ARGV )
    {
        if( /\A\-c$/i ) {        # do not stop in case of error
            $Fail = "go"; }
        elsif( /\A\-log$/i ) {   # check if the information should be logged. 
            $LOG = 1; }
        elsif( /\A\-quiet$/i ) { # check if the information should be logged. 
            $QUIET = 1; }
        elsif( /\A\-l$/i ) {     # generate only *.l files
            $OnlyLFiles = 1; }
        elsif( /\A\-b$/i ) {     # do not use binary release, if any
            $SkipBinary = 1; }
        elsif( /\A\-showtime$/i ) {     # Look for show time
            $ShowTime = 1; }
        elsif( /\A\-g/i ) {
            $PrintGraph = 1; 
           if( /\A\-g\:/i )
           {                                                                      # Print the dependency graph.
              $PrintGraph = 1;
              if( $' eq "" ) {                                                   # 4.3
                  $error = $error . "\tNo graph file specified in -g: option\n"; # 4.3
               }                                                              # 4.3
              else {                                                             # 4.3
                $PrintGraphFile = $';                                          # 4.3
              }                                                              # 4.3
           }
        }
        elsif( /\A\-dbg$/i ) {                                                    # Print debug info
            $DBG = 1; }
        elsif( /\A\-target\:/ )
        {
            if( $' eq "" ) { $error = $error . "\tNo target name specified in -target: option\n"; }
            elsif( ($' eq "clean") || ($' eq "clean_all") || ($' eq "userdoc")|| ($' eq "devdoc")|| ($' eq "qmore")|| ($' eq "qac") || ($' eq "rgd")|| ($' eq "lint")) { $SkipBinary = 1; }
            $TargetSpecified  = "yes";

            $ExtraGoal_target = $ExtraGoal_target . " " . $';
        }
        elsif( /\A\-h$/i || /\A\-help$/i )
        { # help
            DisplayUsage();
            exit 0;
        }
		elsif( /\A\-list:/ )
        {
			$ApplicationList++;
            if( $' eq "" ) { $error = $error .  "\tNo file name specified in -list: option\n";}
            else{
			$appListFile=$';
			if (-f $appListFile) {
				open (APPLIST,"<$appListFile") || die ("Unable to open $appListFile\n");
					while (<APPLIST>) {
					chomp;
					$_ =~ s/\s+//g;
					$_ =~ s/\#.*//g;
					next if $_ =~ /^$/;
					$appList .= "$_ ";
				}
				close APPLIST;
				push (@apps_to_build,split / /,$appList);
			}
			else{
				$error .= "\t${appListFile} File not found\n";
			}
			}			
        }
		elsif( /\A\-/ )
        {
			$error .= "Unknown option $_\n";
		}
        else
        {
            if( $error eq "" )
            {
					$ApplicationList++;
					push (@apps_to_build,$_);
            }
        }
    }
    $QUIET = 0 if ($DBG == 1);

    if( $error ne "" || $ApplicationList == 0)
    {
        $string = qq (ERROR:\tWrong use of parameters.\n $error);
        write();
        DisplayUsage();
        exit 1;
    }
}
#---------------------------------------------------------------------------------------------
#
sub ExistEnvironment
{
    my ($var) = @_;
    if( !exists $ENV {$var} )
    {
        print "Environment variable $var not defined\n";
        return 1;
    }
    return 0;
}
#---------------------------------------------------------------------------------------------
# Check and initialize environment
#
sub CheckEnvironment
{
    my $errors = 0;

    if( !exists $ENV{MAKE} )
    {
        printf "MAKE environment variable not set.\n";
        printf "Using default value \"gmake -r\".\n";
        $MAKE="gmake -r";
    }
    else
    {
        $MAKE=$ENV{MAKE};
    }

    $errors += ExistEnvironment('_TMROOT');
    foreach $param( @parameters )
    {
        if( ($param ne $DIVERSITY) and ($param ne $HOST) and ($param ne $BSL) ) { $errors += ExistEnvironment($param); }
    }
    if( $ENV {$CPUCLASS} eq "tm" ) { $errors += ExistEnvironment($HOST); }

    #if (($errors==0) and (not -d "$ENV{'_TMREPORTS'}")){
    #    mkdir "$ENV{'_TMREPORTS'}", 0755 or die "Can not make directory $ENV{'_TMREPORTS'}.\n";
    #}

    #------------------------------------------------------------------
    # There is a difference between Unix shell (support ${env_var}, $env_var) and
    # Perl interpretation of env_var (support $(env_var)). To ensure 
    # the Unix model, a small rework of env.variables is made in this Perl script.
    # This variables are correctly interpretet from gmake, but not from Perl.
   
    # Open the prjlist.txt file, if its not set then set the value of 
    # RootLocations to the value of _TMROOT
    open(PRJLISTFILE, $TM_PRJLIST) or $RootLocations = $ENV {'_TMROOT'};

    while (<PRJLISTFILE>) 
   {
      chomp;
     # Remove the leading and trainling blanks 
      $_ =~ s/^\s+|\s+$//g;

     #Ignore comment lines
      next if(/^#/ || /^\n/) ;

      my @reqprj = split;
      my $entry="";
      foreach my $loc(@reqprj)
      {
        my $entry  = $loc;

        # Ignore the value if it is preceded by #
        $entry   =~ s/\#(.)*//g;

        # Match for the presence of the value that has $variablename or
        # $(variablename) or ${variablename}
        if($entry =~m/\$[\{\(]{0,1}(\w+)[\}\)]{0,1}/)
        {
         # Warn if the matched variable is not set   
          print "Warning:\t$1 Environment not set\n\t\tSkipping the entry $loc in prjlist.txt\n" if(!exists $ENV{$1});
        }

        # Replace the variable to the corresponding environment value set in shell
        $entry =~ s/\$[\{\(]{0,1}(\w+)[\}\)]{0,1}/$ENV{$1}/g;

        # If the value contains the tilde (~), then  
        # expand the tilde and then append the expanded value to 
        # rootlocations
        if($entry=~m/^\~/)
        {
          $entry = expand_tilde($entry) if($Config{osname}!~m/win/i);
        }
        # Append the RootLocations
        $RootLocations = ${RootLocations}." ".${entry};
      }
   }
   close PRJLISTFILE;

    $MyRootLocations =${MyRootLocations}." ".${RootLocations};
    if( $errors > 0 ) { exit 1; }
    $string = qq(\nRoot locations: $MyRootLocations \n$format\n);
    write();
}

######################################################################
# Module Name : expand_tilde
# Description : This module expands the ~ character and returns the 
# value as expanded value of the ~
######################################################################
sub expand_tilde {
  my( $file ) = shift;
  $file =~ s{
    ^ ~         # find a leading tilde
    (           # save this in $1
    [^/]        # a non-slash character
    *           # repeated 0 or more times (0 means me)
    )
  }{
    $1
    ? (getpwnam($1))[7]
    : ( $ENV{HOME} || $ENV{LOGDIR} )
  }ex;

  $file
}

#---------------------------------------------------------------------------------------
#
# FindFileLocation
# Usually the components location is in a subdirectory of _TMROOT (_TMCURPRJ if it is defined)
# If not we have to look in all locations specified in _TMTGTREQPRG
#
sub FindDirLocation
{
    my ($Location) = @_;
    if( -d $Location ) { #Absolute path is used!
        return $Location;
    }
    if ($Location =~ /^comps\//) {
	$Location1 =$Location;
	$Location1 =~ s/^comps\///;
	if (defined $comps{$Location1}) {
		return $comps{$Location1};
	}
    }
    my @reqprj     = split / /, $MyRootLocations;
    # first we are looking in the components
    foreach $DirName( reverse @reqprj )
    {
        if( -d "$DirName/$Location" ) {
        #print "$DirName/$Location is used \n";
            return "$DirName/$Location"; }
    }
    # ... and then in intfs
    foreach $DirName( reverse @reqprj )
    {
        my $intfsLocation = $Location;
        $intfsLocation =~ s/comps\//intfs\//;

        #print "checking for $DirName/$intfsLocation ...\n";
        if( -d "$DirName/$intfsLocation" ) {

        #print "$DirName/$intfsLocation is used\n";
            return "$DirName/$intfsLocation"; }
    }
	    return "$ENV{'_TMROOT'}/$Location";
}
#------------------------------------------------------------------------------
#
# InterpretLine($module, $nameList)
#
# $module is some component we're building
#
# $nameList is a whitespace separated list of modules that $module
# depends on
#
# $module and the words in $nameList may have diversity and release
# decorations on them
#
# We add appropriately to the $Libs, $libIndex, and $LibsPntr structures

sub InterpretLine
{
    my ($lib, $Line) = @_;

    my $t;
    my @t;
    my $libUndec     = $lib;
    $libUndec =~ s/_.*//g; #Just the component name
    # $libUndec                $lib with diversity and release decorations
    #                          removed
    #
    # $libIndex{$lib}          integer index into $Libs of the library
    #                          $lib; entries are made for both the
    #                          decorated and undecorated form if a given
    #                          item is decorated with diversity or release
    #
    #                          There is no index for the application
    #
    # $Libs[$i]                name of the library whose index is $i, with
    #                          decorations as seen in its first appearance
    #
    # $LibsPntr[0][0]          integer number of libraries required by
    #                          the application
    #
    # $LibsPntr[0][1..n]       integer indices of libraries required by
    #                          the application
    #
    # $LibsPntr[$i + 1][0]     integer number of libraries required by
    #                          $Libs[$i]
    #
    # $LibsPntr[$i + 1][1..n]  integer indices of libraries required
    #                          by $Libs[$i]

    # $libP    index into $LibPntr for $lib
    my $libP;
    if( defined($libIndex {$libUndec}) )
    {
        $libP = $libIndex{ $libUndec } +1;
        if( $lib ne $libUndec ) { $libIndex {$lib} = $libIndex {$libUndec}; }
    }
    else { $libP = 0; }
    $Line =~ s/\t+/" "/g; # strip all the tabs
  $Line   =~ s/^\s+|\s+$//;
    (@t)  = split(/\s+/, $Line);

    # @t is an array of the incoming words

    foreach $t( @t )
    {
        # strip diversity and release
        my $tUndec = $t;
        $tUndec =~ s/_.*//g;
        if( !defined $libIndex{$tUndec} )
        {
            # we've never seen $t before; add it to the library list

            $Libs[$NrLibs] = $t; # remember the undecorated form
            $libIndex{$tUndec} = $NrLibs;
            $LibsPntr[++$NrLibs][0] = 0;
        }
        if( $t ne $tUndec ) { $libIndex {$t} = $libIndex {$tUndec}; }

        # $lib requires $t
        #
        # We add $t's index to the end of $lib's $LibsPntr array unless
        # it's already somewhere in the list.

        my $i;
        my $found = 0;
        for( $found = 0, $i = 1; ($i <= $LibsPntr[$libP][0]) and ($found == 0); $i++ )
        {
            if( $LibsPntr[$libP][$i] == $libIndex {$t} ) { $found = 1;

            #        break;
                }
        }
        if( !$found ) { $LibsPntr[$libP][++$LibsPntr[$libP][0]] = $libIndex {$t}; }
    }
}
#------------------------------------------------------------------------------
#
# FindDependentLibraries($makeDir, $makeName, $module)
#
# $makeDir/$makeName is a makefile for a particular module.
#
# $module is either the top level $BuildEntry or the name of a module on
# which $BuildEntry is directly or indirectly dependent.
#
# If we've seen $module before, we just return.
#
# If we can find a .l for the module, we read it and pass the contents
# to InterpretLine().
#
# If we can't find a .l for it, we invoke the makefile with
#   var=LIBS _sde_print_var
# to have him tell us what his immediate dependents are.
#
# Optimize by remembering anything we've already looked up and not
# looking it up again.
#
# Return the number of Libspecifications

sub FindDependentLibraries
{
    my ($makeDir, $makeName, $module) = @_;
    my $line;
    # $moduleUndec is $module without any diversity and release
    my $moduleUndec                   = $module;
    $moduleUndec =~ s/_.*//g;
    $moduleSeen {$moduleUndec} = 0;
    #This is a dead code as just above
    #the value is initialised to 0 and subsequently checked for 1
    # if we've seen this module before, just return
	if( $moduleSeen{$moduleUndec} == 1) { return($NrLibs); }
    $moduleSeen {$moduleUndec} = 1;
    # The .l file is found at
    #   $(_TMTGTBUILDROOT)/$(DIR_LOCAL)/tmp/$(_SDE_LIB_CONFIGURATION)/$(_SDE_DIVERSITY)/<comp>.l
    #
    # if _TMTGTBUILDROOT is not defined, _TMROOT is used; they both are
    # environment variables.
    # $(DIR_LOCAL) is possibly $moduleUndec or comps/$moduleUndec or the
    # last part of $moduleUndec.
    # $(_SDE_LIB_CONFIGURATION) is
    # $(DIR_CONFIG)_$(_TMTGTENDIAN)_$(_TMTGTCPUTYPE).
    # $(DIR_CONFIG) is $(_TMTGTCPUCLASS)$(_TMTOOLCHAIN)_$(_TMTGTOSCLASS).
    # $(_TMTGTCPUCLASS) is an available environmental.
    # $(_TMTGTOSCLASS) is an available environmental.
    # $(_TMTGTENDIAN) is an available environmental.
    # $(_TMTGTCPUTYPE) is an available environmental.
    # $(_SDE_DIVERSITY) is $(_TMDIVERSITY:%_=%)$(REL_SUFFIX).
    # $(_TMDIVERSITY) is an available environmental.
    # $(REL_SUFFIX) is derived from $(_TMTGTREL).
    # $(_TMTGTREL) is an available environmental.
    # <comp> is possibly $moduleUndec, or perhaps the part of $moduleUndec
    # after the last "/".
    #
    # name0:    $(_TMTGTBUILDROOT)/ or $(_TMROOT)/ if _TMTGTBUILDROOT is not defined
    # name1:    /tmp/$(_TMTGTCPUCLASS)_$(_TMTGTOSCLASS)_$(_TMTGTENDIAN)_$(_TMTGTCPUTYPE)/
    # name2:    $(_TMDIVERSITY:%_=%)
    # name3:    derived from $(_TMTGTREL)
    # name4:    the part of $moduleUndec after any last "/"
    # name5:    .l
    # name6:    .j
    #
    # Whew.

    my $name0;
    if( exists $ENV {'_TMTGTBUILDROOT'} ) { $name0 = "$ENV{'_TMTGTBUILDROOT'}/"; }
    else { $name0 = "$ENV{'_TMROOT'}/"; }
    my $name1 = "/tmp/"."$DirConfig"."_$ENV{'_TMTGTENDIAN'}_$ENV{'_TMTGTCPUTYPE'}/";
    my $name2 = $ENV {'_TMDIVERSITY'};

    #Sort the diversity items alphabetically.Ex. if _TMDIVERSITY is
    # _sp_flo_ ,then variable name2 should contain _flo_sp_
    my @diversity_items = sort(split(/_+/, $name2));
    $name2 = join('_', @diversity_items);

    my $name3 = $ENV {'_TMTGTREL'};
    if( ($name3 eq "ret") || ($name3 eq "retail") ) { $name3 = ($name2 eq "") ? "./" : "/"; }
    elsif( ($name3 eq "dbg") || ($name3 eq "debug") ) { $name3 = "_g/"; }
    elsif( $name3 eq "trace" ) { $name3 = "_t/"; }
    else { $name3 = "_a/"; }
    my $name4 = $moduleUndec;
    $name4 =~ s/^.*\///;
    my $name5 = ".l";
    my $name6 = ".j";

    my $lfile  = "$name0$moduleUndec$name1$name2$name3$moduleUndec$name5";
    if( !-f $lfile )
    {
        $lfile = "$name0" . "comps/$moduleUndec$name1$name2$name3$moduleUndec$name5";
        if( !-f $lfile )
        {
            $lfile = "$name0$name4$name1$name2$name3$moduleUndec$name5";
            if( !-f $lfile )
            {
                $lfile = "$name0$moduleUndec$name1$name2$name3$name4$name5";
                if( !-f $lfile )
                {
                    $lfile = "$name0" . "comps/$moduleUndec$name1$name2$name3$name4$name5";
                    if( !-f $lfile )
                    {
                        $lfile = "$name0$name4$name1$name2$name3$name4$name5";
                        if( !-f $lfile ) { $lfile = ""; # no .l lfile
                            }
                    }
                }
            }
        }
    }

    my $jfile  = "$name0$moduleUndec$name1$name2$name3$moduleUndec$name6";
    if( !-f $jfile )
    {
        $jfile = "$name0" . "comps/$moduleUndec$name1$name2$name3$moduleUndec$name6";
        if( !-f $jfile )
        {
            $jfile = "$name0$name4$name1$name2$name3$moduleUndec$name6";
            if( !-f $jfile )
            {
                $jfile = "$name0$moduleUndec$name1$name2$name3$name4$name6";
                if( !-f $jfile )
                {
                    $jfile = "$name0" . "comps/$moduleUndec$name1$name2$name3$name4$name6";
                    if( !-f $jfile )
                    {
                        $jfile = "$name0$name4$name1$name2$name3$name4$name6";
                        if( !-f $jfile ) { $jfile = ""; # no .l jfile
                            }
                    }
                }
            }
        }
    }

    # At this point, if $lfile is not empty, we can just read it for our
    # dependencies.  Otherwise, we have to ask the makefile to print the
    # LIBS variable for us.

	if( ($jfile ne "") && open(MAKEOUT, "< $jfile") )
    {
		# We can just use the .j jfile.
        while( defined($line = <MAKEOUT>) )
        {
            chomp $line;
            $line =~ s/^\s*//g;
      $line       =~ s/\s*$//g;
            $line =~ s/\s+/ /g; # replace more spaces by one space
            InterpretLine($module, $line);
        }
    }

	if( ($lfile ne "") && open(MAKEOUT, "< $lfile") )
    {
		# We can just use the .l lfile.
        while( defined($line = <MAKEOUT>) )
        {
            chomp $line;
            $line =~ s/^\s*//g;
      $line       =~ s/\s*$//g;
            $line =~ s/\s+/ /g; # replace more spaces by one space
            InterpretLine($module, $line);
        }
    }
    else
    {
        # Get the dependent library names by querying LIBS and JAVA_REQUIRES
        #on the console
        my $ExtraSDELibsGoal = "";

        #    if ($OnlyLFiles == 1){
        $ExtraSDELibsGoal = "_sde_libs";

        #    }
        PrintLog("SDE2: Executed command $MAKE -C $makeDir -f $makeName var=LIBS var2=JAVA_REQUIRES _sde_print_var_5 $ExtraSDELibsGoal\n") if ($DBG
                                                                                                                                                         == 1);
        open(MAKEOUT, "$MAKE --no-print-directory -C $makeDir -f $makeName var=LIBS var2=JAVA_REQUIRES _sde_print_var_5 $ExtraSDELibsGoal |") or die "Can't start $MAKE\n";
        while( defined($line = <MAKEOUT>) )
        {
            chomp $line;
            if( $line =~ /^\s*LIBS\s*=\s*/ )
            {
                $line =~ s/^\s*LIBS\s*=\s*//;
        $line         =~ s/\s*$//g;
                $line =~ s/\s+/ /g; # replace more spaces by one space
				InterpretLine($module, $line);
            }
            elsif( $line =~ /^\s*JAVA_REQUIRES\s*=\s*/ )
            {
                $line =~ s/^\s*JAVA_REQUIRES\s*=\s*//;
        $line         =~ s/\s*$//g;
                $line =~ s/\s+/ /g; # replace more spaces by one space
                if( $line ne "" ) { $java_is_required = 1; }
                InterpretLine($module, $line);
            }
        }
    }
    close MAKEOUT;
    return $NrLibs;
}
#-------------------------------------------------------------------
# Evaluate the library specification
# Find the RELTYPE, DIVERSITY and the module
#
sub EvalLibs
{
    my ($Libspec) = @_;
    my $Module;
    my $Rel;
    my $Cnt       = 0;
    my @elem;
    my $LastDiversityElem;
    my $i;

    $Rel = '*';
    if( $Libspec =~ /\$\(REL\_SUFFIX\)/ ) { $Rel = $DefaultRel;

    ($Libspec)                                   = split(/\$/, $Libspec, 2); }

    # Find possible Rel, is last parameter
    $Cnt    = $Libspec =~ tr/_/_/;

    #  print "Libspec= $Libspec. Count = $Cnt\n";                   # Debug statement
    $Module = $Libspec;
    if( $Cnt > 0 )
    {
        @elem          = split(/_/, $Libspec);
    $LastDiversityElem = $#elem -1;
        $Module        = $elem[0];
        if( $elem[$#elem] eq 'a' ) { $Rel = 'assert'; }
        elsif( $elem[$#elem] eq 'g' ) { $Rel = 'debug'; }
        elsif( $elem[$#elem] eq 't' ) { $Rel = 'trace'; }
        else { $LastDiversityElem = $#elem;

        $Rel                      = 'retail'; }

    #    for ($i = 1; $i <= $LastDiversityElem; $i++) { # Diversity may consist underscores
    #      $Diversity = "$Diversity$elem[$i]_";
    #    }
    #    if ($Diversity ne '') {
    #      $Diversity = "_".$Diversity;
    #    }
    }
    else { $Rel = 'retail'; }
    if( $Rel eq '*' ) { $Rel = $DefaultRel; }

    #  return ($Module, $Rel, $Diversity);
    return($Module, $Rel);
}
#------------------------------------------------------------------------------------
# call the Make for combination Component/Configuration
#
sub ExecMake
{
	( my $BuildEntry, my $BuildLocation, my $Rel) = @_;
	if (!exists $moduleBuilt{"${BuildEntry}_${BuildLocation}_${Rel}"}) {
	$moduleBuilt{"${BuildEntry}_${BuildLocation}_${Rel}"}= 1;
	my $Command;
    my $BuildLocDir;
    my $BuildType;
    my $errors;
    my $warnings;
    my $line;
    #  $ENV {$RELTYPE}   = $Rel;
    #  $ENV {$DIVERSITY} = $Diversity;
    $BuildLocDir = FindDirLocation("$BuildEntry/$BuildLocation");
    $BuildLocDir =~s!/$!!g;
    $BuildLocDir =~s!/+!/!g;
    if( $BuildEntry eq $CompsDirName ) { $BuildType = "Library";

    $BuildEntryValue                                = $BuildLocation; }
    else { $BuildType = "Application";
    $BuildEntryValue  = $BuildEntry;
    $BuildEntryValue  =~ s/comps\///; }
    if( $^O eq "MSWin32" )
    {
        ($Drive) = split(/\:/, $BuildLocDir);

        $Command = "$Drive:";
        PrintLog("SDE2: Executed command: $Command\n") if ($DBG == 1); # Debug statement
        system($Command);
    }
    chdir($BuildLocDir) or die "Can't chdir to $BuildLocDir\n";
    PrintLog("SDE2: chdir $BuildLocDir\n") if ($DBG == 1); # Debug statement
    ###Start time
    (@dateTime) = localtime(time);

    $startTime  = timelocal(@dateTime);
    my ($sec, $min, $hour, undef, undef, undef, undef, undef, undef) = @dateTime;
	if ($BuildType =~"Library") {
	@dllstobelinked=();
	@libstobelinked=();
	$dlllist="";
	$liblist="";
	if (defined $deferreddlls{$BuildLocation} && $LinkType=~ /^dynamic$/){
	@dllstobelinked=();
	@libstobelinked=();
	$dlllist="NONE ";
	$liblist="NONE ";
	$LibBuilt="DLL";
	open(MAKEOUT, "$MAKE --no-print-directory -f $NameMakefile var=_SDE_RECURSE_STATIC_LIBS _sde_print_var |") or die "Can't start $MAKE\n";
        PrintLog("SDE2: Looking for deferred dll dependencies\n") if ($DBG == 1);
        while( defined($line = <MAKEOUT>) )
        {
			$ExtradllGoal="";
			#    print "Line : $line <<\n";
            if( $line =~ /^\s*_SDE_RECURSE_STATIC_LIBS\s*=\s*/ )
            {
                $line =~ s/^\s*_SDE_RECURSE_STATIC_LIBS\s*=\s*//;                
                if( $line !~ /^$/ )
                {
		            @deferreddllsdeps = split /\s+/, $line;
					foreach $dll (@deferreddllsdeps) {
						if (defined $deferreddlls{$dll}) {
							push (@dllstobelinked,$dll);
							$ExtradllGoal .= "_${dll}_LOADED=$LoadType ";
						}
						elsif (defined $embeddlls{$dll}) {
							$ExtradllGoal .= "_${dll}_LOADED=$LoadType ";
							push (@dllstobelinked,$dll);
						}
						else {
							push (@libstobelinked,$dll);
						}
					}			
				}
			}
		}
		foreach $dll (@dllstobelinked) {
			$dlllist.="$dll ";
		}
		foreach $lib (@libstobelinked) {
			$liblist.="$lib ";
		}
		$dlllist =~s/ \s*$//g;
		$liblist =~s/ \s*$//g;
	}
	elsif (defined $embeddlls{$BuildLocation} && $LinkType=~ /^dynamic$/){
		@dllstobelinked=();
		@libstobelinked=();
		$dlllist="NONE ";
		$liblist="NONE ";
		$LibBuilt="DLL";
		open(MAKEOUT, "$MAKE --no-print-directory -f $NameMakefile var=_SDE_RECURSE_STATIC_LIBS _sde_print_var |") or die "Can't start $MAKE\n";
        PrintLog("SDE2: Looking for deferred dll dependencies\n") if ($DBG == 1);
        while( defined($line = <MAKEOUT>) )
        {
            $ExtradllGoal="";
			#    print "Line : $line <<\n";
            if( $line =~ /^\s*_SDE_RECURSE_STATIC_LIBS\s*=\s*/ )
            {
                $line =~ s/^\s*_SDE_RECURSE_STATIC_LIBS\s*=\s*//;                
                if( $line !~ /^$/ )
                {
		            @deferreddllsdeps = split /\s+/, $line;
					foreach $dll (@deferreddllsdeps) {
						if (defined $deferreddlls{$dll}) {
							push (@dllstobelinked,$dll);
							$ExtradllGoal .= "_${dll}_LOADED=$LoadType ";
						}
						elsif (defined $embeddlls{$dll}) {
							push (@dllstobelinked,$dll);
							$ExtradllGoal .= "_${dll}_LOADED=$LoadType ";
						}
						else {
							push (@libstobelinked,$dll);
						}
					}			
				}
			}
		}
	foreach $dll (@dllstobelinked) {
		$dlllist.="$dll ";
	}
	foreach $lib (@libstobelinked) {
		$liblist.="$lib ";
	}
	$dlllist =~s/ \s*$//g;
	$liblist =~s/ \s*$//g;
	}
	else
	{
		$LibBuilt="Static Library" if ($LinkType=~/^dynamic$/ && @deferreddllslist>0);
	}
	}
    if( $TargetSpecified eq "yes" )
    {
        my $printString = qq ($format2
Executing the target(s) $ExtraGoal_target for $BuildLocDir 
$format2\n);
        PrintLog($printString);
    }
    else
    {
   my $ConfigurationBuilt=$DirConfig."_$ENV{_TMTGTENDIAN}_$ENV{_TMTGTCPUTYPE}";
   if ($BuildType eq "Application") {
	   my $printString="";
      if ($ENV{$DIVERSITY}!~/^\s*$/) {
	  $printString
         = qq ($format2
Building: $BuildLocDir for $ConfigurationBuilt with $Rel and $ENV{$DIVERSITY}
$format2\n);
	  }
	  else {
      $printString
         = qq ($format2
Building: $BuildLocDir for $ConfigurationBuilt with $Rel
$format2\n);
	  }
           PrintLog($printString);
   }
   else {
	   my $printString="";
      if ($ENV{$DIVERSITY}!~/^\s*$/) {
      $printString
         = qq ($format2
Building $LibBuilt: $BuildLocDir for $ConfigurationBuilt with $Rel and $ENV{$DIVERSITY} ($CurLib/$NrLibs)
$format2\n);   
	  }
	  else {
      $printString
         = qq ($format2
Building $LibBuilt: $BuildLocDir for $ConfigurationBuilt with $Rel ($CurLib/$NrLibs)
$format2\n);   
	  }
           PrintLog($printString);
      }   
    }
    PrintLog("SDE2: Building $BuildType: $BuildLocation for $Rel, $ENV{$DIVERSITY}\n") if ($DBG == 1);

    my $ExtraGoal = "";
    if( $DefaultRel ne $Rel )
    {
        if( $Rel eq "debug" ) { $ExtraGoal = "_force_debug"; }
        elsif( $Rel eq "assert" ) { $ExtraGoal = "_force_assert"; }
        elsif( $Rel eq "trace" ) { $ExtraGoal = "_force_trace"; }
        elsif( $Rel eq "retail" ) { $ExtraGoal = "_force_retail"; }
    }
    #------------------------------------------------------------------
    # check for binary release
    #------------------------------------------------------------------
    my $BinaryReleaseAvailable = 0;
    if( $SkipBinary == 0 && $BuildType !~ "Application")
    {
        PrintLog("SDE2: Executed command: $ENV{'MAKE'} -f $NameMakefile var=TARGETNAME var2=JAVA_JARFILE _sde_print_var_5 $ExtraGoal\n") if ($DBG == 1);
        my $Cmd = "$ENV{'MAKE'} -f $NameMakefile check_binary_release 2>$BLACKHOLE";
        PrintLog("SDE2: Executing $Cmd\n") if ($DBG == 1);
	if (`$Cmd` =~ /check_binary_release=true/) {
	  $BinaryReleaseAvailable = 1;
	  PrintLog("Binary release available, skip the build process.\n") if ($DBG == 1);
	}
    } # skip binary release
    #------------------------------------------------------------------
    # start building process
    #------------------------------------------------------------------
    if( $TargetSpecified eq "yes" ) { $ExtraGoal = $ExtraGoal . " " . $ExtraGoal_target; }
    else { $ExtraGoal = "all " . $ExtraGoal; }
    if( $BinaryReleaseAvailable == 0 )
    {
	$Command = "$MAKE --no-print-directory -f $NameMakefile $ExtraGoal";
	$Command = "$MAKE --no-print-directory -f $NameMakefile $ExtraGoal ${ExtradllGoal} BUILD_DLLS=\"$dlllist\" BUILD_LIBS=\"$liblist\"" if (@deferreddllslist>0||@embeddllslist>0) && $BuildType!~"Application";
        PrintLog "SDE2: Executed command: $Command\n" if ($DBG == 1); # Debug statement

	$errors   = 0;
	$warnings = 0;
	@Contentsofpipe=();

        if (!open(PIPE, "$Command 2>&1|"))
	{
	  $Exit_value = $! + 0;
	  $Exit_value_summary += $Exit_value;
	} else {
	  while( defined($line = <PIPE>) )
	  {
            PrintLog($line) if ($QUIET != 1);
            if( $line =~ /\b(?:error|no rule)\b/i )
            {
                $errors++;
            }
            elsif( $line =~ /[^-]warning\b/i ) { $warnings++; }
			push (@Contentsofpipe,$line);
	  }
	  close(PIPE);
	  $Exit_value = ($?) / 256;
	  if ($Exit_value != 0 && $QUIET == 1) {
            map {print $_} @Contentsofpipe;
	  }
	  $Exit_value_summary += $Exit_value;
	  $errors ||= 1 unless $Exit_value == 0;
	}

        my (@dateTime) = localtime(time);
        my $endTime    = timelocal(@dateTime);
        my $elapsed    = $endTime -$startTime;
	   $comps_elapsed{$BuildEntryValue}=$elapsed if ($ShowTime == 1);
        if( $Exit_value != 0 )
        {
            $Message = "$BuildType: $BuildEntryValue : build_failed (Elapsed time: $elapsed sec)\n";
            #PrintLog("$Message \n");
        }
        #elsif ($warnings > 0)
        #{
        #  $Message = "$BuildType: $BuildLocation: built with warnings\n";
        #}
        else
        {
            $Message = "$BuildType: $BuildEntryValue : build completed (Elapsed time: $elapsed sec)\n";
            if( $TargetSpecified eq "yes" ) { $Message = "Target(s): $ExtraGoal_target: build completed\n"; }
        }
        #  if ($Exit_value > 0) {
        #     PrintLog ("$BuildType: $BuildLocation: build_failed\n");
        #  }
        #  else {
        #    PrintLog ("$BuildType: $BuildLocation: built successfully\n");
        #  }
        PrintLog($Message);
        exit(1) if $Exit_value != 0;

    #  close ERRORLOGFILE;
    } # binary release available
	}
	else{
		PrintLog("$format2\n$BuildLocation: Already built for another application\n$format2\n") if ($DBG == 1);
	}
}

sub do_PrintGraph
{
    #
    # Changes made for version 4.3
    #

    print "digraph SDEGraph {\n\tsize = \"7.27,10.69\";\n";               # 4.3
    ( $x) = @_;

    $x =~ s./._.g;                                                        # 4.3
    print "   App   [label=$x];\n";                                         # 4.3
    for( $i = 0; $i < $NrLibs; $i++ ) {                                   # 4.3
        print "   Comp$i \[label=$Libs[$i]\];\n";                           # 4.3
        }                                                                 # 4.3
    for( $i = -1; $i < $NrLibs; $i++ )
    {                                                                     # 4.3
        if( $i == -1 )                                                    # 4.3
            {                                                             # 4.3
            print "\tApp  -> {";                                          # 4.3
            }                                                             # 4.3
        else                                                              # 4.3
            {                                                             # 4.3
            print "\tComp$i -> {";                                        # 4.3
            }                                                             # 4.3
        for( $j = 1; $j <= $LibsPntr[$i +1][0]; $j++ )                    # 4.3
        {                                                                 # 4.3   
            print " Comp$LibsPntr[$i+1][$j]";                             # 4.3
            if( $j != $LibsPntr[$i +1][0] )                               # 4.3
                {                                                         # 4.3
                print ";";                                                # 4.3
                }                                                         # 4.3
        }                                                                 # 4.3
        print "}\n";                                                      # 4.3
    }                                                                     # 4.3
    print "}\n";                                                          # 4.3
    if( $PrintGraphFile ne '' )
    {                                                                     # 4.3
        open(GRAPHFILE, ">" . $PrintGraphFile);                           # 4.3      
        print GRAPHFILE "digraph SDEGraph {\n\tsize = \"7.27,10.69\";\n"; # 4.3
        $x = $BuildEntry;                                                 # 4.3

        $x =~ s./._.g;                                                    # 4.3
        print GRAPHFILE "   App   [label=$x];\n";                           # 4.3
        for( $i = 0; $i < $NrLibs; $i++ ) {                               # 4.3
            print GRAPHFILE "   Comp$i \[label=$Libs[$i]\];\n";             # 4.3
            }                                                             # 4.3
        for( $i = -1; $i < $NrLibs; $i++ )
        {                                                                 # 4.3
            if( $i == -1 )                                                # 4.3
                {                                                         # 4.3
                print GRAPHFILE "\tApp  -> {";                            # 4.3
                }                                                         # 4.3
            else                                                          # 4.3
                {                                                         # 4.3
                print GRAPHFILE "\tComp$i -> {";                          # 4.3
                }                                                         # 4.3
            for( $j = 1; $j <= $LibsPntr[$i +1][0]; $j++ )                # 4.3
            {                                                             # 4.3   
                print GRAPHFILE " Comp$LibsPntr[$i+1][$j]";               # 4.3
                if( $j != $LibsPntr[$i +1][0] )                           # 4.3
                    {                                                     # 4.3
                    print GRAPHFILE ";";                                  # 4.3
                    }                                                     # 4.3
            }                                                             # 4.3
            print GRAPHFILE "}\n";                                        # 4.3
        }                                                                 # 4.3
        print GRAPHFILE "}\n";                                            # 4.3
        close GRAPHFILE;                                                  # 4.3
    }                                                                     # 4.3
}

$SIG {'INT'} = \&Interrupt;
$SIG {'QUIT'} = \&Interrupt;
$SIG {'HUP'} = \&Interrupt;
#$SIG {'TRAP'} = \&Interrupt;
$SIG {'ABRT'} = \&Interrupt;
$SIG {'STOP'} = \&Interrupt;
$SIG {"INT"} = \&Interrupt;
;
$SIG {"QUIT"} = \&Interrupt;

sub Interrupt
{
    my ($signal) = @_;
    print "Caught Interrupt\: SIG{$signal} \n";
    print "Now Exiting\n";
    exit(1);
}
#--------------------------------------------------------------------------------------------
# Create loc_list files
# This function is not called.Hence can be removed. Another function by the same
# name is being executed
sub CreateMakelist
{
    eval {mkpath($_TMTGTBUILDPROJECT)};
   if ($@) {
   print "Couldn't create $_TMTGTBUILDPROJECT: $@";
   }
    readDomains($TM_PRJLIST);
    findComps();
    writeLocLists();
}
#---------------------------------------------------------------------------------------------

#----------------------------------------------------------------------
# Create a directory with all required parents
# Equivalent to "mkdir -p"
#
#sub mkdirp
#{
#    my $path = shift;
#    my $head;
#    my $tail;
#    if( -d $path ) { return; }
#    $path =~ m|^(.*)/([^/]+)$|;
#  $head   = $1;
#    $tail = $2;
#    if( $head ne "" ) { mkdirp($head); }
#    mkdir($path);
#}
#----------------------------------------------------------------------
# Exapand all $var, ${var}, $(var) environment variables
#
sub envExpand
{
    my $inp = shift;
    my $exp;
    my $var;
    my $pre;
    my $post;

    $exp = $inp;

    $var = "start";
    while( $var ne "" )
    {
        $var = "";
        if( $exp =~ m|(.*)\$(\w+)(.*)| ) { $pre = $1;
      $var                                      = $2;
        $post                                   = $3; }
        elsif( $exp =~ m|(.*)\$\{(\w+)\}(.*)| ) { $pre = $1;
      $var                                             = $2;
        $post                                          = $3; }
        elsif( $exp =~ m|(.*)\$\((\w+)\)(.*)| ) { $pre = $1;
      $var                                             = $2;
        $post                                          = $3; }
        if( $var ne "" ) { $exp = $pre . $ENV {$var} . $post; }
    }
    return $exp;
}
#----------------------------------------------------------------------
# Read project domains into internal array
#
sub readDomains
{
    my $prjlist = shift;

    # local *PH ;

    open(PH, "<$prjlist") || die("could not open $prjlist");
    local $/; # enable localized slurp mode
    #Read the entire file contents in 
    my $fileContents = <PH>;
    close PH;

    #Remove the contents if the line is commeneted 
    $fileContents =~ s/\#.*\n//g;

    #Split the file contents  on space
    my @paths = split(/\s+/, $fileContents);
    foreach my $eachPath( @paths )
    {
        chomp;
        $eachPath=~s/\s+//g;
        if( $eachPath ne "" )
        {
            #Expand the path and store it in the domain array
            $domain = envExpand($eachPath);
	    $domain =~ s/\\/\//g; 
            #Split the values on space
            my @splitValues = split(/ /, $domain);
            push @domains, @splitValues;
        }
    }
}
#----------------------------------------------------------------------
# Create hash of all comps/intfs
# Search project list from bottom to top
# Only save unique components in the hash
#
sub findComps
{
    my $domain;
    my $compMakefile;
    my @compMakefiles;
    my $intfsDir;
    my @intfsDirs;
    my $head;
    my $tail;

    #Added the appropriate path to search for the
    # files present on comps dir

    foreach $domain( reverse @domains )
    {
        my @compsDirs = glob("$domain/comps/*");
        foreach my $compsDir( @compsDirs )
        {
            if( $compsDir =~ / / ) { next; }
            if( !-d $compsDir ) { next; }

            # Get the component name and the directory path 
            #Store the value in the hash
            $compsDir =~ m|(.*)/([^/]+)$|;
      $head           = $1;
            $tail     = $2;
            if( !defined($comps {$tail}) ) { $comps {$tail} = "$head/$tail"; }
        }
        @intfsDirs = glob("$domain/intfs/*");
        foreach $intfsDir( @intfsDirs )
        {
            if( $intfsDir =~ / / ) { next; }
            if( !-d $intfsDir ) { next; }
            $intfsDir =~ m|(.*)/([^/]+)$|;
      $head           = $1;
            $tail     = $2;
            if( !defined($comps {$tail}) ) { $comps {$tail} = "$head/$tail"; }
        }
		@typesDirs = glob("$domain/types/*");
        foreach $typesDir( @typesDirs )
        {
            if( $typesDir =~ / / ) { next; }
            if( !-d $typesDir ) { next; }
            $typesDir =~ m|(.*)/([^/]+)$|;
			$head	= $1;
			$tail	= $2;
            if( !defined($comps {$tail}) ) { $comps {$tail} = "$head/$tail"; }
        }
    }
}
#----------------------------------------------------------------------
# write loc_list.mk and loc_list.txt
#
sub writeLocLists
{
    my $comp;
    my $dir;
    local * TH;
    local * MH;

    $string = qq(generating $LOC_LIST_FILENAME ...
generating $LOC_LIST_MKFILENAME ...\n$format\n);
    write();

    open(TH, ">$LOC_LIST_FILENAME") || die("could not open $LOC_LIST_FILENAME");
    open(MH, ">$LOC_LIST_MKFILENAME") || die("could not open $LOC_LIST_MKFILENAME");

    print MH "# $LOC_LIST_MKFILENAME\n";
    print MH "# DO NOT EDIT. This file has been generated automatically.\n";

    #: Write the contents of the hash comps into the file, loc_list.mk and loc_list.txt
    foreach $comp( sort keys %comps )
    {
        $dir = $comps {$comp};
        print TH "$comp $dir ";
        print MH "_$comp" . "_DIR := $dir\n";
    }
    print TH "\n";

    close(TH);
    close(MH);
}
#----------------------------------------------------------------------
# write prjlist.txt
sub writePrjList
{
    my $domain;
    local * PH;

    chmod(0777, $TM_PRJLIST);
    unlink($TM_PRJLIST);

    $string = qq(creating loc_list files ...
generating $TM_PRJLIST ...\n);
    write();

    open(PH, ">$TM_PRJLIST") || die("could not open $TM_PRJLIST");

    print PH "# $TM_PRJLIST\n";
    print PH "# DO NOT EDIT. This file has been generated automatically.\n";

    #: Write the contents present in domains array into the file, prjlist
    foreach $domain( @domains ) { print PH "$domain\n"; }
    close(PH);
}

################################################################################################
# Program start
#

$string
    = qq(\n$format1
     Build script for building components or executable and all their required libraries.\n\n
     build_exe.pl script version $Version\n 
    (c) NXP Semiconductors , 2006\n$format1\n);
write();

PrintLog("Debug mode.\n") if ($DBG == 1);

#------------------------------------------------------------------
# Build subdirectory
#------------------------------------------------------------------
if( $ENV {UNAME} ne "cygwin" ) { $temp_dir = -d '/tmp' ? '/tmp' : $ENV {TMP} || $ENV {TEMP}; }
else { $temp_dir = -d $ENV {TMP} ? $ENV {TMP} : $ENV {TEMP}; }

my @today = localtime(time);
my $applicationStartTime = timelocal(@today);
$ShowTime =0;
$ApplicationList=0;

#Formulate the subdirectory name
my $todaydate            = $today[3] . "-" . ($today[4] + 1)
                               . "-" . ($today[5] - 100) . "-" . $today[2] . "-" . $today[1] . "-" . $today[0];
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = @today;
	$DirConfig1 = "$ENV{'_TMTGTCPUTYPE'}_$ENV{'_TMTGTOS'}";

$BuildSubDir = $DirConfig1."_".$todaydate;

if( ($ENV {'_TMTGTCPUTYPE'} =~ /^tm/) and ($ENV {'_TMTGTOS'} =~  /^psos/) and (exists $ENV {'_TMTCSHOST'}) ) { $BuildSubDir
    = $BuildSubDir . $ENV{'_TMTCSHOST'}; }

if( exists $ENV {'_TMTGTBOARDS'} )
{
    my $boards = $ENV {'_TMTGTBOARDS'};
    $boards      =~ s/tmbsl//g;
      $boards    =~ s/ /_/g;
    $BuildSubDir = $BuildSubDir . $boards;
}

CheckEnvironment();
CheckParameters(@ARGV);
CreateMakelist();

my $error = 0;
$LinkType="";
$LinkType="dynamic" if ($ENV{"_TMLINKTYPE"}=~"dynamic");
$TmReports=$ENV{'_TMREPORTS'};
$TmReports =~ s/\\/\//g;
$error = ExistEnvironment('_TMREPORTS') if ($LOG == 1);

if( $error != 0 ) { exit 1; }

if( ($LOG == 1) && ($error == 0) && (not -d "${TmReports}/${BuildSubDir}") )
{
	eval {mkpath("${TmReports}/${BuildSubDir}")};
	if ($@) {
		print "Couldn't create ${TmReports}/${BuildSubDir}: $@";
   }
}

$DefaultRel    = $ENV {$RELTYPE};

#  $DefaultDiversity    = $ENV{$DIVERSITY};
$ReportLogfile = "${TmReports}/${BuildSubDir}/${ReportLogfile}";

open(REPORTLOGFILE, ">" . $ReportLogfile) or die "Unable to open $ReportLogfile for writing\n" if ($LOG == 1);
my $printYear = $year + 1900;
my $printMonth = $mon + 1;
my $printString = qq(Start time : $printYear-$printMonth-$mday at ${hour}Hrs. ${min}Mts. ${sec}Sec.
$format1 \n);
PrintLog($printString);

#  $Command = "$MAKE -f $ENV{'_TMROOT'}/sde/environment.mk makelist";
#  print STDOUT "SDE2: Executed command: $Command\n" if ($DBG == 1);               # Debug statement
#  print REPORTLOGFILE "SDE2: Executed command: $Command\n" if ($DBG == 1);
#  `$Command`;

#-------------------- Added for solving PR no 509 -----------------
#
#if (exists $ENV{'_TMTGTBUILDROOT'} and $ENV{'_TMTGTBUILDROOT'} ne $ENV{'_TMROOT'}) {
#  if ($ExtraGoal_target =~ /clean_all/) {
#   print STDOUT "Removing the Build location completely.....\n";
#   print REPORTLOGFILE "Removing the Build location completely.....\n";
#   $Command = "$MAKE -f $MakeDirectory\/$NameMakefile clean_all";
#        print STDOUT "SDE2: Executed command: $Command\n" if ($DBG == 1);               # Debug statement
#        print REPORTLOGFILE "SDE2: Executed command: $Command\n" if ($DBG == 1);
#       `$Command`;
#      $ExtraGoal_target =~ s/clean_all//; # Remove clean_all from the target string
#      if ($ExtraGoal_target =~ /^\s*$/) {
#      exit 1
#      }
#  }
#}
#
#---------------------------------------------------------------------------------------
# Creates tmFlags files appriory, PR 586
%moduleBuilt=();
foreach $BuildEntry (@apps_to_build) {
%moduleSeen=();
%comps_elapsed=();
%libIndex=();
$NrLibs =0;
@Libs=();
$MakeDirectory = FindDirLocation($BuildEntry);
if( !-e "$MakeDirectory\/$NameMakefile" ) { print "Error: Cannot find $MakeDirectory\/$NameMakefile\n";
$Exit_value_summary += 1;
next;}

#$Command = "$MAKE -C $MakeDirectory _TMNODEPENDENCIES=1 makelist";
#print "SDE2: Executed command: $Command\n" if ($DBG == 1);               # Debug statement
#print REPORTLOGFILE "SDE2: Executed command: $Command\n" if ($DBG == 1); # Debug statement
#`$Command`;

#: start First step:
# Recurses via LIB and JAVA_REQUIRES section thru component makefiles
# and creates *.l file.
# Circular dependencies are not allowed as it is a design error, print a error message 
#: end
#---------------------------------------------------------------------------------------
my $string = qq($format2\nBuilding $BuildEntry\n$format2\n);
PrintLog($string);

$OldNrLibs  = 0;

$OldNrLibs_ = 0;

$LibsPntr[0][0] = 0;

$NrLibs = FindDependentLibraries($MakeDirectory, $NameMakefile, $BuildEntry);

#: Check for the circular dependeny.If same entries present 
#in Libs array then set circ_deps flag to 1
while( $OldNrLibs_ < $NrLibs )
{
    #going recursively into all other libraries
    for( my $i = $OldNrLibs; $i < $NrLibs; $i++ )
    {
        my $libname = $Libs[$i];
        my $circ_deps = 0;
        for( my $j = 0; $j < $i; $j++ )
        {
            if( $Libs[$i] eq $Libs[$j] ) { $circ_deps = 1; }
        }
        if( $circ_deps == 0 )
        {
            $libname =~ s/(\w+)\$\(.*/$1/;
            my @libelem = split(/_/, $libname);
            $libname = $libelem[0];
            PrintLog("SDE2: Calculating recursively for $libname\n") if ($DBG == 1);
            $MakeDirectory = FindDirLocation("comps/$libname");

            $OldNrLibs     = $i +1;
            PrintLog("Recursing for $MakeDirectory $NameMakefile $libname\n") if ($DBG == 1);
            $NrLibs = FindDependentLibraries($MakeDirectory, $NameMakefile, $libname);
        }
        else {

        #: See here 
            PrintLog("Recursing for $Libs[$j] skipped. Possible circular dependencies! \n"); }
    }
    $OldNrLibs_ = $NrLibs;
} #end of while statement
#----------------------------------------  
# adding needed suffixes to the lib names
#----------------------------------------  
#:start Second step
# Goes thru _SDE_RECURSE_STATIC_SFX_LIBS which contains the 
# libs name required.
#end
my $line;
my @libslist;

if( $java_is_required == 0 )
{ # we are not able to make dep. graph from SDE2 if JAVA_REQUIRES section is present
    $BuildLocDir = FindDirLocation($BuildEntry);
    chdir($BuildLocDir) or die "Can't chdir to $BuildLocDir\n";

    PrintLog("SDE2: Make Dir: $BuildLocDir \n") if ($DBG == 1);
    open(MAKEOUT, "$MAKE --no-print-directory var=_SDE_RECURSE_STATIC_SFX_LIBS var2=_SDE_DEFERRED_DLLS var3=_SDE_EMBED_DLLS var4=DIR_CONFIG _sde_print_var_5 |") or die "Can't start $MAKE\n";
    while( defined($line = <MAKEOUT>) )
    {
        chomp $line;
        if( $line =~ /^\s*_SDE_RECURSE_STATIC_SFX_LIBS\s*=\s*/ )
        {
            $line =~ s/^\s*_SDE_RECURSE_STATIC_SFX_LIBS\s*=\s*//;
        $line     =~ s/\s*$//g;
            $line =~ s/\s+/ /g; # replace more spaces by one space
            PrintLog("Libs line: $line \n");
            @libslist = split /\s+/, $line;
        }
	elsif( $line =~ /^\s*_SDE_DEFERRED_DLLS\s*=\s*/  && $LinkType=~ /^dynamic$/)
        {
            $line =~ s/^\s*_SDE_DEFERRED_DLLS\s*=\s*//;
			$line =~ s/\s*$//g;
            $line =~ s/\s+/ /g; # replace more spaces by one space
            PrintLog("\nDeferred DLLS required: $line \n\n") if ($line!~/^\s*$/);
            @deferreddllslist = split /\s+/, $line;
			foreach $dll (@deferreddllslist) {
				$deferreddlls{$dll} = 1;
			}			
        }
	elsif( $line =~ /^\s*_SDE_EMBED_DLLS\s*=\s*/  && $LinkType=~ /^dynamic$/)
        {
            $line =~ s/^\s*_SDE_EMBED_DLLS\s*=\s*//;
			$line =~ s/\s*$//g;
            $line =~ s/\s+/ /g; # replace more spaces by one space
            PrintLog("Embed DLLS required: $line \n\n") if ($line!~/^\s*$/);
            @embeddllslist = split /\s+/, $line;
			foreach $dll (@embeddllslist) {
				$embeddlls{$dll} = 1;
			}			
        }
        {
            $line =~ s/^\s*DIR_CONFIG\s*=\s*//;
			$line =~ s/\s*$//g;
            $line =~ s/\s+/ /g; # replace more spaces by one space
	    $DirConfig=$line;
        }
    }
    close MAKEOUT;
}

if( $PrintGraph ) { do_PrintGraph($BuildEntry); }

if( ($java_is_required == 1) || ((@libslist == 0) and ($NrLibs > 0)) )
{
    # Here we are building only a component without EXPORTS section
    # Therefore the LIBS line is empty and we apply the previous algorithm.

    if( $java_is_required == 0 )
    {
        $string
            = qq(\nWARNING: No other components are required to build this component!
                    However we build all dependent libraries with their default flavours, which will be needed on the level of executable or DLL!
                    Libraries to be build: \n);
        PrintLog($string);
    }
    foreach $x( @Libs ) { PrintLog("$x\n") }
    ; # Debug statement
    ########################## 1.1.6 Algorithm applies -- begin

    my $AllBuilds = $NrLibs;
    my $OldAllBuilds = -1;
    my $ForceBuild = 0;
    $CurLib = 0;

    #:Commented     while (($AllBuilds>0) and ($OnlyLFiles==0)){
    if( $OnlyLFiles == 0 ) { do
    {
        #:Commeneted             for ($i = $NrLibs-1; ($i >= 0) && ($AllBuilds>0); --$i) {
        for( $i = $NrLibs -1; $i >= 0; $i-- )
        {
            if( ($LibsPntr[$i +1][0] == 0) or (($LibsPntr[$i +1][0] > 0) and ($ForceBuild == 1)) )
            {
                ($Module, $Rel) = EvalLibs($Libs[$i]);
      $CurLib += 1;
                ExecMake($CompsDirName, $Module, $DefaultRel);
                $LibsPntr[$i +1][0] = -1;

                #remove all pointers
                if( $ForceBuild == 0 )
                {
                    for( $j = -1; $j < $NrLibs; $j++ )
                    {
                        for( $k = 1; $k <= $LibsPntr[$j +1][0]; $k++ )
                        {
                            if( $LibsPntr[$j +1][$k] == $i )
                            {
                                for( $kk = $k; $kk
                                    < $LibsPntr[$j +1][0]; $kk++ ) { $LibsPntr[$j +1][$kk] = $LibsPntr[$j +1][$kk +1]; }
                                $LibsPntr[$j +1][0]--;
                            }
                        }
                    }
                }
                $AllBuilds--;
                if( $Exit_value > 0 and $Fail eq 'stop' )
                {
                    $AllBuilds = -2; #last
                    PrintLog("EXIT!\n");
		    exit 1;
                }
                ;
            }
            $Exit_value_summary += $Exit_value;
        } #        print "#### End of for loop\n";
        if( $OldAllBuilds == $AllBuilds )
        {
            $ForceBuild = 1;
            PrintLog("Dependency graph failed, forcing the build!\n");
        }
    }while($AllBuilds < 0); # To be removed
        }                   #    print "#### End of while loop\n";
########################## 1.1.6 Algorithm applies -- end
}
else
{
    $CurLib = 0;
    if( $OnlyLFiles == 0 )
    {
        PrintLog("Number of Libs: $NrLibs\n") if ($DBG == 1); # Debug statement
        foreach $libsitem( reverse @libslist )
        {
            if( $Exit_value == 0 or $Fail eq 'go' )
            { # no errors
                my @listdiv = split /_/, $libsitem;

                #              for (my $ii=1; $ii<@listdiv; $ii++){
                #            if (($listdiv[$ii] ne 'g') and ($listdiv[$ii] ne 'a') and (not ($ENV{'_TMDIVERSITY'} =~ "_$listdiv[$ii]_"))){
                #                     PrintLog ("$format2\n");
                #                     PrintLog ("Warning: Required diversity _".$listdiv[$ii]."_ is not present in _TMDIVERSITY !!!\n");
                #            }
                #              }
                ($Module, $Rel) = EvalLibs($libsitem);
      $CurLib += 1;
                ExecMake($CompsDirName, $Module, $Rel);
            }
            ;
        }
    }
} # end of else statement


if( ($Exit_value == 0 or $Fail eq 'go') and ($OnlyLFiles == 0) )
{
    ExecMake($BuildEntry, "", $DefaultRel);
    $Exit_value_summary += $Exit_value;
}

my @endtoday = localtime(time);
my $applicationEndTime = timelocal(@endtoday);
my $totalTime = $applicationEndTime -$applicationStartTime;
print "\n$format\n";
if ($ShowTime == 1) {
   foreach $component (keys(%comps_elapsed)) {
      PrintLog("\t$component : $comps_elapsed{$component} Seconds\n");
   }
   PrintLog("$format\nTotal time taken to build $BuildEntry = $totalTime sec \n$format\n");
}
}
close REPORTLOGFILE;
# Don't just exit with $Exit_value_summary, because if it is 256 then it's the same
# as exiting with 0!
exit ($Exit_value_summary == 0 ? 0 : 1);

#
# Program end
################################################################################################
