#!perl -w
use strict;

# import some modules
use File::Spec;

# define global variables
my $inputDir=$ARGV[0];
my $outFile=$ARGV[1];
my $pathSetDir=$ARGV[2];
my $condition;

my @TI_LIBS;
my @TI_MAIN_LIBS;
my (@TI_BSS_LIBS, @TI_CONST_LIBS, @CONST_BOOT_LIB, @BSS_BOOT_LIB,@BSS_DAR_LIB);
my (@SP_LIB, @SP_LOC);
my @CMD_TEMPLATE;

if ($#ARGV < 0) {
  print "usage:   gen_targetSet <inputDir> <outputFile> <pathSetDir>\n";
  print "example: gen_targetSet busyb_integration busyb_integration/tsFragment.xml x:/g23m/system/busyb\n";
  exit;
}

# Find the target set files
#
my @tsFiles = glob("$inputDir/*.ts");
$#tsFiles >= 0 || die "No *.ts files found\n";

# open the output file
#
open (OUT,">$outFile")||die "can't open $outFile \n";

# process all input files
#
foreach (@tsFiles) {
  my $line;
  # open the input file
  #
  open (IN,"<$_")||die "can't open $_ \n";

  # calculate the condition 
  #
  $condition = calcConditionFromFileName($_);

  # read the input file
  #
  while(defined($line = <IN>))
  {
    # remove trailing \n
    chomp($line);
    
    # now find all entries and generate corresponding output strings
    #

    # first the "normal" libs
    if ($line =~ /^\[TI_LIBS\]\s*/) {
      my @tmp = split(/\s+/,$');
      my $element;
      foreach $element(@tmp) {
        my $libName = calcRelativePathFromPathset ($element, $pathSetDir);
        # all *main* libs must be placed at the very beginning,
        # otherwise the Visual Linker complains
        if ($libName =~ /\\main_/) {
          push(@TI_MAIN_LIBS, "<sourceFile pathRef=\"\" path=\"$libName\" require=\"$condition\"/>");
        }
        else {
          push(@TI_LIBS, "<sourceFile pathRef=\"\" path=\"$libName\" require=\"$condition\"/>");
        }
      }
    }
    # now the linker command file templates
    elsif ($line =~ /^\[CMD_TEMPLATE\]\s*/) {
      my $fileName = calcRelativePathFromPathset ($', $pathSetDir);
      push (@CMD_TEMPLATE, "<sourceFile pathRef=\"\" path=\"$fileName\" require=\"$condition\"/>");
    }

    # now all others: that are those that need memory placement
    # (TI_BSS_LIBS, TI_CONST_LIBS, CONST_BOOT_LIB, CONST_BOOT_LIB, BSS_BOOT_LIB, BSS_DAR_LIB)
    elsif ($line =~ /^\[(\w+)\]\s*/) {
      my $restLine = $';
      my $pattern = $1;

      # replace TI_BSS_LIBS with BSS_LIBS and TI_CONST_LIBS with CONST_LIBS
      $pattern =~ s/TI_BSS_LIBS/BSS_LIBS/;
      $pattern =~ s/TI_CONST_LIBS/CONST_LIBS/;

      my @AoA;
      my @tmp = split(/\s+\(|\)\s+/,$restLine);
      @AoA = createLibAndLocArrays(\@tmp, "$pattern", $condition);
      push(@SP_LIB, @{$AoA[0]});
      push(@SP_LOC, @{$AoA[1]});
    }
  }
  # close the input file
  #
  close IN;
}

# now generate the output file
#
print OUT "<!-- This is a generated file! Do not change ! -->\n\n";
print OUT "<!-- It's output is based on the information in the following files:\n";
foreach (@tsFiles) {
  print OUT "\t$_\n";
}

print OUT "-->\n<!-- All of it must be placed somewhere in a targetSet document! -->\n\n\n";

print OUT "<!-- The next lines contain all SSA lib's that DO NOT NEED special memory placement! -->\n\n";
foreach (@TI_MAIN_LIBS,@TI_LIBS) {
  print OUT "$_\n";
}
print OUT "\n\n\n\n\n";

print OUT "<!-- The next lines contain all linker command file templates! -->\n\n";
foreach (@CMD_TEMPLATE) {
  print OUT "$_\n";
}
print OUT "\n\n\n\n\n";

print OUT "<!-- The next lines contain memory placement commands for all SSA lib's that DO NEED special memory placement! -->\n\n";
foreach (@SP_LOC) {
  print OUT "$_\n";
}
print OUT "\n\n\n\n\n";

print OUT "<!-- The next lines contain all SSA lib's that DO NEED special memory placement!\nThe order corresponds with the previews section. Do not change it!-->\n\n";
foreach (@SP_LIB) {
  print OUT "$_\n";
}


# close the file
#
close OUT;


######################################################################################################
# this function takes as the input the output of split for all libs that need special memory placement
# this is an array which looks as follows
# Array: liba (.text) libb (.const) ...
#
# it returns two arrays which lokk as follows
# Array A: liba libb ..
# Array B: (.text) (.const)
#
sub createLibAndLocArrays
{
  my @libsAndSections = @{$_[0]};
  my $section = $_[1];
  my $condition = $_[2];
  my $i = 0;
  my (@libs, @places);

  foreach (@libsAndSections) {
    if($i==0)  {
      my $libName = calcRelativePathFromPathset ($_, $pathSetDir);
      push(@libs, "<sourceFile pathRef=\"\" path=\"$libName\" require=\"$condition\"/>");
      $i++;
    }
    else {
      my $location = "($section)-($_)+";
      push(@places, "<condValue value=\"$location\" require=\"$condition\" />" );
      $i--;
    }
  }

  return (\@libs, \@places);
}


###########################################
# calculate the condition from the filename
# make aaa==1 &#38 bbb==2 from aaa1_bbb2.ts
#
sub calcConditionFromFileName
{
my $condition = "";
my @cond;
my $i = 0;

# remove directory part
my ($drive,$directories,$file);
($drive,$directories,$file) = File::Spec->splitpath($_[0]);

# now remove file extension
$file =~ /\.\w*/;

# now split the name into sub conditions e.g. aaa1 bbb2
@cond = split(/_/,$`);

foreach (@cond) {
  while (s/([a-zA-Z0-9]+)-(\d+)//) {
    $condition = $condition . "(" . $1 . "==" . $2 .")";
    defined($cond[++$i]) && ($condition = $condition . " &#38;&#38; ");
    }
  }
  $condition =~ s/ &#38;&#38; $//;
  return $condition;
}
###########################################

########################################################
# correct obscure behavior of File::Spec->abs2rel,
# which inserts a drive letter befor a relative path !!!
#
sub calcRelativePathFromPathset
{
  my ($drive,$directories,$file);

  ($drive,$directories,$file) = File::Spec->splitpath( File::Spec->abs2rel ($_[0], $_[1]) );

  return File::Spec->catpath("",$directories,$file);
}
########################################################
