kerneltest/f32test/loader/dlltree.pl
changeset 0 a41df078684a
child 148 31ea0f8e3c99
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 # Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 # All rights reserved.
       
     3 # This component and the accompanying materials are made available
       
     4 # under the terms of the License "Eclipse Public License v1.0"
       
     5 # which accompanies this distribution, and is available
       
     6 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 #
       
     8 # Initial Contributors:
       
     9 # Nokia Corporation - initial contribution.
       
    10 #
       
    11 # Contributors:
       
    12 #
       
    13 # Description:
       
    14 # \f32test\loader\dlltree.pl
       
    15 # Generate header and build files for one or more trees
       
    16 # of DLLs and EXEs according to a description file.
       
    17 # 
       
    18 #
       
    19 
       
    20 require Cwd;
       
    21 
       
    22 my $dllbasename='dllt';
       
    23 my $dllext='.dll';
       
    24 my $exebasename='exet';
       
    25 my $exeext='.exe';
       
    26 my $mmpext='.mmp';
       
    27 my $defext='.def';
       
    28 my $libext='.lib';
       
    29 
       
    30 my $source0ext='.cpp';
       
    31 my $source1ext='.cia';
       
    32 my $xippath="sys\\bin\\";
       
    33 my $nonxippath="sys\\bin\\";
       
    34 
       
    35 my $hostpath="\\Epoc32\\Release\\##MAIN##\\##BUILD##\\";
       
    36 
       
    37 my $flag_value_exe=1;
       
    38 my $flag_value_fixed=2;
       
    39 my $flag_value_data=4;
       
    40 my $flag_value_xip=8;
       
    41 my $flag_value_dll_in_cycle=16;
       
    42 my $flag_value_data_in_tree=32;
       
    43 my $flag_value_xip_data_in_tree=64;
       
    44 my $flag_value_exports=128;
       
    45 my $flag_value_pagedcode=256;
       
    46 my $flag_value_unpagedcode=512;
       
    47 my $flag_value_idrive=1024;
       
    48 my $flag_value_vdrive=2048;
       
    49 my $flag_value_bytepair=4096;
       
    50 my $flag_value_uncompressed=8192;
       
    51 my $flag_value_targetonly=16384;
       
    52 my $flag_value_pageddata=32768;
       
    53 my $flag_value_unpageddata=65536;
       
    54 
       
    55 my $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst;
       
    56 ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime;
       
    57 my $copy_end=$year+1900;
       
    58 
       
    59 my $argc=scalar(@ARGV);
       
    60 ($argc==1 or $argc==2 or $argc==3) or die "Usage: perl dlltree.pl <filename> <dir> [-allowbad]\n";
       
    61 my $infile=$ARGV[0];
       
    62 open IN, $infile or die "Cannot open input file $infile\n";
       
    63 my @in;
       
    64 while (<IN>)	{
       
    65 	push @in, $_;
       
    66 }
       
    67 close IN;
       
    68 my $destdir='';
       
    69 if ($argc>=2) {
       
    70 	$destdir=$ARGV[1];
       
    71 	unless (-d $destdir) {
       
    72 		mkdir $destdir, 0777 or die "Can't create directory $destdir\n";
       
    73 	}
       
    74 	chdir $destdir or die "Can't chdir to directory $destdir\n";
       
    75 }
       
    76 my $allowbad;
       
    77 if ($argc==3) {
       
    78 	if ($ARGV[2] eq '-allowbad') {
       
    79 		$allowbad = 1;
       
    80 	}
       
    81 }
       
    82 $cwd=Cwd::getcwd();
       
    83 $destpath=$cwd;
       
    84 $destpath=~s/\//\\/g;
       
    85 if ($destpath=~/^\w\:(.*)/) {
       
    86 	$destpath=$1;
       
    87 }
       
    88 unless ($destpath=~/^(.*?)\\$/) {
       
    89 	$destpath.='\\';
       
    90 }
       
    91 #print "$cwd\n";
       
    92 #print "$destpath\n";
       
    93 
       
    94 my @modules;
       
    95 my @testcases;
       
    96 my $line=0;
       
    97 my $modnum=0;
       
    98 my $state=0;
       
    99 my $concat;
       
   100 foreach (@in)	{
       
   101 	++$line;
       
   102 	next if (/^\s*$/ or /^\s*\#/);
       
   103 	if ($state==0)	{
       
   104 		if (/^\!TESTCASES/) {
       
   105 			$state=1;
       
   106 			next;
       
   107 		}
       
   108 		my @moddesc=split;
       
   109 		my $modname=shift @moddesc;
       
   110 		if (grep {lc($$_{name}) eq lc($modname)} @modules) {
       
   111 			die "Duplicate module specification at line $line\n";
       
   112 		}
       
   113 		my %module;
       
   114 		$module{name}=$modname;
       
   115 		$module{num}=$modnum;
       
   116 		$module{exports}=1;
       
   117 		$module{nclients}=0;	# number of modules which import from this one
       
   118 		while (scalar(@moddesc)) {
       
   119 			my $att=shift @moddesc;
       
   120 			if ($att=~/^\:$/) {
       
   121 				last;
       
   122 			} elsif ($att=~/^X$/i) {
       
   123 				$module{exe}=1;
       
   124 			} elsif ($att=~/^F$/i) {
       
   125 				$module{fixed}=1;
       
   126 			} elsif ($att=~/^D$/i) {
       
   127 				$module{data}=1;
       
   128 			} elsif ($att=~/^P$/i) {
       
   129 				$module{pagedcode}=1;
       
   130 			} elsif ($att=~/^PD$/i) {
       
   131 				$module{pageddata}=1;
       
   132 			} elsif ($att=~/^B$/i) {
       
   133 				$module{bytepair}=1;
       
   134 			} elsif ($att=~/^U$/i) {
       
   135 				$module{uncompressed}=1;
       
   136 			} elsif ($att=~/^I$/i) {
       
   137 				$module{idrive}=1;
       
   138 			} elsif ($att=~/^V$/i) {
       
   139 				$module{vdrive}=1;
       
   140 			} elsif ($att=~/^N$/i) {
       
   141 				$module{unpagedcode}=1;
       
   142 			} elsif ($att=~/^T$/i) {
       
   143 				$module{targetonly}=1;
       
   144 			} elsif ($att=~/^R(.*?)$/i) {
       
   145 				$module{xip}=1;
       
   146 				my $attp=$1;
       
   147 				if ($attp=~/^\,(.*?)$/) {
       
   148 					$module{attpname}=$1;
       
   149 				} elsif (!($attp=~/^\s*$/)) {
       
   150 					die "Garbage following R attribute at line $line\n";
       
   151 				}
       
   152 			}
       
   153 		}
       
   154 		if ($module{fixed} && !$module{exe}) {
       
   155 			die "Can't have FIXED without EXE at line $line\n";
       
   156 		}
       
   157 		if ($module{pagedcode} && $module{xip}) {
       
   158 			die "Can't have PAGEDCODE with XIP at line $line\n";
       
   159 		}
       
   160 
       
   161 		# makmake won't support paged binaries which aren't bytepair or uncompressed.
       
   162 		# However, P can be specified without them in dlltree.txt.  This program generates
       
   163 		# an MMP file with neither flag.  The flag is added when the files are copied to
       
   164 		# internal media by T_LDRTST.  (It would be pointless to copy the files to removable
       
   165 		# media and then edit them because removable media doesn't support paging.)
       
   166 
       
   167 		my $bothCodePageFlags = $module{pagedcode} && $module{unpagedcode};
       
   168 		if ($bothCodePageFlags && !$module{idrive}) {
       
   169 			die "Can't have PAGEDCODE and UNPAGEDCODE without INTERNAL DRIVE at line $line\n";
       
   170 		}
       
   171 		if ($module{unpagedcode} && $module{xip}) {
       
   172 			die "Can't have UNPAGEDCODE with XIP at line $line\n";
       
   173 		}
       
   174 		if ($module{pageddata} && !$module{exe}) {
       
   175 			die "Can't have PAGEDDATA without EXE at line $line\n";
       
   176 		}
       
   177 		if ($module{idrive} && $module{xip}) {
       
   178 			die "Can't have INTERNAL DRIVE with XIP at line $line\n";
       
   179 		}
       
   180 		if ($module{vdrive} && $module{xip}) {
       
   181 			die "Can't have REMOVABLE DRIVE with XIP at line $line\n";
       
   182 		}
       
   183 		if ($module{idrive} && $module{vdrive}) {
       
   184 			die "Can't have INTERNAL DRIVE with REMOVABLE DRIVE at line $line\n";
       
   185 		}
       
   186 		if ($module{bytepair} && $module{uncompressed}) {
       
   187 			die "Can't have BYTEPAIR with UNCOMPRESSED at line $line\n";
       
   188 		}
       
   189 		if ($module{exe}) {
       
   190 			if ($module{attpname}) {
       
   191 				warn "Attach process with EXE ignored at line $line\n";
       
   192 				delete $module{attpname};
       
   193 			}
       
   194 			$module{basefilename}=$exebasename.$modnum;
       
   195 			$module{filename}=$module{basefilename}.$exeext;
       
   196 			$module{source0}=$exebasename.$source0ext;
       
   197 			$module{source1}="";
       
   198 			$module{trgtype}='exexp';
       
   199 			$module{lib}=$module{basefilename}.$libext;
       
   200 		} else {
       
   201 			$module{basefilename}=$dllbasename.$modnum;
       
   202 			$module{filename}=$module{basefilename}.$dllext;
       
   203 			$module{source0}=$dllbasename.$source0ext;
       
   204 			$module{source1}=$dllbasename.$source1ext;
       
   205 			$module{trgtype}='dll';
       
   206 			$module{lib}=$module{basefilename}.$libext;
       
   207 		}
       
   208 		$module{depnames}=\@moddesc;	# dependency names are left over
       
   209 		$module{line}=$line;
       
   210 		$module{mark}=0;
       
   211 		push @modules, \%module;
       
   212 		++$modnum;
       
   213 	} elsif ($state<=2) {
       
   214 		if ($state==1) {
       
   215 			$concat="";
       
   216 			die "Syntax error at line $line\n" unless (/^(\w+)\:/);
       
   217 		}
       
   218 		if (/^(.*?)\\$/) {
       
   219 			$concat.=$1;
       
   220 			$concat.=' ';
       
   221 			$state=2;
       
   222 			next;
       
   223 		} else {
       
   224 			$concat.=$_;
       
   225 			$state=1;
       
   226 		}
       
   227 		my @modlist=split(/\s+/, $concat);
       
   228 		my $tcname=shift @modlist;
       
   229 		$tcname=~/^(.*?)\:$/ or die "???\n";
       
   230 		$tcname=$1;
       
   231 		my %tc;
       
   232 		$tc{name}=$tcname;
       
   233 		$tc{mod_names}=\@modlist;
       
   234 		push @testcases, \%tc;
       
   235 	}
       
   236 }
       
   237 foreach $modref (@modules) {
       
   238 	my $moddepref=$$modref{depnames};
       
   239 	my @deps;
       
   240 	foreach (@$moddepref) {
       
   241 		my $depname=lc($_);
       
   242 		my @match=grep {lc($$_{name}) eq $depname} @modules;
       
   243 		if (scalar(@match)==0) {
       
   244 			die "Unknown dependent module $depname at line $$modref{line}\n";
       
   245 		}
       
   246 		my $depref=$match[0];
       
   247 		if ($$modref{xip} and !$$depref{xip}) {
       
   248 			die "Illegal dependency: $$modref{name} (XIP) on $$depref{name} (non-XIP)\n";
       
   249 		}
       
   250 		push @deps, $$depref{num};
       
   251 		++$$depref{nclients};
       
   252 	}
       
   253 	$$modref{deps}=\@deps;
       
   254 	my $attpname=$$modref{attpname};
       
   255 	if ($attpname) {
       
   256 		my @match=grep {lc($$_{name}) eq lc($attpname)} @modules;
       
   257 		if (scalar(@match)==0) {
       
   258 			die "Unknown attach process $attpname at line $$modref{line}\n";
       
   259 		}
       
   260 		my $attpref=$match[0];
       
   261 		if (!$$attpref{exe}) {
       
   262 			die "Specified attach process is not EXE at line $$modref{line}\n";
       
   263 		} elsif (!$$attpref{xip}) {
       
   264 			die "Specified attach process is not XIP at line $$modref{line}\n";
       
   265 		}
       
   266 		$$modref{attp}=$attpref;
       
   267 	}
       
   268 }
       
   269 foreach $tcref (@testcases) {
       
   270 	my $modlistref=$$tcref{mod_names};
       
   271 	my @modnums;
       
   272 	foreach $modname (@$modlistref) {
       
   273 		next if ($modname=~/^\s*$/);
       
   274 		my @match=grep {lc($$_{name}) eq lc($modname)} @modules;
       
   275 		if (scalar(@match)==0) {
       
   276 			die "Unknown module $modname in test case $$tcref{name}\n";
       
   277 		}
       
   278 		push @modnums, $match[0]->{num};
       
   279 	}
       
   280 	$$tcref{modules}=\@modnums;
       
   281 	$$tcref{count}=scalar(@modnums);
       
   282 }
       
   283 my $next_mark=0;
       
   284 foreach $modref (@modules) {
       
   285 	if ($$modref{nclients}==0 and $$modref{exe}) {
       
   286 		# EXE with no exports
       
   287 		$$modref{exports}=0;
       
   288 		$$modref{trgtype}='exe';
       
   289 	}
       
   290 	++$next_mark;
       
   291 	my $modnum=$$modref{num};
       
   292 	my @tcdeps;
       
   293 	calc_tc(\@tcdeps, \@modules, $modref, $next_mark);
       
   294 	$$modref{tcdeps}=\@tcdeps;
       
   295 	if (grep {$_==$modnum} @tcdeps) {
       
   296 		$$modref{cycle}=1;
       
   297 	}
       
   298 	my @exes=grep {$modules[$_]->{exe}} @tcdeps;
       
   299 	my $nexes=scalar(@exes);
       
   300 
       
   301 	unless ($allowbad) {
       
   302 		if ($nexes>1) {
       
   303 			die "Module $$modref{name} links to more than one EXE\n";
       
   304 		} elsif ($nexes==1) {
       
   305 			my $exeref=$modules[$exes[0]];
       
   306 			$$modref{linkexe}=$exeref;
       
   307 			if ($$modref{exe}) {
       
   308 				if ($$exeref{num}!=$modnum) {
       
   309 					die "EXE $modref{name} links to another EXE\n";
       
   310 				}
       
   311 			} else {
       
   312 				if ($$modref{attp} and $$exeref{num}!=$modref->{attp}->{num}) {
       
   313 					die "DLL $$modref{name} ($modnum) incompatible attach process\n";
       
   314 				}
       
   315 				if (!$$modref{attp}) {
       
   316 					$$modref{attp}=$exeref;
       
   317 				}
       
   318 			}
       
   319 		}
       
   320 	}
       
   321 	if ($$modref{exe}) {
       
   322 		foreach $depnum (@tcdeps) {
       
   323 			my $depref=$modules[$depnum];
       
   324 			my $depattpref=$depref->{attp};
       
   325 			if ($depattpref and $depattpref->{num}!=$modnum) {
       
   326 				die "DEP DLL $$depref{name} ($$depref{num}) incompatible attach process\n";
       
   327 			}
       
   328 #			if (!$depattpref) {
       
   329 #				$$depref{attp}=$modref;
       
   330 #			}
       
   331 		}
       
   332 	}
       
   333 }
       
   334 foreach $modref (@modules) {
       
   335 	my @total_deps;
       
   336 	my $tcdepref=$$modref{tcdeps};
       
   337 	push @total_deps, @$tcdepref;
       
   338 	my $linkexe=$$modref{linkexe};
       
   339 	if ($linkexe) {
       
   340 		my $exetcdepref=$$linkexe{tcdeps};
       
   341 		push @total_deps, @$exetcdepref;
       
   342 	}
       
   343 	push @total_deps, $$modref{num};
       
   344 	my $data=scalar(grep {$modules[$_]->{data}} @total_deps);
       
   345 	if ($data!=0) {
       
   346 		$$modref{dataintree}=1;
       
   347 	}
       
   348 	my $xipdata=scalar(grep {$modules[$_]->{data} and $modules[$_]->{xip}} @total_deps);
       
   349 	if ($xipdata!=0) {
       
   350 		$$modref{xipdataintree}=1;
       
   351 	}
       
   352 }
       
   353 
       
   354 #foreach $modref (@modules) {
       
   355 #	print "Module $$modref{num}:\n";
       
   356 #	print "\tName:     $$modref{name}\n";
       
   357 #	print "\tFilename: $$modref{filename}\n";
       
   358 #	my $depref=$$modref{deps};
       
   359 #	my $ndeps=scalar(@$depref);
       
   360 #	print "\t#Deps:    $ndeps\n";
       
   361 #	print "\tDeps:     ",join(',',@$depref),"\n";
       
   362 #}
       
   363 
       
   364 my @bldinf;
       
   365 my $bldname='dlltree.inf';
       
   366 push @bldinf, "// $destpath$bldname\n";
       
   367 push @bldinf, "//\n";
       
   368 push @bldinf, "// Copyright (c) 2000-$copy_end Symbian Ltd. All rights reserved.\n";
       
   369 push @bldinf, "//\n";
       
   370 push @bldinf, "\n";
       
   371 push @bldinf, "PRJ_PLATFORMS\n";
       
   372 push @bldinf, "BASEUSERDEFAULT\n";
       
   373 push @bldinf, "\n";
       
   374 push @bldinf, "PRJ_TESTMMPFILES\n";
       
   375 push @bldinf, "\n";
       
   376 
       
   377 my @dlltree;
       
   378 my $dlltreename='dlltree.h';
       
   379 push @dlltree, "// $destpath$dlltreename\n";
       
   380 push @dlltree, "//\n";
       
   381 push @dlltree, "// Copyright (c) 2000-$copy_end Symbian Ltd. All rights reserved.\n";
       
   382 push @dlltree, "//\n";
       
   383 push @dlltree, "\n";
       
   384 push @dlltree, "#ifndef __DLLTREE_H__\n";
       
   385 push @dlltree, "#define __DLLTREE_H__\n";
       
   386 push @dlltree, "#include <e32std.h>\n";
       
   387 push @dlltree, "\n";
       
   388 push @dlltree, "class MDllList;\n";
       
   389 push @dlltree, "\n";
       
   390 
       
   391 my $ibyname='ldrtest.iby';
       
   392 my @iby;
       
   393 
       
   394 foreach $modref (@modules) {
       
   395 	my @mmp;
       
   396 	my $num=$$modref{num};
       
   397 	my $mmpname=$$modref{basefilename}.$mmpext;
       
   398 	my $defname=$$modref{basefilename}.$defext;
       
   399 	my $depsref=$$modref{deps};
       
   400 	my $ndeps=scalar(@$depsref);
       
   401 	push @mmp, "// $destpath$mmpname\n";
       
   402 	push @mmp, "//\n";
       
   403 	push @mmp, "// Copyright (c) 2000-$copy_end Symbian Ltd. All rights reserved.\n";
       
   404 	push @mmp, "//\n";
       
   405 	push @mmp, "// Generated from $$modref{name}\n";
       
   406 	push @mmp, "\n";
       
   407 	push @mmp, "macro             __DLLNUM$num\n";
       
   408 	push @mmp, "target            $$modref{filename}\n";
       
   409 	push @mmp, "targettype        $$modref{trgtype}\n";
       
   410 	push @mmp, "sourcepath        .\n";
       
   411 	push @mmp, "source            $$modref{source0} $$modref{source1}\n";
       
   412 	push @mmp, "library           euser.lib efsrv.lib\n";
       
   413 	push @mmp, "Capability		NONE\n";
       
   414 	foreach (@$depsref) {
       
   415 		my $depref=$modules[$_];
       
   416 		push @mmp, "library           $$depref{lib}\n";
       
   417 	}
       
   418 	if ($$modref{exports}) {
       
   419 		push @mmp, "deffile           ./$defname\n";
       
   420 		push @mmp, "nostrictdef\n";
       
   421 	}
       
   422 	push @mmp, "OS_LAYER_SYSTEMINCLUDE_SYMBIAN   \n";
       
   423 	push @mmp, "systeminclude     ../../../e32test/mmu   \n";
       
   424 	push @mmp, "userinclude       . \n";
       
   425 	if ($$modref{fixed}) {
       
   426 		push @mmp, "epocfixedprocess\n";
       
   427 	}
       
   428 
       
   429 	# if both paged flags are set or the compression is not pageable then print neither.
       
   430 	# T_LDRTST will add the required flags when it copies the file to internal media.
       
   431 
       
   432 	my $bothCodePageFlags = $$modref{pagedcode} && $$modref{unpagedcode};
       
   433 	my $pageableCompression = $$modref{bytepair} || $$modref{uncompressed};
       
   434 	if (!$bothCodePageFlags && $pageableCompression) {
       
   435 		push @mmp, "pagedcode\n" if $$modref{pagedcode};
       
   436 		push @mmp, "unpagedcode\n" if $$modref{unpagedcode};
       
   437 	}
       
   438 
       
   439 	if ($$modref{exe}) {
       
   440 		# make exes unpageddata by default
       
   441 		if (!$$modref{pageddata}) {
       
   442 			$$modref{unpageddata}=1;
       
   443 		}
       
   444 		if ($$modref{pageddata}) {
       
   445 			push @mmp, "pageddata\n";
       
   446 		}
       
   447 		if ($$modref{unpageddata}) {
       
   448 			push @mmp, "unpageddata\n";
       
   449 		}
       
   450 	}
       
   451 
       
   452 	if ($$modref{bytepair}) {
       
   453 		push @mmp, "bytepaircompresstarget\n";
       
   454 	}
       
   455 
       
   456 	if ($$modref{uncompressed}) {
       
   457 		push @mmp, "nocompresstarget\n";
       
   458 	}
       
   459 
       
   460 	if ($$modref{data} && !$$modref{exe}) {
       
   461 		push @mmp, "epocallowdlldata\n";
       
   462 	}
       
   463 	push @mmp, sprintf("uid               0x00000000 0x%08x\n", $num+256);
       
   464 	push @mmp, "SMPSAFE\n";
       
   465 	$$modref{mmp}=\@mmp;
       
   466 
       
   467 	if ($$modref{exports}) {
       
   468 		my @def;
       
   469 		push @def, "EXPORTS\n";
       
   470 		if ($$modref{exe}) {
       
   471 			push @def, "\tRegisterConstructorCall @ 1 NONAME\n";
       
   472 			push @def, "\tRegisterInitCall @ 2 NONAME\n";
       
   473 			push @def, "\tRegisterDestructorCall @ 3 NONAME\n";
       
   474 		} else {
       
   475 			push @def, "\tInit$num @ 1 NONAME\n";
       
   476 			push @def, "\tChkC$num @ 2 NONAME\n";
       
   477 			push @def, "\tBlkI$num @ 3 NONAME\n";
       
   478 			push @def, "\tGetGeneration @ 4 NONAME\n";
       
   479 			push @def, "\tRBlkI$num @ 5 NONAME\n";
       
   480 			push @def, "\tSetCloseLib @ 6 NONAME\n";
       
   481 		}
       
   482 		$$modref{def}=\@def;
       
   483 	}
       
   484 
       
   485 	push @bldinf, "$$modref{basefilename}\t\tsupport\n";
       
   486 
       
   487 	if ($num==0) {
       
   488 		push @dlltree, "#if defined(__DLLNUM$num)\n";
       
   489 	} else {
       
   490 		push @dlltree, "#elif defined(__DLLNUM$num)\n";
       
   491 	}
       
   492 	push @dlltree, "#define DLLNUM               $num\n";
       
   493 	if ($$modref{exe}) {
       
   494 		push @dlltree, "#define EXENUM               $num\n";
       
   495 		push @dlltree, "_LIT(KServerName, \"$$modref{name}\");\n";
       
   496 	}
       
   497 	push @dlltree, "#define INITFUNC             Init$num\n";
       
   498 	push @dlltree, "#define CHKCFUNC             ChkC$num\n";
       
   499 	push @dlltree, "#define BLKIFUNC             BlkI$num\n";
       
   500 	push @dlltree, "#define RBLKIFUNC            RBlkI$num\n";
       
   501 	push @dlltree, "#define CHKDEPS(r)           (\\\n";
       
   502 	foreach (@$depsref) {
       
   503 		my $depref=$modules[$_];
       
   504 		unless ($$depref{exe}) {
       
   505 			my $func="ChkC$_";
       
   506 			push @dlltree, "\t((r)=$func())!=0 ||\\\n";
       
   507 		}
       
   508 	}
       
   509 	push @dlltree, "\t((r)=0)!=0 )\n";
       
   510 	push @dlltree, "#define INITDEPS(r,l)        (\\\n";
       
   511 	foreach (@$depsref) {
       
   512 		my $depref=$modules[$_];
       
   513 		unless ($$depref{exe}) {
       
   514 			my $func="Init$_";
       
   515 			push @dlltree, "\t((r)=$func(l))!=0 ||\\\n";
       
   516 		}
       
   517 	}
       
   518 	push @dlltree, "\t((r)=0)!=0 )\n";
       
   519 	my $link_to_exe;
       
   520 	push @dlltree, "#define RBLKIFUNC_DEPS(i,g)  {\\\n";
       
   521 	foreach (@$depsref) {
       
   522 		my $depref=$modules[$_];
       
   523 		if ($$depref{exe}) {
       
   524 			$link_to_exe=1;
       
   525 		} else {
       
   526 			my $func="RBlkI$_";
       
   527 			push @dlltree, "\t(i)=$func(i,g);\\\n";
       
   528 		}
       
   529 	}
       
   530 	push @dlltree, "\t}\n";
       
   531 	if ($link_to_exe) {
       
   532 		push @dlltree, "#define __DLL_LINK_TO_EXE\n";
       
   533 	}
       
   534 	if ($$modref{cycle}) {
       
   535 		push @dlltree, "#define __DLL_IN_CYCLE\n";
       
   536 	}
       
   537 	if ($$modref{data}) {
       
   538 		push @dlltree, "#define __MODULE_HAS_DATA\n";
       
   539 	}
       
   540 	if ($$modref{exports}) {
       
   541 		push @dlltree, "#define __MODULE_EXPORT\t\tEXPORT_C\n";
       
   542 		push @dlltree, "#define __MODULE_IMPORT\t\tIMPORT_C\n";
       
   543 	} else {
       
   544 		push @dlltree, "#define __MODULE_EXPORT\n";
       
   545 		push @dlltree, "#define __MODULE_IMPORT\n";
       
   546 	}
       
   547 	foreach (@$depsref) {
       
   548 		my $depref=$modules[$_];
       
   549 		if ($$depref{exe}) {
       
   550 		} else {
       
   551 			push @dlltree, "extern \"C\" IMPORT_C TInt Init$_(MDllList&);\n";
       
   552 			push @dlltree, "extern \"C\" IMPORT_C TInt ChkC$_();\n";
       
   553 			push @dlltree, "extern \"C\" IMPORT_C TInt RBlkI$_(TInt, TInt);\n";
       
   554 		}
       
   555 	}
       
   556 	my $hostfullpathname=$hostpath.$$modref{filename};
       
   557 	if ($$modref{xip}) {
       
   558 		my $epocfullpathname=$xippath.$$modref{filename};
       
   559 		my $flags;
       
   560 		if ($$modref{attp}) {
       
   561 			$flags='process '.$modref->{attp}->{filename};
       
   562 		}
       
   563 		push @iby, "file=$hostfullpathname\t\t$epocfullpathname\t\t$flags\n";
       
   564 	} else {
       
   565 		my $epocfullpathname=$nonxippath.$$modref{filename};
       
   566 		push @iby, "data=$hostfullpathname\t\t$epocfullpathname\n";
       
   567 	}
       
   568 }
       
   569 
       
   570 #push @dlltree, "#else\n";
       
   571 #push @dlltree, "#error No __DLLNUM macro defined\n";
       
   572 push @dlltree, "#endif\n";
       
   573 push @dlltree, "\n";
       
   574 
       
   575 my $module_count=scalar(@modules);
       
   576 push @dlltree, "const TInt KNumModules=$module_count;\n";
       
   577 push @dlltree, "\n";
       
   578 push @dlltree, "#ifdef __INCLUDE_DEPENDENCY_GRAPH\n";
       
   579 push @dlltree, "static const TText* const ModuleName[KNumModules] =\n";
       
   580 push @dlltree, "\t\{\n";
       
   581 foreach $modref (@modules) {
       
   582 	my $string="\t(const TText*)L\"$$modref{name}\"";
       
   583 	unless ($$modref{num}==$module_count-1) {
       
   584 		$string.=',';
       
   585 	}
       
   586 	push @dlltree, $string;
       
   587 	my $pad=41-length($string);
       
   588 	$pad=($pad+3)/4;
       
   589 	push @dlltree, "\t"x$pad, "\/*", $$modref{num}, "*\/\n";
       
   590 }
       
   591 push @dlltree, "\t\};\n";
       
   592 push @dlltree, "\n";
       
   593 push @dlltree, "#define MODULE_NAME(n)	TPtrC(ModuleName[n])\n";
       
   594 push @dlltree, "\n";
       
   595 push @dlltree, "static const TText* const ModuleFileName[KNumModules] =\n";
       
   596 push @dlltree, "\t\{\n";
       
   597 foreach $modref (@modules) {
       
   598 	if ($$modref{idrive} || $$modref{vdrive}) {
       
   599 		my $fn = $$modref{filename};
       
   600 		my $used_nxip_path = "?:\\$nonxippath$fn";
       
   601 		$used_nxip_path =~ s/\\/\\\\/g;		# double backslashes
       
   602 		substr($used_nxip_path,0,1) = $$modref{idrive} ? "0" : "1";
       
   603 		push @dlltree, "\t(const TText*)L\"$used_nxip_path\"";
       
   604 	} else {
       
   605 		push @dlltree, "\t(const TText*)L\"$$modref{filename}\"";
       
   606 	}
       
   607 	if ($$modref{num}==$module_count-1) {
       
   608 		push @dlltree, "\n";
       
   609 	} else {
       
   610 		push @dlltree, ",\n";
       
   611 	}
       
   612 }
       
   613 push @dlltree, "\t\};\n";
       
   614 push @dlltree, "\n";
       
   615 push @dlltree, "#define MODULE_FILENAME(n)	TPtrC(ModuleFileName[n])\n";
       
   616 push @dlltree, "\n";
       
   617 foreach $modref (@modules) {
       
   618 	my $modnum=$$modref{num};
       
   619 	my $tcdepsref=$$modref{tcdeps};
       
   620 	my $numdeps=scalar(@$tcdepsref);
       
   621 	push @dlltree, "static const TInt Module$modnum","Deps[] =\n";
       
   622 	push @dlltree, "\t\{$numdeps";
       
   623 	if ($numdeps) {
       
   624 		push @dlltree, ",", join(',',@$tcdepsref)
       
   625 	}
       
   626 	push @dlltree, "\};\n";
       
   627 }
       
   628 push @dlltree, "static const TInt* const ModuleDependencies[KNumModules] =\n";
       
   629 push @dlltree, "\t\{\n";
       
   630 foreach $modref (@modules) {
       
   631 	my $modnum=$$modref{num};
       
   632 	push @dlltree, "\tModule$modnum","Deps";
       
   633 	if ($$modref{num}==$module_count-1) {
       
   634 		push @dlltree, "\n";
       
   635 	} else {
       
   636 		push @dlltree, ",\n";
       
   637 	}
       
   638 }
       
   639 push @dlltree, "\t\};\n";
       
   640 push @dlltree, "\n";
       
   641 push @dlltree, sprintf "const TInt KModuleFlagExe=0x%04x;\n", $flag_value_exe;
       
   642 push @dlltree, sprintf "const TInt KModuleFlagFixed=0x%04x;\n", $flag_value_fixed;
       
   643 push @dlltree, sprintf "const TInt KModuleFlagData=0x%04x;\n", $flag_value_data;
       
   644 #push @dlltree, "#ifdef __EPOC32__\n";
       
   645 push @dlltree, sprintf "const TInt KModuleFlagXIP=0x%04x;\n", $flag_value_xip;
       
   646 push @dlltree, sprintf "const TInt KModuleFlagPagedCode=0x%04x;\n", $flag_value_pagedcode;
       
   647 push @dlltree, sprintf "const TInt KModuleFlagUnpagedCode=0x%04x;\n", $flag_value_unpagedcode;
       
   648 push @dlltree, sprintf "const TInt KModuleFlagIDrive=0x%04x;\n", $flag_value_idrive;
       
   649 push @dlltree, sprintf "const TInt KModuleFlagVDrive=0x%04x;\n", $flag_value_vdrive;
       
   650 push @dlltree, sprintf "const TInt KModuleFlagBytePair=0x%04x;\n", $flag_value_bytepair;
       
   651 push @dlltree, sprintf "const TInt KModuleFlagUncompressed=0x%04x;\n", $flag_value_uncompressed;
       
   652 #push @dlltree, "#else\n";
       
   653 #push @dlltree, sprintf "const TInt KModuleFlagXIP=0x%04x;\n", 0;	# no XIPs on emulator
       
   654 #push @dlltree, "#endif\n";
       
   655 push @dlltree, sprintf "const TInt KModuleFlagDllInCycle=0x%04x;\n", $flag_value_dll_in_cycle;
       
   656 push @dlltree, sprintf "const TInt KModuleFlagDataInTree=0x%04x;\n", $flag_value_data_in_tree;
       
   657 #push @dlltree, "#ifdef __EPOC32__\n";
       
   658 push @dlltree, sprintf "const TInt KModuleFlagXIPDataInTree=0x%04x;\n", $flag_value_xip_data_in_tree;
       
   659 #push @dlltree, "#else\n";
       
   660 #push @dlltree, sprintf "const TInt KModuleFlagXIPDataInTree=0x%04x;\n", 0;
       
   661 #push @dlltree, "#endif\n";
       
   662 push @dlltree, sprintf "const TInt KModuleFlagExports=0x%04x;\n", $flag_value_exports;
       
   663 push @dlltree, sprintf "const TInt KModuleFlagTargetOnly=0x%04x;\n", $flag_value_targetonly;
       
   664 push @dlltree, sprintf "const TInt KModuleFlagPagedData=0x%04x;\n", $flag_value_pageddata;
       
   665 push @dlltree, sprintf "const TInt KModuleFlagUnpagedData=0x%04x;\n", $flag_value_unpageddata;
       
   666 push @dlltree, "static const TInt ModuleFlags[KNumModules] =\n";
       
   667 push @dlltree, "\t\{\n";
       
   668 foreach $modref (@modules) {
       
   669 	my $flags=0;
       
   670 	my @flagNames = ();
       
   671 
       
   672 	push @flagNames, "KModuleFlagExe" if ($$modref{exe});
       
   673 	push @flagNames, "KModuleFlagFixed" if ($$modref{fixed});
       
   674 	push @flagNames, "KModuleFlagData" if ($$modref{data});
       
   675 	push @flagNames, "KModuleFlagXIP" if ($$modref{xip});
       
   676 	push @flagNames, "KModuleFlagPagedCode" if ($$modref{pagedcode});
       
   677 	push @flagNames, "KModuleFlagUnpagedCode" if ($$modref{unpagedcode});
       
   678 	push @flagNames, "KModuleFlagPagedData" if ($$modref{pageddata});
       
   679 	push @flagNames, "KModuleFlagUnpagedData" if (!$$modref{pageddata});
       
   680 	push @flagNames, "KModuleFlagIDrive" if ($$modref{idrive});
       
   681 	push @flagNames, "KModuleFlagVDrive" if ($$modref{vdrive});
       
   682 	push @flagNames, "KModuleFlagBytePair" if ($$modref{bytepair});
       
   683 	push @flagNames, "KModuleFlagDllInCycle" if ($$modref{cycle});
       
   684 	push @flagNames, "KModuleFlagDataInTree" if ($$modref{dataintree});
       
   685 	push @flagNames, "KModuleFlagXIPDataInTree" if ($$modref{xipdataintree});
       
   686 	push @flagNames, "KModuleFlagExports" if ($$modref{exports});
       
   687 	push @flagNames, "KModuleFlagUncompressed" if ($$modref{uncompressed});
       
   688 	push @flagNames, "KModuleFlagTargetOnly" if ($$modref{targetonly});
       
   689 
       
   690 	@flagNames = qw(0) if (scalar(@flagNames) == 0);
       
   691 	my $flagString = "/\* " . $$modref{num} . " \*/\t" . join(' | ', @flagNames);
       
   692 	unless ($$modref{num}==$module_count-1) {
       
   693 		$flagString.=',';
       
   694 	}
       
   695 	push @dlltree, $flagString . "\n";
       
   696 }
       
   697 push @dlltree, "\t\};\n";
       
   698 push @dlltree, "\n";
       
   699 foreach $modref (@modules) {
       
   700 	my $modnum=$$modref{num};
       
   701 	my @rblki;
       
   702 	++$next_mark;
       
   703 	calc_rblki(\@rblki, \@modules, $modref, $next_mark);
       
   704 	my $rblki_count=scalar(@rblki);
       
   705 	my $rblki_sum=0;
       
   706 	foreach (@rblki) {
       
   707 		$rblki_sum += $_;
       
   708 	}
       
   709 	push @dlltree, "static const TInt Module$modnum","RBlkIParams[2] = \{ $rblki_count, $rblki_sum \};\n";
       
   710 }
       
   711 push @dlltree, "\n";
       
   712 push @dlltree, "static const TInt* const ModuleRBlkIParams[KNumModules] =\n";
       
   713 push @dlltree, "\t\{\n";
       
   714 foreach $modref (@modules) {
       
   715 	my $modnum=$$modref{num};
       
   716 	push @dlltree, "\tModule$modnum","RBlkIParams";
       
   717 	if ($$modref{num}==$module_count-1) {
       
   718 		push @dlltree, "\n";
       
   719 	} else {
       
   720 		push @dlltree, ",\n";
       
   721 	}
       
   722 }
       
   723 push @dlltree, "\t\};\n";
       
   724 push @dlltree, "\n";
       
   725 foreach $modref (@modules) {
       
   726 	my $modnum=$$modref{num};
       
   727 	my $mod_attp=$modnum;
       
   728 	my $mod_linkp=$modnum;
       
   729 	unless ($$modref{exe}) {
       
   730 		$mod_attp = ($$modref{attp}) ? ($modref->{attp}->{num}) : -1;
       
   731 		$mod_linkp = ($$modref{linkexe}) ? ($modref->{linkexe}->{num}) : -1;
       
   732 	}
       
   733 	push @dlltree, "static const TInt Module$modnum","ExeInfo[2] = \{ $mod_attp, $mod_linkp \};\n";
       
   734 }
       
   735 push @dlltree, "\n";
       
   736 push @dlltree, "static const TInt* const ModuleExeInfo[KNumModules] =\n";
       
   737 push @dlltree, "\t\{\n";
       
   738 foreach $modref (@modules) {
       
   739 	my $modnum=$$modref{num};
       
   740 	push @dlltree, "\tModule$modnum","ExeInfo";
       
   741 	if ($$modref{num}==$module_count-1) {
       
   742 		push @dlltree, "\n";
       
   743 	} else {
       
   744 		push @dlltree, ",\n";
       
   745 	}
       
   746 }
       
   747 push @dlltree, "\t\};\n";
       
   748 
       
   749 foreach $tcref (@testcases) {
       
   750 	push @dlltree, "\n";
       
   751 	my $modlistref=$$tcref{modules};
       
   752 	my $count=$$tcref{count};
       
   753 	my $arraysize=$count+1;
       
   754 	push @dlltree, "static const TInt TC_$$tcref{name}\[$arraysize\]=\n\t\{\n";
       
   755 	if ($count==0) {
       
   756 		push @dlltree, "\t$count\n";
       
   757 	} else {
       
   758 		push @dlltree, "\t$count\,\n";
       
   759 	}
       
   760 	foreach (@$modlistref) {
       
   761 		--$count;
       
   762 		if ($count==0) {
       
   763 			push @dlltree, "\t$_\n";
       
   764 		} else {
       
   765 			push @dlltree, "\t$_\,\n";
       
   766 		}
       
   767 	}
       
   768 	push @dlltree, "\t\};\n";
       
   769 }
       
   770 
       
   771 push @dlltree, "#endif\n";
       
   772 push @dlltree, "\n";
       
   773 push @dlltree, "#endif\n";
       
   774 
       
   775 foreach $modref (@modules) {
       
   776 	my $mmpname=$$modref{basefilename}.$mmpext;
       
   777 	my $mmpref=$$modref{mmp};
       
   778 	open OUT, ">$mmpname" or die "Could not open $mmpname for output\n";
       
   779 	print OUT @$mmpref;
       
   780 	close OUT;
       
   781 	if ($$modref{exports}) {
       
   782 		my $defname=$$modref{basefilename}.$defext;
       
   783 		my $defref=$$modref{def};
       
   784 		open OUT, ">$defname" or die "Could not open $defname for output\n";
       
   785 		print OUT @$defref;
       
   786 		close OUT;
       
   787 	}
       
   788 }
       
   789 if (!$allowbad) {
       
   790 	push @bldinf, "t_ldrtst\n";
       
   791 }
       
   792 open OUT, ">$bldname" or die "Could not open $bldname for output\n";
       
   793 print OUT @bldinf;
       
   794 close OUT;
       
   795 open OUT, ">$dlltreename" or die "Could not open $dlltreename for output\n";
       
   796 print OUT @dlltree;
       
   797 close OUT;
       
   798 my $testbatch = "$ENV{EPOCROOT}epoc32\\build";
       
   799 $destpath =~ s/\//\\/go;
       
   800 $testbatch.="\\" unless ($destpath =~ /^\\/);
       
   801 $testbatch.=$destpath;
       
   802 $testbatch.="##MAIN##.auto.bat";
       
   803 if (!$allowbad) {
       
   804 	push @iby, "data=$testbatch\t\ttest\\loader.auto.bat\n";
       
   805 }
       
   806 open OUT, ">$ibyname" or die "Could not open $ibyname for output\n";
       
   807 print OUT @iby;
       
   808 close OUT;
       
   809 
       
   810 #
       
   811 # Accumulate list of dependency numbers
       
   812 # 1st arg = \output list
       
   813 # 2nd arg = \module list
       
   814 # 3rd arg = \module to start from
       
   815 # 4th arg = mark value to use
       
   816 #
       
   817 sub calc_tc($$$$) {
       
   818 	my ($out, $mods, $modref, $mark)=@_;
       
   819 	my $depsref=$$modref{deps};
       
   820 	foreach $dep (@$depsref) {
       
   821 		my $depref=$$mods[$dep];
       
   822 		if ($$depref{mark} != $mark) {
       
   823 			$$depref{mark}=$mark;
       
   824 			unless ($$depref{exe}) {
       
   825 				calc_tc($out, $mods, $depref, $mark);
       
   826 			}
       
   827 			push @$out, $dep;
       
   828 		}
       
   829 	}
       
   830 }
       
   831 
       
   832 #
       
   833 # Accumulate RBlkI parameters
       
   834 # 1st arg = \output list
       
   835 # 2nd arg = \module list
       
   836 # 3rd arg = \module to start from
       
   837 # 4th arg = mark value to use
       
   838 #
       
   839 sub calc_rblki($$$$) {
       
   840 	my ($out, $mods, $modref, $mark)=@_;
       
   841 	if ($$modref{mark} != $mark) {
       
   842 		$$modref{mark}=$mark;
       
   843 		if (!$$modref{exe} and $$modref{data}) {
       
   844 			push @$out, $$modref{num};
       
   845 			my $depsref=$$modref{deps};
       
   846 			foreach $dep (@$depsref) {
       
   847 				calc_rblki($out, $mods, $$mods[$dep], $mark);
       
   848 			}
       
   849 		}
       
   850 	}
       
   851 }
       
   852 
       
   853 
       
   854