:
eval 'exec perl -wS $0 ${1+"$@"}'
    if 0;
#*************************************************************************
#
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# 
# Copyright 2000, 2010 Oracle and/or its affiliates.
#
# OpenOffice.org - a multi-platform office productivity suite
#
# This file is part of OpenOffice.org.
#
# OpenOffice.org is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License version 3
# only, as published by the Free Software Foundation.
#
# OpenOffice.org is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License version 3 for more details
# (a copy is included in the LICENSE file that accompanied this code).
#
# You should have received a copy of the GNU Lesser General Public License
# version 3 along with OpenOffice.org.  If not, see
# <http://www.openoffice.org/license.html>
# for a copy of the LGPLv3 License.
#
#*************************************************************************
#
use XML::Parser;
# ------------------------------------------------------------------------
# Other global stuff
$is_debug=0;
my $path = $ENV{'INPATH'} . "/";
my $quot = '"';
my %template_hash=();
my %vcproj_hash=();
# ------------------------------------------------------------------------
# Global stuff for parsing the *.vcproj files (XML::Parser)
#
my $ConfigurationGlobal = 1; # Release = 1, Debug=0
my $Configuration = undef;
my %configelements = ();
my %files = ();
my %files2copy = ();
my %files_special = ();
my $Release = 1;
     # Release = 1, Debug = 0, undef = 2
my $file_tmp = "";      # temporary storage for file name
my $CustomSection = 0;
# ------------------------------------------------------------------------
# ------------------------------------------------------------------------
# e.g. %object_hash with Key = blabla.cpp
# contains a Hash:
# Header: "..\\common\\unicode\\utypes.h ..\\common\\unicode\\uset.h"
# CFlags: Common (set in templates file) or special sequence
# CDefs:  Common (set in templates file) or special sequence
# ------------------------------------------------------------------------
my $configfile = shift;
my $sourcePath = shift;
if ( !$configfile ) {
    $configfile = "createmak.cfg";
}
if ( !$sourcePath ) {
    $inpath = $ENV{"INPATH"};
    $sourcePath = $inpath . "\\misc\\build\\icu\\source";
}
$dir = "";
$header = "";
$sep = "\\\\";

%project_by_id =();
%project_by_name = ();
%project_dependencies = ();
my @builddeps = prepare_allinone_all_mak(\%project_by_id,\%project_by_name,\%project_dependencies,$sourcePath);

fillTemplateHash($configfile);

create_allinone_all_mak(\@builddeps,\%project_by_id,$sourcePath);
my @dirs = ();
foreach $projectname(keys %project_by_name)
{
    my $dir = $project_by_name{$projectname}[1];
    $dir =~ /\.\.\\(.+)\\(.+)\.vcproj/;
    my $dir1 = $1;
    my $dir2 = $2;
    if ( $dir1 !~ /$dir2$/ ) {
        $dir1 .= "\.$dir2";
    }
    print "$dir1 - $dir2\n" if ($is_debug);
    push @dirs, $dir1;
}

# set nonpro switch (linking against debug runtime if nonpro=1)
my $nonpro = ($ENV{"PROEXT"} ne ".pro");
print "Non Product Build" if ($nonpro);

