sbsv1/abld/e32util/efreeze.pl
changeset 40 68f68128601f
equal deleted inserted replaced
39:fa9d7d89d3d6 40:68f68128601f
       
     1 #!/usr/bin/perl
       
     2 # Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 # All rights reserved.
       
     4 # This component and the accompanying materials are made available
       
     5 # under the terms of "Eclipse Public License v1.0"
       
     6 # which accompanies this distribution, and is available
       
     7 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 #
       
     9 # Initial Contributors:
       
    10 # Nokia Corporation - initial contribution.
       
    11 #
       
    12 # Contributors:
       
    13 #
       
    14 # Description:
       
    15 # all variables called *Path* are set up to end with a backslash
       
    16 # all variables called *Path or *File are stored as absolute (file)paths
       
    17 # all variables called UpPath* are stored as relative paths
       
    18 # 
       
    19 #
       
    20 
       
    21 
       
    22 use FindBin;		# for FindBin::Bin
       
    23 use Getopt::Long;
       
    24 
       
    25 my $PerlLibPath;    # fully qualified pathname of the directory containing our Perl modules
       
    26 
       
    27 BEGIN {
       
    28 # check user has a version of perl that will cope
       
    29 	require 5.005_03;
       
    30 # establish the path to the Perl libraries: currently the same directory as this script
       
    31 	$PerlLibPath = $FindBin::Bin;	# X:/epoc32/tools
       
    32 # do not convert slashes for linux
       
    33 	if ($^O eq "MSWin32") {
       
    34 		$PerlLibPath =~ s/\//\\/g;	# X:\epoc32\tools
       
    35 		$PerlLibPath .= "\\";
       
    36 	}
       
    37 }
       
    38 
       
    39 # Version
       
    40 my $MajorVersion = 1;
       
    41 my $MinorVersion = 1;
       
    42 my $PatchVersion = 1;
       
    43 
       
    44 use lib $PerlLibPath;
       
    45 use Defutl;
       
    46 
       
    47 # THE MAIN PROGRAM SECTION
       
    48 ##########################
       
    49 
       
    50 {
       
    51 	my %Options;
       
    52 
       
    53 	# process the command-line
       
    54 	unless (GetOptions(\%Options, 'compare', 'remove')) {
       
    55 		exit 1;
       
    56 	}
       
    57 	unless (@ARGV==2) {
       
    58 		&Usage;
       
    59 	}
       
    60 
       
    61 	my $FRZFILE;
       
    62 	my $GENFILE;
       
    63 
       
    64 	($FRZFILE,$GENFILE)=(@ARGV);
       
    65 	
       
    66 #	check the file exists
       
    67 	unless (-e $FRZFILE) {
       
    68 		warn "WARNING: $FRZFILE: File not found - OK if freezing for first time\n";
       
    69 	}
       
    70 	unless (-e $GENFILE) {
       
    71 		die "EFREEZE ERROR: $GENFILE: File not found\n";
       
    72 	}
       
    73 
       
    74 #	Read the Frozen .DEF file if it exists
       
    75 	my @FrzDataStruct;
       
    76 	my $FrzExportsOn=0;
       
    77 	if (-e $FRZFILE) {
       
    78 		eval { &Def_ReadFileL(\@FrzDataStruct, $FRZFILE, $FrzExportsOn); };
       
    79 		die $@ if $@;
       
    80 	}
       
    81 
       
    82 #	Read the New .DEF file
       
    83 	my @GenDataStruct;
       
    84 	my $Dummy;
       
    85 	if ($GENFILE) {
       
    86 		eval { &Def_ReadFileL(\@GenDataStruct, $GENFILE, $Dummy, ($Options{compare} or $Options{remove})); };
       
    87 	}
       
    88 	die $@ if $@;
       
    89 
       
    90 #	Compare the frozen .DEF data with the new .DEF file
       
    91 	my (@NewDataStruct, @MissingDataStruct, @BadDataStruct);
       
    92 	eval { &CompareFrzGenL (\@NewDataStruct, \@MissingDataStruct, \@BadDataStruct, \@FrzDataStruct, \@GenDataStruct, $Options{remove}); };
       
    93 	die $@ if $@;
       
    94 
       
    95 #	check for errors
       
    96 	my $NumRemoved;
       
    97 	my $Ref;
       
    98 	my @Errors;
       
    99 	my $Title='EFREEZE ERROR:';
       
   100 	if ($Options{compare}) {
       
   101 		$Title='EFREEZE:';
       
   102 	}
       
   103 	if (@MissingDataStruct and $Options{remove}) {
       
   104 #		Mark missing exports as ABSENT in DEF file
       
   105 		$NumRemoved=@MissingDataStruct;
       
   106 		if ($Options{compare}) {
       
   107 			print "EFREEZE: Marking $NumRemoved Export(s) as ABSENT :\n";
       
   108 		} else {
       
   109 			print "EFREEZE: Marking $NumRemoved Export(s) as ABSENT in $FRZFILE :\n";
       
   110 		}
       
   111 		foreach (@MissingDataStruct) {
       
   112 			$$_{Absent} = 1;
       
   113 			my $Comment='';
       
   114 			if ($$_{Comment}) {
       
   115 				$Comment=" ; $$_{Comment}";
       
   116 			}
       
   117 			my $r3unused = $$_{R3Unused} ? " R3UNUSED" : "";
       
   118 			print "  $$_{Name} \@ $$_{Ordinal} NONAME$r3unused$Comment\n";
       
   119 		}
       
   120 	}
       
   121 	elsif (@MissingDataStruct) {
       
   122 		my $Num=@MissingDataStruct;
       
   123 		push @Errors, "$Title $FRZFILE: $Num Frozen Export(s) missing from $GENFILE (POSSIBLE COMPATIBILITY BREAK):\n"; 
       
   124 		foreach $Ref (@MissingDataStruct) {
       
   125 			my $r3unused = $$Ref{R3Unused} ? " R3UNUSED" : "";
       
   126 			push @Errors, "  $$Ref{LineNum}: $$Ref{Name} \@ $$Ref{Ordinal} NONAME$r3unused\n";
       
   127 		}
       
   128 		push @Errors, "\n";
       
   129 	}
       
   130 	if (@BadDataStruct) {
       
   131 		my $Num=@BadDataStruct;
       
   132 		push @Errors, "$Title $GENFILE: $Num function(s) exported at wrong ordinal:\n";
       
   133 		foreach $Ref (@BadDataStruct) {
       
   134 			my $r3unused = $$Ref{R3Unused} ? " R3UNUSED" : "";
       
   135 			push @Errors, "  $$Ref{LineNum}: $$Ref{Name} \@ $$Ref{Ordinal} NONAME$r3unused\n";
       
   136 		}
       
   137 	}
       
   138 	if (@Errors) {
       
   139 		unless ($Options{compare}) {
       
   140 			die @Errors;
       
   141 		}
       
   142 		else {
       
   143 			print @Errors;
       
   144 		}
       
   145 	}
       
   146 
       
   147 #	Update the frozen .DEF file
       
   148 	eval { &UpdateFrzFileL(\@NewDataStruct, \@FrzDataStruct, $FRZFILE, $FrzExportsOn, $Options{compare}, $NumRemoved); };
       
   149 	die $@ if $@;
       
   150 	
       
   151 
       
   152 	exit;
       
   153 }
       
   154 
       
   155 #######################################################################
       
   156 # SUBROUTINES
       
   157 #######################################################################
       
   158 
       
   159 sub Usage () {
       
   160 
       
   161 	print(
       
   162 		"\n",
       
   163 		"EFREEZE - .DEF file maintenance utility V$MajorVersion.$MinorVersion.$PatchVersion\n",
       
   164 		"\n",
       
   165 		"EFREEZE {options} [frozen .DEF file] [new .DEF file]\n",
       
   166 		"\n",
       
   167 		"options:   (case-insensitive)\n",
       
   168 		"  -Compare\n",
       
   169 		"  -Remove\n",
       
   170 		"\n"
       
   171 	);
       
   172 	exit 1;
       
   173 }
       
   174 
       
   175 sub CompareFrzGenL ($$$$$$) {
       
   176 	my ($NewStructRef, $MissingStructRef, $BadStructRef, $FrzStructRef, $GenStructRef, $remove)=@_;
       
   177 
       
   178 #	compare the input export data with the frozen data
       
   179 
       
   180 #	take a copy of the frozen .DEF file structure that we can trash
       
   181 	my @TmpStruct=@$FrzStructRef;
       
   182 
       
   183 #	remove any entries not containing export data and get the highest ordinal value used
       
   184 	my $LastOrdinal=0;
       
   185 	foreach (@TmpStruct) {
       
   186 		if ($$_{Name}) {
       
   187 			if ($LastOrdinal<$$_{Ordinal}) {
       
   188 				$LastOrdinal=$$_{Ordinal};
       
   189 			}
       
   190 			next;
       
   191 		}
       
   192 		undef $_;
       
   193 	}
       
   194 
       
   195 	my $GenRef;
       
   196 	my $TmpRef;
       
   197 	GENLOOP: foreach $GenRef (@$GenStructRef) {
       
   198 		next unless $$GenRef{Name};		# ignore lines in the .DEF file not containing an export
       
   199 		foreach $TmpRef (@TmpStruct) {
       
   200 			next unless defined $TmpRef; # ignore nullified entries in the temporary array
       
   201 #			does the function name match?
       
   202 			if ($$GenRef{Name} eq $$TmpRef{Name}) {
       
   203 #				check the names have the same ordinals
       
   204 				if ($remove or $$GenRef{Ordinal}==$$TmpRef{Ordinal}) {
       
   205 					undef $TmpRef;
       
   206 					next GENLOOP;
       
   207 				}
       
   208 #				store exports with the wrong ordinals
       
   209 				push @$BadStructRef, $GenRef;
       
   210 				undef $TmpRef;
       
   211 				next GENLOOP;
       
   212 			}
       
   213 #			Absent export?
       
   214 			if ($$TmpRef{Absent} and $$TmpRef{Ordinal}==$$GenRef{Ordinal}) {
       
   215 				next GENLOOP;
       
   216 			}
       
   217 		}
       
   218 #		store new exports not found in the frozen .DEF file with the right ordinal value
       
   219 		$LastOrdinal++;
       
   220 		$$GenRef{Ordinal}=$LastOrdinal;
       
   221 		push @$NewStructRef, $GenRef;
       
   222 	}
       
   223 
       
   224 #	all the exports left in the frozen .DEF file weren't found
       
   225 	foreach $TmpRef (@TmpStruct) {
       
   226 		next unless defined $TmpRef; # ignore nullified entries in the temporary array
       
   227 		next if $$TmpRef{Absent};	# skip entries marked as ABSENT in the DEF file
       
   228 		push @$MissingStructRef, $TmpRef;
       
   229 	}
       
   230 }
       
   231 
       
   232 sub UpdateFrzFileL ($$$$$$) {
       
   233 	my ($NewStructRef, $FrzStructRef, $FILE, $ExportsOn, $Compare, $NumRemoved)=@_;
       
   234 
       
   235 #	add the exports to the frozen .DEF file text
       
   236 	unless (@$NewStructRef or $NumRemoved) {
       
   237 		print "EFREEZE: DEF file up to date\n";
       
   238 		return;
       
   239 	}
       
   240 
       
   241 	my $NumNewExports=@$NewStructRef;
       
   242 	unless ($Compare) {
       
   243 # 		abort the operation unless the frozen .DEF file is writeable
       
   244 		if (-e $FILE and not -w $FILE) {
       
   245 			die
       
   246 				"EFREEZE ERROR: Can't append $NumNewExports New Export(s) to $FILE\n",
       
   247 				"  as file is not writeable.  Check source code control system.\n"
       
   248 			;
       
   249 		}
       
   250 		print "EFREEZE: Appending $NumNewExports New Export(s) to $FILE:\n" if ($NumNewExports);
       
   251 	}
       
   252 	else {
       
   253 		print "EFREEZE: $NumNewExports New Export(s):\n" if ($NumNewExports);
       
   254 	}
       
   255 
       
   256 	my @Text;
       
   257 	my $ExportsDeclared;
       
   258 
       
   259 #	Process the frozen .DEF file
       
   260 	if (@$FrzStructRef) { # there is already a frozen .DEF file
       
   261 		my $FrzRef;
       
   262 
       
   263 #		get the lines of text from the frozen .DEF file
       
   264 		foreach $FrzRef (@$FrzStructRef) {
       
   265 			next if (!$FrzRef);
       
   266 			if (!defined($$FrzRef{Ordinal})) {
       
   267 				push @Text, $$FrzRef{Line};
       
   268 				$ExportsDeclared = 1 if ($$FrzRef{Line} =~ /^\s*EXPORTS\s*(\s+\S+.*)?$/io);
       
   269 				next;
       
   270 			}
       
   271 			my $Comment='';
       
   272 			if ($$FrzRef{Comment}) {
       
   273 				$Comment=" ; $$FrzRef{Comment}";
       
   274 			}
       
   275 			my $r3unused = $$FrzRef{R3Unused} ? " R3UNUSED" : "";
       
   276 			my $absent = $$FrzRef{Absent} ? " ABSENT" : "";
       
   277 
       
   278 			my $data = "";
       
   279 			if( !($$FrzRef{Name} =~ /^(_ZTI|_ZTV|_ZTT)/))
       
   280 			{
       
   281 #				A symbol name with the above pattern indicates that it is a Data symbol.
       
   282 #				Mark symbols as DATA only when it cannot be found from the name alone (i.e.,
       
   283 #				explicitly exported data symbols).
       
   284 
       
   285 				if(($$FrzRef{Data}) and ($$FrzRef{Size}) ){
       
   286 				$data = " DATA $$FrzRef{Size}";
       
   287 				}
       
   288 			}
       
   289 			push @Text, "\t$$FrzRef{Name} \@ $$FrzRef{Ordinal} NONAME$data$r3unused$absent$Comment\n";
       
   290 		}
       
   291 
       
   292 #		strip any blank lines at the end of the frozen .DEF file text
       
   293 		foreach (reverse @Text) {
       
   294 			if (/^\s*$/o) {
       
   295 				$_='';
       
   296 				next;
       
   297 			}
       
   298 			last;
       
   299 		}
       
   300 
       
   301 	}
       
   302 
       
   303 #	Add an EXPORTS section header if there aren't already exports
       
   304 	unshift @Text, "EXPORTS\n" unless ($ExportsDeclared);
       
   305 
       
   306 	my $NewRef;
       
   307 	foreach $NewRef (@$NewStructRef) {
       
   308 		my $Comment='';
       
   309 		if ($$NewRef{Comment}) {
       
   310 			$Comment=" ; $$NewRef{Comment}";
       
   311 		}
       
   312 		my $r3unused = $$NewRef{R3Unused} ? " R3UNUSED" : "";
       
   313 		my $absent = $$NewRef{Absent} ? " ABSENT" : "";
       
   314 
       
   315 		my $data = "";
       
   316 		if( !($$NewRef{Name} =~ /^(_ZTV|_ZTI|_ZTT)/)) {
       
   317 #				A symbol name with the above pattern indicates that it is a Data symbol.
       
   318 #				Mark symbols as DATA only when it cannot be found from the name alone (i.e.,
       
   319 #				explicitly exported data symbols).
       
   320 			if(($$NewRef{Data}) and ($$NewRef{Size}) ){
       
   321 			$data = " DATA $$NewRef{Size}";
       
   322 			}
       
   323 		}
       
   324 		print "  $$NewRef{Name} \@ $$NewRef{Ordinal} NONAME$r3unused$Comment\n";
       
   325 		push @Text, "\t$$NewRef{Name} \@ $$NewRef{Ordinal} NONAME$data$r3unused$absent$Comment\n";
       
   326 	}
       
   327 
       
   328 #	add a terminating newline
       
   329 	push @Text, "\n";
       
   330 
       
   331 	unless ($Compare) {
       
   332 #		write the new frozen .DEF file
       
   333 		eval { &Def_WriteFileL(\@Text, $FILE); };
       
   334 		die $@ if $@;
       
   335 	}
       
   336 }
       
   337