os/kernelhwsrv/kerneltest/f32test/loader/dlltree.pl
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kerneltest/f32test/loader/dlltree.pl	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,854 @@
     1.4 +# Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +# All rights reserved.
     1.6 +# This component and the accompanying materials are made available
     1.7 +# under the terms of the License "Eclipse Public License v1.0"
     1.8 +# which accompanies this distribution, and is available
     1.9 +# at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +#
    1.11 +# Initial Contributors:
    1.12 +# Nokia Corporation - initial contribution.
    1.13 +#
    1.14 +# Contributors:
    1.15 +#
    1.16 +# Description:
    1.17 +# \f32test\loader\dlltree.pl
    1.18 +# Generate header and build files for one or more trees
    1.19 +# of DLLs and EXEs according to a description file.
    1.20 +# 
    1.21 +#
    1.22 +
    1.23 +require Cwd;
    1.24 +
    1.25 +my $dllbasename='dllt';
    1.26 +my $dllext='.dll';
    1.27 +my $exebasename='exet';
    1.28 +my $exeext='.exe';
    1.29 +my $mmpext='.mmp';
    1.30 +my $defext='.def';
    1.31 +my $libext='.lib';
    1.32 +
    1.33 +my $source0ext='.cpp';
    1.34 +my $source1ext='.cia';
    1.35 +my $xippath="sys\\bin\\";
    1.36 +my $nonxippath="sys\\bin\\";
    1.37 +
    1.38 +my $hostpath="\\Epoc32\\Release\\##MAIN##\\##BUILD##\\";
    1.39 +
    1.40 +my $flag_value_exe=1;
    1.41 +my $flag_value_fixed=2;
    1.42 +my $flag_value_data=4;
    1.43 +my $flag_value_xip=8;
    1.44 +my $flag_value_dll_in_cycle=16;
    1.45 +my $flag_value_data_in_tree=32;
    1.46 +my $flag_value_xip_data_in_tree=64;
    1.47 +my $flag_value_exports=128;
    1.48 +my $flag_value_pagedcode=256;
    1.49 +my $flag_value_unpagedcode=512;
    1.50 +my $flag_value_idrive=1024;
    1.51 +my $flag_value_vdrive=2048;
    1.52 +my $flag_value_bytepair=4096;
    1.53 +my $flag_value_uncompressed=8192;
    1.54 +my $flag_value_targetonly=16384;
    1.55 +my $flag_value_pageddata=32768;
    1.56 +my $flag_value_unpageddata=65536;
    1.57 +
    1.58 +my $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst;
    1.59 +($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime;
    1.60 +my $copy_end=$year+1900;
    1.61 +
    1.62 +my $argc=scalar(@ARGV);
    1.63 +($argc==1 or $argc==2 or $argc==3) or die "Usage: perl dlltree.pl <filename> <dir> [-allowbad]\n";
    1.64 +my $infile=$ARGV[0];
    1.65 +open IN, $infile or die "Cannot open input file $infile\n";
    1.66 +my @in;
    1.67 +while (<IN>)	{
    1.68 +	push @in, $_;
    1.69 +}
    1.70 +close IN;
    1.71 +my $destdir='';
    1.72 +if ($argc>=2) {
    1.73 +	$destdir=$ARGV[1];
    1.74 +	unless (-d $destdir) {
    1.75 +		mkdir $destdir, 0777 or die "Can't create directory $destdir\n";
    1.76 +	}
    1.77 +	chdir $destdir or die "Can't chdir to directory $destdir\n";
    1.78 +}
    1.79 +my $allowbad;
    1.80 +if ($argc==3) {
    1.81 +	if ($ARGV[2] eq '-allowbad') {
    1.82 +		$allowbad = 1;
    1.83 +	}
    1.84 +}
    1.85 +$cwd=Cwd::getcwd();
    1.86 +$destpath=$cwd;
    1.87 +$destpath=~s/\//\\/g;
    1.88 +if ($destpath=~/^\w\:(.*)/) {
    1.89 +	$destpath=$1;
    1.90 +}
    1.91 +unless ($destpath=~/^(.*?)\\$/) {
    1.92 +	$destpath.='\\';
    1.93 +}
    1.94 +#print "$cwd\n";
    1.95 +#print "$destpath\n";
    1.96 +
    1.97 +my @modules;
    1.98 +my @testcases;
    1.99 +my $line=0;
   1.100 +my $modnum=0;
   1.101 +my $state=0;
   1.102 +my $concat;
   1.103 +foreach (@in)	{
   1.104 +	++$line;
   1.105 +	next if (/^\s*$/ or /^\s*\#/);
   1.106 +	if ($state==0)	{
   1.107 +		if (/^\!TESTCASES/) {
   1.108 +			$state=1;
   1.109 +			next;
   1.110 +		}
   1.111 +		my @moddesc=split;
   1.112 +		my $modname=shift @moddesc;
   1.113 +		if (grep {lc($$_{name}) eq lc($modname)} @modules) {
   1.114 +			die "Duplicate module specification at line $line\n";
   1.115 +		}
   1.116 +		my %module;
   1.117 +		$module{name}=$modname;
   1.118 +		$module{num}=$modnum;
   1.119 +		$module{exports}=1;
   1.120 +		$module{nclients}=0;	# number of modules which import from this one
   1.121 +		while (scalar(@moddesc)) {
   1.122 +			my $att=shift @moddesc;
   1.123 +			if ($att=~/^\:$/) {
   1.124 +				last;
   1.125 +			} elsif ($att=~/^X$/i) {
   1.126 +				$module{exe}=1;
   1.127 +			} elsif ($att=~/^F$/i) {
   1.128 +				$module{fixed}=1;
   1.129 +			} elsif ($att=~/^D$/i) {
   1.130 +				$module{data}=1;
   1.131 +			} elsif ($att=~/^P$/i) {
   1.132 +				$module{pagedcode}=1;
   1.133 +			} elsif ($att=~/^PD$/i) {
   1.134 +				$module{pageddata}=1;
   1.135 +			} elsif ($att=~/^B$/i) {
   1.136 +				$module{bytepair}=1;
   1.137 +			} elsif ($att=~/^U$/i) {
   1.138 +				$module{uncompressed}=1;
   1.139 +			} elsif ($att=~/^I$/i) {
   1.140 +				$module{idrive}=1;
   1.141 +			} elsif ($att=~/^V$/i) {
   1.142 +				$module{vdrive}=1;
   1.143 +			} elsif ($att=~/^N$/i) {
   1.144 +				$module{unpagedcode}=1;
   1.145 +			} elsif ($att=~/^T$/i) {
   1.146 +				$module{targetonly}=1;
   1.147 +			} elsif ($att=~/^R(.*?)$/i) {
   1.148 +				$module{xip}=1;
   1.149 +				my $attp=$1;
   1.150 +				if ($attp=~/^\,(.*?)$/) {
   1.151 +					$module{attpname}=$1;
   1.152 +				} elsif (!($attp=~/^\s*$/)) {
   1.153 +					die "Garbage following R attribute at line $line\n";
   1.154 +				}
   1.155 +			}
   1.156 +		}
   1.157 +		if ($module{fixed} && !$module{exe}) {
   1.158 +			die "Can't have FIXED without EXE at line $line\n";
   1.159 +		}
   1.160 +		if ($module{pagedcode} && $module{xip}) {
   1.161 +			die "Can't have PAGEDCODE with XIP at line $line\n";
   1.162 +		}
   1.163 +
   1.164 +		# makmake won't support paged binaries which aren't bytepair or uncompressed.
   1.165 +		# However, P can be specified without them in dlltree.txt.  This program generates
   1.166 +		# an MMP file with neither flag.  The flag is added when the files are copied to
   1.167 +		# internal media by T_LDRTST.  (It would be pointless to copy the files to removable
   1.168 +		# media and then edit them because removable media doesn't support paging.)
   1.169 +
   1.170 +		my $bothCodePageFlags = $module{pagedcode} && $module{unpagedcode};
   1.171 +		if ($bothCodePageFlags && !$module{idrive}) {
   1.172 +			die "Can't have PAGEDCODE and UNPAGEDCODE without INTERNAL DRIVE at line $line\n";
   1.173 +		}
   1.174 +		if ($module{unpagedcode} && $module{xip}) {
   1.175 +			die "Can't have UNPAGEDCODE with XIP at line $line\n";
   1.176 +		}
   1.177 +		if ($module{pageddata} && !$module{exe}) {
   1.178 +			die "Can't have PAGEDDATA without EXE at line $line\n";
   1.179 +		}
   1.180 +		if ($module{idrive} && $module{xip}) {
   1.181 +			die "Can't have INTERNAL DRIVE with XIP at line $line\n";
   1.182 +		}
   1.183 +		if ($module{vdrive} && $module{xip}) {
   1.184 +			die "Can't have REMOVABLE DRIVE with XIP at line $line\n";
   1.185 +		}
   1.186 +		if ($module{idrive} && $module{vdrive}) {
   1.187 +			die "Can't have INTERNAL DRIVE with REMOVABLE DRIVE at line $line\n";
   1.188 +		}
   1.189 +		if ($module{bytepair} && $module{uncompressed}) {
   1.190 +			die "Can't have BYTEPAIR with UNCOMPRESSED at line $line\n";
   1.191 +		}
   1.192 +		if ($module{exe}) {
   1.193 +			if ($module{attpname}) {
   1.194 +				warn "Attach process with EXE ignored at line $line\n";
   1.195 +				delete $module{attpname};
   1.196 +			}
   1.197 +			$module{basefilename}=$exebasename.$modnum;
   1.198 +			$module{filename}=$module{basefilename}.$exeext;
   1.199 +			$module{source0}=$exebasename.$source0ext;
   1.200 +			$module{source1}="";
   1.201 +			$module{trgtype}='exexp';
   1.202 +			$module{lib}=$module{basefilename}.$libext;
   1.203 +		} else {
   1.204 +			$module{basefilename}=$dllbasename.$modnum;
   1.205 +			$module{filename}=$module{basefilename}.$dllext;
   1.206 +			$module{source0}=$dllbasename.$source0ext;
   1.207 +			$module{source1}=$dllbasename.$source1ext;
   1.208 +			$module{trgtype}='dll';
   1.209 +			$module{lib}=$module{basefilename}.$libext;
   1.210 +		}
   1.211 +		$module{depnames}=\@moddesc;	# dependency names are left over
   1.212 +		$module{line}=$line;
   1.213 +		$module{mark}=0;
   1.214 +		push @modules, \%module;
   1.215 +		++$modnum;
   1.216 +	} elsif ($state<=2) {
   1.217 +		if ($state==1) {
   1.218 +			$concat="";
   1.219 +			die "Syntax error at line $line\n" unless (/^(\w+)\:/);
   1.220 +		}
   1.221 +		if (/^(.*?)\\$/) {
   1.222 +			$concat.=$1;
   1.223 +			$concat.=' ';
   1.224 +			$state=2;
   1.225 +			next;
   1.226 +		} else {
   1.227 +			$concat.=$_;
   1.228 +			$state=1;
   1.229 +		}
   1.230 +		my @modlist=split(/\s+/, $concat);
   1.231 +		my $tcname=shift @modlist;
   1.232 +		$tcname=~/^(.*?)\:$/ or die "???\n";
   1.233 +		$tcname=$1;
   1.234 +		my %tc;
   1.235 +		$tc{name}=$tcname;
   1.236 +		$tc{mod_names}=\@modlist;
   1.237 +		push @testcases, \%tc;
   1.238 +	}
   1.239 +}
   1.240 +foreach $modref (@modules) {
   1.241 +	my $moddepref=$$modref{depnames};
   1.242 +	my @deps;
   1.243 +	foreach (@$moddepref) {
   1.244 +		my $depname=lc($_);
   1.245 +		my @match=grep {lc($$_{name}) eq $depname} @modules;
   1.246 +		if (scalar(@match)==0) {
   1.247 +			die "Unknown dependent module $depname at line $$modref{line}\n";
   1.248 +		}
   1.249 +		my $depref=$match[0];
   1.250 +		if ($$modref{xip} and !$$depref{xip}) {
   1.251 +			die "Illegal dependency: $$modref{name} (XIP) on $$depref{name} (non-XIP)\n";
   1.252 +		}
   1.253 +		push @deps, $$depref{num};
   1.254 +		++$$depref{nclients};
   1.255 +	}
   1.256 +	$$modref{deps}=\@deps;
   1.257 +	my $attpname=$$modref{attpname};
   1.258 +	if ($attpname) {
   1.259 +		my @match=grep {lc($$_{name}) eq lc($attpname)} @modules;
   1.260 +		if (scalar(@match)==0) {
   1.261 +			die "Unknown attach process $attpname at line $$modref{line}\n";
   1.262 +		}
   1.263 +		my $attpref=$match[0];
   1.264 +		if (!$$attpref{exe}) {
   1.265 +			die "Specified attach process is not EXE at line $$modref{line}\n";
   1.266 +		} elsif (!$$attpref{xip}) {
   1.267 +			die "Specified attach process is not XIP at line $$modref{line}\n";
   1.268 +		}
   1.269 +		$$modref{attp}=$attpref;
   1.270 +	}
   1.271 +}
   1.272 +foreach $tcref (@testcases) {
   1.273 +	my $modlistref=$$tcref{mod_names};
   1.274 +	my @modnums;
   1.275 +	foreach $modname (@$modlistref) {
   1.276 +		next if ($modname=~/^\s*$/);
   1.277 +		my @match=grep {lc($$_{name}) eq lc($modname)} @modules;
   1.278 +		if (scalar(@match)==0) {
   1.279 +			die "Unknown module $modname in test case $$tcref{name}\n";
   1.280 +		}
   1.281 +		push @modnums, $match[0]->{num};
   1.282 +	}
   1.283 +	$$tcref{modules}=\@modnums;
   1.284 +	$$tcref{count}=scalar(@modnums);
   1.285 +}
   1.286 +my $next_mark=0;
   1.287 +foreach $modref (@modules) {
   1.288 +	if ($$modref{nclients}==0 and $$modref{exe}) {
   1.289 +		# EXE with no exports
   1.290 +		$$modref{exports}=0;
   1.291 +		$$modref{trgtype}='exe';
   1.292 +	}
   1.293 +	++$next_mark;
   1.294 +	my $modnum=$$modref{num};
   1.295 +	my @tcdeps;
   1.296 +	calc_tc(\@tcdeps, \@modules, $modref, $next_mark);
   1.297 +	$$modref{tcdeps}=\@tcdeps;
   1.298 +	if (grep {$_==$modnum} @tcdeps) {
   1.299 +		$$modref{cycle}=1;
   1.300 +	}
   1.301 +	my @exes=grep {$modules[$_]->{exe}} @tcdeps;
   1.302 +	my $nexes=scalar(@exes);
   1.303 +
   1.304 +	unless ($allowbad) {
   1.305 +		if ($nexes>1) {
   1.306 +			die "Module $$modref{name} links to more than one EXE\n";
   1.307 +		} elsif ($nexes==1) {
   1.308 +			my $exeref=$modules[$exes[0]];
   1.309 +			$$modref{linkexe}=$exeref;
   1.310 +			if ($$modref{exe}) {
   1.311 +				if ($$exeref{num}!=$modnum) {
   1.312 +					die "EXE $modref{name} links to another EXE\n";
   1.313 +				}
   1.314 +			} else {
   1.315 +				if ($$modref{attp} and $$exeref{num}!=$modref->{attp}->{num}) {
   1.316 +					die "DLL $$modref{name} ($modnum) incompatible attach process\n";
   1.317 +				}
   1.318 +				if (!$$modref{attp}) {
   1.319 +					$$modref{attp}=$exeref;
   1.320 +				}
   1.321 +			}
   1.322 +		}
   1.323 +	}
   1.324 +	if ($$modref{exe}) {
   1.325 +		foreach $depnum (@tcdeps) {
   1.326 +			my $depref=$modules[$depnum];
   1.327 +			my $depattpref=$depref->{attp};
   1.328 +			if ($depattpref and $depattpref->{num}!=$modnum) {
   1.329 +				die "DEP DLL $$depref{name} ($$depref{num}) incompatible attach process\n";
   1.330 +			}
   1.331 +#			if (!$depattpref) {
   1.332 +#				$$depref{attp}=$modref;
   1.333 +#			}
   1.334 +		}
   1.335 +	}
   1.336 +}
   1.337 +foreach $modref (@modules) {
   1.338 +	my @total_deps;
   1.339 +	my $tcdepref=$$modref{tcdeps};
   1.340 +	push @total_deps, @$tcdepref;
   1.341 +	my $linkexe=$$modref{linkexe};
   1.342 +	if ($linkexe) {
   1.343 +		my $exetcdepref=$$linkexe{tcdeps};
   1.344 +		push @total_deps, @$exetcdepref;
   1.345 +	}
   1.346 +	push @total_deps, $$modref{num};
   1.347 +	my $data=scalar(grep {$modules[$_]->{data}} @total_deps);
   1.348 +	if ($data!=0) {
   1.349 +		$$modref{dataintree}=1;
   1.350 +	}
   1.351 +	my $xipdata=scalar(grep {$modules[$_]->{data} and $modules[$_]->{xip}} @total_deps);
   1.352 +	if ($xipdata!=0) {
   1.353 +		$$modref{xipdataintree}=1;
   1.354 +	}
   1.355 +}
   1.356 +
   1.357 +#foreach $modref (@modules) {
   1.358 +#	print "Module $$modref{num}:\n";
   1.359 +#	print "\tName:     $$modref{name}\n";
   1.360 +#	print "\tFilename: $$modref{filename}\n";
   1.361 +#	my $depref=$$modref{deps};
   1.362 +#	my $ndeps=scalar(@$depref);
   1.363 +#	print "\t#Deps:    $ndeps\n";
   1.364 +#	print "\tDeps:     ",join(',',@$depref),"\n";
   1.365 +#}
   1.366 +
   1.367 +my @bldinf;
   1.368 +my $bldname='dlltree.inf';
   1.369 +push @bldinf, "// $destpath$bldname\n";
   1.370 +push @bldinf, "//\n";
   1.371 +push @bldinf, "// Copyright (c) 2000-$copy_end Symbian Ltd. All rights reserved.\n";
   1.372 +push @bldinf, "//\n";
   1.373 +push @bldinf, "\n";
   1.374 +push @bldinf, "PRJ_PLATFORMS\n";
   1.375 +push @bldinf, "BASEUSERDEFAULT\n";
   1.376 +push @bldinf, "\n";
   1.377 +push @bldinf, "PRJ_TESTMMPFILES\n";
   1.378 +push @bldinf, "\n";
   1.379 +
   1.380 +my @dlltree;
   1.381 +my $dlltreename='dlltree.h';
   1.382 +push @dlltree, "// $destpath$dlltreename\n";
   1.383 +push @dlltree, "//\n";
   1.384 +push @dlltree, "// Copyright (c) 2000-$copy_end Symbian Ltd. All rights reserved.\n";
   1.385 +push @dlltree, "//\n";
   1.386 +push @dlltree, "\n";
   1.387 +push @dlltree, "#ifndef __DLLTREE_H__\n";
   1.388 +push @dlltree, "#define __DLLTREE_H__\n";
   1.389 +push @dlltree, "#include <e32std.h>\n";
   1.390 +push @dlltree, "\n";
   1.391 +push @dlltree, "class MDllList;\n";
   1.392 +push @dlltree, "\n";
   1.393 +
   1.394 +my $ibyname='ldrtest.iby';
   1.395 +my @iby;
   1.396 +
   1.397 +foreach $modref (@modules) {
   1.398 +	my @mmp;
   1.399 +	my $num=$$modref{num};
   1.400 +	my $mmpname=$$modref{basefilename}.$mmpext;
   1.401 +	my $defname=$$modref{basefilename}.$defext;
   1.402 +	my $depsref=$$modref{deps};
   1.403 +	my $ndeps=scalar(@$depsref);
   1.404 +	push @mmp, "// $destpath$mmpname\n";
   1.405 +	push @mmp, "//\n";
   1.406 +	push @mmp, "// Copyright (c) 2000-$copy_end Symbian Ltd. All rights reserved.\n";
   1.407 +	push @mmp, "//\n";
   1.408 +	push @mmp, "// Generated from $$modref{name}\n";
   1.409 +	push @mmp, "\n";
   1.410 +	push @mmp, "macro             __DLLNUM$num\n";
   1.411 +	push @mmp, "target            $$modref{filename}\n";
   1.412 +	push @mmp, "targettype        $$modref{trgtype}\n";
   1.413 +	push @mmp, "sourcepath        .\n";
   1.414 +	push @mmp, "source            $$modref{source0} $$modref{source1}\n";
   1.415 +	push @mmp, "library           euser.lib efsrv.lib\n";
   1.416 +	push @mmp, "Capability		NONE\n";
   1.417 +	foreach (@$depsref) {
   1.418 +		my $depref=$modules[$_];
   1.419 +		push @mmp, "library           $$depref{lib}\n";
   1.420 +	}
   1.421 +	if ($$modref{exports}) {
   1.422 +		push @mmp, "deffile           ./$defname\n";
   1.423 +		push @mmp, "nostrictdef\n";
   1.424 +	}
   1.425 +	push @mmp, "OS_LAYER_SYSTEMINCLUDE_SYMBIAN   \n";
   1.426 +	push @mmp, "systeminclude     ../../../e32test/mmu   \n";
   1.427 +	push @mmp, "userinclude       . \n";
   1.428 +	if ($$modref{fixed}) {
   1.429 +		push @mmp, "epocfixedprocess\n";
   1.430 +	}
   1.431 +
   1.432 +	# if both paged flags are set or the compression is not pageable then print neither.
   1.433 +	# T_LDRTST will add the required flags when it copies the file to internal media.
   1.434 +
   1.435 +	my $bothCodePageFlags = $$modref{pagedcode} && $$modref{unpagedcode};
   1.436 +	my $pageableCompression = $$modref{bytepair} || $$modref{uncompressed};
   1.437 +	if (!$bothCodePageFlags && $pageableCompression) {
   1.438 +		push @mmp, "pagedcode\n" if $$modref{pagedcode};
   1.439 +		push @mmp, "unpagedcode\n" if $$modref{unpagedcode};
   1.440 +	}
   1.441 +
   1.442 +	if ($$modref{exe}) {
   1.443 +		# make exes unpageddata by default
   1.444 +		if (!$$modref{pageddata}) {
   1.445 +			$$modref{unpageddata}=1;
   1.446 +		}
   1.447 +		if ($$modref{pageddata}) {
   1.448 +			push @mmp, "pageddata\n";
   1.449 +		}
   1.450 +		if ($$modref{unpageddata}) {
   1.451 +			push @mmp, "unpageddata\n";
   1.452 +		}
   1.453 +	}
   1.454 +
   1.455 +	if ($$modref{bytepair}) {
   1.456 +		push @mmp, "bytepaircompresstarget\n";
   1.457 +	}
   1.458 +
   1.459 +	if ($$modref{uncompressed}) {
   1.460 +		push @mmp, "nocompresstarget\n";
   1.461 +	}
   1.462 +
   1.463 +	if ($$modref{data} && !$$modref{exe}) {
   1.464 +		push @mmp, "epocallowdlldata\n";
   1.465 +	}
   1.466 +	push @mmp, sprintf("uid               0x00000000 0x%08x\n", $num+256);
   1.467 +	push @mmp, "SMPSAFE\n";
   1.468 +	$$modref{mmp}=\@mmp;
   1.469 +
   1.470 +	if ($$modref{exports}) {
   1.471 +		my @def;
   1.472 +		push @def, "EXPORTS\n";
   1.473 +		if ($$modref{exe}) {
   1.474 +			push @def, "\tRegisterConstructorCall @ 1 NONAME\n";
   1.475 +			push @def, "\tRegisterInitCall @ 2 NONAME\n";
   1.476 +			push @def, "\tRegisterDestructorCall @ 3 NONAME\n";
   1.477 +		} else {
   1.478 +			push @def, "\tInit$num @ 1 NONAME\n";
   1.479 +			push @def, "\tChkC$num @ 2 NONAME\n";
   1.480 +			push @def, "\tBlkI$num @ 3 NONAME\n";
   1.481 +			push @def, "\tGetGeneration @ 4 NONAME\n";
   1.482 +			push @def, "\tRBlkI$num @ 5 NONAME\n";
   1.483 +			push @def, "\tSetCloseLib @ 6 NONAME\n";
   1.484 +		}
   1.485 +		$$modref{def}=\@def;
   1.486 +	}
   1.487 +
   1.488 +	push @bldinf, "$$modref{basefilename}\t\tsupport\n";
   1.489 +
   1.490 +	if ($num==0) {
   1.491 +		push @dlltree, "#if defined(__DLLNUM$num)\n";
   1.492 +	} else {
   1.493 +		push @dlltree, "#elif defined(__DLLNUM$num)\n";
   1.494 +	}
   1.495 +	push @dlltree, "#define DLLNUM               $num\n";
   1.496 +	if ($$modref{exe}) {
   1.497 +		push @dlltree, "#define EXENUM               $num\n";
   1.498 +		push @dlltree, "_LIT(KServerName, \"$$modref{name}\");\n";
   1.499 +	}
   1.500 +	push @dlltree, "#define INITFUNC             Init$num\n";
   1.501 +	push @dlltree, "#define CHKCFUNC             ChkC$num\n";
   1.502 +	push @dlltree, "#define BLKIFUNC             BlkI$num\n";
   1.503 +	push @dlltree, "#define RBLKIFUNC            RBlkI$num\n";
   1.504 +	push @dlltree, "#define CHKDEPS(r)           (\\\n";
   1.505 +	foreach (@$depsref) {
   1.506 +		my $depref=$modules[$_];
   1.507 +		unless ($$depref{exe}) {
   1.508 +			my $func="ChkC$_";
   1.509 +			push @dlltree, "\t((r)=$func())!=0 ||\\\n";
   1.510 +		}
   1.511 +	}
   1.512 +	push @dlltree, "\t((r)=0)!=0 )\n";
   1.513 +	push @dlltree, "#define INITDEPS(r,l)        (\\\n";
   1.514 +	foreach (@$depsref) {
   1.515 +		my $depref=$modules[$_];
   1.516 +		unless ($$depref{exe}) {
   1.517 +			my $func="Init$_";
   1.518 +			push @dlltree, "\t((r)=$func(l))!=0 ||\\\n";
   1.519 +		}
   1.520 +	}
   1.521 +	push @dlltree, "\t((r)=0)!=0 )\n";
   1.522 +	my $link_to_exe;
   1.523 +	push @dlltree, "#define RBLKIFUNC_DEPS(i,g)  {\\\n";
   1.524 +	foreach (@$depsref) {
   1.525 +		my $depref=$modules[$_];
   1.526 +		if ($$depref{exe}) {
   1.527 +			$link_to_exe=1;
   1.528 +		} else {
   1.529 +			my $func="RBlkI$_";
   1.530 +			push @dlltree, "\t(i)=$func(i,g);\\\n";
   1.531 +		}
   1.532 +	}
   1.533 +	push @dlltree, "\t}\n";
   1.534 +	if ($link_to_exe) {
   1.535 +		push @dlltree, "#define __DLL_LINK_TO_EXE\n";
   1.536 +	}
   1.537 +	if ($$modref{cycle}) {
   1.538 +		push @dlltree, "#define __DLL_IN_CYCLE\n";
   1.539 +	}
   1.540 +	if ($$modref{data}) {
   1.541 +		push @dlltree, "#define __MODULE_HAS_DATA\n";
   1.542 +	}
   1.543 +	if ($$modref{exports}) {
   1.544 +		push @dlltree, "#define __MODULE_EXPORT\t\tEXPORT_C\n";
   1.545 +		push @dlltree, "#define __MODULE_IMPORT\t\tIMPORT_C\n";
   1.546 +	} else {
   1.547 +		push @dlltree, "#define __MODULE_EXPORT\n";
   1.548 +		push @dlltree, "#define __MODULE_IMPORT\n";
   1.549 +	}
   1.550 +	foreach (@$depsref) {
   1.551 +		my $depref=$modules[$_];
   1.552 +		if ($$depref{exe}) {
   1.553 +		} else {
   1.554 +			push @dlltree, "extern \"C\" IMPORT_C TInt Init$_(MDllList&);\n";
   1.555 +			push @dlltree, "extern \"C\" IMPORT_C TInt ChkC$_();\n";
   1.556 +			push @dlltree, "extern \"C\" IMPORT_C TInt RBlkI$_(TInt, TInt);\n";
   1.557 +		}
   1.558 +	}
   1.559 +	my $hostfullpathname=$hostpath.$$modref{filename};
   1.560 +	if ($$modref{xip}) {
   1.561 +		my $epocfullpathname=$xippath.$$modref{filename};
   1.562 +		my $flags;
   1.563 +		if ($$modref{attp}) {
   1.564 +			$flags='process '.$modref->{attp}->{filename};
   1.565 +		}
   1.566 +		push @iby, "file=$hostfullpathname\t\t$epocfullpathname\t\t$flags\n";
   1.567 +	} else {
   1.568 +		my $epocfullpathname=$nonxippath.$$modref{filename};
   1.569 +		push @iby, "data=$hostfullpathname\t\t$epocfullpathname\n";
   1.570 +	}
   1.571 +}
   1.572 +
   1.573 +#push @dlltree, "#else\n";
   1.574 +#push @dlltree, "#error No __DLLNUM macro defined\n";
   1.575 +push @dlltree, "#endif\n";
   1.576 +push @dlltree, "\n";
   1.577 +
   1.578 +my $module_count=scalar(@modules);
   1.579 +push @dlltree, "const TInt KNumModules=$module_count;\n";
   1.580 +push @dlltree, "\n";
   1.581 +push @dlltree, "#ifdef __INCLUDE_DEPENDENCY_GRAPH\n";
   1.582 +push @dlltree, "static const TText* const ModuleName[KNumModules] =\n";
   1.583 +push @dlltree, "\t\{\n";
   1.584 +foreach $modref (@modules) {
   1.585 +	my $string="\t(const TText*)L\"$$modref{name}\"";
   1.586 +	unless ($$modref{num}==$module_count-1) {
   1.587 +		$string.=',';
   1.588 +	}
   1.589 +	push @dlltree, $string;
   1.590 +	my $pad=41-length($string);
   1.591 +	$pad=($pad+3)/4;
   1.592 +	push @dlltree, "\t"x$pad, "\/*", $$modref{num}, "*\/\n";
   1.593 +}
   1.594 +push @dlltree, "\t\};\n";
   1.595 +push @dlltree, "\n";
   1.596 +push @dlltree, "#define MODULE_NAME(n)	TPtrC(ModuleName[n])\n";
   1.597 +push @dlltree, "\n";
   1.598 +push @dlltree, "static const TText* const ModuleFileName[KNumModules] =\n";
   1.599 +push @dlltree, "\t\{\n";
   1.600 +foreach $modref (@modules) {
   1.601 +	if ($$modref{idrive} || $$modref{vdrive}) {
   1.602 +		my $fn = $$modref{filename};
   1.603 +		my $used_nxip_path = "?:\\$nonxippath$fn";
   1.604 +		$used_nxip_path =~ s/\\/\\\\/g;		# double backslashes
   1.605 +		substr($used_nxip_path,0,1) = $$modref{idrive} ? "0" : "1";
   1.606 +		push @dlltree, "\t(const TText*)L\"$used_nxip_path\"";
   1.607 +	} else {
   1.608 +		push @dlltree, "\t(const TText*)L\"$$modref{filename}\"";
   1.609 +	}
   1.610 +	if ($$modref{num}==$module_count-1) {
   1.611 +		push @dlltree, "\n";
   1.612 +	} else {
   1.613 +		push @dlltree, ",\n";
   1.614 +	}
   1.615 +}
   1.616 +push @dlltree, "\t\};\n";
   1.617 +push @dlltree, "\n";
   1.618 +push @dlltree, "#define MODULE_FILENAME(n)	TPtrC(ModuleFileName[n])\n";
   1.619 +push @dlltree, "\n";
   1.620 +foreach $modref (@modules) {
   1.621 +	my $modnum=$$modref{num};
   1.622 +	my $tcdepsref=$$modref{tcdeps};
   1.623 +	my $numdeps=scalar(@$tcdepsref);
   1.624 +	push @dlltree, "static const TInt Module$modnum","Deps[] =\n";
   1.625 +	push @dlltree, "\t\{$numdeps";
   1.626 +	if ($numdeps) {
   1.627 +		push @dlltree, ",", join(',',@$tcdepsref)
   1.628 +	}
   1.629 +	push @dlltree, "\};\n";
   1.630 +}
   1.631 +push @dlltree, "static const TInt* const ModuleDependencies[KNumModules] =\n";
   1.632 +push @dlltree, "\t\{\n";
   1.633 +foreach $modref (@modules) {
   1.634 +	my $modnum=$$modref{num};
   1.635 +	push @dlltree, "\tModule$modnum","Deps";
   1.636 +	if ($$modref{num}==$module_count-1) {
   1.637 +		push @dlltree, "\n";
   1.638 +	} else {
   1.639 +		push @dlltree, ",\n";
   1.640 +	}
   1.641 +}
   1.642 +push @dlltree, "\t\};\n";
   1.643 +push @dlltree, "\n";
   1.644 +push @dlltree, sprintf "const TInt KModuleFlagExe=0x%04x;\n", $flag_value_exe;
   1.645 +push @dlltree, sprintf "const TInt KModuleFlagFixed=0x%04x;\n", $flag_value_fixed;
   1.646 +push @dlltree, sprintf "const TInt KModuleFlagData=0x%04x;\n", $flag_value_data;
   1.647 +#push @dlltree, "#ifdef __EPOC32__\n";
   1.648 +push @dlltree, sprintf "const TInt KModuleFlagXIP=0x%04x;\n", $flag_value_xip;
   1.649 +push @dlltree, sprintf "const TInt KModuleFlagPagedCode=0x%04x;\n", $flag_value_pagedcode;
   1.650 +push @dlltree, sprintf "const TInt KModuleFlagUnpagedCode=0x%04x;\n", $flag_value_unpagedcode;
   1.651 +push @dlltree, sprintf "const TInt KModuleFlagIDrive=0x%04x;\n", $flag_value_idrive;
   1.652 +push @dlltree, sprintf "const TInt KModuleFlagVDrive=0x%04x;\n", $flag_value_vdrive;
   1.653 +push @dlltree, sprintf "const TInt KModuleFlagBytePair=0x%04x;\n", $flag_value_bytepair;
   1.654 +push @dlltree, sprintf "const TInt KModuleFlagUncompressed=0x%04x;\n", $flag_value_uncompressed;
   1.655 +#push @dlltree, "#else\n";
   1.656 +#push @dlltree, sprintf "const TInt KModuleFlagXIP=0x%04x;\n", 0;	# no XIPs on emulator
   1.657 +#push @dlltree, "#endif\n";
   1.658 +push @dlltree, sprintf "const TInt KModuleFlagDllInCycle=0x%04x;\n", $flag_value_dll_in_cycle;
   1.659 +push @dlltree, sprintf "const TInt KModuleFlagDataInTree=0x%04x;\n", $flag_value_data_in_tree;
   1.660 +#push @dlltree, "#ifdef __EPOC32__\n";
   1.661 +push @dlltree, sprintf "const TInt KModuleFlagXIPDataInTree=0x%04x;\n", $flag_value_xip_data_in_tree;
   1.662 +#push @dlltree, "#else\n";
   1.663 +#push @dlltree, sprintf "const TInt KModuleFlagXIPDataInTree=0x%04x;\n", 0;
   1.664 +#push @dlltree, "#endif\n";
   1.665 +push @dlltree, sprintf "const TInt KModuleFlagExports=0x%04x;\n", $flag_value_exports;
   1.666 +push @dlltree, sprintf "const TInt KModuleFlagTargetOnly=0x%04x;\n", $flag_value_targetonly;
   1.667 +push @dlltree, sprintf "const TInt KModuleFlagPagedData=0x%04x;\n", $flag_value_pageddata;
   1.668 +push @dlltree, sprintf "const TInt KModuleFlagUnpagedData=0x%04x;\n", $flag_value_unpageddata;
   1.669 +push @dlltree, "static const TInt ModuleFlags[KNumModules] =\n";
   1.670 +push @dlltree, "\t\{\n";
   1.671 +foreach $modref (@modules) {
   1.672 +	my $flags=0;
   1.673 +	my @flagNames = ();
   1.674 +
   1.675 +	push @flagNames, "KModuleFlagExe" if ($$modref{exe});
   1.676 +	push @flagNames, "KModuleFlagFixed" if ($$modref{fixed});
   1.677 +	push @flagNames, "KModuleFlagData" if ($$modref{data});
   1.678 +	push @flagNames, "KModuleFlagXIP" if ($$modref{xip});
   1.679 +	push @flagNames, "KModuleFlagPagedCode" if ($$modref{pagedcode});
   1.680 +	push @flagNames, "KModuleFlagUnpagedCode" if ($$modref{unpagedcode});
   1.681 +	push @flagNames, "KModuleFlagPagedData" if ($$modref{pageddata});
   1.682 +	push @flagNames, "KModuleFlagUnpagedData" if (!$$modref{pageddata});
   1.683 +	push @flagNames, "KModuleFlagIDrive" if ($$modref{idrive});
   1.684 +	push @flagNames, "KModuleFlagVDrive" if ($$modref{vdrive});
   1.685 +	push @flagNames, "KModuleFlagBytePair" if ($$modref{bytepair});
   1.686 +	push @flagNames, "KModuleFlagDllInCycle" if ($$modref{cycle});
   1.687 +	push @flagNames, "KModuleFlagDataInTree" if ($$modref{dataintree});
   1.688 +	push @flagNames, "KModuleFlagXIPDataInTree" if ($$modref{xipdataintree});
   1.689 +	push @flagNames, "KModuleFlagExports" if ($$modref{exports});
   1.690 +	push @flagNames, "KModuleFlagUncompressed" if ($$modref{uncompressed});
   1.691 +	push @flagNames, "KModuleFlagTargetOnly" if ($$modref{targetonly});
   1.692 +
   1.693 +	@flagNames = qw(0) if (scalar(@flagNames) == 0);
   1.694 +	my $flagString = "/\* " . $$modref{num} . " \*/\t" . join(' | ', @flagNames);
   1.695 +	unless ($$modref{num}==$module_count-1) {
   1.696 +		$flagString.=',';
   1.697 +	}
   1.698 +	push @dlltree, $flagString . "\n";
   1.699 +}
   1.700 +push @dlltree, "\t\};\n";
   1.701 +push @dlltree, "\n";
   1.702 +foreach $modref (@modules) {
   1.703 +	my $modnum=$$modref{num};
   1.704 +	my @rblki;
   1.705 +	++$next_mark;
   1.706 +	calc_rblki(\@rblki, \@modules, $modref, $next_mark);
   1.707 +	my $rblki_count=scalar(@rblki);
   1.708 +	my $rblki_sum=0;
   1.709 +	foreach (@rblki) {
   1.710 +		$rblki_sum += $_;
   1.711 +	}
   1.712 +	push @dlltree, "static const TInt Module$modnum","RBlkIParams[2] = \{ $rblki_count, $rblki_sum \};\n";
   1.713 +}
   1.714 +push @dlltree, "\n";
   1.715 +push @dlltree, "static const TInt* const ModuleRBlkIParams[KNumModules] =\n";
   1.716 +push @dlltree, "\t\{\n";
   1.717 +foreach $modref (@modules) {
   1.718 +	my $modnum=$$modref{num};
   1.719 +	push @dlltree, "\tModule$modnum","RBlkIParams";
   1.720 +	if ($$modref{num}==$module_count-1) {
   1.721 +		push @dlltree, "\n";
   1.722 +	} else {
   1.723 +		push @dlltree, ",\n";
   1.724 +	}
   1.725 +}
   1.726 +push @dlltree, "\t\};\n";
   1.727 +push @dlltree, "\n";
   1.728 +foreach $modref (@modules) {
   1.729 +	my $modnum=$$modref{num};
   1.730 +	my $mod_attp=$modnum;
   1.731 +	my $mod_linkp=$modnum;
   1.732 +	unless ($$modref{exe}) {
   1.733 +		$mod_attp = ($$modref{attp}) ? ($modref->{attp}->{num}) : -1;
   1.734 +		$mod_linkp = ($$modref{linkexe}) ? ($modref->{linkexe}->{num}) : -1;
   1.735 +	}
   1.736 +	push @dlltree, "static const TInt Module$modnum","ExeInfo[2] = \{ $mod_attp, $mod_linkp \};\n";
   1.737 +}
   1.738 +push @dlltree, "\n";
   1.739 +push @dlltree, "static const TInt* const ModuleExeInfo[KNumModules] =\n";
   1.740 +push @dlltree, "\t\{\n";
   1.741 +foreach $modref (@modules) {
   1.742 +	my $modnum=$$modref{num};
   1.743 +	push @dlltree, "\tModule$modnum","ExeInfo";
   1.744 +	if ($$modref{num}==$module_count-1) {
   1.745 +		push @dlltree, "\n";
   1.746 +	} else {
   1.747 +		push @dlltree, ",\n";
   1.748 +	}
   1.749 +}
   1.750 +push @dlltree, "\t\};\n";
   1.751 +
   1.752 +foreach $tcref (@testcases) {
   1.753 +	push @dlltree, "\n";
   1.754 +	my $modlistref=$$tcref{modules};
   1.755 +	my $count=$$tcref{count};
   1.756 +	my $arraysize=$count+1;
   1.757 +	push @dlltree, "static const TInt TC_$$tcref{name}\[$arraysize\]=\n\t\{\n";
   1.758 +	if ($count==0) {
   1.759 +		push @dlltree, "\t$count\n";
   1.760 +	} else {
   1.761 +		push @dlltree, "\t$count\,\n";
   1.762 +	}
   1.763 +	foreach (@$modlistref) {
   1.764 +		--$count;
   1.765 +		if ($count==0) {
   1.766 +			push @dlltree, "\t$_\n";
   1.767 +		} else {
   1.768 +			push @dlltree, "\t$_\,\n";
   1.769 +		}
   1.770 +	}
   1.771 +	push @dlltree, "\t\};\n";
   1.772 +}
   1.773 +
   1.774 +push @dlltree, "#endif\n";
   1.775 +push @dlltree, "\n";
   1.776 +push @dlltree, "#endif\n";
   1.777 +
   1.778 +foreach $modref (@modules) {
   1.779 +	my $mmpname=$$modref{basefilename}.$mmpext;
   1.780 +	my $mmpref=$$modref{mmp};
   1.781 +	open OUT, ">$mmpname" or die "Could not open $mmpname for output\n";
   1.782 +	print OUT @$mmpref;
   1.783 +	close OUT;
   1.784 +	if ($$modref{exports}) {
   1.785 +		my $defname=$$modref{basefilename}.$defext;
   1.786 +		my $defref=$$modref{def};
   1.787 +		open OUT, ">$defname" or die "Could not open $defname for output\n";
   1.788 +		print OUT @$defref;
   1.789 +		close OUT;
   1.790 +	}
   1.791 +}
   1.792 +if (!$allowbad) {
   1.793 +	push @bldinf, "t_ldrtst\n";
   1.794 +}
   1.795 +open OUT, ">$bldname" or die "Could not open $bldname for output\n";
   1.796 +print OUT @bldinf;
   1.797 +close OUT;
   1.798 +open OUT, ">$dlltreename" or die "Could not open $dlltreename for output\n";
   1.799 +print OUT @dlltree;
   1.800 +close OUT;
   1.801 +my $testbatch = "$ENV{EPOCROOT}epoc32\\build";
   1.802 +$destpath =~ s/\//\\/go;
   1.803 +$testbatch.="\\" unless ($destpath =~ /^\\/);
   1.804 +$testbatch.=$destpath;
   1.805 +$testbatch.="##MAIN##.auto.bat";
   1.806 +if (!$allowbad) {
   1.807 +	push @iby, "data=$testbatch\t\ttest\\loader.auto.bat\n";
   1.808 +}
   1.809 +open OUT, ">$ibyname" or die "Could not open $ibyname for output\n";
   1.810 +print OUT @iby;
   1.811 +close OUT;
   1.812 +
   1.813 +#
   1.814 +# Accumulate list of dependency numbers
   1.815 +# 1st arg = \output list
   1.816 +# 2nd arg = \module list
   1.817 +# 3rd arg = \module to start from
   1.818 +# 4th arg = mark value to use
   1.819 +#
   1.820 +sub calc_tc($$$$) {
   1.821 +	my ($out, $mods, $modref, $mark)=@_;
   1.822 +	my $depsref=$$modref{deps};
   1.823 +	foreach $dep (@$depsref) {
   1.824 +		my $depref=$$mods[$dep];
   1.825 +		if ($$depref{mark} != $mark) {
   1.826 +			$$depref{mark}=$mark;
   1.827 +			unless ($$depref{exe}) {
   1.828 +				calc_tc($out, $mods, $depref, $mark);
   1.829 +			}
   1.830 +			push @$out, $dep;
   1.831 +		}
   1.832 +	}
   1.833 +}
   1.834 +
   1.835 +#
   1.836 +# Accumulate RBlkI parameters
   1.837 +# 1st arg = \output list
   1.838 +# 2nd arg = \module list
   1.839 +# 3rd arg = \module to start from
   1.840 +# 4th arg = mark value to use
   1.841 +#
   1.842 +sub calc_rblki($$$$) {
   1.843 +	my ($out, $mods, $modref, $mark)=@_;
   1.844 +	if ($$modref{mark} != $mark) {
   1.845 +		$$modref{mark}=$mark;
   1.846 +		if (!$$modref{exe} and $$modref{data}) {
   1.847 +			push @$out, $$modref{num};
   1.848 +			my $depsref=$$modref{deps};
   1.849 +			foreach $dep (@$depsref) {
   1.850 +				calc_rblki($out, $mods, $$mods[$dep], $mark);
   1.851 +			}
   1.852 +		}
   1.853 +	}
   1.854 +}
   1.855 +
   1.856 +
   1.857 +