foreach $dir(@dirs)
{
    next if ($dir eq "data.makedata"); # very special don't overwrite this file
    # ------------------------------------------------------------------------
    # Reset global stuff for parsing the *.vcproj files (XML::Parser)
    #
    $Configuration = $ConfigurationGlobal; # Release = 1, Debug=0
    %configelements = ();
    %files = ();
       # contains all relevant *.c,*.cpp,*.h,*.rc files
    %files2copy = ();
    %files_special = ();
    $Release = 2;
     # Release = 1, Debug = 0, undef = 2
    $file_tmp = "";      # temporary storage for file name
    $CustomSection = 0;
    # ------------------------------------------------------------------------

    my $extra_mak = "";
    ($dir, $extra_mak) = handle_extra_mak_files($dir); # handle e.g. tools/genrb.derb entires

    my @mak=(); # Array for make file *.mak
    my %deps=();
    my %object_hash=();
    my %collected_header=();
    my %collect_header_target_hash=();
    my %collect_object_target_hash=();
    my $vcproj_file = "";
    my $resource_file = "";

    # $dir : common,i18n,...
    chomp $dir;
    next if ( $dir eq "" );
    my $fullpath = $sourcePath . "\\" . $dir;
    if ( $extra_mak eq "" ) {
        if ($dir =~ /(.+)+\\(.+)$/)
        {
            $vcproj_file = $fullpath ."\\$2.vcproj";
        } else
        {
            $vcproj_file = $fullpath ."\\$dir.vcproj";
        }
    } else
    {
        $vcproj_file = $fullpath . "\\" . $extra_mak . ".vcproj";
    }


    # Parse the *.vcproj file
    my $parser = new XML::Parser(ErrorContext => 2);
    $parser->setHandlers(Start => \&start_handler,
                 Char  => \&char_handler);
    $parser->parsefile($vcproj_file);
    if ( $file_tmp ) {
        # save a file which hasn't been saved yet
        $files{ $file_tmp } = 1;        # save it now
        $file_tmp = "";                 # has been saved now reset it
    }

    # is there a resource file?
    foreach $i (keys %files)
    {
        if ($i =~ /\.rc/)
        {
            $resource_file = $i;
        }
    }
    # Fill hash %deps for dependencies for all files in directory ($testdir)
    # %files contains all relevant files from *.vcproj

    getAllFilesDeps($fullpath,\%deps,\%files);
    my $includedir = $configelements{"Release"}{"OutputDirectory"};     # e.g. OutputDirectory = ..\..\lib
    $includedir =~ s/lib/include/;
    foreach $file( sort keys %deps)
    {
        $file =~ /(.+)\.(.+)/;
        my $name = $1;
        my $ext  = $2;
        next if (!defined $name);
        $object = "\$(INTDIR)\\" . "$name.obj";
        $collect_object_target_hash{$object}=1;

        createMakDepSection($dir,$name,$ext,$deps{$file},\@mak,\%files_special);
    }
    my %all_target_hash=();
    foreach $header(sort keys %files2copy)
    {
        my $dir;
        my $file;
        #$pathdepth = "..\\..";
        $file = $header;
        $header =~ s/^\.\\//;
        $inputpath = $file;
        $target = $includedir . "\\" . $header;
        $target =~ /.+\\(.+)\\.+$/;
        $targetpath = $configelements{"Release"}{"CommandLine"};
        chomp $targetpath;
        # set %all_target_hash and @mak
        createCopySection($file,$inputpath,$target,$targetpath,\@mak,\%all_target_hash);
        $collect_header_target_hash{$target}=1;
    }
    my $test = $configelements{"Release"}{"OutputFile"};
    $all_target_hash{$test}=1;

    # set name of the *.mak file
    my $mak_file="";
    if ( $extra_mak eq "" ) {
        $mak_file = $vcproj_file;
        $mak_file =~ s/vcproj/mak/;
    } else
    {
        # extra_mak eg. derb, stringperf
        $mak_file = $fullpath . "\\$extra_mak" . "\.mak";
    }

    # generate the content of the *.mak file
    # in @mak array
    print "extra_mak=$extra_mak\n" if ($is_debug);
    print "mak_file=$mak_file\n" if ($is_debug);
    open(MAKFILE, ">$mak_file") || die "Can't open $mak_file\n";
    print_all_target($fullpath, \%all_target_hash);

    # $extra_mak handles further *.mak files in a directory
    print_flags($dir,$extra_mak,'CFlags',$nonpro);    # depends on directory
    print_simple_flag("Rules");
    print_simple_flag("Link");
    print_common_linkflags();
#    print_flags($fullpath,$extra_mak,'LinkFlags'); # depends on directory
#    print_lib32_objs($fullpath,$extra_mak,\%collect_object_target_hash,$resource_file);
    print_flags($dir,$extra_mak,'LinkFlags'); # depends on directory
    print_lib32_objs($dir,$extra_mak,\%collect_object_target_hash,$resource_file);

    # write @mak array into the *.mak file
    foreach $line(@mak)
    {
        print MAKFILE $line;
    }
    $|=1;
    print "."; # user entertainment
    $|=0;
}
print "\ndone\n";
exit;

############################################################################
sub getKey		#01.04.2008 09:46
############################################################################
 {
    my $line = shift;
    $line =~ /\[(.+)\]/;
    return $1;
}	##getKey

############################################################################
sub fillTemplateHash		#01.04.2008 10:48
############################################################################
 {
    my $file = shift;
    open (TEMPLATE, "< $file") || die "Can't open template file $file\n";
    my $key = "";
    while ( $line=<TEMPLATE> ) {
        if ( $line =~ /\[.+\]/ ) {
            print $line if ($is_debug);
            if ( $key ne "" ) {
                $template_hash{$key}=[@cmdlines];
                @cmdlines="";
                $key="";
            }
            $key = getKey( $line );
        } else
        {
            push @cmdlines, $line;
        }
    } # while
}	##fillTemplateHash

