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