diff -r 22486c9c7b15 -r 378360dbbdba sbsv1/abld/e32util/efreeze.pl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sbsv1/abld/e32util/efreeze.pl Wed Jun 30 11:35:58 2010 +0800 @@ -0,0 +1,337 @@ +#!/usr/bin/perl +# Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). +# All rights reserved. +# This component and the accompanying materials are made available +# under the terms of "Eclipse Public License v1.0" +# which accompanies this distribution, and is available +# at the URL "http://www.eclipse.org/legal/epl-v10.html". +# +# Initial Contributors: +# Nokia Corporation - initial contribution. +# +# Contributors: +# +# Description: +# all variables called *Path* are set up to end with a backslash +# all variables called *Path or *File are stored as absolute (file)paths +# all variables called UpPath* are stored as relative paths +# +# + + +use FindBin; # for FindBin::Bin +use Getopt::Long; + +my $PerlLibPath; # fully qualified pathname of the directory containing our Perl modules + +BEGIN { +# check user has a version of perl that will cope + require 5.005_03; +# establish the path to the Perl libraries: currently the same directory as this script + $PerlLibPath = $FindBin::Bin; # X:/epoc32/tools +# do not convert slashes for linux + if ($^O eq "MSWin32") { + $PerlLibPath =~ s/\//\\/g; # X:\epoc32\tools + $PerlLibPath .= "\\"; + } +} + +# Version +my $MajorVersion = 1; +my $MinorVersion = 1; +my $PatchVersion = 1; + +use lib $PerlLibPath; +use Defutl; + +# THE MAIN PROGRAM SECTION +########################## + +{ + my %Options; + + # process the command-line + unless (GetOptions(\%Options, 'compare', 'remove')) { + exit 1; + } + unless (@ARGV==2) { + &Usage; + } + + my $FRZFILE; + my $GENFILE; + + ($FRZFILE,$GENFILE)=(@ARGV); + +# check the file exists + unless (-e $FRZFILE) { + warn "WARNING: $FRZFILE: File not found - OK if freezing for first time\n"; + } + unless (-e $GENFILE) { + die "EFREEZE ERROR: $GENFILE: File not found\n"; + } + +# Read the Frozen .DEF file if it exists + my @FrzDataStruct; + my $FrzExportsOn=0; + if (-e $FRZFILE) { + eval { &Def_ReadFileL(\@FrzDataStruct, $FRZFILE, $FrzExportsOn); }; + die $@ if $@; + } + +# Read the New .DEF file + my @GenDataStruct; + my $Dummy; + if ($GENFILE) { + eval { &Def_ReadFileL(\@GenDataStruct, $GENFILE, $Dummy, ($Options{compare} or $Options{remove})); }; + } + die $@ if $@; + +# Compare the frozen .DEF data with the new .DEF file + my (@NewDataStruct, @MissingDataStruct, @BadDataStruct); + eval { &CompareFrzGenL (\@NewDataStruct, \@MissingDataStruct, \@BadDataStruct, \@FrzDataStruct, \@GenDataStruct, $Options{remove}); }; + die $@ if $@; + +# check for errors + my $NumRemoved; + my $Ref; + my @Errors; + my $Title='EFREEZE ERROR:'; + if ($Options{compare}) { + $Title='EFREEZE:'; + } + if (@MissingDataStruct and $Options{remove}) { +# Mark missing exports as ABSENT in DEF file + $NumRemoved=@MissingDataStruct; + if ($Options{compare}) { + print "EFREEZE: Marking $NumRemoved Export(s) as ABSENT :\n"; + } else { + print "EFREEZE: Marking $NumRemoved Export(s) as ABSENT in $FRZFILE :\n"; + } + foreach (@MissingDataStruct) { + $$_{Absent} = 1; + my $Comment=''; + if ($$_{Comment}) { + $Comment=" ; $$_{Comment}"; + } + my $r3unused = $$_{R3Unused} ? " R3UNUSED" : ""; + print " $$_{Name} \@ $$_{Ordinal} NONAME$r3unused$Comment\n"; + } + } + elsif (@MissingDataStruct) { + my $Num=@MissingDataStruct; + push @Errors, "$Title $FRZFILE: $Num Frozen Export(s) missing from $GENFILE (POSSIBLE COMPATIBILITY BREAK):\n"; + foreach $Ref (@MissingDataStruct) { + my $r3unused = $$Ref{R3Unused} ? " R3UNUSED" : ""; + push @Errors, " $$Ref{LineNum}: $$Ref{Name} \@ $$Ref{Ordinal} NONAME$r3unused\n"; + } + push @Errors, "\n"; + } + if (@BadDataStruct) { + my $Num=@BadDataStruct; + push @Errors, "$Title $GENFILE: $Num function(s) exported at wrong ordinal:\n"; + foreach $Ref (@BadDataStruct) { + my $r3unused = $$Ref{R3Unused} ? " R3UNUSED" : ""; + push @Errors, " $$Ref{LineNum}: $$Ref{Name} \@ $$Ref{Ordinal} NONAME$r3unused\n"; + } + } + if (@Errors) { + unless ($Options{compare}) { + die @Errors; + } + else { + print @Errors; + } + } + +# Update the frozen .DEF file + eval { &UpdateFrzFileL(\@NewDataStruct, \@FrzDataStruct, $FRZFILE, $FrzExportsOn, $Options{compare}, $NumRemoved); }; + die $@ if $@; + + + exit; +} + +####################################################################### +# SUBROUTINES +####################################################################### + +sub Usage () { + + print( + "\n", + "EFREEZE - .DEF file maintenance utility V$MajorVersion.$MinorVersion.$PatchVersion\n", + "\n", + "EFREEZE {options} [frozen .DEF file] [new .DEF file]\n", + "\n", + "options: (case-insensitive)\n", + " -Compare\n", + " -Remove\n", + "\n" + ); + exit 1; +} + +sub CompareFrzGenL ($$$$$$) { + my ($NewStructRef, $MissingStructRef, $BadStructRef, $FrzStructRef, $GenStructRef, $remove)=@_; + +# compare the input export data with the frozen data + +# take a copy of the frozen .DEF file structure that we can trash + my @TmpStruct=@$FrzStructRef; + +# remove any entries not containing export data and get the highest ordinal value used + my $LastOrdinal=0; + foreach (@TmpStruct) { + if ($$_{Name}) { + if ($LastOrdinal<$$_{Ordinal}) { + $LastOrdinal=$$_{Ordinal}; + } + next; + } + undef $_; + } + + my $GenRef; + my $TmpRef; + GENLOOP: foreach $GenRef (@$GenStructRef) { + next unless $$GenRef{Name}; # ignore lines in the .DEF file not containing an export + foreach $TmpRef (@TmpStruct) { + next unless defined $TmpRef; # ignore nullified entries in the temporary array +# does the function name match? + if ($$GenRef{Name} eq $$TmpRef{Name}) { +# check the names have the same ordinals + if ($remove or $$GenRef{Ordinal}==$$TmpRef{Ordinal}) { + undef $TmpRef; + next GENLOOP; + } +# store exports with the wrong ordinals + push @$BadStructRef, $GenRef; + undef $TmpRef; + next GENLOOP; + } +# Absent export? + if ($$TmpRef{Absent} and $$TmpRef{Ordinal}==$$GenRef{Ordinal}) { + next GENLOOP; + } + } +# store new exports not found in the frozen .DEF file with the right ordinal value + $LastOrdinal++; + $$GenRef{Ordinal}=$LastOrdinal; + push @$NewStructRef, $GenRef; + } + +# all the exports left in the frozen .DEF file weren't found + foreach $TmpRef (@TmpStruct) { + next unless defined $TmpRef; # ignore nullified entries in the temporary array + next if $$TmpRef{Absent}; # skip entries marked as ABSENT in the DEF file + push @$MissingStructRef, $TmpRef; + } +} + +sub UpdateFrzFileL ($$$$$$) { + my ($NewStructRef, $FrzStructRef, $FILE, $ExportsOn, $Compare, $NumRemoved)=@_; + +# add the exports to the frozen .DEF file text + unless (@$NewStructRef or $NumRemoved) { + print "EFREEZE: DEF file up to date\n"; + return; + } + + my $NumNewExports=@$NewStructRef; + unless ($Compare) { +# abort the operation unless the frozen .DEF file is writeable + if (-e $FILE and not -w $FILE) { + die + "EFREEZE ERROR: Can't append $NumNewExports New Export(s) to $FILE\n", + " as file is not writeable. Check source code control system.\n" + ; + } + print "EFREEZE: Appending $NumNewExports New Export(s) to $FILE:\n" if ($NumNewExports); + } + else { + print "EFREEZE: $NumNewExports New Export(s):\n" if ($NumNewExports); + } + + my @Text; + my $ExportsDeclared; + +# Process the frozen .DEF file + if (@$FrzStructRef) { # there is already a frozen .DEF file + my $FrzRef; + +# get the lines of text from the frozen .DEF file + foreach $FrzRef (@$FrzStructRef) { + next if (!$FrzRef); + if (!defined($$FrzRef{Ordinal})) { + push @Text, $$FrzRef{Line}; + $ExportsDeclared = 1 if ($$FrzRef{Line} =~ /^\s*EXPORTS\s*(\s+\S+.*)?$/io); + next; + } + my $Comment=''; + if ($$FrzRef{Comment}) { + $Comment=" ; $$FrzRef{Comment}"; + } + my $r3unused = $$FrzRef{R3Unused} ? " R3UNUSED" : ""; + my $absent = $$FrzRef{Absent} ? " ABSENT" : ""; + + my $data = ""; + if( !($$FrzRef{Name} =~ /^(_ZTI|_ZTV|_ZTT)/)) + { +# A symbol name with the above pattern indicates that it is a Data symbol. +# Mark symbols as DATA only when it cannot be found from the name alone (i.e., +# explicitly exported data symbols). + + if(($$FrzRef{Data}) and ($$FrzRef{Size}) ){ + $data = " DATA $$FrzRef{Size}"; + } + } + push @Text, "\t$$FrzRef{Name} \@ $$FrzRef{Ordinal} NONAME$data$r3unused$absent$Comment\n"; + } + +# strip any blank lines at the end of the frozen .DEF file text + foreach (reverse @Text) { + if (/^\s*$/o) { + $_=''; + next; + } + last; + } + + } + +# Add an EXPORTS section header if there aren't already exports + unshift @Text, "EXPORTS\n" unless ($ExportsDeclared); + + my $NewRef; + foreach $NewRef (@$NewStructRef) { + my $Comment=''; + if ($$NewRef{Comment}) { + $Comment=" ; $$NewRef{Comment}"; + } + my $r3unused = $$NewRef{R3Unused} ? " R3UNUSED" : ""; + my $absent = $$NewRef{Absent} ? " ABSENT" : ""; + + my $data = ""; + if( !($$NewRef{Name} =~ /^(_ZTV|_ZTI|_ZTT)/)) { +# A symbol name with the above pattern indicates that it is a Data symbol. +# Mark symbols as DATA only when it cannot be found from the name alone (i.e., +# explicitly exported data symbols). + if(($$NewRef{Data}) and ($$NewRef{Size}) ){ + $data = " DATA $$NewRef{Size}"; + } + } + print " $$NewRef{Name} \@ $$NewRef{Ordinal} NONAME$r3unused$Comment\n"; + push @Text, "\t$$NewRef{Name} \@ $$NewRef{Ordinal} NONAME$data$r3unused$absent$Comment\n"; + } + +# add a terminating newline + push @Text, "\n"; + + unless ($Compare) { +# write the new frozen .DEF file + eval { &Def_WriteFileL(\@Text, $FILE); }; + die $@ if $@; + } +} +