############################################################################
sub createCopySection		#01.04.2008 11:37
############################################################################
 {
    my $header	   = shift;
    my $inputpath  = shift;
    my $target	   = shift;
    my $targetpath = shift;
    my $ref_make_file = shift; # Array written later to make file *.mak
    my $ref_all_target_hash = shift;  # reference to fill all_target_hash;
    if ( $target !~ /\\include/ && $target !~ /\\bin/) {
        return; # $target contains nonsense
    }
    if ( !$targetpath ) {
        # $targetpath is empty! (Due to missing entry in *.vcproj file)
        # Generate $targetpath here from $target
        my $t = $target;
        $t =~ /(.+)\\(.+)$/;
        $targetpath = "copy \"\$(InputPath)\" " . $1;
        chomp $targetpath;
    }
    $targetpath =~ s/\r$//; # remove x0A from EOL if the is one
    my @template = @{$template_hash{"Copy"}};
    my $line = "";
    foreach $line(@template)
    {
        $line =~ s/<HEADER>/$header/g;
        $line =~ s/<INPUTPATH>/$inputpath/g;
        $line =~ s/<TARGET>/$target/g;
        $line =~ s/<TARGETPATH>/$targetpath/;
        push @{$ref_make_file}, $line;           # from template
        $$ref_all_target_hash{$target} = 1;       # "\"$target\" ";
     # save for target ALL:
    }
}	##createCopySection

############################################################################
sub createMakDepSection		#01.04.2008 13:36
############################################################################
 {
    # creates the dependency section in the make file
    my $dir         = shift;
    my $source 		= shift;
    my $extension	= shift;
    my $ref_header_list	= shift;
    my $ref_make_file = shift; # Array written later to make file *.mak
    my $ref_special_file = shift; # hash for special files (compiler flags, include paths)
    my $header_list = "";
    my $special_flag = 0;

    return if ( !defined $source );
    foreach $header(@{$ref_header_list})
    {
        if ( ($header =~ /^\.\.\\.+/) && (-e $header )) {
            $header_list = $header_list . " " . $header; # this header is located in an other directory
        } else
        {
            $header_list = $header_list . " .\\" . $header;
        }
    }

    #special handling
    # compile this file with other compiler switches
    my $file = $source . "\." . $extension;
    $dir =~ s/\\/_/;
    my @template = @{$template_hash{"CFlags_$dir"}};
    if ( defined $$ref_special_file{"AdditionalIncludeDirectories"}{$file} ) {
        $special_flag = 1;
        my $includepath = $$ref_special_file{"AdditionalIncludeDirectories"}{$file};
        $includepath =~ s/\;/\/I /g;                   # subst ; with /I for multiple paths
        $line = "CPP_SWITCH_INCLUDE=/I  $includepath\n";
        push @{$ref_make_file}, $line;
        foreach $line(@template)
        {
            if ( $line =~ /CPP_PROJ/)
            {
                $line =~ s/CPP_PROJ=/CPPX_PROJ=/;
                $line =~ s/\$\(CDEFS\)/\$\(CDEFS\) \$\(CPP_SWITCH_INCLUDE\)/; # include $(CPP_SWITCH_INCLUDE)
                push @{$ref_make_file}, $line;
            }
        }
    }
    if ( $$ref_special_file{"DisableLanguageExtensions"}{$file} )
    {
        # FALSE = /Ze
        $special_flag = 1;
        foreach $line(@template)
        {
            if ( $line =~ /CPP_PROJ/)
            {
                $line =~ s/CPP_PROJ=/CPPX_PROJ=/;
                $line =~ s/-Za/-Ze/;
                if ( $nonpro )
                {
                    # if non product link against debug libraries
                    $line =~ s/-MD/-MDd/;
                    $line =~ s/-MT/-MTd/;
                }
                push @{$ref_make_file}, $line;
            }
        }
    }

    @template = @{$template_hash{"Deps"}};
    my $line = "";
    foreach $line(@template)
    {
        $line =~ s/<SOURCEFILE>/$source/g;
        $line =~ s/<EXT>/$extension/g;
        $line =~ s/<HEADER_LIST>/$header_list/g;
        push @{$ref_make_file}, $line;
    }

    if ( $special_flag )
    {
        pop @{$ref_make_file}; # remove empty line
        push @{$ref_make_file},"\t\$(CPP) @<<\n";
        push @{$ref_make_file},"\t\$(CPPX_PROJ) \$(SOURCE)\n";
        push @{$ref_make_file},"<<\n\n";
        $special_flag = 0;
    }

}	##createMakDepSection


############################################################################
sub getFilenameFromPath		#10.04.2008 13:03
############################################################################
{
    my $path = shift;
    $path =~ /.+\\(.+)$/;
    return $1;
}	##getFilenameFromPath

