xref: /aoo41x/main/icu/createmak.pl (revision cdf0e10c)
1:
2eval 'exec perl -wS $0 ${1+"$@"}'
3    if 0;
4#*************************************************************************
5#
6# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7#
8# Copyright 2000, 2010 Oracle and/or its affiliates.
9#
10# OpenOffice.org - a multi-platform office productivity suite
11#
12# This file is part of OpenOffice.org.
13#
14# OpenOffice.org is free software: you can redistribute it and/or modify
15# it under the terms of the GNU Lesser General Public License version 3
16# only, as published by the Free Software Foundation.
17#
18# OpenOffice.org is distributed in the hope that it will be useful,
19# but WITHOUT ANY WARRANTY; without even the implied warranty of
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21# GNU Lesser General Public License version 3 for more details
22# (a copy is included in the LICENSE file that accompanied this code).
23#
24# You should have received a copy of the GNU Lesser General Public License
25# version 3 along with OpenOffice.org.  If not, see
26# <http://www.openoffice.org/license.html>
27# for a copy of the LGPLv3 License.
28#
29#*************************************************************************
30#
31use XML::Parser;
32# ------------------------------------------------------------------------
33# Other global stuff
34$is_debug=0;
35my $path = $ENV{'INPATH'} . "/";
36my $quot = '"';
37my %template_hash=();
38my %vcproj_hash=();
39# ------------------------------------------------------------------------
40# Global stuff for parsing the *.vcproj files (XML::Parser)
41#
42my $ConfigurationGlobal = 1; # Release = 1, Debug=0
43my $Configuration = undef;
44my %configelements = ();
45my %files = ();
46my %files2copy = ();
47my %files_special = ();
48my $Release = 1;
49     # Release = 1, Debug = 0, undef = 2
50my $file_tmp = "";      # temporary storage for file name
51my $CustomSection = 0;
52# ------------------------------------------------------------------------
53# ------------------------------------------------------------------------
54# e.g. %object_hash with Key = blabla.cpp
55# contains a Hash:
56# Header: "..\\common\\unicode\\utypes.h ..\\common\\unicode\\uset.h"
57# CFlags: Common (set in templates file) or special sequence
58# CDefs:  Common (set in templates file) or special sequence
59# ------------------------------------------------------------------------
60my $configfile = shift;
61my $sourcePath = shift;
62if ( !$configfile ) {
63    $configfile = "createmak.cfg";
64}
65if ( !$sourcePath ) {
66    $inpath = $ENV{"INPATH"};
67    $sourcePath = $inpath . "\\misc\\build\\icu\\source";
68}
69$dir = "";
70$header = "";
71$sep = "\\\\";
72
73%project_by_id =();
74%project_by_name = ();
75%project_dependencies = ();
76my @builddeps = prepare_allinone_all_mak(\%project_by_id,\%project_by_name,\%project_dependencies,$sourcePath);
77
78fillTemplateHash($configfile);
79
80create_allinone_all_mak(\@builddeps,\%project_by_id,$sourcePath);
81my @dirs = ();
82foreach $projectname(keys %project_by_name)
83{
84    my $dir = $project_by_name{$projectname}[1];
85    $dir =~ /\.\.\\(.+)\\(.+)\.vcproj/;
86    my $dir1 = $1;
87    my $dir2 = $2;
88    if ( $dir1 !~ /$dir2$/ ) {
89        $dir1 .= "\.$dir2";
90    }
91    print "$dir1 - $dir2\n" if ($is_debug);
92    push @dirs, $dir1;
93}
94
95# set nonpro switch (linking against debug runtime if nonpro=1)
96my $nonpro = ($ENV{"PROEXT"} ne ".pro");
97print "Non Product Build" if ($nonpro);
98
99foreach $dir(@dirs)
100{
101    next if ($dir eq "data.makedata"); # very special don't overwrite this file
102    # ------------------------------------------------------------------------
103    # Reset global stuff for parsing the *.vcproj files (XML::Parser)
104    #
105    $Configuration = $ConfigurationGlobal; # Release = 1, Debug=0
106    %configelements = ();
107    %files = ();
108       # contains all relevant *.c,*.cpp,*.h,*.rc files
109    %files2copy = ();
110    %files_special = ();
111    $Release = 2;
112     # Release = 1, Debug = 0, undef = 2
113    $file_tmp = "";      # temporary storage for file name
114    $CustomSection = 0;
115    # ------------------------------------------------------------------------
116
117    my $extra_mak = "";
118    ($dir, $extra_mak) = handle_extra_mak_files($dir); # handle e.g. tools/genrb.derb entires
119
120    my @mak=(); # Array for make file *.mak
121    my %deps=();
122    my %object_hash=();
123    my %collected_header=();
124    my %collect_header_target_hash=();
125    my %collect_object_target_hash=();
126    my $vcproj_file = "";
127    my $resource_file = "";
128
129    # $dir : common,i18n,...
130    chomp $dir;
131    next if ( $dir eq "" );
132    my $fullpath = $sourcePath . "\\" . $dir;
133    if ( $extra_mak eq "" ) {
134        if ($dir =~ /(.+)+\\(.+)$/)
135        {
136            $vcproj_file = $fullpath ."\\$2.vcproj";
137        } else
138        {
139            $vcproj_file = $fullpath ."\\$dir.vcproj";
140        }
141    } else
142    {
143        $vcproj_file = $fullpath . "\\" . $extra_mak . ".vcproj";
144    }
145
146
147    # Parse the *.vcproj file
148    my $parser = new XML::Parser(ErrorContext => 2);
149    $parser->setHandlers(Start => \&start_handler,
150                 Char  => \&char_handler);
151    $parser->parsefile($vcproj_file);
152    if ( $file_tmp ) {
153        # save a file which hasn't been saved yet
154        $files{ $file_tmp } = 1;        # save it now
155        $file_tmp = "";                 # has been saved now reset it
156    }
157
158    # is there a resource file?
159    foreach $i (keys %files)
160    {
161        if ($i =~ /\.rc/)
162        {
163            $resource_file = $i;
164        }
165    }
166    # Fill hash %deps for dependencies for all files in directory ($testdir)
167    # %files contains all relevant files from *.vcproj
168
169    getAllFilesDeps($fullpath,\%deps,\%files);
170    my $includedir = $configelements{"Release"}{"OutputDirectory"};     # e.g. OutputDirectory = ..\..\lib
171    $includedir =~ s/lib/include/;
172    foreach $file( sort keys %deps)
173    {
174        $file =~ /(.+)\.(.+)/;
175        my $name = $1;
176        my $ext  = $2;
177        next if (!defined $name);
178        $object = "\$(INTDIR)\\" . "$name.obj";
179        $collect_object_target_hash{$object}=1;
180
181        createMakDepSection($dir,$name,$ext,$deps{$file},\@mak,\%files_special);
182    }
183    my %all_target_hash=();
184    foreach $header(sort keys %files2copy)
185    {
186        my $dir;
187        my $file;
188        #$pathdepth = "..\\..";
189        $file = $header;
190        $header =~ s/^\.\\//;
191        $inputpath = $file;
192        $target = $includedir . "\\" . $header;
193        $target =~ /.+\\(.+)\\.+$/;
194        $targetpath = $configelements{"Release"}{"CommandLine"};
195        chomp $targetpath;
196        # set %all_target_hash and @mak
197        createCopySection($file,$inputpath,$target,$targetpath,\@mak,\%all_target_hash);
198        $collect_header_target_hash{$target}=1;
199    }
200    my $test = $configelements{"Release"}{"OutputFile"};
201    $all_target_hash{$test}=1;
202
203    # set name of the *.mak file
204    my $mak_file="";
205    if ( $extra_mak eq "" ) {
206        $mak_file = $vcproj_file;
207        $mak_file =~ s/vcproj/mak/;
208    } else
209    {
210        # extra_mak eg. derb, stringperf
211        $mak_file = $fullpath . "\\$extra_mak" . "\.mak";
212    }
213
214    # generate the content of the *.mak file
215    # in @mak array
216    print "extra_mak=$extra_mak\n" if ($is_debug);
217    print "mak_file=$mak_file\n" if ($is_debug);
218    open(MAKFILE, ">$mak_file") || die "Can't open $mak_file\n";
219    print_all_target($fullpath, \%all_target_hash);
220
221    # $extra_mak handles further *.mak files in a directory
222    print_flags($dir,$extra_mak,'CFlags',$nonpro);    # depends on directory
223    print_simple_flag("Rules");
224    print_simple_flag("Link");
225    print_common_linkflags();
226#    print_flags($fullpath,$extra_mak,'LinkFlags'); # depends on directory
227#    print_lib32_objs($fullpath,$extra_mak,\%collect_object_target_hash,$resource_file);
228    print_flags($dir,$extra_mak,'LinkFlags'); # depends on directory
229    print_lib32_objs($dir,$extra_mak,\%collect_object_target_hash,$resource_file);
230
231    # write @mak array into the *.mak file
232    foreach $line(@mak)
233    {
234        print MAKFILE $line;
235    }
236	$|=1;
237    print "."; # user entertainment
238	$|=0;
239}
240print "\ndone\n";
241exit;
242
243############################################################################
244sub getKey		#01.04.2008 09:46
245############################################################################
246 {
247	my $line = shift;
248	$line =~ /\[(.+)\]/;
249	return $1;
250}	##getKey
251
252############################################################################
253sub fillTemplateHash		#01.04.2008 10:48
254############################################################################
255 {
256	my $file = shift;
257	open (TEMPLATE, "< $file") || die "Can't open template file $file\n";
258    my $key = "";
259	while ( $line=<TEMPLATE> ) {
260		if ( $line =~ /\[.+\]/ ) {
261            print $line if ($is_debug);
262			if ( $key ne "" ) {
263				$template_hash{$key}=[@cmdlines];
264				@cmdlines="";
265				$key="";
266			}
267			$key = getKey( $line );
268		} else
269		{
270			push @cmdlines, $line;
271		}
272	} # while
273}	##fillTemplateHash
274
275############################################################################
276sub createCopySection		#01.04.2008 11:37
277############################################################################
278 {
279	my $header	   = shift;
280	my $inputpath  = shift;
281	my $target	   = shift;
282	my $targetpath = shift;
283	my $ref_make_file = shift; # Array written later to make file *.mak
284    my $ref_all_target_hash = shift;  # reference to fill all_target_hash;
285    if ( $target !~ /\\include/ && $target !~ /\\bin/) {
286        return; # $target contains nonsense
287    }
288    if ( !$targetpath ) {
289        # $targetpath is empty! (Due to missing entry in *.vcproj file)
290        # Generate $targetpath here from $target
291        my $t = $target;
292        $t =~ /(.+)\\(.+)$/;
293        $targetpath = "copy \"\$(InputPath)\" " . $1;
294        chomp $targetpath;
295    }
296    $targetpath =~ s/\r$//; # remove x0A from EOL if the is one
297	my @template = @{$template_hash{"Copy"}};
298	my $line = "";
299	foreach $line(@template)
300	{
301		$line =~ s/<HEADER>/$header/g;
302		$line =~ s/<INPUTPATH>/$inputpath/g;
303		$line =~ s/<TARGET>/$target/g;
304        $line =~ s/<TARGETPATH>/$targetpath/;
305        push @{$ref_make_file}, $line;           # from template
306        $$ref_all_target_hash{$target} = 1;       # "\"$target\" ";
307     # save for target ALL:
308	}
309}	##createCopySection
310
311############################################################################
312sub createMakDepSection		#01.04.2008 13:36
313############################################################################
314 {
315	# creates the dependency section in the make file
316    my $dir         = shift;
317	my $source 		= shift;
318	my $extension	= shift;
319	my $ref_header_list	= shift;
320	my $ref_make_file = shift; # Array written later to make file *.mak
321    my $ref_special_file = shift; # hash for special files (compiler flags, include paths)
322	my $header_list = "";
323    my $special_flag = 0;
324
325    return if ( !defined $source );
326	foreach $header(@{$ref_header_list})
327	{
328        if ( ($header =~ /^\.\.\\.+/) && (-e $header )) {
329			$header_list = $header_list . " " . $header; # this header is located in an other directory
330		} else
331		{
332			$header_list = $header_list . " .\\" . $header;
333		}
334	}
335
336    #special handling
337    # compile this file with other compiler switches
338    my $file = $source . "\." . $extension;
339    $dir =~ s/\\/_/;
340    my @template = @{$template_hash{"CFlags_$dir"}};
341    if ( defined $$ref_special_file{"AdditionalIncludeDirectories"}{$file} ) {
342        $special_flag = 1;
343        my $includepath = $$ref_special_file{"AdditionalIncludeDirectories"}{$file};
344        $includepath =~ s/\;/\/I /g;                   # subst ; with /I for multiple paths
345        $line = "CPP_SWITCH_INCLUDE=/I  $includepath\n";
346		push @{$ref_make_file}, $line;
347        foreach $line(@template)
348        {
349            if ( $line =~ /CPP_PROJ/)
350            {
351                $line =~ s/CPP_PROJ=/CPPX_PROJ=/;
352                $line =~ s/\$\(CDEFS\)/\$\(CDEFS\) \$\(CPP_SWITCH_INCLUDE\)/; # include $(CPP_SWITCH_INCLUDE)
353                push @{$ref_make_file}, $line;
354            }
355        }
356    }
357    if ( $$ref_special_file{"DisableLanguageExtensions"}{$file} )
358    {
359        # FALSE = /Ze
360        $special_flag = 1;
361        foreach $line(@template)
362        {
363            if ( $line =~ /CPP_PROJ/)
364            {
365                $line =~ s/CPP_PROJ=/CPPX_PROJ=/;
366                $line =~ s/-Za/-Ze/;
367                if ( $nonpro )
368                {
369                    # if non product link against debug libraries
370                    $line =~ s/-MD/-MDd/;
371                    $line =~ s/-MT/-MTd/;
372                }
373                push @{$ref_make_file}, $line;
374            }
375        }
376    }
377
378    @template = @{$template_hash{"Deps"}};
379	my $line = "";
380	foreach $line(@template)
381	{
382		$line =~ s/<SOURCEFILE>/$source/g;
383		$line =~ s/<EXT>/$extension/g;
384        $line =~ s/<HEADER_LIST>/$header_list/g;
385		push @{$ref_make_file}, $line;
386	}
387
388    if ( $special_flag )
389    {
390        pop @{$ref_make_file}; # remove empty line
391        push @{$ref_make_file},"\t\$(CPP) @<<\n";
392        push @{$ref_make_file},"\t\$(CPPX_PROJ) \$(SOURCE)\n";
393        push @{$ref_make_file},"<<\n\n";
394        $special_flag = 0;
395    }
396
397}	##createMakDepSection
398
399
400############################################################################
401sub getFilenameFromPath		#10.04.2008 13:03
402############################################################################
403{
404	my $path = shift;
405	$path =~ /.+\\(.+)$/;
406	return $1;
407}	##getFilenameFromPath
408
409############################################################################
410sub getAllFilesDeps		#08.04.2008 09:39
411############################################################################
412{
413	my $path = shift;
414	my $ref_deps = shift;
415    my $ref_allfiles = shift;       # contains all relevant files from *.vcproj
416    my %local_header_hash=();       # contains all local header
417
418    my @all_files = keys %{$ref_allfiles};
419
420    # collect lokal header names in %header_hash
421    foreach $file(@all_files)
422    {
423        if ( $file =~ /.+\.h/ ) {
424            chomp $file;
425            $local_header_hash{$file} = 1;
426        }
427    }
428
429	foreach $file(@all_files)
430	{
431        my @header_deps=();
432        my $skip = 0;
433
434        $file =~ s/^\.\\//; # remove leading .\
435
436		# exclude sub directories and several file extensions
437        # *.dep,*.h,*.in,*.mak,*.pl,*.txt,*.vcproj.*.rc and origs of patch files (*.*~) and
438        # .cvsignore (files beginning with .)
439        next if ( (-d "$path$sep$file") || ($file =~ /.+(_|\~|dep|h|in|mak|pl|txt|vcproj|rc)$/) || ($file =~ /^\.+./));
440        parse_header_deps($path,$file,\@header_deps,\%local_header_hash);
441		handle_dep_to_other_directory($path,$file,\@header_deps,$$ref_vcproj{$file}) if ($$ref_vcproj{$file});
442		$$ref_deps{$file}=[@header_deps];
443    }
444}	##getAllFilesDeps
445
446 ############################################################################
447 sub parse_header_deps		#14.06.2006 18:04
448 ############################################################################
449  {
450	# get includes from c/cpp file
451	# call create_deps(path,file,\$link_obj)
452	#
453	my $path = shift;
454	my $cfile = shift;
455	my $ref_header_deps = shift;
456    my $ref_local_header_hash = shift;
457
458	my $fullpath = $path . $sep . $cfile;
459	my $unicodedep="";
460   	open(IN, "<$fullpath") || die "can't open $fullpath\n";
461	while ( $line = <IN> ) {
462		next if ($line !~ /^.?\#include.+/); # handle include lines only
463		if ($line =~ /.+?\s(.+)/)
464		{
465			$header = $1;
466			if ( ($header !~ /^<.+/) && ($header !~ /.+\.c.+$/) ) {
467				# no <stdio> etc. header
468				$header =~ s/\s+\/\*.+\*\///; # delete <blanks>/* ... */
469				$header =~ s/\s+\/\/.+//;	   # delete <blanks>//......
470				$header =~ s/\//\\/;		   # subst. / with \
471				$header =~ s/^\"/\".\\/;
472				$header =~ s/\"//g;
473				$header =~ s/\.\\//;
474                my $test = $$ref_local_header_hash{$header};
475                    my $header_fullpath = $path . "\\" . $header;
476                if ( $test || (($header =~ /\\/) && (-e $header_fullpath))) {
477                    push @{$ref_header_deps}, $header;
478                }
479			}
480		}
481	}
482 }	##parse_header_deps
483
484############################################################################
485sub handle_dep_to_other_directory		#16.04.2008 15:11
486############################################################################
487{
488	# there has been an additional include directoy detected
489	# now try to find out which header (parsed from c/cpp-file)
490	# comes from this directory by checking: does it exist there?
491	my $path = shift;
492	my $file = shift;
493	my $ref_header_deps = shift;
494	my $path_additional = shift;
495	my $search_path = $path . "\\" . $path_additional;
496	my $counter = 0;
497	foreach $header(@{$ref_header_deps})
498	{
499		my $full_path = $search_path . "\\" . $header;
500		if ( -e "$full_path" )
501		{
502			$$ref_header_deps[$counter] = $path_additional . "\\" .	$header;
503		}
504		$counter++
505	}
506} 	##handle_dep_to_other_directory
507
508############################################################################
509sub print_lib32_objs		#18.04.2008 12:54
510############################################################################
511 {
512    # generate Link section
513	my $path = shift;
514    my $extra_mak = shift;
515	my $ref_objecthash = shift;
516    my $resource_file = shift;
517	# output link objects
518	print MAKFILE "LINK32_OBJS= \\\n";
519    # print objects
520	foreach $object(sort keys %{$ref_objecthash})
521	{
522		print MAKFILE "\t$object \\\n";
523	}
524
525    # print *.res if *.rc exists
526    if ( $resource_file ne "" ) {
527        my $res_file = $resource_file;
528        $res_file =~ s/\.rc/\.res/;
529        $res_file =~ /(.+)\\(.+)$/;
530        $res_file = $2;
531        print MAKFILE "\t\$(INTDIR)\\$res_file \\\n";
532    }
533
534    # add import libs and res files
535    print_flags($path,$extra_mak,"AdditionalLinkObjects");
536    my $outfile = $configelements{"Release"}{"OutputFile"};
537
538    # section for linking
539    print_link_template($path,$outfile);
540
541    # section for creating res files
542    # setting for rsc, res target etc.
543    print "resource_file=$resource_file\n" if ($is_debug);
544    print_rsc_template($resource_file) if ($resource_file);
545    print_simple_flag("Special_extra_uconv") if ($outfile =~ /uconv/);
546}	##print_lib32_objs
547
548############################################################################
549sub print_all_target        #26.06.2008 13:27
550############################################################################
551 {
552    my $path = shift;
553    my $ref_all_target_hash = shift;
554    my $filename = getFilenameFromPath($path);
555    my $outdir = $configelements{"Release"}{"OutputDirectory"};
556    print MAKFILE "NULL=\n";
557    print MAKFILE "OUTDIR=$outdir\n";
558    print MAKFILE "OutDir=$outdir\n";
559    print MAKFILE "INTDIR=.\\Release\n\n";
560    print MAKFILE "ALL: ";
561    foreach $target(sort keys %{$ref_all_target_hash})
562    {
563        if ( $target =~ /\.exe/ ) {
564            my $out = $target;
565            $out =~ s/.\\Release/\.\.\\\.\.\\\.\.\\bin/;
566            $out =~ s/\$\(OutDir\)/\.\.\\\.\.\\\.\.\\bin/;
567            $out =~ s/\//\\/; # convert / to \
568            $target = $out;
569        }
570        print MAKFILE "\"$target\" ";
571    }
572
573    # Append [Target_<dir>] item e.g. ../../icuxy36.dll
574    my $targetkey = "Target_" . $filename;
575    my @target = ();
576    if ( exists $template_hash{$targetkey}  ) {
577        @target = @{$template_hash{$targetkey}};
578    }
579    my $additional_target="";
580    foreach $additional_target(@target)
581    {
582        print MAKFILE $additional_target if ($additional_target ne "");
583    }
584    print MAKFILE "\n\n";
585    print MAKFILE "\"\$(OUTDIR)\" : \n";
586    print MAKFILE "\tif not exist \"\$(OUTDIR)/\$(NULL)\" mkdir \"\$(OUTDIR)\"\n\n";
587    print MAKFILE "!IF \"\$(OUTDIR)\" != \"\$(INTDIR)\"\n";
588    print MAKFILE "\"\$(INTDIR)\" : \n";
589    print MAKFILE "\tif not exist \"\$(INTDIR)/\$(NULL)\" mkdir \"\$(INTDIR)\"\n";
590    print MAKFILE "!ENDIF\n";
591    print MAKFILE "\n\n";
592}   ##print_all_target
593
594############################################################################
595sub print_simple_flag		#18.04.2008 13:39
596############################################################################
597{
598	my $simple_flag = shift;
599	my @template = @{$template_hash{$simple_flag}};
600	foreach $line(@template)
601	{
602		print MAKFILE $line;
603	}
604}	##print_rules
605
606############################################################################
607sub print_link_template       #18.04.2008 13:39
608############################################################################
609{
610    my $dir = shift;
611    my $outfile = shift;
612    my $manifest;
613    # set resource id for manifest file
614    if ( $outfile =~ /\.exe/ ) {
615        $manifest = 1;
616    } else
617    {
618        $manifest = 2;
619    }
620    my @template = ();
621    if ($dir =~ /stubdata/ ) {
622        @template = @{$template_hash{"Special_stubdata"}};
623    } else
624    {
625        @template = @{$template_hash{"LinkTemplate"}};
626    }
627
628    print MAKFILE "\n"; # insert blank line
629	foreach $line(@template)
630	{
631        $line =~ s/<OUTFILE>/$outfile/;
632        $line =~ s/<MANIFEST>/$manifest/;
633		print MAKFILE $line;
634	}
635
636    # insert special stuff for
637    # extras/uconv/uconv.mak
638    if ( $dir =~ /uconv/ ) {
639        print_flags($dir,"","Special");
640    }
641
642    # for *.exe files an additional
643    # copy section is required to get
644    # the stuff into the global bin directory
645    my %dummy = ();
646    my @mak = ();
647    if( $manifest ==1 )
648    {
649        # source,inputpath,target,action
650        my $out = $outfile;
651        $out =~ s/.\\.*Release/\.\.\\\.\.\\\.\.\\bin/;
652        $out =~ s/\$\(OutDir\)/\.\.\\\.\.\\\.\.\\bin/;
653        $out =~ s/\//\\/;       # subst / with \
654        $outfile =~ s/\//\\/;   # subst / with \
655        createCopySection($outfile,$outfile,$out,"copy \"\$(InputPath)\" .\\..\\..\\..\\bin",\@mak,\%dummy);
656        foreach $line(@mak)
657        {
658            print MAKFILE $line;
659        }
660    }
661}	##print_rules
662
663############################################################################
664sub print_rsc_template      #04.11.2008 14:48
665############################################################################
666 {
667    # print resource compiler setting + resource target
668    my $resourcefile = shift;
669    # skip this if no res file required
670
671    return if (!$resourcefile);
672    $resfile = $resourcefile;
673    #remove file extension (.res)
674    $resfile =~ /(.+)\\(.+)\.(.+)/;
675    $resfile = $2;
676
677    my @template = @{$template_hash{"RSC_Template"}};
678    print MAKFILE "\n"; # insert blank line
679	foreach $line(@template)
680	{
681        $line =~ s/<FILE>/$resourcefile/;
682        $line =~ s/<FILEOUT>/$resfile/;
683		print MAKFILE $line;
684	}
685}   ##print_rsc_template
686
687############################################################################
688sub print_flags		#18.04.2008 14:19
689############################################################################
690{
691    # CFlags, LinkFlags
692    my $dir = shift;
693    my $extra_mak = shift; # eg. derb.mak, stringperf.mak
694	my $flag = shift;
695    my $nonpro = shift;
696	my @template = ();
697    my $switch = "";
698    $dir =~ s/\\/_/g if ($dir);            # change \ to _
699    $switch = "$flag" . "_" . "$dir" if ($dir);
700    handle_CFlags() if ($flag eq "CFlags");  # get and print Preprocessor defines
701    $switch .= "\." . $extra_mak if ( $extra_mak ne "" ) ;
702    if ( exists $template_hash{$switch} ) {
703        @template = @{$template_hash{$switch}};
704        foreach $line(@template)
705        {
706            if ( $nonpro )
707            {
708                # if non product link against debug libraries
709                $line =~ s/-MD/-MDd/;
710                $line =~ s/-MT/-MTd/;
711            }
712            print MAKFILE $line;
713        }
714    }
715}	##print_flags
716
717############################################################################
718sub handle_CFlags       #28.01.2009 11:20
719############################################################################
720 {
721
722    my $ppdefs = $configelements{"Release"}{"PreprocessorDefinitions"};
723    my $ppinc  = $configelements{"Release"}{"AdditionalIncludeDirectories"};
724    my @template = @{$template_hash{"General_CFlags"}};
725    $ppdefs =~ s/;/ -D/g; # subst ; with -D switch
726    $ppdefs = "-D" . $ppdefs;
727    $ppinc =~ s/(;|,)/ -I/g; # subst ; with -I switch
728    $ppinc = "-I" . $ppinc;
729    print "ppdefs=$ppdefs\n" if ($is_debug);
730    print "ppinc =$ppinc\n" if ($is_debug);
731	foreach $line(@template)
732	{
733        $line =~ s/<AddIncDirs>/$ppinc/;
734        $line =~ s/<PreProcDefs>/$ppdefs/;
735		print MAKFILE $line;
736	}
737}   ##handle_CFlags
738
739############################################################################
740sub print_common_linkflags      #21.11.2008 11:47
741############################################################################
742 {
743    my @template = @{$template_hash{"CommonLinkFlags"}};
744    my $outfile = $configelements{"Release"}{"OutputFile"};
745    my $pdbfile = $configelements{"Release"}{"ProgramDatabaseFile"};
746    $pdbfile =~ s/\//\\/;   # subst / with \
747    $outfile =~ s/\//\\/;   # subst / with \
748    print "PATH=$path OUTFILE=$outfile\n" if ($is_debug);
749	foreach $line(@template)
750	{
751        $line =~ s/<OUTFILE>/$outfile/;
752        $line =~ s/<PDBFILE>/$pdbfile/;
753		print MAKFILE $line;
754	}
755}   ##print_common_linkflags
756
757############################################################################
758sub handle_extra_mak_files      #25.08.2008 14:32
759############################################################################
760{
761    # extract extra filename for *.mak file
762    # e.g input: tools\genrb.derb
763    #    output: derb
764    my $direntry = shift;
765    my $out = "";
766    my $dir = "";
767    if ( $direntry =~ /(.+)\.(.+)$/ ) {
768        $dir = $1;
769        $out = $2;
770    } else
771    {
772        $dir = $direntry;
773    }
774    return ($dir,$out);
775}   ##handle_extra_mak_files
776
777############################################################################
778sub prepare_allinone_all_mak
779############################################################################
780{
781    # Read in allinone.sln
782    # Fills hashes and returns an array with build order
783    # uses topographical sorting
784
785    my $href_project_by_id = shift;
786    my $href_project_by_name = shift;
787    my $href_project_dependencies = shift;
788    my $sourcePath = shift;
789
790    my $allslnfile = $sourcePath . "\\allinone\\allinone.sln";
791    my @projectdeps;
792    my $projectname;
793    my $projectpath;
794    my $projectid;
795
796    # fill hash tables
797    open (SLN, "< $allslnfile") || die "Can't open $allslnfile\n";
798    while ($line = <SLN>)
799    {
800        my @project = ();
801        if ( $line =~ /^Project\(/ ) {
802            @project = split( /,/, $line);
803            if ( $#project ) {
804                $projectname = "";
805                $projectpath = "";
806                $projectid = "";
807                @projectdeps = ();
808                my @subarray = ();
809                @subarray = split( /=/, $project[0]);
810                $projectname = $subarray[1];
811                $projectname =~ s/\"//g;      # remove "
812                $projectpath = $project[1];
813                $projectid = $project[2];
814                $projectid =~ s/\"//g;        # remove "
815                $projectid =~ s/.+\{//g;      # remove til {
816                $projectid =~ s/\}\n//g;      # remove }<CR>
817                my @pnp = ($projectname,$projectpath);
818                my @pip = ($projectid,$projectpath);
819                $$href_project_by_id{$projectid}=[@pnp];
820                $$href_project_by_name{$projectname} =[@pip];
821            }
822        } # $line =~ /^Project\(/
823        if ( $line =~ /ProjectSection\(/ ) {
824            $psect = 1;
825            next;
826        }
827        if ( $line =~ /EndProjectSection/ ) {
828            $psect = 0;
829            $$href_project_dependencies{$projectid}=[@projectdeps];
830            next;
831        }
832        if ( $psect ) {
833            my @tarray = split(/=/, $line);
834            $depends_on_id = $tarray[0];
835            $depends_on_id =~ s/.+\{//g;
836            $depends_on_id =~ s/\}.+//g;
837             print "+$depends_on_id-\n" if ($is_debug);
838
839            push @projectdeps, $depends_on_id;
840        }
841    }
842    ########################################
843    # sort here and generate build order
844    ########################################
845    $objektzahl=0;
846    %hashindex=();
847
848    foreach $projectid(keys %{$href_project_by_id})
849    {
850        if ( $$href_project_dependencies{$projectid} )
851        {
852            @deps = @{$$href_project_dependencies{$projectid}};
853        } else
854        {
855            @deps = ();
856        }
857        for  $counter(0..$#deps)
858        {
859            $v = find_or_create_element($deps[$counter]);
860            $n = find_or_create_element($projectid);
861            push @{$nachfolgerliste[$v]},$n;
862        }
863    }
864
865    for $n (0..$objektzahl-1)
866    {
867            $vorgaengerzahl[$n]=0;
868    }
869    for $v (0..$objektzahl-1)
870    {
871            for $n (@{$nachfolgerliste[$v]})
872            {
873                    ++$vorgaengerzahl[$n];
874            }
875    }
876
877    @hilfsliste=();
878    for $n (0..$objektzahl-1)
879    {
880        push(@hilfsliste,$n) if ($vorgaengerzahl[$n]==0)
881    }
882
883    $ausgabe=0;
884    @builddep =();
885    while (defined($v=pop(@hilfsliste)))
886    {
887        push @builddep, $name[$v];                           # save build order by project_id;
888        ++$ausgabe;
889        for $n (@{$nachfolgerliste[$v]})
890        {
891                --$vorgaengerzahl[$n];
892                push(@hilfsliste,$n) if ($vorgaengerzahl[$n]==0);
893        }
894    } # while
895    die "Cyclic dependencies found! Stopping now.\n" if $ausgabe<$objektzahl;
896    ##############################################################
897    # End of sorting stuff
898    ##############################################################
899
900    return @builddep;
901    ###############################################################
902    ###########################
903    # sub for sorting only
904    ###########################
905    sub find_or_create_element
906    {
907        my ($str)=@_;
908        my ($idx)=$hashindex{$str};
909        if (!defined($idx)) {               # new element ...
910                $idx=$objektzahl++;
911                $hashindex{$str}=$idx;
912                $name[$idx]=$str;
913            @{$nachfolgerliste[$idx]}=();
914        }
915        return $idx;
916    } # find_or_create_element
917}  # prepare_allinone_all_mak
918
919############################################################################
920sub create_allinone_all_mak     #09.02.2009 09:22
921############################################################################
922{
923    my $ref_buildorder = shift;
924    my $href_project_by_id = shift;
925    my $sourcePath = shift;
926    my $allmakfile = $sourcePath . "\\allinone\\all.mak";
927    open (ALLMAK, ">$allmakfile") || die "Can't write to $allmakfile \n";
928    print ALLMAK "ALL: ";
929    foreach $proj(@{$ref_buildorder})
930    {
931        print ALLMAK $$href_project_by_id{$proj}[0];
932    }
933    print ALLMAK "\n\n";
934
935    foreach $proj( @{$ref_buildorder} )
936    {
937        print "$proj $$href_project_by_id{$proj}[0] $$href_project_by_id{$proj}[1]\n";
938        my $prjdir = $$href_project_by_id{$proj}[1];
939        $prjdir =~ /(.+)\\(.+)$/;
940        $prjdir = $1;
941        $prjname = $2;
942        $prjdir =~ s/^.+\"//;
943        $prjname =~ s/\"$//;
944        $prjname =~ s/vcproj/mak/;
945        $allinonehelpstring = $prjdir;
946        $allinonehelpstring =~ s/^\.+\\//; # remove ..\
947        my $backcount = "";
948        while ($allinonehelpstring=~ /.+\\/g) # counts the occuring \
949        {
950            $backcount .= "..\\";
951        }
952        $allinonedir = $backcount . "..\\allinone";
953
954        # write all.mak
955        $$href_project_by_id{$proj}[0] =~ s/^\s+//;
956        if ( $$href_project_by_id{$proj}[0] ne "makedata" )
957        {
958            my @template = @{$template_hash{"AllInOnePrj"}};
959            foreach $line(@template)
960            {
961                $line =~ s/<PRJ>/$$href_project_by_id{$proj}[0]/;
962                $line =~ s/<PRJDIR>/$prjdir/;
963                $line =~ s/<PRJMAK>/$prjname/;
964                $line =~ s/<ALLINONEDIR>/$allinonedir/;
965                print ALLMAK $line;
966            }
967        } else
968        {
969            #special code snippet
970            print ALLMAK "makedata : \n";
971            print ALLMAK "     cd \"..\\data\"\n";
972            print ALLMAK "     nmake /f makedata.mak icumake=\$(MAKEDIR)\\..\\data cfg=Release\n";
973            print ALLMAK "     cd \"..\\allinone\"\n\n";
974        }
975    }
976    close ALLMAK;
977}   ##create_allinone_all_mak
978
979############################################################################
980
981# ------------------------------------------------------------------------
982# XML parser handling
983# ------------------------------------------------------------------------
984
985############################################################################
986sub start_handler
987############################################################################
988{
989    my $p = shift;           # pointer to parser
990    my $el = shift;          # element
991
992    # Deal with attributes
993
994    my $CompilerSection = 0;
995    my $LinkerSection = 0;
996    my $ConfigSection = ($el eq "Configuration");
997
998    while (@_)
999    {
1000 #       shift if ( $el eq "FileConfiguration" );
1001        my $att = shift;
1002        my $val = shift;
1003        $CustomSection = 0;
1004        if ($special_file && defined $att & $att ne "Name")
1005        {
1006            print "$special_file - $att - $val\n";
1007            my @param = ($att,$val);
1008            $files_special{ $special_file } = [@param]; # files with special compiler switch
1009            @test = @{$files_special{ $special_file }};
1010            print "test=@test\n";
1011            $special_file="";
1012        }
1013        if ( $ConfigSection && $att eq "Name" && $val eq "Release|Win32" ) {
1014            $Release = 1;
1015            $config = "Release";                                                             # Release
1016        }
1017        if ( $ConfigSection && $att eq "Name" && $val eq "Debug|Win32" ) {
1018            $Release = 0;                                                             # Debug
1019            $config = "Debug";
1020        }
1021        if ( $att eq "Name" && $val eq "VCCLCompilerTool" ) {
1022            $CompilerSection = 1;
1023        }
1024        if ( $att eq "Name" && $val eq "VCLinkerTool" ) {
1025            $LinkerSection = 1;
1026        }
1027        if ( $att eq "Name" && $val eq "VCCustomBuildTool" ) {
1028            $CustomSection = 1;
1029        }
1030
1031        # For Configuration Infos like compiler defines etc.
1032        if ( $att eq "PreprocessorDefinitions" && $CompilerSection ) {
1033           $configelements{$config}{$att} = $val;
1034        }
1035        if ( $att eq "AdditionalIncludeDirectories" && $CompilerSection ) {
1036           #$configelements{$config}{$att} = $val;
1037            if ( ($file_tmp ne "") && ($val ne "") ) {
1038                $files{ $file_tmp } = 1;        # save it now
1039                $file_tmp =~ s/^\.\\//;         # remove leading .\
1040                $files_special{"AdditionalIncludeDirectories"}{$file_tmp} = $val;
1041                print "Include $val: $file_tmp\n" if ($is_debug);
1042                $file_tmp = "";                 # has been saved now reset it
1043            } else
1044            {
1045               $configelements{$config}{$att} = $val;
1046            }
1047        }
1048        if ( ($att eq "DisableLanguageExtensions") && $CompilerSection ) {
1049           #$configelements{$config}{$att} = $val;
1050            if ( ($file_tmp ne "") && ($val ne "")) {
1051                $files{ $file_tmp } = 1;        # save it now
1052                $file_tmp =~ s/^\.\\//;         # remove leading .\
1053                $files_special{"DisableLanguageExtensions"}{$file_tmp} = $val;
1054                print "-Ze: $file_tmp\n" if ($is_debug);
1055                $file_tmp = "";                 # has been saved now reset it
1056            }
1057        }
1058        if ( $att eq "OutputDirectory" ) {
1059           $configelements{$config}{$att} = $val;
1060        }
1061        if ( $att eq "OutputFile" && $LinkerSection ) {
1062           $configelements{$config}{$att} = $val;
1063        }
1064        if ( $att eq "ProgramDatabaseFile" ) {
1065           $configelements{$config}{$att} = $val;
1066        }
1067        if ( $att eq "ImportLibrary" && $LinkerSection ) {
1068           $configelements{$config}{$att} = $val;
1069        }
1070        if ($att eq "CommandLine") {
1071           $configelements{$config}{$att} = $val;
1072        }
1073        if (($att eq "PreprocessorDefinitions") && $ConfigSection) {
1074           $configelements{$config}{$att} = $val;
1075        }
1076
1077        # Is the file in the step before a header
1078        # which has to be copied into the global
1079        # include path?
1080        if ( $file_tmp ne "" )
1081        {
1082            $config = "Release";
1083            if ( ($att eq "CommandLine") && ($el eq "Tool") )
1084            {
1085                if ( $file_tmp =~ /.+\.h$/ ) {
1086                    $files2copy{ $file_tmp } = $val; # unicode + layout header to copy
1087                    $file_tmp = "";                 # has been saved now reset it
1088                }
1089            }
1090        } # if $file_tmp
1091
1092        # For files
1093        if ( $att eq "RelativePath" ) {
1094            if ( $file_tmp ) {
1095                # no special file (include dir / compiler switch)
1096                $files{ $file_tmp } = 1;        # save it now
1097                $file_tmp = "";                 # has been saved now reset it
1098            }
1099            # store temporary the file name
1100            $file_tmp = $val if ($val !~ /\.mk$/);  # no *.mk files
1101        }
1102    } # while @_
1103}  # End start_handler
1104
1105############################################################################
1106sub char_handler
1107############################################################################
1108{
1109}  # End char_handler
1110