############################################################################
sub getAllFilesDeps		#08.04.2008 09:39
############################################################################
{
    my $path = shift;
    my $ref_deps = shift;
    my $ref_allfiles = shift;       # contains all relevant files from *.vcproj
    my %local_header_hash=();       # contains all local header

    my @all_files = keys %{$ref_allfiles};

    # collect lokal header names in %header_hash
    foreach $file(@all_files)
    {
        if ( $file =~ /.+\.h/ ) {
            chomp $file;
            $local_header_hash{$file} = 1;
        }
    }

    foreach $file(@all_files)
    {
        my @header_deps=();
        my $skip = 0;

        $file =~ s/^\.\\//; # remove leading .\

        # exclude sub directories and several file extensions
        # *.dep,*.h,*.in,*.mak,*.pl,*.txt,*.vcproj.*.rc and origs of patch files (*.*~) and
        # .cvsignore (files beginning with .)
        next if ( (-d "$path$sep$file") || ($file =~ /.+(_|\~|dep|h|in|mak|pl|txt|vcproj|rc)$/) || ($file =~ /^\.+./));
        parse_header_deps($path,$file,\@header_deps,\%local_header_hash);
        handle_dep_to_other_directory($path,$file,\@header_deps,$$ref_vcproj{$file}) if ($$ref_vcproj{$file});
        $$ref_deps{$file}=[@header_deps];
    }
}	##getAllFilesDeps

 ############################################################################
 sub parse_header_deps		#14.06.2006 18:04
 ############################################################################
  {
    # get includes from c/cpp file
    # call create_deps(path,file,\$link_obj)
    #
    my $path = shift;
    my $cfile = shift;
    my $ref_header_deps = shift;
    my $ref_local_header_hash = shift;

    my $fullpath = $path . $sep . $cfile;
    my $unicodedep="";
       open(IN, "<$fullpath") || die "can't open $fullpath\n";
    while ( $line = <IN> ) {
        next if ($line !~ /^.?\#include.+/); # handle include lines only
        if ($line =~ /.+?\s(.+)/)
        {
            $header = $1;
            if ( ($header !~ /^<.+/) && ($header !~ /.+\.c.+$/) ) {
                # no <stdio> etc. header
                $header =~ s/\s+\/\*.+\*\///; # delete <blanks>/* ... */
                $header =~ s/\s+\/\/.+//;	   # delete <blanks>//......
                $header =~ s/\//\\/;		   # subst. / with \
                $header =~ s/^\"/\".\\/;
                $header =~ s/\"//g;
                $header =~ s/\.\\//;
                my $test = $$ref_local_header_hash{$header};
                    my $header_fullpath = $path . "\\" . $header;
                if ( $test || (($header =~ /\\/) && (-e $header_fullpath))) {
                    push @{$ref_header_deps}, $header;
                }
            }
        }
    }
 }	##parse_header_deps

############################################################################
sub handle_dep_to_other_directory		#16.04.2008 15:11
############################################################################
{
    # there has been an additional include directoy detected
    # now try to find out which header (parsed from c/cpp-file)
    # comes from this directory by checking: does it exist there?
    my $path = shift;
    my $file = shift;
    my $ref_header_deps = shift;
    my $path_additional = shift;
    my $search_path = $path . "\\" . $path_additional;
    my $counter = 0;
    foreach $header(@{$ref_header_deps})
    {
        my $full_path = $search_path . "\\" . $header;
        if ( -e "$full_path" )
        {
            $$ref_header_deps[$counter] = $path_additional . "\\" .	$header;
        }
        $counter++
    }
} 	##handle_dep_to_other_directory

############################################################################
sub print_lib32_objs		#18.04.2008 12:54
############################################################################
 {
    # generate Link section
    my $path = shift;
    my $extra_mak = shift;
    my $ref_objecthash = shift;
    my $resource_file = shift;
    # output link objects
    print MAKFILE "LINK32_OBJS= \\\n";
    # print objects
    foreach $object(sort keys %{$ref_objecthash})
    {
        print MAKFILE "\t$object \\\n";
    }

    # print *.res if *.rc exists
    if ( $resource_file ne "" ) {
        my $res_file = $resource_file;
        $res_file =~ s/\.rc/\.res/;
        $res_file =~ /(.+)\\(.+)$/;
        $res_file = $2;
        print MAKFILE "\t\$(INTDIR)\\$res_file \\\n";
    }

    # add import libs and res files
    print_flags($path,$extra_mak,"AdditionalLinkObjects");
    my $outfile = $configelements{"Release"}{"OutputFile"};

    # section for linking
    print_link_template($path,$outfile);

    # section for creating res files
    # setting for rsc, res target etc.
    print "resource_file=$resource_file\n" if ($is_debug);
    print_rsc_template($resource_file) if ($resource_file);
    print_simple_flag("Special_extra_uconv") if ($outfile =~ /uconv/);
}	##print_lib32_objs

############################################################################
sub print_all_target        #26.06.2008 13:27
############################################################################
 {
    my $path = shift;
    my $ref_all_target_hash = shift;
    my $filename = getFilenameFromPath($path);
    my $outdir = $configelements{"Release"}{"OutputDirectory"};
    print MAKFILE "NULL=\n";
    print MAKFILE "OUTDIR=$outdir\n";
    print MAKFILE "OutDir=$outdir\n";
    print MAKFILE "INTDIR=.\\Release\n\n";
    print MAKFILE "ALL: ";
    foreach $target(sort keys %{$ref_all_target_hash})
    {
        if ( $target =~ /\.exe/ ) {
            my $out = $target;
            $out =~ s/.\\Release/\.\.\\\.\.\\\.\.\\bin/;
            $out =~ s/\$\(OutDir\)/\.\.\\\.\.\\\.\.\\bin/;
            $out =~ s/\//\\/; # convert / to \
            $target = $out;
        }
        print MAKFILE "\"$target\" ";
    }

    # Append [Target_<dir>] item e.g. ../../icuxy36.dll
    my $targetkey = "Target_" . $filename;
    my @target = ();
    if ( exists $template_hash{$targetkey}  ) {
        @target = @{$template_hash{$targetkey}};
    }
    my $additional_target="";
    foreach $additional_target(@target)
    {
        print MAKFILE $additional_target if ($additional_target ne "");
    }
    print MAKFILE "\n\n";
    print MAKFILE "\"\$(OUTDIR)\" : \n";
    print MAKFILE "\tif not exist \"\$(OUTDIR)/\$(NULL)\" mkdir \"\$(OUTDIR)\"\n\n";
    print MAKFILE "!IF \"\$(OUTDIR)\" != \"\$(INTDIR)\"\n";
    print MAKFILE "\"\$(INTDIR)\" : \n";
    print MAKFILE "\tif not exist \"\$(INTDIR)/\$(NULL)\" mkdir \"\$(INTDIR)\"\n";
    print MAKFILE "!ENDIF\n";
    print MAKFILE "\n\n";
}   ##print_all_target

############################################################################
sub print_simple_flag		#18.04.2008 13:39
############################################################################
{
    my $simple_flag = shift;
    my @template = @{$template_hash{$simple_flag}};
    foreach $line(@template)
    {
        print MAKFILE $line;
    }
}	##print_rules

############################################################################
sub print_link_template       #18.04.2008 13:39
############################################################################
{
    my $dir = shift;
    my $outfile = shift;
    my $manifest;
    # set resource id for manifest file
    if ( $outfile =~ /\.exe/ ) {
        $manifest = 1;
    } else
    {
        $manifest = 2;
    }
    my @template = ();
    if ($dir =~ /stubdata/ ) {
        @template = @{$template_hash{"Special_stubdata"}};
    } else
    {
        @template = @{$template_hash{"LinkTemplate"}};
    }

    print MAKFILE "\n"; # insert blank line
    foreach $line(@template)
    {
        $line =~ s/<OUTFILE>/$outfile/;
        $line =~ s/<MANIFEST>/$manifest/;
        print MAKFILE $line;
    }

    # insert special stuff for
    # extras/uconv/uconv.mak
    if ( $dir =~ /uconv/ ) {
        print_flags($dir,"","Special");
    }

    # for *.exe files an additional
    # copy section is required to get
    # the stuff into the global bin directory
    my %dummy = ();
    my @mak = ();
    if( $manifest ==1 )
    {
        # source,inputpath,target,action
        my $out = $outfile;
        $out =~ s/.\\.*Release/\.\.\\\.\.\\\.\.\\bin/;
        $out =~ s/\$\(OutDir\)/\.\.\\\.\.\\\.\.\\bin/;
        $out =~ s/\//\\/;       # subst / with \
        $outfile =~ s/\//\\/;   # subst / with \
        createCopySection($outfile,$outfile,$out,"copy \"\$(InputPath)\" .\\..\\..\\..\\bin",\@mak,\%dummy);
        foreach $line(@mak)
        {
            print MAKFILE $line;
        }
    }
}	##print_rules

############################################################################
sub print_rsc_template      #04.11.2008 14:48
############################################################################
 {
    # print resource compiler setting + resource target
    my $resourcefile = shift;
    # skip this if no res file required

    return if (!$resourcefile);
    $resfile = $resourcefile;
    #remove file extension (.res)
    $resfile =~ /(.+)\\(.+)\.(.+)/;
    $resfile = $2;

    my @template = @{$template_hash{"RSC_Template"}};
    print MAKFILE "\n"; # insert blank line
    foreach $line(@template)
    {
        $line =~ s/<FILE>/$resourcefile/;
        $line =~ s/<FILEOUT>/$resfile/;
        print MAKFILE $line;
    }
}   ##print_rsc_template

############################################################################
sub print_flags		#18.04.2008 14:19
############################################################################
{
    # CFlags, LinkFlags
    my $dir = shift;
    my $extra_mak = shift; # eg. derb.mak, stringperf.mak
    my $flag = shift;
    my $nonpro = shift;
    my @template = ();
    my $switch = "";
    $dir =~ s/\\/_/g if ($dir);            # change \ to _
    $switch = "$flag" . "_" . "$dir" if ($dir);
    handle_CFlags() if ($flag eq "CFlags");  # get and print Preprocessor defines
    $switch .= "\." . $extra_mak if ( $extra_mak ne "" ) ;
    if ( exists $template_hash{$switch} ) {
        @template = @{$template_hash{$switch}};
        foreach $line(@template)
        {
            if ( $nonpro )
            {
                # if non product link against debug libraries
                $line =~ s/-MD/-MDd/;
                $line =~ s/-MT/-MTd/;
            }
            print MAKFILE $line;
        }
    }
}	##print_flags

############################################################################
sub handle_CFlags       #28.01.2009 11:20
############################################################################
 {

    my $ppdefs = $configelements{"Release"}{"PreprocessorDefinitions"};
    my $ppinc  = $configelements{"Release"}{"AdditionalIncludeDirectories"};
    my @template = @{$template_hash{"General_CFlags"}};
    $ppdefs =~ s/;/ -D/g; # subst ; with -D switch
    $ppdefs = "-D" . $ppdefs;
    $ppinc =~ s/(;|,)/ -I/g; # subst ; with -I switch
    $ppinc = "-I" . $ppinc;
    print "ppdefs=$ppdefs\n" if ($is_debug);
    print "ppinc =$ppinc\n" if ($is_debug);
    foreach $line(@template)
    {
        $line =~ s/<AddIncDirs>/$ppinc/;
        $line =~ s/<PreProcDefs>/$ppdefs/;
        print MAKFILE $line;
    }
}   ##handle_CFlags

############################################################################
sub print_common_linkflags      #21.11.2008 11:47
############################################################################
 {
    my @template = @{$template_hash{"CommonLinkFlags"}};
    my $outfile = $configelements{"Release"}{"OutputFile"};
    my $pdbfile = $configelements{"Release"}{"ProgramDatabaseFile"};
    $pdbfile =~ s/\//\\/;   # subst / with \
    $outfile =~ s/\//\\/;   # subst / with \
    print "PATH=$path OUTFILE=$outfile\n" if ($is_debug);
    foreach $line(@template)
    {
        $line =~ s/<OUTFILE>/$outfile/;
        $line =~ s/<PDBFILE>/$pdbfile/;
        print MAKFILE $line;
    }
}   ##print_common_linkflags

############################################################################
sub handle_extra_mak_files      #25.08.2008 14:32
############################################################################
{
    # extract extra filename for *.mak file
    # e.g input: tools\genrb.derb
    #    output: derb
    my $direntry = shift;
    my $out = "";
    my $dir = "";
    if ( $direntry =~ /(.+)\.(.+)$/ ) {
        $dir = $1;
        $out = $2;
    } else
    {
        $dir = $direntry;
    }
    return ($dir,$out);
}   ##handle_extra_mak_files

############################################################################
sub prepare_allinone_all_mak
############################################################################
{
    # Read in allinone.sln
    # Fills hashes and returns an array with build order
    # uses topographical sorting

    my $href_project_by_id = shift;
    my $href_project_by_name = shift;
    my $href_project_dependencies = shift;
    my $sourcePath = shift;

    my $allslnfile = $sourcePath . "\\allinone\\allinone.sln";
    my @projectdeps;
    my $projectname;
    my $projectpath;
    my $projectid;

    # fill hash tables
    open (SLN, "< $allslnfile") || die "Can't open $allslnfile\n";
    while ($line = <SLN>)
    {
        my @project = ();
        if ( $line =~ /^Project\(/ ) {
            @project = split( /,/, $line);
            if ( $#project ) {
                $projectname = "";
                $projectpath = "";
                $projectid = "";
                @projectdeps = ();
                my @subarray = ();
                @subarray = split( /=/, $project[0]);
                $projectname = $subarray[1];
                $projectname =~ s/\"//g;      # remove "
                $projectpath = $project[1];
                $projectid = $project[2];
                $projectid =~ s/\"//g;        # remove "
                $projectid =~ s/.+\{//g;      # remove til {
                $projectid =~ s/\}\n//g;      # remove }<CR>
                my @pnp = ($projectname,$projectpath);
                my @pip = ($projectid,$projectpath);
                $$href_project_by_id{$projectid}=[@pnp];
                $$href_project_by_name{$projectname} =[@pip];
            }
        } # $line =~ /^Project\(/
        if ( $line =~ /ProjectSection\(/ ) {
            $psect = 1;
            next;
        }
        if ( $line =~ /EndProjectSection/ ) {
            $psect = 0;
            $$href_project_dependencies{$projectid}=[@projectdeps];
            next;
        }
        if ( $psect ) {
            my @tarray = split(/=/, $line);
            $depends_on_id = $tarray[0];
            $depends_on_id =~ s/.+\{//g;
            $depends_on_id =~ s/\}.+//g;
             print "+$depends_on_id-\n" if ($is_debug);

            push @projectdeps, $depends_on_id;
        }
    }
    ########################################
    # sort here and generate build order
    ########################################
    $objektzahl=0;
    %hashindex=();

    foreach $projectid(keys %{$href_project_by_id})
    {
        if ( $$href_project_dependencies{$projectid} )
        {
            @deps = @{$$href_project_dependencies{$projectid}};
        } else
        {
            @deps = ();
        }
        for  $counter(0..$#deps)
        {
            $v = find_or_create_element($deps[$counter]);
            $n = find_or_create_element($projectid);
            push @{$nachfolgerliste[$v]},$n;
        }
    }

    for $n (0..$objektzahl-1)
    {
            $vorgaengerzahl[$n]=0;
    }
    for $v (0..$objektzahl-1)
    {
            for $n (@{$nachfolgerliste[$v]})
            {
                    ++$vorgaengerzahl[$n];
            }
    }

    @hilfsliste=();
    for $n (0..$objektzahl-1)
    {
        push(@hilfsliste,$n) if ($vorgaengerzahl[$n]==0)
    }

    $ausgabe=0;
    @builddep =();
    while (defined($v=pop(@hilfsliste)))
    {
        push @builddep, $name[$v];                           # save build order by project_id;
        ++$ausgabe;
        for $n (@{$nachfolgerliste[$v]})
        {
                --$vorgaengerzahl[$n];
                push(@hilfsliste,$n) if ($vorgaengerzahl[$n]==0);
        }
    } # while
    die "Cyclic dependencies found! Stopping now.\n" if $ausgabe<$objektzahl;
    ##############################################################
    # End of sorting stuff
    ##############################################################

    return @builddep;
    ###############################################################
    ###########################
    # sub for sorting only
    ###########################
    sub find_or_create_element
    {
        my ($str)=@_;
        my ($idx)=$hashindex{$str};
        if (!defined($idx)) {               # new element ...
                $idx=$objektzahl++;
                $hashindex{$str}=$idx;
                $name[$idx]=$str;
            @{$nachfolgerliste[$idx]}=();
        }
        return $idx;
    } # find_or_create_element
}  # prepare_allinone_all_mak

############################################################################
sub create_allinone_all_mak     #09.02.2009 09:22
############################################################################
{
    my $ref_buildorder = shift;
    my $href_project_by_id = shift;
    my $sourcePath = shift;
    my $allmakfile = $sourcePath . "\\allinone\\all.mak";
    open (ALLMAK, ">$allmakfile") || die "Can't write to $allmakfile \n";
    print ALLMAK "ALL: ";
    foreach $proj(@{$ref_buildorder})
    {
        print ALLMAK $$href_project_by_id{$proj}[0];
    }
    print ALLMAK "\n\n";

    foreach $proj( @{$ref_buildorder} )
    {
        print "$proj $$href_project_by_id{$proj}[0] $$href_project_by_id{$proj}[1]\n";
        my $prjdir = $$href_project_by_id{$proj}[1];
        $prjdir =~ /(.+)\\(.+)$/;
        $prjdir = $1;
        $prjname = $2;
        $prjdir =~ s/^.+\"//;
        $prjname =~ s/\"$//;
        $prjname =~ s/vcproj/mak/;
        $allinonehelpstring = $prjdir;
        $allinonehelpstring =~ s/^\.+\\//; # remove ..\
        my $backcount = "";
        while ($allinonehelpstring=~ /.+\\/g) # counts the occuring \
        {
            $backcount .= "..\\";
        }
        $allinonedir = $backcount . "..\\allinone";

        # write all.mak
        $$href_project_by_id{$proj}[0] =~ s/^\s+//;
        if ( $$href_project_by_id{$proj}[0] ne "makedata" )
        {
            my @template = @{$template_hash{"AllInOnePrj"}};
            foreach $line(@template)
            {
                $line =~ s/<PRJ>/$$href_project_by_id{$proj}[0]/;
                $line =~ s/<PRJDIR>/$prjdir/;
                $line =~ s/<PRJMAK>/$prjname/;
                $line =~ s/<ALLINONEDIR>/$allinonedir/;
                print ALLMAK $line;
            }
        } else
        {
            #special code snippet
            print ALLMAK "makedata : \n";
            print ALLMAK "     cd \"..\\data\"\n";
            print ALLMAK "     nmake /f makedata.mak icumake=\$(MAKEDIR)\\..\\data cfg=Release\n";
            print ALLMAK "     cd \"..\\allinone\"\n\n";
        }
    }
    close ALLMAK;
}   ##create_allinone_all_mak

############################################################################

# ------------------------------------------------------------------------
# XML parser handling
# ------------------------------------------------------------------------

############################################################################
sub start_handler
############################################################################
{
    my $p = shift;           # pointer to parser
    my $el = shift;          # element

    # Deal with attributes

    my $CompilerSection = 0;
    my $LinkerSection = 0;
    my $ConfigSection = ($el eq "Configuration");

    while (@_)
    {
 #       shift if ( $el eq "FileConfiguration" );
        my $att = shift;
        my $val = shift;
        $CustomSection = 0;
        if ($special_file && defined $att & $att ne "Name")
        {
            print "$special_file - $att - $val\n";
            my @param = ($att,$val);
            $files_special{ $special_file } = [@param]; # files with special compiler switch
            @test = @{$files_special{ $special_file }};
            print "test=@test\n";
            $special_file="";
        }
        if ( $ConfigSection && $att eq "Name" && $val eq "Release|Win32" ) {
            $Release = 1;
            $config = "Release";                                                             # Release
        }
        if ( $ConfigSection && $att eq "Name" && $val eq "Debug|Win32" ) {
            $Release = 0;                                                             # Debug
            $config = "Debug";
        }
        if ( $att eq "Name" && $val eq "VCCLCompilerTool" ) {
            $CompilerSection = 1;
        }
        if ( $att eq "Name" && $val eq "VCLinkerTool" ) {
            $LinkerSection = 1;
        }
        if ( $att eq "Name" && $val eq "VCCustomBuildTool" ) {
            $CustomSection = 1;
        }

        # For Configuration Infos like compiler defines etc.
        if ( $att eq "PreprocessorDefinitions" && $CompilerSection ) {
           $configelements{$config}{$att} = $val;
        }
        if ( $att eq "AdditionalIncludeDirectories" && $CompilerSection ) {
           #$configelements{$config}{$att} = $val;
            if ( ($file_tmp ne "") && ($val ne "") ) {
                $files{ $file_tmp } = 1;        # save it now
                $file_tmp =~ s/^\.\\//;         # remove leading .\
                $files_special{"AdditionalIncludeDirectories"}{$file_tmp} = $val;
                print "Include $val: $file_tmp\n" if ($is_debug);
                $file_tmp = "";                 # has been saved now reset it
            } else
            {
               $configelements{$config}{$att} = $val;
            }
        }
        if ( ($att eq "DisableLanguageExtensions") && $CompilerSection ) {
           #$configelements{$config}{$att} = $val;
            if ( ($file_tmp ne "") && ($val ne "")) {
                $files{ $file_tmp } = 1;        # save it now
                $file_tmp =~ s/^\.\\//;         # remove leading .\
                $files_special{"DisableLanguageExtensions"}{$file_tmp} = $val;
                print "-Ze: $file_tmp\n" if ($is_debug);
                $file_tmp = "";                 # has been saved now reset it
            }
        }
        if ( $att eq "OutputDirectory" ) {
           $configelements{$config}{$att} = $val;
        }
        if ( $att eq "OutputFile" && $LinkerSection ) {
           $configelements{$config}{$att} = $val;
        }
        if ( $att eq "ProgramDatabaseFile" ) {
           $configelements{$config}{$att} = $val;
        }
        if ( $att eq "ImportLibrary" && $LinkerSection ) {
           $configelements{$config}{$att} = $val;
        }
        if ($att eq "CommandLine") {
           $configelements{$config}{$att} = $val;
        }
        if (($att eq "PreprocessorDefinitions") && $ConfigSection) {
           $configelements{$config}{$att} = $val;
        }

        # Is the file in the step before a header
        # which has to be copied into the global
        # include path?
        if ( $file_tmp ne "" )
        {
            $config = "Release";
            if ( ($att eq "CommandLine") && ($el eq "Tool") )
            {
                if ( $file_tmp =~ /.+\.h$/ ) {
                    $files2copy{ $file_tmp } = $val; # unicode + layout header to copy
                    $file_tmp = "";                 # has been saved now reset it
                }
            }
        } # if $file_tmp

        # For files
        if ( $att eq "RelativePath" ) {
            if ( $file_tmp ) {
                # no special file (include dir / compiler switch)
                $files{ $file_tmp } = 1;        # save it now
                $file_tmp = "";                 # has been saved now reset it
            }
            # store temporary the file name
            $file_tmp = $val if ($val !~ /\.mk$/);  # no *.mk files
        }
    } # while @_
}  # End start_handler

############################################################################
sub char_handler
############################################################################
{
}  # End char_handler
