abi-compliance-checker.pl revision 35c44fd1428ba96f71ba80f1d45c175a9ab4a197
1d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor#!/usr/bin/perl 2d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor########################################################################### 3d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# ABI Compliance Checker (ACC) 1.98.1 4d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# A tool for checking backward compatibility of a C/C++ library API 5d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# 6d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# Copyright (C) 2009-2010 The Linux Foundation 7d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# Copyright (C) 2009-2011 Institute for System Programming, RAS 8d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# Copyright (C) 2011-2012 Nokia Corporation and/or its subsidiary(-ies) 9d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# Copyright (C) 2011-2012 ROSA Laboratory 10d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# 11d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# Written by Andrey Ponomarenko 12d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# 13d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# PLATFORMS 14d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# ========= 15d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# Linux, FreeBSD, Mac OS X, Haiku, MS Windows, Symbian 16d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# 1787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# REQUIREMENTS 1887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# ============ 19651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines# Linux 20d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# - G++ (3.0-4.7, recommended 4.5 or newer) 21d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# - GNU Binutils (readelf, c++filt, objdump) 22d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# - Perl 5 (5.8 or newer) 23d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# 24c640058aa7f224a71ce3b1d2601d84e1b57f82d3Alexey Bataev# Mac OS X 25d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# - Xcode (gcc, otool, c++filt) 26d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# 27d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# MS Windows 28d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# - MinGW (3.0-4.7, recommended 4.5 or newer) 2987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# - MS Visual C++ (dumpbin, undname, cl) 30d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# - Active Perl 5 (5.8 or newer) 31d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# - Sigcheck v1.71 or newer 32d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# - Info-ZIP 3.0 (zip, unzip) 33d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# - Add gcc.exe path (C:\MinGW\bin\) to your system PATH variable 344fa7eab771ab8212e1058bd1a91061ff120c8fbbAlexey Bataev# - Run vsvars32.bat (C:\Microsoft Visual Studio 9.0\Common7\Tools\) 35d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# 36d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# This program is free software: you can redistribute it and/or modify 37d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# it under the terms of the GNU General Public License or the GNU Lesser 384d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky# General Public License as published by the Free Software Foundation. 39d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor# 407d66f8cafd807e551efb4739cdb37fc272cf5345Chandler Carruth# This program is distributed in the hope that it will be useful, 417d66f8cafd807e551efb4739cdb37fc272cf5345Chandler Carruth# but WITHOUT ANY WARRANTY; without even the implied warranty of 427d66f8cafd807e551efb4739cdb37fc272cf5345Chandler Carruth# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 437d66f8cafd807e551efb4739cdb37fc272cf5345Chandler Carruth# GNU General Public License for more details. 446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines# 456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines# You should have received a copy of the GNU General Public License 466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines# and the GNU Lesser General Public License along with this program. 476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines# If not, see <http://www.gnu.org/licenses/>. 4887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar########################################################################### 497d66f8cafd807e551efb4739cdb37fc272cf5345Chandler Carruthuse Getopt::Long; 507d66f8cafd807e551efb4739cdb37fc272cf5345Chandler CarruthGetopt::Long::Configure ("posix_default", "no_ignore_case"); 516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesuse File::Path qw(mkpath rmtree); 526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesuse File::Temp qw(tempdir); 536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesuse File::Copy qw(copy move); 546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesuse Cwd qw(abs_path cwd); 556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesuse Data::Dumper; 566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesuse Config; 577d66f8cafd807e551efb4739cdb37fc272cf5345Chandler Carruth 587d66f8cafd807e551efb4739cdb37fc272cf5345Chandler Carruthmy $TOOL_VERSION = "1.98.1"; 596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy $ABI_DUMP_VERSION = "2.17"; 606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy $OLDEST_SUPPORTED_VERSION = "1.18"; 616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy $XML_REPORT_VERSION = "1.0"; 627d66f8cafd807e551efb4739cdb37fc272cf5345Chandler Carruthmy $XML_ABI_DUMP_VERSION = "1.1"; 63d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregormy $OSgroup = get_OSgroup(); 64facfc77487a890bfb7b5eee7e21cd2b395a9faafChandler Carruthmy $ORIG_DIR = cwd(); 65dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthmy $TMP_DIR = tempdir(CLEANUP=>1); 66dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 67dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth# Internal modules 68dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthmy $MODULES_DIR = get_Modules(); 696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinespush(@INC, get_dirname($MODULES_DIR)); 706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines# Rules DB 716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %RULES_PATH = ( 726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "Binary" => $MODULES_DIR."/RulesBin.xml", 736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "Source" => $MODULES_DIR."/RulesSrc.xml"); 74dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 754967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarmy ($Help, $ShowVersion, %Descriptor, $TargetLibraryName, $GenerateTemplate, 764967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar$TestTool, $DumpAPI, $SymbolsListPath, $CheckHeadersOnly_Opt, $UseDumps, 77dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth$CheckObjectsOnly_Opt, $AppPath, $StrictCompat, $DumpVersion, $ParamNamesPath, 78dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth%RelativeDirectory, $TargetLibraryFName, $TestDump, $CheckImpl, $LoggingPath, 79dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth%TargetVersion, $InfoMsg, $UseOldDumps, %UsedDump, $CrossGcc, %OutputLogPath, 80dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth$OutputReportPath, $OutputDumpPath, $ShowRetVal, $SystemRoot_Opt, $DumpSystem, 81dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth$CmpSystems, $TargetLibsPath, $Debug, $CrossPrefix, $UseStaticLibs, $NoStdInc, 82dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth$TargetComponent_Opt, $TargetSysInfo, $TargetHeader, $ExtendedCheck, $Quiet, 83dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth$SkipHeadersPath, $Cpp2003, $LogMode, $StdOut, $ListAffected, $ReportFormat, 84dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth$UserLang, $TargetHeadersPath, $BinaryOnly, $SourceOnly, $BinaryReportPath, 85dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth$SourceReportPath, $UseXML, $Browse, $OpenReport, $SortDump, $DumpFormat); 86dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 87dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthmy $CmdName = get_filename($0); 88ea245e0ba48caf7e7acf870880c030d7ddc76667Craig Silversteinmy %OS_LibExt = ( 89dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "dynamic" => { 90ea245e0ba48caf7e7acf870880c030d7ddc76667Craig Silverstein "default"=>"so", 91dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "macos"=>"dylib", 92dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "windows"=>"dll", 93ea245e0ba48caf7e7acf870880c030d7ddc76667Craig Silverstein "symbian"=>"dso" 94dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth }, 95ea245e0ba48caf7e7acf870880c030d7ddc76667Craig Silverstein "static" => { 96dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "default"=>"a", 97dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "windows"=>"lib", 98dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "symbian"=>"lib" 99ea245e0ba48caf7e7acf870880c030d7ddc76667Craig Silverstein } 100dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth); 101dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 102dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthmy %OS_Archive = ( 103e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth "windows"=>"zip", 104dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "default"=>"tar.gz" 105dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth); 106b5c202f9e4f6d0f230d5cb8848779259ebf95b7fChandler Carruth 107b5c202f9e4f6d0f230d5cb8848779259ebf95b7fChandler Carruthmy %ERROR_CODE = ( 108b5c202f9e4f6d0f230d5cb8848779259ebf95b7fChandler Carruth # Compatible verdict 10980434a334c92d2f24f38fbbd14acd6c3f6c72306Michael Han "Compatible"=>0, 110b5c202f9e4f6d0f230d5cb8848779259ebf95b7fChandler Carruth "Success"=>0, 111b5c202f9e4f6d0f230d5cb8848779259ebf95b7fChandler Carruth # Incompatible verdict 112dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "Incompatible"=>1, 113dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth # Undifferentiated error code 114dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "Error"=>2, 115dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth # System command is not found 116dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "Not_Found"=>3, 117dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth # Cannot access input files 118dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "Access_Error"=>4, 119dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth # Cannot compile header files 120dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "Cannot_Compile"=>5, 121dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth # Header compiled with errors 122dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "Compile_Error"=>6, 123e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth # Invalid input ABI dump 124dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "Invalid_Dump"=>7, 125760c8af273d9871d063250ae626fb6df94c121f2John McCall # Incompatible version of ABI dump 126760c8af273d9871d063250ae626fb6df94c121f2John McCall "Dump_Version"=>8, 127760c8af273d9871d063250ae626fb6df94c121f2John McCall # Cannot find a module 128760c8af273d9871d063250ae626fb6df94c121f2John McCall "Module_Error"=>9, 129760c8af273d9871d063250ae626fb6df94c121f2John McCall # Empty intersection between 130760c8af273d9871d063250ae626fb6df94c121f2John McCall # headers and shared objects 131760c8af273d9871d063250ae626fb6df94c121f2John McCall "Empty_Intersection"=>10, 132760c8af273d9871d063250ae626fb6df94c121f2John McCall # Empty set of symbols in headers 133760c8af273d9871d063250ae626fb6df94c121f2John McCall "Empty_Set"=>11 134760c8af273d9871d063250ae626fb6df94c121f2John McCall); 135760c8af273d9871d063250ae626fb6df94c121f2John McCall 1364967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarmy %HomePage = ( 1374967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "Wiki"=>"http://ispras.linuxbase.org/index.php/ABI_compliance_checker", 1384967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "Dev1"=>"https://github.com/lvc/abi-compliance-checker", 1394967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "Dev2"=>"http://forge.ispras.ru/projects/abi-compliance-checker" 1406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines); 141db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky 14287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarmy $ShortUsage = "ABI Compliance Checker (ACC) $TOOL_VERSION 14387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarA tool for checking backward compatibility of a C/C++ library API 14487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarCopyright (C) 2012 ROSA Laboratory 14587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarLicense: GNU LGPL or GNU GPL 1464967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 1474967a710c84587c654b56c828382219c3937dacbPirama Arumuga NainarUsage: $CmdName [options] 1484967a710c84587c654b56c828382219c3937dacbPirama Arumuga NainarExample: $CmdName -lib NAME -old OLD.xml -new NEW.xml 14987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 150db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick LewyckyOLD.xml and NEW.xml are XML-descriptors: 1516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 152db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky <version> 153760c8af273d9871d063250ae626fb6df94c121f2John McCall 1.0 154760c8af273d9871d063250ae626fb6df94c121f2John McCall </version> 155760c8af273d9871d063250ae626fb6df94c121f2John McCall 156536bab452fa38692834233187ed3d49b83722cb3Craig Silverstein <headers> 157a40bc724849f9cdc6a7706bc5d230685c3bdf63cDouglas Gregor /path/to/headers/ 158a40bc724849f9cdc6a7706bc5d230685c3bdf63cDouglas Gregor </headers> 159a40bc724849f9cdc6a7706bc5d230685c3bdf63cDouglas Gregor 160ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie <libs> 161c28a335184207a47f34eb9d1707dc8d7c6c7b8b6Richard Smith /path/to/libraries/ 16252ec0c0357ce970ca52a27c1086626450f0967e7Daniel Jasper </libs> 16352ec0c0357ce970ca52a27c1086626450f0967e7Daniel Jasper 164c28a335184207a47f34eb9d1707dc8d7c6c7b8b6Richard SmithMore info: $CmdName --help\n"; 1654967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 1664967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarif($#ARGV==-1) { 1674967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar printMsg("INFO", $ShortUsage); 168db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky exit(0); 169717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan} 170db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky 171e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruthforeach (2 .. $#ARGV) 17287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar{ # correct comma separated options 17387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if($ARGV[$_-1] eq ",") { 174db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky $ARGV[$_-2].=",".$ARGV[$_]; 1754967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar splice(@ARGV, $_-1, 2); 1764967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 1774967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar elsif($ARGV[$_-1]=~/,\Z/) { 1784967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $ARGV[$_-1].=$ARGV[$_]; 1794967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar splice(@ARGV, $_, 1); 1804967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 1814967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar elsif($ARGV[$_]=~/\A,/ 1824967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar and $ARGV[$_] ne ",") { 1834967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $ARGV[$_-1].=$ARGV[$_]; 1844967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar splice(@ARGV, $_, 1); 1854967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 1864967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar} 187db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky 188717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong WanGetOptions("h|help!" => \$Help, 189db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "i|info!" => \$InfoMsg, 190e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth "v|version!" => \$ShowVersion, 191db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "dumpversion!" => \$DumpVersion, 192dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth# general options 193db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "l|lib|library=s" => \$TargetLibraryName, 1944d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "d1|old|o=s" => \$Descriptor{1}{"Path"}, 195717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan "d2|new|n=s" => \$Descriptor{2}{"Path"}, 1964d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "dump|dump-abi|dump_abi=s" => \$DumpAPI, 1974d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "old-dumps!" => \$UseOldDumps, 1984d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky# extra options 1994d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "d|descriptor-template!" => \$GenerateTemplate, 2004d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "app|application=s" => \$AppPath, 201651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "static-libs!" => \$UseStaticLibs, 202651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "cross-gcc|gcc-path=s" => \$CrossGcc, 203651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "cross-prefix|gcc-prefix=s" => \$CrossPrefix, 204651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "sysroot=s" => \$SystemRoot_Opt, 205651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "v1|version1|vnum=s" => \$TargetVersion{1}, 206651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "v2|version2=s" => \$TargetVersion{2}, 207651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "s|strict!" => \$StrictCompat, 208db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "symbols-list=s" => \$SymbolsListPath, 209717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan "skip-headers=s" => \$SkipHeadersPath, 210db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "headers-only|headers_only!" => \$CheckHeadersOnly_Opt, 211e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth "objects-only!" => \$CheckObjectsOnly_Opt, 212db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "check-impl|check-implementation!" => \$CheckImpl, 213dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "show-retval!" => \$ShowRetVal, 214db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "use-dumps!" => \$UseDumps, 215db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "nostdinc!" => \$NoStdInc, 216db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "dump-system=s" => \$DumpSystem, 217e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth "sysinfo=s" => \$TargetSysInfo, 218dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "cmp-systems!" => \$CmpSystems, 219db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "libs-list=s" => \$TargetLibsPath, 220ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie "headers-list=s" => \$TargetHeadersPath, 221dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregor "header=s" => \$TargetHeader, 222dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregor "ext|extended!" => \$ExtendedCheck, 223dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregor "q|quiet!" => \$Quiet, 224dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregor "stdout!" => \$StdOut, 225dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregor "report-format=s" => \$ReportFormat, 22665019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor "dump-format=s" => \$DumpFormat, 22765019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor "xml!" => \$UseXML, 22865019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor "lang=s" => \$UserLang, 22965019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor "binary|bin|abi!" => \$BinaryOnly, 230ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie "source|src|api!" => \$SourceOnly, 231dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth# other options 232dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "test!" => \$TestTool, 233db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "test-dump!" => \$TestDump, 234e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth "debug!" => \$Debug, 235dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "cpp-compatible!" => \$Cpp2003, 236db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "p|params=s" => \$ParamNamesPath, 237dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "relpath1|relpath=s" => \$RelativeDirectory{1}, 238dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "relpath2=s" => \$RelativeDirectory{2}, 239db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "dump-path=s" => \$OutputDumpPath, 240e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth "sort!" => \$SortDump, 2414d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "report-path=s" => \$OutputReportPath, 242dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "bin-report-path=s" => \$BinaryReportPath, 243db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "src-report-path=s" => \$SourceReportPath, 2444d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "log-path=s" => \$LoggingPath, 2454d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "log1-path=s" => \$OutputLogPath{1}, 2464d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "log2-path=s" => \$OutputLogPath{2}, 2474d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "logging-mode=s" => \$LogMode, 2484d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "list-affected!" => \$ListAffected, 2494d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "l-full|lib-full=s" => \$TargetLibraryFName, 250db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "component=s" => \$TargetComponent_Opt, 251dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "b|browse=s" => \$Browse, 252dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "open!" => \$OpenReport 253db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky) or ERR_MESSAGE(); 254e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth 255dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthsub ERR_MESSAGE() 256dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth{ 257dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth printMsg("INFO", "\n".$ShortUsage); 258db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky exit($ERROR_CODE{"Error"}); 2590f8c08843fc6c8abe03654f609e1e03fcc557855Craig Silverstein} 2600f8c08843fc6c8abe03654f609e1e03fcc557855Craig Silverstein 2610f8c08843fc6c8abe03654f609e1e03fcc557855Craig Silversteinmy $LIB_TYPE = $UseStaticLibs?"static":"dynamic"; 2624d072932287eb074a4168804cac1acb18a51d5e8Craig Silversteinmy $SLIB_TYPE = $LIB_TYPE; 2630f8c08843fc6c8abe03654f609e1e03fcc557855Craig Silversteinif($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic") 2640f8c08843fc6c8abe03654f609e1e03fcc557855Craig Silverstein{ # show as "shared" library 265cbb67480094b3bcb5b715acd827cbad55e2a204cSean Hunt $SLIB_TYPE = "shared"; 2660f8c08843fc6c8abe03654f609e1e03fcc557855Craig Silverstein} 267011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregormy $LIB_EXT = getLIB_EXT($OSgroup); 268011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregormy $AR_EXT = getAR_EXT($OSgroup); 269011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregormy $BYTE_SIZE = 8; 2706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy $COMMON_LOG_PATH = "logs/run.log"; 27149007d7561212c0ae168702c1af1404c01ef43ffJames Dennett 27249007d7561212c0ae168702c1af1404c01ef43ffJames Dennettmy $HelpMessage=" 27349007d7561212c0ae168702c1af1404c01ef43ffJames DennettNAME: 27449007d7561212c0ae168702c1af1404c01ef43ffJames Dennett ABI Compliance Checker ($CmdName) 27549007d7561212c0ae168702c1af1404c01ef43ffJames Dennett Check backward compatibility of a C/C++ library API 27649007d7561212c0ae168702c1af1404c01ef43ffJames Dennett 27749007d7561212c0ae168702c1af1404c01ef43ffJames DennettDESCRIPTION: 27887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar ABI Compliance Checker (ACC) is a tool for checking backward binary and 27987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks 28087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and 28187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary 28287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar and/or source-level compatibility: changes in calling stack, v-table changes, 28387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar removed symbols, renamed fields, etc. Binary incompatibility may result in 28487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar crashing or incorrect behavior of applications built with an old version of 28587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar a library if they run on a new one. Source incompatibility may result in 28649007d7561212c0ae168702c1af1404c01ef43ffJames Dennett recompilation errors with a new library version. 287651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 288651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines The tool is intended for developers of software libraries and maintainers 289651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines of operating systems who are interested in ensuring backward compatibility, 290651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines i.e. allow old applications to run or to be recompiled with newer library 291651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines versions. 2926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 293651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Also the tool can be used by ISVs for checking applications portability to 294651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines new library versions. Found issues can be taken into account when adapting 295651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines the application to a new library version. 296651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines This tool is free software: you can redistribute it and/or modify it 298dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth under the terms of the GNU LGPL or GNU GPL. 29987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 30087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarUSAGE: 30187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $CmdName [options] 30287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 30387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarEXAMPLE: 30487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $CmdName -lib NAME -old OLD.xml -new NEW.xml 30587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 30687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar OLD.xml and NEW.xml are XML-descriptors: 30787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 30887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar <version> 30987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 1.0 31087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar </version> 31187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 31287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar <headers> 31387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar /path1/to/header(s)/ 31487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar /path2/to/header(s)/ 31587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar ... 31687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar </headers> 31787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 31887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar <libs> 31987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar /path1/to/library(ies)/ 32087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar /path2/to/library(ies)/ 32187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar ... 32287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar </libs> 32387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 32487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarINFORMATION OPTIONS: 32587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar -h|-help 32687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Print this help. 32787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 32887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar -i|-info 32987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Print complete info. 33087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 33187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar -v|-version 33287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Print version information. 3336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 334dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth -dumpversion 33587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Print the tool version ($TOOL_VERSION) and don't do anything else. 33687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 337dfc35e33177a433b56454f1d2b5e53734f65b288Chandler CarruthGENERAL OPTIONS: 338dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth -l|-lib|-library <name> 339dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth Library name (without version). 340dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth It affects only on the path and the title of the report. 341dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 342e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth -d1|-old|-o <path> 3436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Descriptor of 1st (old) library version. 3446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines It may be one of the following: 3456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 3466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 1. XML-descriptor (VERSION.xml file): 3476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 3486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines <version> 349e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth 1.0 350d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor </version> 351db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky 3526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines <headers> 3536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines /path1/to/header(s)/ 3546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines /path2/to/header(s)/ 3556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ... 35687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar </headers> 35787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 3586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines <libs> 3594967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar /path1/to/library(ies)/ 3606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines /path2/to/library(ies)/ 3616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ... 3626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines </libs> 3636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 3646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ... (XML-descriptor template 3656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines can be generated by -d option) 3666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 367e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth 2. ABI dump generated by -dump option 368dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 3. Directory with headers and/or $SLIB_TYPE libraries 3697d66f8cafd807e551efb4739cdb37fc272cf5345Chandler Carruth 4. Single header file 3707d66f8cafd807e551efb4739cdb37fc272cf5345Chandler Carruth 5. Single $SLIB_TYPE library 371dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 6. Comma separated list of headers and/or libraries 3726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 3736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines If you are using an 2-6 descriptor types then you should 3746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines specify version numbers with -v1 <num> and -v2 <num> options too. 3756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 37687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar For more information, please see: 3774967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar http://ispras.linuxbase.org/index.php/Library_Descriptor 3784967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 3794967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar -d2|-new|-n <path> 3804967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Descriptor of 2nd (new) library version. 3816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 3826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines -dump|-dump-abi <descriptor path(s)> 3836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Dump library ABI to gzipped TXT format file. You can transfer it 3846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines anywhere and pass instead of the descriptor. Also it can be used 3856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for debugging the tool. Compatible dump versions: ".majorVersion($ABI_DUMP_VERSION).".0<=V<=$ABI_DUMP_VERSION 3866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 3876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines -old-dumps 388e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth Enable support for old-version ABI dumps ($OLDEST_SUPPORTED_VERSION<=V<".majorVersion($ABI_DUMP_VERSION).".0).\n"; 389dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 3907d66f8cafd807e551efb4739cdb37fc272cf5345Chandler Carruthsub HELP_MESSAGE() { 3917d66f8cafd807e551efb4739cdb37fc272cf5345Chandler Carruth printMsg("INFO", $HelpMessage." 3927d66f8cafd807e551efb4739cdb37fc272cf5345Chandler CarruthMORE INFO: 393db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky $CmdName --info\n"); 3946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 3956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 3966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinessub INFO_MESSAGE() 3976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines{ 3986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines printMsg("INFO", "$HelpMessage 3997d66f8cafd807e551efb4739cdb37fc272cf5345Chandler CarruthEXTRA OPTIONS: 400dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth -d|-descriptor-template 4017d66f8cafd807e551efb4739cdb37fc272cf5345Chandler Carruth Create XML-descriptor template ./VERSION.xml 4027d66f8cafd807e551efb4739cdb37fc272cf5345Chandler Carruth 403dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth -app|-application <path> 404facfc77487a890bfb7b5eee7e21cd2b395a9faafChandler Carruth This option allows to specify the application that should be checked 4056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for portability to the new library version. 4066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 407facfc77487a890bfb7b5eee7e21cd2b395a9faafChandler Carruth -static-libs 4086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Check static libraries instead of the shared ones. The <libs> section 409dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth of the XML-descriptor should point to static libraries location. 4106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 411dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth -cross-gcc|-gcc-path <path> 412dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth Path to the cross GCC compiler to use instead of the usual (host) GCC. 413dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 414dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth -cross-prefix|-gcc-prefix <prefix> 415dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth GCC toolchain prefix. 416e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth 4176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines -sysroot <dirpath> 4186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Specify the alternative root directory. The tool will search for include 4196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines paths in the <dirpath>/usr/include and <dirpath>/usr/lib directories. 4206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 4216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines -v1|-version1 <num> 4226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Specify 1st library version outside the descriptor. This option is needed 423e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth if you have prefered an alternative descriptor type (see -d1 option). 424d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor 425facfc77487a890bfb7b5eee7e21cd2b395a9faafChandler Carruth In general case you should specify it in the XML-descriptor: 4266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines <version> 4276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines VERSION 4284d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky </version> 4296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 4304d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky -v2|-version2 <num> 4316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Specify 2nd library version outside the descriptor. 4324d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky 4334d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky -s|-strict 4344d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky Treat all compatibility warnings as problems. Add a number of \"Low\" 435717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan severity problems to the return value of the tool. 4364d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky 437717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan -headers-only 438717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan Check header files without $SLIB_TYPE libraries. It is easy to run, but may 439717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan provide a low quality compatibility report with false positives and 440717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan without detecting of added/removed symbols. 4414d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky 4424d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky Alternatively you can write \"none\" word to the <libs> section 4434d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky in the XML-descriptor: 444717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan <libs> 4454d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky none 4464d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky </libs> 4474d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky 448717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan -objects-only 449717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan Check $SLIB_TYPE libraries without header files. It is easy to run, but may 4506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines provide a low quality compatibility report with false positives and 4516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines without analysis of changes in parameters and data types. 4526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 4536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Alternatively you can write \"none\" word to the <headers> section 4546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines in the XML-descriptor: 4556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines <headers> 4566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines none 457717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan </headers> 4584d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky 4594d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky -check-impl|-check-implementation 4606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Compare canonified disassembled binary code of $SLIB_TYPE libraries to 461dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth detect changes in the implementation. Add \'Problems with Implementation\' 4626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines section to the report. 463dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 4646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines -show-retval 465dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth Show the symbol's return type in the report. 466dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 467dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth -symbols-list <path> 468dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth This option allows to specify a file with a list of symbols (mangled 469dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth names in C++) that should be checked, other symbols will not be checked. 470e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth 4716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines -skip-headers <path> 4726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines The file with the list of header files, that should not be checked. 4736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 4746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines -use-dumps 4756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Make dumps for two versions of a library and compare dumps. This should 4766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines increase the performance of the tool and decrease the system memory usage. 477e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth 4789a55591af3e5506b95a9718e15380129fbfc5ebcSean Hunt -nostdinc 4799a55591af3e5506b95a9718e15380129fbfc5ebcSean Hunt Do not search the GCC standard system directories for header files. 480dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 481dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth -dump-system <name> -sysroot <dirpath> 482dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth Find all the shared libraries and header files in <dirpath> directory, 4838d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo create XML descriptors and make ABI dumps for each library. The result 4848d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo set of ABI dumps can be compared (--cmp-systems) with the other one 4858d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo created for other version of operating system in order to check them for 4868d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo compatibility. Do not forget to specify -cross-gcc option if your target 4878d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo system requires some specific version of GCC compiler (different from 4888d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo the host GCC). The system ABI dump will be generated to: 489536bab452fa38692834233187ed3d49b83722cb3Craig Silverstein sys_dumps/<name>/<arch> 490dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 491cf4679e60a5c5fa13e4bfe69f8186658c828af49Craig Silverstein -dump-system <descriptor.xml> 492dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth The same as the previous option but takes an XML descriptor of the target 493dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth system as input, where you should describe it: 494dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 4954d072932287eb074a4168804cac1acb18a51d5e8Craig Silverstein /* Primary sections */ 496dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 497dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth <name> 498651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines /* Name of the system */ 499176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines </name> 500c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 5016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines <headers> 5024fa7eab771ab8212e1058bd1a91061ff120c8fbbAlexey Bataev /* The list of paths to header files and/or 503543c4ae954f2bce5ac58ed22080f23cbd94794d2Alexey Bataev directories with header files, one per line */ 504c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines </headers> 5054967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 5064967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar <libs> 5074967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar /* The list of paths to shared libraries and/or 50890226acd0b9be2964343cd63ae604bf0a656d33bArgyrios Kyrtzidis directories with shared libraries, one per line */ 50987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar </libs> 5104967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 51186b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek /* Optional sections */ 51286b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek 5136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines <search_headers> 51486b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek /* List of directories to be searched 51587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar for header files to automatically 51687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar generate include paths, one per line */ 51787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar </search_headers> 51886b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek 51987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar <search_libs> 52087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar /* List of directories to be searched 52187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar for shared libraries to resolve 52286b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek dependencies, one per line */ 52386b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek </search_libs> 5246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 5256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines <tools> 52687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar /* List of directories with tools used 52786b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek for analysis (GCC toolchain), one per line */ 5286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines </tools> 52986b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek 53087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar <cross_prefix> 53186b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek /* GCC toolchain prefix. 5326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Examples: 5336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines arm-linux-gnueabi 53487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar arm-none-symbianelf */ 53586b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek </cross_prefix> 5366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 53786b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek <gcc_options> 53887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar /* Additional GCC options, one per line */ 53990226acd0b9be2964343cd63ae604bf0a656d33bArgyrios Kyrtzidis </gcc_options> 54086b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek 54186b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek -sysinfo <dir> 5426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines This option may be used with -dump-system to dump ABI of operating 5436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines systems and configure the dumping process. 54487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Default: 54590226acd0b9be2964343cd63ae604bf0a656d33bArgyrios Kyrtzidis modules/Targets/{unix, symbian, windows} 5466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 54786b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek -cmp-systems -d1 sys_dumps/<name1>/<arch> -d2 sys_dumps/<name2>/<arch> 54887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Compare two system ABI dumps. Create compatibility reports for each 54990226acd0b9be2964343cd63ae604bf0a656d33bArgyrios Kyrtzidis library and the common HTML report including the summary of test 55086b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek results for all checked libraries. Report will be generated to: 55186b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek sys_compat_reports/<name1>_to_<name2>/<arch> 55286b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek 55386b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek -libs-list <path> 5546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines The file with a list of libraries, that should be dumped by 5556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines the -dump-system option or should be checked by the -cmp-systems option. 55686b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek 5576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines -header <name> 5586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Check/Dump ABI of this header only. 55987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 56086b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek -headers-list <path> 56186b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek The file with a list of headers, that should be checked/dumped. 56286b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek 56386b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek -ext|-extended 56486b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek If your library A is supposed to be used by other library B and you 56590226acd0b9be2964343cd63ae604bf0a656d33bArgyrios Kyrtzidis want to control the ABI of B, then you should enable this option. The 56687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar tool will check for changes in all data types, even if they are not 567dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth used by any function in the library A. Such data types are not part 5684967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar of the A library ABI, but may be a part of the ABI of the B library. 5694967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 5704967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar The short scheme is: 5714967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar app C (broken) -> lib B (broken ABI) -> lib A (stable ABI) 5724967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 5734967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar -q|-quiet 5744967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Print all messages to the file instead of stdout and stderr. 5754967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Default path (can be changed by -log-path option): 5764967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $COMMON_LOG_PATH 5774967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 5784967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar -stdout 5794967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Print analysis results (compatibility reports and ABI dumps) to stdout 5804967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar instead of creating a file. This would allow piping data to other programs. 5814967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 5824967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar -report-format <fmt> 5834967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Change format of compatibility report. 5844967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Formats: 5854967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar htm - HTML format (default) 5866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines xml - XML format 58787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 58887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar -dump-format <fmt> 589db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky Change format of ABI dump. 590e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth Formats: 591db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky perl - Data::Dumper format (default) 59287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar xml - XML format 5934967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 59487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar -xml 59587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Alias for: --report-format=xml or --dump-format=xml 59686b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek 5974967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar -lang <lang> 5984967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Set library language (C or C++). You can use this option if the tool 59986b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek cannot auto-detect a language. This option may be useful for checking 60087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar C-library headers (--lang=C) in --headers-only or --extended modes. 6014967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 6024967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar -binary|-bin|-abi 6034967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Show \"Binary\" compatibility problems only. 6044967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Generate report to: 6054967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar compat_reports/<library name>/<v1>_to_<v2>/abi_compat_report.html 6064967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 6074967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar -source|-src|-api 6084967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Show \"Source\" compatibility problems only. 6094967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Generate report to: 6104967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar compat_reports/<library name>/<v1>_to_<v2>/src_compat_report.html 6114967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 61286b32fd702d794bb655c59a1238bf7422869f506Ted KremenekOTHER OPTIONS: 6134967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar -test 6144967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Run internal tests. Create two binary incompatible versions of a sample 6154967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar library and run the tool to check them for compatibility. This option 6164967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar allows to check if the tool works correctly in the current environment. 6174967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 6184967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar -test-dump 6194967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Test ability to create, read and compare ABI dumps. 6204967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 6214967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar -debug 622d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor Debugging mode. Print debug info on the screen. Save intermediate 623db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky analysis stages in the debug directory: 624e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth debug/<library>/<version>/ 625db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky 626db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky Also consider using --dump option for debugging the tool. 62787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 62887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar -cpp-compatible 6296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines If your header file is written in C language and can be compiled by 6306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines the C++ compiler (i.e. doesn't contain C++-keywords and other bad 631dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth things), then you can tell ACC about this and speedup the analysis. 632db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky 633e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth -p|-params <path> 634db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky Path to file with the function parameter names. It can be used 635db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky for improving report view if the library header files have no 636dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth parameter names. File format: 6376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 6386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines func1;param1;param2;param3 ... 6396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines func2;param1;param2;param3 ... 640d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor ... 641d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor 642db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky -relpath <path> 643e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth Replace {RELPATH} macros to <path> in the XML-descriptor used 644db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky for dumping the library ABI (see -dump option). 645db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky 6466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines -relpath1 <path> 6474d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky Replace {RELPATH} macros to <path> in the 1st XML-descriptor (-d1). 6484d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky 6494d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky -relpath2 <path> 6504d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky Replace {RELPATH} macros to <path> in the 2nd XML-descriptor (-d2). 6514d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky 6524d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky -dump-path <path> 6536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump. 6546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Default: 65539e6ab4be93d9c5e729a578ddd9d415cd2d49872David Blaikie abi_dumps/<library>/<library>_<version>.abi.$AR_EXT 6564d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky 6574d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky -sort 6584d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky Enable sorting of data in ABI dumps. 6594d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky 6604d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky -report-path <path> 6614d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky Path to compatibility report. 662651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Default: 663651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines compat_reports/<library name>/<v1>_to_<v2>/compat_report.html 664651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 665651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines -bin-report-path <path> 666651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Path to \"Binary\" compatibility report. 6676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Default: 668dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth compat_reports/<library name>/<v1>_to_<v2>/abi_compat_report.html 669db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky 670e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth -src-report-path <path> 671db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky Path to \"Source\" compatibility report. 672c28a335184207a47f34eb9d1707dc8d7c6c7b8b6Richard Smith Default: 673c28a335184207a47f34eb9d1707dc8d7c6c7b8b6Richard Smith compat_reports/<library name>/<v1>_to_<v2>/src_compat_report.html 67452ec0c0357ce970ca52a27c1086626450f0967e7Daniel Jasper 675d0b982ca5cf685af08d5015e8c2dfae3ecab1a0bCraig Silverstein -log-path <path> 676d0b982ca5cf685af08d5015e8c2dfae3ecab1a0bCraig Silverstein Log path for all messages. 677db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky Default: 6789a55591af3e5506b95a9718e15380129fbfc5ebcSean Hunt logs/<library>/<version>/log.txt 6796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 6806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines -log1-path <path> 6816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Log path for 1st version of a library. 6826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Default: 683651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines logs/<library name>/<v1>/log.txt 6849a55591af3e5506b95a9718e15380129fbfc5ebcSean Hunt 685651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines -log2-path <path> 686d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor Log path for 2nd version of a library. 687651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Default: 688651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines logs/<library name>/<v2>/log.txt 689651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 690651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines -logging-mode <mode> 691651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Change logging mode. 692e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth Modes: 693db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky w - overwrite old logs (default) 694db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky a - append old logs 695dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth n - do not write any logs 696dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 6976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines -list-affected 698dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth Generate file with the list of incompatible 6996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines symbols beside the HTML compatibility report. 700dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth Use 'c++filt \@file' command from GNU binutils 701e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth to unmangle C++ symbols in the generated file. 702dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth Default names: 7036c321e35008f2c99eeb1409b43859a04c48e5ce5Chandler Carruth abi_affected.txt 7046c321e35008f2c99eeb1409b43859a04c48e5ce5Chandler Carruth src_affected.txt 705db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky 706db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky -component <name> 707db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky The component name in the title and summary of the HTML report. 708db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky Default: 70914aba76042e041b2c5e439bf4ae353a0a3c7fd73Douglas Gregor library 710db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky 711176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines -l-full|-lib-full <name> 712e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth Change library name in the report title to <name>. By default 713db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky will be displayed a name specified by -l option. 714db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky 715db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky -b|-browse <program> 7166c321e35008f2c99eeb1409b43859a04c48e5ce5Chandler Carruth Open report(s) in the browser (firefox, opera, etc.). 717d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor 718d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor -open 719e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth Open report(s) in the default browser. 720db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky 721d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas GregorREPORT: 7226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Compatibility report will be generated to: 723dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregor compat_reports/<library name>/<v1>_to_<v2>/compat_report.html 7246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 725dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregor Log will be generated to: 726dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregor logs/<library name>/<v1>/log.txt 727ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie logs/<library name>/<v2>/log.txt 7286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 7296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen HinesEXIT CODES: 730ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie 0 - Compatible. The tool has run without any errors. 731dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregor non-zero - Incompatible or the tool has run with errors. 732dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregor 733dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas GregorREPORT BUGS TO: 734dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregor Andrey Ponomarenko <aponomarenko\@rosalab.ru> 735dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregor 736176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesMORE INFORMATION: 737dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregor ".$HomePage{"Wiki"}." 738ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie ".$HomePage{"Dev1"}."\n"); 739dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregor} 740dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregor 741dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregormy $DescriptorTemplate = " 742dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregor<?xml version=\"1.0\" encoding=\"utf-8\"?> 743dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregor<descriptor> 744ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie 745dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregor/* Primary sections */ 746dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregor 747dc355713be51fcb4ee52d9fd6b4548ceff47fadfDouglas Gregor<version> 7486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines /* Version of the library */ 74965019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor</version> 7506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 75165019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor<headers> 75265019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor /* The list of paths to header files and/or 75365019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor directories with header files, one per line */ 75465019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor</headers> 75565019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor 75665019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor<libs> 757ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie /* The list of paths to shared libraries (*.$LIB_EXT) and/or 75865019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor directories with shared libraries, one per line */ 759ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie</libs> 76065019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor 76165019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor/* Optional sections */ 76265019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor 76365019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor<include_paths> 76465019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor /* The list of include paths that will be provided 76565019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor to GCC to compile library headers, one per line. 76665019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor NOTE: If you define this section then the tool 76765019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor will not automatically generate include paths */ 76865019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor</include_paths> 769ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie 77065019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor<add_include_paths> 77165019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor /* The list of include paths that will be added 77265019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor to the automatically generated include paths, one per line */ 7736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines</add_include_paths> 774dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 775db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky<skip_include_paths> 7766c321e35008f2c99eeb1409b43859a04c48e5ce5Chandler Carruth /* The list of include paths that will be removed from the 7776c321e35008f2c99eeb1409b43859a04c48e5ce5Chandler Carruth list of automatically generated include paths, one per line */ 7786c321e35008f2c99eeb1409b43859a04c48e5ce5Chandler Carruth</skip_include_paths> 779db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky 780e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth<gcc_options> 781db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky /* Additional GCC options, one per line */ 782db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky</gcc_options> 7836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 784dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth<include_preamble> 7856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines /* The list of header files that will be 786db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky included before other headers, one per line. 787db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky Examples: 788db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky 1) tree.h for libxml2 789db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky 2) ft2build.h for freetype2 */ 790d7a6b1640e565487d163023a6a2e83f55476ae96Eli Friedman</include_preamble> 791e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth 792d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor<defines> 793db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky /* The list of defines that will be added at the 794dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth headers compiling stage, one per line: 795d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor #define A B 796db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky #define C D */ 797a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor</defines> 798a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor 7996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines<add_namespaces> 800db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky /* The list of namespaces that should be added to the alanysis 801db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky if the tool cannot find them automatically, one per line */ 802dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth</add_namespaces> 803db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky 804db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky<skip_types> 805dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth /* The list of data types, that 806dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth should not be checked, one per line */ 807d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor</skip_types> 808d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor 809e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth<skip_symbols> 810db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky /* The list of functions (mangled/symbol names in C++), 811db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky that should not be checked, one per line */ 8124d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky</skip_symbols> 8134d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky 8146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines<skip_namespaces> 8154d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky /* The list of C++ namespaces, that 8166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines should not be checked, one per line */ 8174d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky</skip_namespaces> 8184d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky 8194d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky<skip_constants> 8204d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky /* The list of constants that should 8214d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky not be checked, one name per line */ 8224d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky</skip_constants> 823d7a6b1640e565487d163023a6a2e83f55476ae96Eli Friedman 8244d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky<skip_headers> 8254d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky /* The list of header files and/or directories 8264d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky with header files that should not be checked, one per line */ 827fcf431609769a9600c24618d1a33135caec4fef2Zhanyong Wan</skip_headers> 828fcf431609769a9600c24618d1a33135caec4fef2Zhanyong Wan 829fcf431609769a9600c24618d1a33135caec4fef2Zhanyong Wan<skip_libs> 830ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie /* The list of shared libraries and/or directories 831f1fe3759e6e8b1756c514f1181c86bd4b9d1666cDouglas Gregor with shared libraries that should not be checked, one per line */ 8324d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky</skip_libs> 8334d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky 8344d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky<skip_including> 835a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor /* The list of header files, that cannot be included 836b6744efecba58792cce20d2d7b9ee39927c5422eDouglas Gregor directly (or non-self compiled ones), one per line */ 837b6744efecba58792cce20d2d7b9ee39927c5422eDouglas Gregor</skip_including> 8386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 839a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor<search_headers> 8406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines /* List of directories to be searched 8414d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky for header files to automatically 8424d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky generate include paths, one per line. */ 8434d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky</search_headers> 8444d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky 8454d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky<search_libs> 8464d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky /* List of directories to be searched 8474d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky for shared librariess to resolve 8484d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky dependencies, one per line */ 8494d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky</search_libs> 8504d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky 8514d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky<tools> 8524d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky /* List of directories with tools used 8536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for analysis (GCC toolchain), one per line */ 854dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth</tools> 8556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 856dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth<cross_prefix> 857dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth /* GCC toolchain prefix. 858dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth Examples: 859d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor arm-linux-gnueabi 860e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth arm-none-symbianelf */ 861db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky</cross_prefix> 862db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky 8636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines</descriptor>"; 8644d072932287eb074a4168804cac1acb18a51d5e8Craig Silverstein 8656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %Operator_Indication = ( 86676852c218a207ef43583515cb835b6e855353a0fDouglas Gregor "not" => "~", 86776852c218a207ef43583515cb835b6e855353a0fDouglas Gregor "assign" => "=", 868ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie "andassign" => "&=", 8698268fe7c4bdfa341975a687a8a5e236c2c5b88a4James Dennett "orassign" => "|=", 8700f8c08843fc6c8abe03654f609e1e03fcc557855Craig Silverstein "xorassign" => "^=", 8714967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "or" => "|", 8724967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "xor" => "^", 8734967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "addr" => "&", 8744967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "and" => "&", 8754967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "lnot" => "!", 8764967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "eq" => "==", 8774967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "ne" => "!=", 8784967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "lt" => "<", 8794967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "lshift" => "<<", 8804967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "lshiftassign" => "<<=", 8814967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "rshiftassign" => ">>=", 8820f8c08843fc6c8abe03654f609e1e03fcc557855Craig Silverstein "call" => "()", 8830f8c08843fc6c8abe03654f609e1e03fcc557855Craig Silverstein "mod" => "%", 8840f8c08843fc6c8abe03654f609e1e03fcc557855Craig Silverstein "modassign" => "%=", 8856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "subs" => "[]", 8866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "land" => "&&", 8876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "lor" => "||", 8886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "rshift" => ">>", 889b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar "ref" => "->", 89004fa7a33279808dc3e5117c41b5f84c40eeb7362Richard Smith "le" => "<=", 891011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor "deref" => "*", 892011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor "mult" => "*", 8930f8c08843fc6c8abe03654f609e1e03fcc557855Craig Silverstein "preinc" => "++", 8946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "delete" => " delete", 89587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar "vecnew" => " new[]", 89687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar "vecdelete" => " delete[]", 89787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar "predec" => "--", 89849007d7561212c0ae168702c1af1404c01ef43ffJames Dennett "postinc" => "++", 89949007d7561212c0ae168702c1af1404c01ef43ffJames Dennett "postdec" => "--", 90049007d7561212c0ae168702c1af1404c01ef43ffJames Dennett "plusassign" => "+=", 901dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "plus" => "+", 902dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "minus" => "-", 903dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "minusassign" => "-=", 9046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "gt" => ">", 9056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "ge" => ">=", 9066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "new" => " new", 9074967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "multassign" => "*=", 9084967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "divassign" => "/=", 9096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "div" => "/", 9104967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "neg" => "-", 9114967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "pos" => "+", 9126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "memref" => "->*", 913d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor "compound" => "," ); 914d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor 9156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %UnknownOperator; 916db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky 9176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %NodeType= ( 918db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "array_type" => "Array", 9196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "binfo" => "Other", 920db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "boolean_type" => "Intrinsic", 9216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "complex_type" => "Intrinsic", 9226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "const_decl" => "Other", 923db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "enumeral_type" => "Enum", 9246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "field_decl" => "Other", 9256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "function_decl" => "Other", 926db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "function_type" => "FunctionType", 9276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "identifier_node" => "Other", 9286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "integer_cst" => "Other", 929db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "integer_type" => "Intrinsic", 930dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "method_type" => "MethodType", 9316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "namespace_decl" => "Other", 9326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "parm_decl" => "Other", 9336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "pointer_type" => "Pointer", 934db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "real_cst" => "Other", 9356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "real_type" => "Intrinsic", 936651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "record_type" => "Struct", 9376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "reference_type" => "Ref", 93812df246d6dea2ee1f92c186f922f1afcf499647aReid Kleckner "string_cst" => "Other", 9396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "template_decl" => "Other", 9406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "template_type_parm" => "Other", 941d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor "tree_list" => "Other", 9426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "tree_vec" => "Other", 9436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "type_decl" => "Other", 944db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "union_type" => "Union", 945dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "var_decl" => "Other", 9466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "void_type" => "Intrinsic", 9476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines # "nop_expr" => "Other", 9486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines # "addr_expr" => "Other", 949db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "offset_type" => "Other" ); 950dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 9516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %CppKeywords_C = map {$_=>1} ( 9526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines # C++ 2003 keywords 9536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "public", 9546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "protected", 955d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor "private", 956dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "default", 9576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "template", 9586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "new", 9596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines #"asm", 9606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "dynamic_cast", 961d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor "auto", 9626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "try", 963d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor "namespace", 9646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "typename", 965d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor "using", 966651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "reinterpret_cast", 967651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "friend", 968db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "class", 969dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "virtual", 970651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "const_cast", 971db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "mutable", 972651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "static_cast", 973651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "export", 974651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines # C++0x keywords 975d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor "noexcept", 976651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "nullptr", 977651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "constexpr", 978651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "static_assert", 979176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines "explicit", 980176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines # cannot be used as a macro name 981176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines # as it is an operator in C++ 982651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "and", 983d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor #"and_eq", 9846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "not", 9856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines #"not_eq", 986d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor "or" 9876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines #"or_eq", 9886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines #"bitand", 989d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor #"bitor", 9906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines #"xor", 991db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky #"xor_eq", 9926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines #"compl" 9936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines); 994d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor 995ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Huntmy %CppKeywords_F = map {$_=>1} ( 9966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "delete", 9976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "catch", 9986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "alignof", 999ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt "thread_local", 10006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "decltype", 100134b41d939a1328f484511c6002ba2456db879a29Richard Smith "typeid" 10026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines); 10036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 10046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %CppKeywords_O = map {$_=>1} ( 10056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "bool", 10066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "register", 1007db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "inline", 1008dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "operator" 10096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines); 10106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 10116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %CppKeywords_A = map {$_=>1} ( 1012d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor "this", 10136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "throw" 1014d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor); 10156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 10166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesforeach (keys(%CppKeywords_C), 10179d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCallkeys(%CppKeywords_F), 10186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hineskeys(%CppKeywords_O)) { 1019075f8f1b6bed4d1b224c74f87508534cc6392ce6Abramo Bagnara $CppKeywords_A{$_}=1; 1020dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth} 10216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 102233500955d731c73717af52088b7fc0e7a85681e7John McCall# Header file extensions as described by gcc 10236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+"; 10246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 10256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %IntrinsicMangling = ( 10266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "void" => "v", 10276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "bool" => "b", 10286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "wchar_t" => "w", 1029d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor "char" => "c", 103033500955d731c73717af52088b7fc0e7a85681e7John McCall "signed char" => "a", 10316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "unsigned char" => "h", 10326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "short" => "s", 10336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "unsigned short" => "t", 1034d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor "int" => "i", 10356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "unsigned int" => "j", 10367536dd5e6c99584481b7dab68b7e7d8df9c54054Douglas Gregor "long" => "l", 10376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "unsigned long" => "m", 1038d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor "long long" => "x", 1039dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "__int64" => "x", 10406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "unsigned long long" => "y", 10416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "__int128" => "n", 10426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "unsigned __int128" => "o", 10436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "float" => "f", 104487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar "double" => "d", 104587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar "long double" => "e", 104687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar "__float80" => "e", 10476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "__float128" => "g", 1048d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor "..." => "z" 10496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines); 10506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 1051dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthmy %StdcxxMangling = ( 10526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "3std"=>"St", 1053b001de7458d17c17e6d8b8034c7cfcefd3b70c00Eli Friedman "3std9allocator"=>"Sa", 10544967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "3std12basic_string"=>"Sb", 10554967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "3std12basic_stringIcE"=>"Ss", 1056dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "3std13basic_istreamIcE"=>"Si", 1057dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "3std13basic_ostreamIcE"=>"So", 10584d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "3std14basic_iostreamIcE"=>"Sd" 10594d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky); 10604d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky 1061ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikiemy %ConstantSuffix = ( 1062ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie "unsigned int"=>"u", 1063a40bc724849f9cdc6a7706bc5d230685c3bdf63cDouglas Gregor "long"=>"l", 1064717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan "unsigned long"=>"ul", 10656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "long long"=>"ll", 10666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "unsigned long long"=>"ull" 10676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines); 10686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 10696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %ConstantSuffixR = 10706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesreverse(%ConstantSuffix); 10716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 10726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %OperatorMangling = ( 10734d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "~" => "co", 10744d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "=" => "aS", 10756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "|" => "or", 10766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "^" => "eo", 10776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "&" => "an",#ad (addr) 10786b3f1ebce775499aff03845193de78128671262fCraig Silverstein "==" => "eq", 10796b3f1ebce775499aff03845193de78128671262fCraig Silverstein "!" => "nt", 10806b3f1ebce775499aff03845193de78128671262fCraig Silverstein "!=" => "ne", 10816b3f1ebce775499aff03845193de78128671262fCraig Silverstein "<" => "lt", 10826b3f1ebce775499aff03845193de78128671262fCraig Silverstein "<=" => "le", 10836b3f1ebce775499aff03845193de78128671262fCraig Silverstein "<<" => "ls", 10846b3f1ebce775499aff03845193de78128671262fCraig Silverstein "<<=" => "lS", 10856b3f1ebce775499aff03845193de78128671262fCraig Silverstein ">" => "gt", 10866b3f1ebce775499aff03845193de78128671262fCraig Silverstein ">=" => "ge", 10876b3f1ebce775499aff03845193de78128671262fCraig Silverstein ">>" => "rs", 10886b3f1ebce775499aff03845193de78128671262fCraig Silverstein ">>=" => "rS", 10896b3f1ebce775499aff03845193de78128671262fCraig Silverstein "()" => "cl", 10906b3f1ebce775499aff03845193de78128671262fCraig Silverstein "%" => "rm", 10916b3f1ebce775499aff03845193de78128671262fCraig Silverstein "[]" => "ix", 10926b3f1ebce775499aff03845193de78128671262fCraig Silverstein "&&" => "aa", 10936b3f1ebce775499aff03845193de78128671262fCraig Silverstein "||" => "oo", 1094c34c2116346a29869b47b190f6dea589823d6947Craig Silverstein "*" => "ml",#de (deref) 10954d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "++" => "pp",# 10966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "--" => "mm",# 10974d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "new" => "nw", 10984d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "delete" => "dl", 1099717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan "new[]" => "na", 11006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "delete[]" => "da", 11016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "+=" => "pL", 11024d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "+" => "pl",#ps (pos) 11036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "-" => "mi",#ng (neg) 11046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "-=" => "mI", 11054d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "*=" => "mL", 11066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "/=" => "dV", 11076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "&=" => "aN", 11084d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "|=" => "oR", 11096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "%=" => "rM", 11106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "^=" => "eO", 11114d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "/" => "dv", 11126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "->*" => "pm", 11136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "->" => "pt",#rf (ref) 11144d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "," => "cm", 11154d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "?" => "qu", 11164d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "." => "dt", 11174d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "sizeof"=> "sz"#st 1118717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan); 11196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 11206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %Intrinsic_Keywords = map {$_=>1} ( 11216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "true", 11224d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "false", 11236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "_Bool", 11246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "_Complex", 1125651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "const", 11266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "int", 11276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "long", 112812df246d6dea2ee1f92c186f922f1afcf499647aReid Kleckner "void", 11296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "short", 1130cf4679e60a5c5fa13e4bfe69f8186658c828af49Craig Silverstein "float", 1131cf4679e60a5c5fa13e4bfe69f8186658c828af49Craig Silverstein "volatile", 1132cf4679e60a5c5fa13e4bfe69f8186658c828af49Craig Silverstein "restrict", 1133cf4679e60a5c5fa13e4bfe69f8186658c828af49Craig Silverstein "unsigned", 1134cf4679e60a5c5fa13e4bfe69f8186658c828af49Craig Silverstein "signed", 1135cf4679e60a5c5fa13e4bfe69f8186658c828af49Craig Silverstein "char", 1136717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan "double", 11376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "class", 11386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "struct", 11396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "union", 11404d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "enum" 1141717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan); 11426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 11436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %GlibcHeader = map {$_=>1} ( 11446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "aliases.h", 11454d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "argp.h", 1146717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan "argz.h", 11476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "assert.h", 11486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "cpio.h", 11496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "ctype.h", 11504d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "dirent.h", 1151717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan "envz.h", 11526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "errno.h", 11536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "error.h", 11546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "execinfo.h", 11554d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "fcntl.h", 11564d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "fstab.h", 11574d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "ftw.h", 1158717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan "glob.h", 11596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "grp.h", 11606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "iconv.h", 11616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "ifaddrs.h", 11626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "inttypes.h", 11634d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "langinfo.h", 11644d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "limits.h", 1165717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan "link.h", 11666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "locale.h", 11676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "malloc.h", 11684d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "math.h", 11694d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "mntent.h", 11704d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "monetary.h", 1171717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan "nl_types.h", 11726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "obstack.h", 11736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "printf.h", 11744d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "pwd.h", 11756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "regex.h", 11766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "sched.h", 11774d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "search.h", 1178536bab452fa38692834233187ed3d49b83722cb3Craig Silverstein "setjmp.h", 1179717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan "shadow.h", 11806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "signal.h", 11814d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "spawn.h", 11826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "stdarg.h", 1183536bab452fa38692834233187ed3d49b83722cb3Craig Silverstein "stdint.h", 11846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "stdio.h", 11856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "stdlib.h", 11866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "string.h", 11876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "tar.h", 11886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "termios.h", 11894d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "time.h", 11906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "ulimit.h", 1191536bab452fa38692834233187ed3d49b83722cb3Craig Silverstein "unistd.h", 11926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "utime.h", 11936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "wchar.h", 11946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "wctype.h", 1195176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines "wordexp.h" ); 1196176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 1197176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesmy %GlibcDir = map {$_=>1} ( 11986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "arpa", 11994d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "bits", 12006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "gnu", 12016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "netinet", 12024d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "net", 12036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "nfs", 12046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "rpc", 12054d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "sys", 1206717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan "linux" ); 12076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 12086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %LocalIncludes = map {$_=>1} ( 12094d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "/usr/local/include", 12104d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "/usr/local" ); 1211717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan 12126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %OS_AddPath=( 12136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines# These paths are needed if the tool cannot detect them automatically 12144d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "macos"=>{ 1215ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt "include"=>{ 12166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "/Library"=>1, 12176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "/Developer/usr/include"=>1 1218ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt }, 121934b41d939a1328f484511c6002ba2456db879a29Richard Smith "lib"=>{ 12206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "/Library"=>1, 12216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "/Developer/usr/lib"=>1 122234b41d939a1328f484511c6002ba2456db879a29Richard Smith }, 12236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "bin"=>{ 12246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "/Developer/usr/bin"=>1 12256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 12266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines }, 12276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "beos"=>{ 12284d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky # Haiku has GCC 2.95.3 by default 12294d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky # try to find GCC>=3.0 in /boot/develop/abi 1230717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan "include"=>{ 12316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "/boot/common"=>1, 12326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "/boot/develop"=>1}, 12336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "lib"=>{ 12346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "/boot/common/lib"=>1, 12356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "/boot/system/lib"=>1, 12364d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "/boot/apps"=>1}, 12376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "bin"=>{ 12384d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky "/boot/common/bin"=>1, 12396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "/boot/system/bin"=>1, 1240075f8f1b6bed4d1b224c74f87508534cc6392ce6Abramo Bagnara "/boot/develop/abi"=>1 12416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 12426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 12439d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall); 1244717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan 12456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %Slash_Type=( 12466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "default"=>"/", 12476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "windows"=>"\\" 12486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines); 12496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 12504d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewyckymy $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"}; 1251717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan 12526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines# Global Variables 12536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %COMMON_LANGUAGE=( 12544d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky 1 => "C", 1255717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan 2 => "C" ); 12566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 12576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy $MAX_COMMAND_LINE_ARGUMENTS = 4096; 12586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION); 1259ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie 12606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy $STDCXX_TESTING = 0; 12616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy $GLIBC_TESTING = 0; 12626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 12636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy $CheckHeadersOnly = $CheckHeadersOnly_Opt; 12644d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewyckymy $CheckObjectsOnly = $CheckObjectsOnly_Opt; 12656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy $TargetComponent; 12666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 12677536dd5e6c99584481b7dab68b7e7d8df9c54054Douglas Gregor# Set Target Component Name 12686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesif($TargetComponent_Opt) { 12694d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky $TargetComponent = lc($TargetComponent_Opt); 1270717cc00c16eabf0eefd3cc69394e97f7229af0c8Zhanyong Wan} 12716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hineselse 12726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines{ # default: library 12736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines # other components: header, system, ... 12746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $TargetComponent = "library"; 127587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar} 127687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 12776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy $TOP_REF = "<a style='font-size:11px;' href='#Top'>to the top</a>"; 12784d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky 12796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy $SystemRoot; 12806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 12814d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewyckymy $MAIN_CPP_DIR; 12826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %RESULT; 1283b001de7458d17c17e6d8b8034c7cfcefd3b70c00Eli Friedmanmy %LOG_PATH; 12844967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarmy %DEBUG_PATH; 12854967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarmy %Cache; 12864d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewyckymy %LibInfo; 12874d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewyckymy $COMPILE_ERRORS = 0; 1288dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthmy %CompilerOptions; 1289dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthmy %CheckedDyLib; 1290dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthmy $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup); 1291dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 1292dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth# Constants (#defines) 1293dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthmy %Constants; 1294dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthmy %SkipConstants; 12956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 12964d072932287eb074a4168804cac1acb18a51d5e8Craig Silverstein# Types 12970c05a1bae9e8a57f56663991d0442a69df34a003Zhanyong Wanmy %TypeInfo; 12980c05a1bae9e8a57f56663991d0442a69df34a003Zhanyong Wanmy %TemplateInstance; 12990c05a1bae9e8a57f56663991d0442a69df34a003Zhanyong Wanmy %TemplateDecl; 1300651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesmy %SkipTypes = ( 13016afcf8875d4e447645cd7bf3733dd8e2eb8455dcTareq A. Siraj "1"=>{}, 13026afcf8875d4e447645cd7bf3733dd8e2eb8455dcTareq A. Siraj "2"=>{} ); 1303651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesmy %CheckedTypes; 1304651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesmy %TName_Tid; 13050c05a1bae9e8a57f56663991d0442a69df34a003Zhanyong Wanmy %EnumMembName_Id; 13060c05a1bae9e8a57f56663991d0442a69df34a003Zhanyong Wanmy %NestedNameSpaces = ( 13070c05a1bae9e8a57f56663991d0442a69df34a003Zhanyong Wan "1"=>{}, 13080c05a1bae9e8a57f56663991d0442a69df34a003Zhanyong Wan "2"=>{} ); 13090c05a1bae9e8a57f56663991d0442a69df34a003Zhanyong Wanmy %UsedType; 1310dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthmy %VirtualTable; 13116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %VirtualTable_Model; 13126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %ClassVTable; 13136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %ClassVTable_Content; 13144967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarmy %VTableClass; 13154967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarmy %AllocableClass; 13164967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarmy %ClassMethods; 13174967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarmy %ClassNames; 13186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %Class_SubClasses; 13194967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarmy %OverriddenMethods; 13204967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarmy $MAX_ID = 0; 13214967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 13224967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar# Typedefs 13234967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarmy %Typedef_BaseName; 13246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %Typedef_Tr; 1325d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregormy %Typedef_Eq; 13266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %StdCxxTypedef; 1327d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregormy %MissedTypedef; 1328dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthmy %MissedBase; 13296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %MissedBase_R; 13306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 13316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines# Symbols 1332c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesmy %SymbolInfo; 1333c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesmy %tr_name; 1334c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesmy %mangled_name_gcc; 1335c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesmy %mangled_name; 1336c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesmy %SkipSymbols = ( 13374967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar "1"=>{}, 13386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "2"=>{} ); 1339d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregormy %SkipNameSpaces = ( 13406afcf8875d4e447645cd7bf3733dd8e2eb8455dcTareq A. Siraj "1"=>{}, 13416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "2"=>{} ); 13424967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarmy %AddNameSpaces = ( 13436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "1"=>{}, 13446afcf8875d4e447645cd7bf3733dd8e2eb8455dcTareq A. Siraj "2"=>{} ); 13456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %SymbolsList; 1346684aa73192d92850a926870be62a1787eb5b7ed9Michael Hanmy %SymbolsList_App; 13476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %CheckedSymbols; 13486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %Symbol_Library = ( 1349d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor "1"=>{}, 13506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "2"=>{} ); 135115de72cf580840c61e5704c2f8a2b56f9d0638e1Douglas Gregormy %Library_Symbol = ( 1352dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth "1"=>{}, 13536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "2"=>{} ); 13546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %DepSymbol_Library = ( 13556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "1"=>{}, 13566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "2"=>{} ); 13576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %DepLibrary_Symbol = ( 13586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "1"=>{}, 1359d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor "2"=>{} ); 1360dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthmy %MangledNames; 13616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %AddIntParams; 13626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %Interface_Impl; 13636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %GlobalDataObject; 13646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 13656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines# Headers 13666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %Include_Preamble; 13676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %Registered_Headers; 13686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %HeaderName_Paths; 13696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %Header_Dependency; 1370dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthmy %Include_Neighbors; 13716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %Include_Paths; 13726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %INC_PATH_AUTODETECT = ( 1373d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor "1"=>1, 1374af0f4d0b2e38c810effc8b024ad2fb6604eec5d3Francois Pichet "2"=>1 ); 13756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %Add_Include_Paths; 13766b02009359a462ffe633696a4441313b462e6566Nico Webermy %Skip_Include_Paths; 13776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %RegisteredDirs; 13786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %Header_ErrorRedirect; 13796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %Header_Includes; 13806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %Header_ShouldNotBeUsed; 13816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %RecursiveIncludes; 13826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %Header_Include_Prefix; 1383af0f4d0b2e38c810effc8b024ad2fb6604eec5d3Francois Pichetmy %SkipHeaders; 13846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %SkipHeadersList=( 1385db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "1"=>{}, 13866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "2"=>{} ); 13876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %SkipLibs; 1388db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewyckymy %Include_Order; 1389dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthmy %TUnit_NameSpaces; 13906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 13916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %C99Mode = ( 13926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "1"=>0, 1393db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky "2"=>0 ); 13946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %AutoPreambleMode = ( 13956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "1"=>0, 13966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "2"=>0 ); 13976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %MinGWMode = ( 13986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "1"=>0, 13996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "2"=>0 ); 1400db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky 14014967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar# Shared Objects 14024967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarmy %DyLib_DefaultPath; 14034967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarmy %InputObject_Paths; 14044967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarmy %RegisteredObjDirs; 14053ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar 14063ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar# System Objects 1407dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthmy %SystemObjects; 140887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarmy %DefaultLibPaths; 140987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 14106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines# System Headers 14116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %SystemHeaders; 14124967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarmy %DefaultCppPaths; 1413ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattnermy %DefaultGccPaths; 1414ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikiemy %DefaultIncPaths; 14156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %DefaultCppHeader; 14166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %DefaultGccHeader; 1417ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikiemy %UserIncPath; 14186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 14196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines# Merging 14206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %CompleteSignature; 14216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy $Version; 14226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %AddedInt; 14236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %RemovedInt; 1424d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregormy %AddedInt_Virt; 14256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %RemovedInt_Virt; 14266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %VirtualReplacement; 1427db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewyckymy %ChangedTypedef; 14286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %CompatRules; 142987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarmy %IncompleteRules; 143087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarmy %UnknownRules; 143187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarmy %VTableChanged_M; 143287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarmy %ExtendedSymbols; 143387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarmy %ReturnedClass; 143487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarmy %ParamClass; 1435dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthmy %SourceAlternative; 14366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %SourceAlternative_B; 14376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %SourceReplacement; 1438dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 14396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines# OS Compliance 14406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy %TargetLibs; 1441dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthmy %TargetHeaders; 14426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 144387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# OS Specifics 144487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarmy $OStarget = $OSgroup; 144587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarmy %TargetTools; 144687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 144787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# Compliance Report 144887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarmy %Type_MaxSeverity; 144987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 145087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# Recursion locks 145187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarmy @RecurLib; 145287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarmy @RecurSymlink; 1453dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthmy @RecurTypes; 14546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy @RecurInclude; 14556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy @RecurConstant; 1456dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 1457dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth# System 1458651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesmy %SystemPaths; 1459651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesmy %DefaultBinPaths; 1460651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesmy $GCC_PATH; 14614967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 14624967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar# Symbols versioning 1463651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesmy %SymVer = ( 1464651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "1"=>{}, 1465651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "2"=>{} ); 1466651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 14674967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar# Problem descriptions 1468651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesmy %CompatProblems; 1469dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthmy %ProblemsWithConstants; 147087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarmy %ImplProblems; 147187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarmy %TotalAffected; 147287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 147387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# Reports 147487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarmy $ContentID = 1; 147587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarmy $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n"; 147687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarmy $ContentSpanStart_Affected = "<span class=\"section_affected\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n"; 147787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarmy $ContentSpanStart_Info = "<span class=\"section_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n"; 147887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarmy $ContentSpanEnd = "</span>\n"; 1479c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesmy $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n"; 1480c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesmy $ContentDivEnd = "</div>\n"; 1481c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesmy $Content_Counter = 0; 1482c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1483c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines# XML Dump 14844967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarmy $TAG_ID = 0; 1485c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesmy $INDENT = " "; 1486dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 1487dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth# Modes 14886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy $JoinReport = 1; 14896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesmy $DoubleReport = 0; 14906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 1491dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthsub get_Modules() 1492dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth{ 14936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my $TOOL_DIR = get_dirname($0); 14946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if(not $TOOL_DIR) 1495dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth { # patch for MS Windows 14966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $TOOL_DIR = "."; 1497d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor } 14984967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar my @SEARCH_DIRS = ( 14994967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar # tool's directory 1500c640058aa7f224a71ce3b1d2601d84e1b57f82d3Alexey Bataev abs_path($TOOL_DIR), 15016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines # relative path to modules 15026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines abs_path($TOOL_DIR)."/../share/abi-compliance-checker", 15036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines # system directory 15046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "ACC_MODULES_INSTALL_PATH" 1505c640058aa7f224a71ce3b1d2601d84e1b57f82d3Alexey Bataev ); 15064967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar foreach my $DIR (@SEARCH_DIRS) 15074967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar { 15084967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if(not is_abs($DIR)) 15094967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar { # relative path 15104967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $DIR = abs_path($TOOL_DIR)."/".$DIR; 15114967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 15124967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if(-d $DIR."/modules") { 15134967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return $DIR."/modules"; 15144967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 15154967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 1516dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth exitStatus("Module_Error", "can't find modules"); 15176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 1518dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 1519dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthsub loadModule($) 1520dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth{ 1521dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth my $Name = $_[0]; 1522dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth my $Path = $MODULES_DIR."/Internals/$Name.pm"; 1523dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth if(not -f $Path) { 1524dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth exitStatus("Module_Error", "can't access \'$Path\'"); 1525dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth } 1526e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth require $Path; 1527db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky} 1528d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor 15296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinessub showPos($) 1530651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines{ 1531651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines my $Number = $_[0]; 1532651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if(not $Number) { 1533651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines $Number = 1; 1534651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1535651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines else { 1536651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines $Number = int($Number)+1; 1537651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 15386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($Number>3) { 15396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return $Number."th"; 1540651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1541651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines elsif($Number==1) { 1542651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return "1st"; 1543651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1544651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines elsif($Number==2) { 1545651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return "2nd"; 1546651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1547651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines elsif($Number==3) { 1548651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return "3rd"; 1549651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1550651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines else { 1551651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return $Number; 1552651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1553651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1554651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1555651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinessub search_Tools($) 1556651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines{ 1557651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines my $Name = $_[0]; 1558651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return "" if(not $Name); 1559651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if(my @Paths = keys(%TargetTools)) 15606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 1561651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines foreach my $Path (@Paths) 1562651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines { 1563651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if(-f joinPath($Path, $Name)) { 1564651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return joinPath($Path, $Name); 15656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 15666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($CrossPrefix) 1567651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines { # user-defined prefix (arm-none-symbianelf, ...) 1568651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines my $Candidate = joinPath($Path, $CrossPrefix."-".$Name); 1569651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if(-f $Candidate) { 1570651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return $Candidate; 1571651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1572651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1573651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1574651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1575651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines else { 1576651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return ""; 1577651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1578651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1579651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1580651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinessub synch_Cmd($) 1581ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo{ 1582ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo my $Name = $_[0]; 1583760c8af273d9871d063250ae626fb6df94c121f2John McCall if(not $GCC_PATH) 1584760c8af273d9871d063250ae626fb6df94c121f2John McCall { # GCC was not found yet 15856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return ""; 15868d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo } 1587a313b2fbba86c901e58dc58df036e731f24fdaeeRichard Smith my $Candidate = $GCC_PATH; 1588651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) { 1589651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return $Candidate; 1590651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1591651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return ""; 1592651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1593651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1594651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinessub get_CmdPath($) 1595651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines{ 1596651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines my $Name = $_[0]; 1597651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return "" if(not $Name); 1598651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if(defined $Cache{"get_CmdPath"}{$Name}) { 1599651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return $Cache{"get_CmdPath"}{$Name}; 1600651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1601651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines my %BinUtils = map {$_=>1} ( 1602651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "c++filt", 1603651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "objdump", 1604651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "readelf" 1605651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ); 1606651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if($BinUtils{$Name} and $GCC_PATH) 1607760c8af273d9871d063250ae626fb6df94c121f2John McCall { 1608760c8af273d9871d063250ae626fb6df94c121f2John McCall if(my $Dir = get_dirname($GCC_PATH)) { 1609536bab452fa38692834233187ed3d49b83722cb3Craig Silverstein $TargetTools{$Dir}=1; 1610760c8af273d9871d063250ae626fb6df94c121f2John McCall } 1611760c8af273d9871d063250ae626fb6df94c121f2John McCall } 1612536bab452fa38692834233187ed3d49b83722cb3Craig Silverstein my $Path = search_Tools($Name); 16138d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo if(not $Path and $OSgroup eq "windows") { 16148d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo $Path = search_Tools($Name.".exe"); 16156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 16166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if(not $Path and $BinUtils{$Name}) 1617c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines { 1618c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if($CrossPrefix) 1619c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines { # user-defined prefix 1620c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines $Path = search_Cmd($CrossPrefix."-".$Name); 1621c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1622c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1623c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if(not $Path and $BinUtils{$Name}) 1624c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines { 1625c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if(my $Candidate = synch_Cmd($Name)) 1626c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines { # synch with GCC 1627c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if($Candidate=~/[\/\\]/) 1628c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines { # command path 1629c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if(-f $Candidate) { 1630c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines $Path = $Candidate; 1631c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1632c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 16338d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo elsif($Candidate = search_Cmd($Candidate)) 16348d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo { # command name 16358d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo $Path = $Candidate; 16368d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo } 16378d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo } 1638dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth } 1639dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth if(not $Path) { 16406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Path = search_Cmd($Name); 16416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 16426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if(not $Path and $OSgroup eq "windows") 16436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { # search for *.exe file 16446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Path=search_Cmd($Name.".exe"); 16456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 16466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($Path=~/\s/) { 16476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Path = "\"".$Path."\""; 1648dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth } 164987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return ($Cache{"get_CmdPath"}{$Name}=$Path); 165087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar} 165187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 165287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarsub search_Cmd($) 1653dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth{ 16546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my $Name = $_[0]; 16556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return "" if(not $Name); 16566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if(defined $Cache{"search_Cmd"}{$Name}) { 16576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return $Cache{"search_Cmd"}{$Name}; 16586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 16596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if(my $DefaultPath = get_CmdPath_Default($Name)) { 1660dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth return ($Cache{"search_Cmd"}{$Name} = $DefaultPath); 1661dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth } 16626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines foreach my $Path (sort {length($a)<=>length($b)} keys(%{$SystemPaths{"bin"}})) 16636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 16646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my $CmdPath = joinPath($Path,$Name); 16656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if(-f $CmdPath) 16666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 1667dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth if($Name=~/gcc/) { 1668162e1c1b487352434552147967c3dd296ebee2f7Richard Smith next if(not check_gcc($CmdPath, "3")); 16696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 16706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return ($Cache{"search_Cmd"}{$Name} = $CmdPath); 16716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 16726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 16736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return ($Cache{"search_Cmd"}{$Name} = ""); 1674162e1c1b487352434552147967c3dd296ebee2f7Richard Smith} 16753e4c6c4c79a03f5cb0c4671d7c282d623c6dc35eRichard Smith 16766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinessub get_CmdPath_Default($) 16776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines{ # search in PATH 16786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return "" if(not $_[0]); 16793e4c6c4c79a03f5cb0c4671d7c282d623c6dc35eRichard Smith if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) { 1680dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth return $Cache{"get_CmdPath_Default"}{$_[0]}; 16816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 16826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0])); 16836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 16846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 16856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinessub get_CmdPath_Default_I($) 16866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines{ # search in PATH 16876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my $Name = $_[0]; 1688d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor if($Name=~/find/) 1689dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth { # special case: search for "find" utility 16906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) { 16916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return "find"; 1692dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth } 16936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 16946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines elsif($Name=~/gcc/) { 16956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return check_gcc($Name, "3"); 16966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 1697dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth if(check_command($Name)) { 1698dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth return $Name; 16996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 17006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($OSgroup eq "windows") 1701dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth { 1702dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth if(`$Name /? 2>\"$TMP_DIR/null\"`) { 1703a0e27f00158c9306d53b0003b94182e415380ea9Francois Pichet return $Name; 17043812999df1a50e0804985c8845fcfa3fd7ffe14cCraig Silverstein } 1705e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth } 1706db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky if($Name!~/which/) 1707d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor { 17086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if(my $WhichCmd = get_CmdPath("which")) 17096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 1710e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth if(`$WhichCmd $Name 2>\"$TMP_DIR/null\"`) { 1711e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth return $Name; 17129f99d06e0d22380b9d1f0609a083dbfbd8b37c10Manuel Klimek } 1713651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1714651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1715dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth foreach my $Path (sort {length($a)<=>length($b)} keys(%DefaultBinPaths)) 1716dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth { 1717dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth if(-f $Path."/".$Name) { 1718dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth return joinPath($Path,$Name); 1719e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth } 1720db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky } 1721d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor return ""; 17226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 17236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 17246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinessub clean_path($) 17256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines{ 17266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my $Path = $_[0]; 17276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Path=~s/[\/\\]+\Z//g; 17286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return $Path; 17296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 17306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 17316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinessub classifyPath($) 17326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines{ 17336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my $Path = $_[0]; 17346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($Path=~/[\*\[]/) 17356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { # wildcard 17366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Path=~s/\*/.*/g; 17376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Path=~s/\\/\\\\/g; 17386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return ($Path, "Pattern"); 17396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 17406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines elsif($Path=~/[\/\\]/) 17416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { # directory or relative path 17426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Path=~s/[\/\\]+\Z//g; 17436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return (path_format($Path, $OSgroup), "Path"); 17446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 17456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines else { 17468d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo return ($Path, "Name"); 17478d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo } 17488d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo} 17498d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo 1750d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregorsub readDescriptor($$) 1751dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth{ 1752dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth my ($LibVersion, $Content) = @_; 1753dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth return if(not $LibVersion); 1754dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\""; 17554d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky if(not $Content) { 1756dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth exitStatus("Error", "$DName is empty"); 1757e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth } 1758db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky if($Content!~/\</) { 1759db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky exitStatus("Error", "incorrect descriptor (see -d1 option)"); 17606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 17616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Content=~s/\/\*(.|\n)+?\*\///g; 1762c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines $Content=~s/<\!--(.|\n)+?-->//g; 1763c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version"); 1764c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if($TargetVersion{$LibVersion}) { 1765c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion}; 1766c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1767c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if(not $Descriptor{$LibVersion}{"Version"}) { 1768c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines exitStatus("Error", "version in the $DName is not specified (<version> section)"); 1769c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1770c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if($Content=~/{RELPATH}/) 1771c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines { 1772c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if(my $RelDir = $RelativeDirectory{$LibVersion}) { 1773c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines $Content =~ s/{RELPATH}/$RelDir/g; 1774c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 1775c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else 1776c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines { 1777c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion"; 1778c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro"); 1779c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 17808d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo } 17818d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo 17828d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo if(not $CheckObjectsOnly_Opt) 17838d2a5ea694ed0002b45deb2bd35db451b16a07d6Larisse Voufo { 1784dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth my $DHeaders = parseTag(\$Content, "headers"); 17856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if(not $DHeaders) { 1786dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth exitStatus("Error", "header files in the $DName are not specified (<headers> section)"); 1787dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth } 17886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines elsif(lc($DHeaders) ne "none") 17896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { # append the descriptor headers list 17906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($Descriptor{$LibVersion}{"Headers"}) 17916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { # multiple descriptors 17926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders; 1793dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth } 179487c2e121cf0522fc266efe2922b58091cd2e0182Francois Pichet else { 179587c2e121cf0522fc266efe2922b58091cd2e0182Francois Pichet $Descriptor{$LibVersion}{"Headers"} = $DHeaders; 17966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 1797dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth foreach my $Path (split(/\s*\n\s*/, $DHeaders)) 17983812999df1a50e0804985c8845fcfa3fd7ffe14cCraig Silverstein { 1799dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth if(not -e $Path) { 18004d2229c7a9514ee2b960aa9e59f7259cebbaa421Nick Lewycky exitStatus("Access_Error", "can't access \'$Path\'"); 1801406f98f6a5a7bde5707085af8d66204e7e76af45Douglas Gregor } 1802406f98f6a5a7bde5707085af8d66204e7e76af45Douglas Gregor } 1803e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth } 1804db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky } 1805c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall if(not $CheckHeadersOnly_Opt) 18066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 180776da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall my $DObjects = parseTag(\$Content, "libs"); 1808dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth if(not $DObjects) { 18096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)"); 18106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 18116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines elsif(lc($DObjects) ne "none") 18126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { # append the descriptor libraries list 18136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($Descriptor{$LibVersion}{"Libs"}) 18146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { # multiple descriptors 1815dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects; 1816dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth } 18176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines else { 18186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Descriptor{$LibVersion}{"Libs"} .= $DObjects; 18196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 18206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines foreach my $Path (split(/\s*\n\s*/, $DObjects)) 18216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 1822dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth if(not -e $Path) { 1823dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth exitStatus("Access_Error", "can't access \'$Path\'"); 18246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 18256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 18266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 18276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 18286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers"))) 1829dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth { 18306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Path = clean_path($Path); 1831dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth if(not -d $Path) { 18323812999df1a50e0804985c8845fcfa3fd7ffe14cCraig Silverstein exitStatus("Access_Error", "can't access directory \'$Path\'"); 183365019acfc46ffb191fac4e781ac0c4b8d0c8434eDouglas Gregor } 18340c05a1bae9e8a57f56663991d0442a69df34a003Zhanyong Wan $Path = path_format($Path, $OSgroup); 1835cf4679e60a5c5fa13e4bfe69f8186658c828af49Craig Silverstein $SystemPaths{"include"}{$Path}=1; 1836536bab452fa38692834233187ed3d49b83722cb3Craig Silverstein } 1837536bab452fa38692834233187ed3d49b83722cb3Craig Silverstein foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs"))) 1838536bab452fa38692834233187ed3d49b83722cb3Craig Silverstein { 1839536bab452fa38692834233187ed3d49b83722cb3Craig Silverstein $Path = clean_path($Path); 1840cf4679e60a5c5fa13e4bfe69f8186658c828af49Craig Silverstein if(not -d $Path) { 18416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines exitStatus("Access_Error", "can't access directory \'$Path\'"); 1842cf4679e60a5c5fa13e4bfe69f8186658c828af49Craig Silverstein } 1843cf4679e60a5c5fa13e4bfe69f8186658c828af49Craig Silverstein $Path = path_format($Path, $OSgroup); 184444db3251aec7c0e6edaf1c70d7d53a272686791aNick Lewycky $SystemPaths{"lib"}{$Path}=1; 184544db3251aec7c0e6edaf1c70d7d53a272686791aNick Lewycky } 184671a7605977113c795edd44fcbd2302ad49506653Argyrios Kyrtzidis foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools"))) 18476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 184871a7605977113c795edd44fcbd2302ad49506653Argyrios Kyrtzidis $Path=clean_path($Path); 184971a7605977113c795edd44fcbd2302ad49506653Argyrios Kyrtzidis if(not -d $Path) { 185044db3251aec7c0e6edaf1c70d7d53a272686791aNick Lewycky exitStatus("Access_Error", "can't access directory \'$Path\'"); 1851cf4679e60a5c5fa13e4bfe69f8186658c828af49Craig Silverstein } 1852cf4679e60a5c5fa13e4bfe69f8186658c828af49Craig Silverstein $Path = path_format($Path, $OSgroup); 1853cf4679e60a5c5fa13e4bfe69f8186658c828af49Craig Silverstein $SystemPaths{"bin"}{$Path}=1; 1854536bab452fa38692834233187ed3d49b83722cb3Craig Silverstein $TargetTools{$Path}=1; 1855536bab452fa38692834233187ed3d49b83722cb3Craig Silverstein } 1856536bab452fa38692834233187ed3d49b83722cb3Craig Silverstein if(my $Prefix = parseTag(\$Content, "cross_prefix")) { 1857536bab452fa38692834233187ed3d49b83722cb3Craig Silverstein $CrossPrefix = $Prefix; 18588ddfb0b72d0e439d01759c1bc7a79ba73dd2830cManuel Klimek } 1859c28a335184207a47f34eb9d1707dc8d7c6c7b8b6Richard Smith foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths"))) 18604b6730d40e7c603bd0e223d3fa8b56a0c88a324aMichael Han { 18614b6730d40e7c603bd0e223d3fa8b56a0c88a324aMichael Han $Path=clean_path($Path); 18624b6730d40e7c603bd0e223d3fa8b56a0c88a324aMichael Han if(not -d $Path) { 18634b6730d40e7c603bd0e223d3fa8b56a0c88a324aMichael Han exitStatus("Access_Error", "can't access directory \'$Path\'"); 18644b6730d40e7c603bd0e223d3fa8b56a0c88a324aMichael Han } 18654967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $Path = path_format($Path, $OSgroup); 18664967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $Descriptor{$LibVersion}{"IncludePaths"}{$Path} = 1; 18674967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 1868c28a335184207a47f34eb9d1707dc8d7c6c7b8b6Richard Smith foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths"))) 1869cf4679e60a5c5fa13e4bfe69f8186658c828af49Craig Silverstein { 18706beaf938c0a2587ac4b2b60a51fbb9a80f72b766Zhanyong Wan $Path=clean_path($Path); 18716beaf938c0a2587ac4b2b60a51fbb9a80f72b766Zhanyong Wan if(not -d $Path) { 1872651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines exitStatus("Access_Error", "can't access directory \'$Path\'"); 1873651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 18746beaf938c0a2587ac4b2b60a51fbb9a80f72b766Zhanyong Wan $Path = path_format($Path, $OSgroup); 18756beaf938c0a2587ac4b2b60a51fbb9a80f72b766Zhanyong Wan $Descriptor{$LibVersion}{"AddIncludePaths"}{$Path} = 1; 18766beaf938c0a2587ac4b2b60a51fbb9a80f72b766Zhanyong Wan } 1877dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths"))) 18786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 1879dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth # skip some auto-generated include paths 1880e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth $Skip_Include_Paths{$LibVersion}{path_format($Path)}=1; 1881db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky } 1882d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including"))) 1883dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth { 18846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines # skip direct including of some headers 18856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $SkipHeadersList{$LibVersion}{$Path} = 2; 18864967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar my ($CPath, $Type) = classifyPath($Path); 18874967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2; 18886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 1889facfc77487a890bfb7b5eee7e21cd2b395a9faafChandler Carruth $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options"); 1890dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"})) { 18916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $CompilerOptions{$LibVersion} .= " ".$Option; 18926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 18934967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers"); 18944967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"})) 18956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 1896facfc77487a890bfb7b5eee7e21cd2b395a9faafChandler Carruth $SkipHeadersList{$LibVersion}{$Path} = 1; 1897dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth my ($CPath, $Type) = classifyPath($Path); 18986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1; 18996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 19004967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs"); 19014967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"})) 19026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 1903facfc77487a890bfb7b5eee7e21cd2b395a9faafChandler Carruth my ($CPath, $Type) = classifyPath($Path); 19040c05a1bae9e8a57f56663991d0442a69df34a003Zhanyong Wan $SkipLibs{$LibVersion}{$Type}{$CPath} = 1; 19050c05a1bae9e8a57f56663991d0442a69df34a003Zhanyong Wan } 1906dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth if(my $DDefines = parseTag(\$Content, "defines")) 19076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 19086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($Descriptor{$LibVersion}{"Defines"}) 19094967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar { # multiple descriptors 19104967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines; 19116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 1912d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor else { 1913dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth $Descriptor{$LibVersion}{"Defines"} = $DDefines; 19146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 19156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 19164967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order"))) 19174967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar { 19186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($Order=~/\A(.+):(.+)\Z/) { 1919dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth $Include_Order{$LibVersion}{$1} = $2; 19206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 1921dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth } 19226c321e35008f2c99eeb1409b43859a04c48e5ce5Chandler Carruth foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")), 1923c874ca1c7378d62aff008d74cf744636730f2db4Argyrios Kyrtzidis split(/\s*\n\s*/, parseTag(\$Content, "skip_types"))) 192452ec0c0357ce970ca52a27c1086626450f0967e7Daniel Jasper { # opaque_types renamed to skip_types (1.23.4) 19257349cce2b303c8cc1e00c3aa7192513d6ca5004fDaniel Jasper $SkipTypes{$LibVersion}{$Type_Name} = 1; 1926c874ca1c7378d62aff008d74cf744636730f2db4Argyrios Kyrtzidis } 1927e3e210c3aa3c1b289eee669a1d235fc16df384a0Chandler Carruth foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")), 1928db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols"))) 1929db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky { # skip_interfaces renamed to skip_symbols (1.22.1) 19306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $SkipSymbols{$LibVersion}{$Symbol} = 1; 1931db3f847cb883fdb19d79c7223fa032e7266c0ee5Nick Lewycky } 19326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) { 1933facfc77487a890bfb7b5eee7e21cd2b395a9faafChandler Carruth $SkipNameSpaces{$LibVersion}{$NameSpace} = 1; 1934dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth } 19356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) { 19366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $AddNameSpaces{$LibVersion}{$NameSpace} = 1; 19376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 19386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) { 19396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $SkipConstants{$LibVersion}{$Constant} = 1; 1940facfc77487a890bfb7b5eee7e21cd2b395a9faafChandler Carruth } 1941dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth if(my $DIncPreamble = parseTag(\$Content, "include_preamble")) 19426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 1943be9aa9614f0f15f2182c9ac5c571a868263131adCraig Silverstein if($Descriptor{$LibVersion}{"IncludePreamble"}) 19446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { # multiple descriptors 19456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble; 19466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 1947dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth else { 19486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble; 19496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 19506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 19516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 1952facfc77487a890bfb7b5eee7e21cd2b395a9faafChandler Carruth 1953dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthsub parseTag($$) 1954facfc77487a890bfb7b5eee7e21cd2b395a9faafChandler Carruth{ 1955dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth my ($CodeRef, $Tag) = @_; 1956dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth return "" if(not $CodeRef or not ${$CodeRef} or not $Tag); 1957dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth if(${$CodeRef}=~s/\<\Q$Tag\E\>((.|\n)+?)\<\/\Q$Tag\E\>//) 19587502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall { 19597502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall my $Content = $1; 19607502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall $Content=~s/(\A\s+|\s+\Z)//g; 19617502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall return $Content; 19627502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall } 1963dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth else { 1964dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth return ""; 19656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 19666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 196787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 196887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarsub addTag(@) 19694967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar{ 19704967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar my $Tag = shift(@_); 19714967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar my $Val = shift(@_); 19724967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar my @Ext = @_; 19736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my $Content = openTag($Tag, @Ext); 19744967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar chomp($Content); 19754967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $Content .= xmlSpecChars($Val); 19764967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $Content .= "</$Tag>\n"; 19774967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $TAG_ID-=1; 19786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 19794967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return $Content; 19804967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar} 19814967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 19826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinessub openTag(@) 1983facfc77487a890bfb7b5eee7e21cd2b395a9faafChandler Carruth{ 1984df5faf5e7ae6823d0af0b801c4ac26d47f2cee97Chad Rosier my $Tag = shift(@_); 198587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar my @Ext = @_; 19866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my $Content = ""; 198787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar foreach (1 .. $TAG_ID) { 19886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Content .= $INDENT; 19896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 199087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $TAG_ID+=1; 19916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if(@Ext) 19926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 199387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $Content .= "<".$Tag; 19946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my $P = 0; 19956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines while($P<=$#Ext-1) 19966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 1997facfc77487a890bfb7b5eee7e21cd2b395a9faafChandler Carruth $Content .= " ".$Ext[$P]; 19986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Content .= "=\"".xmlSpecChars($Ext[$P+1])."\""; 19996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $P+=2; 20006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 20016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Content .= ">\n"; 20026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 20038cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier else { 2004dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth $Content .= "<".$Tag.">\n"; 20056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 20066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return $Content; 20076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 2008dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 2009be9aa9614f0f15f2182c9ac5c571a868263131adCraig Silversteinsub closeTag($) 20106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines{ 20116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my $Tag = $_[0]; 20126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my $Content = ""; 20136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $TAG_ID-=1; 20146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines foreach (1 .. $TAG_ID) { 20156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Content .= $INDENT; 20166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 20176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Content .= "</".$Tag.">\n"; 20184967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return $Content; 20196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 2020dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 2021dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthsub checkTags() 2022dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth{ 20236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($TAG_ID!=0) { 20246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines printMsg("WARNING", "the number of opened tags is not equal to number of closed tags"); 20256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 20266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 20276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 20286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinessub getInfo($) 20296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines{ 20306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my $DumpPath = $_[0]; 20316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return if(not $DumpPath or not -f $DumpPath); 20326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 20336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines readTUDump($DumpPath); 20346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 20356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines # processing info 20366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines setTemplateParams_All(); 20376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines getTypeInfo_All(); 20386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines simplifyNames(); 20396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines getSymbolInfo_All(); 20406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines getVarInfo_All(); 20416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 20426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines # clean memory 20436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines %LibInfo = (); 204452ec0c0357ce970ca52a27c1086626450f0967e7Daniel Jasper %TemplateInstance = (); 20457349cce2b303c8cc1e00c3aa7192513d6ca5004fDaniel Jasper %MangledNames = (); 204687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar %TemplateDecl = (); 204787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar %StdCxxTypedef = (); 204887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar %MissedTypedef = (); 204952ec0c0357ce970ca52a27c1086626450f0967e7Daniel Jasper %Typedef_Tr = (); 20504967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar %Typedef_Eq = (); 205152ec0c0357ce970ca52a27c1086626450f0967e7Daniel Jasper 205252ec0c0357ce970ca52a27c1086626450f0967e7Daniel Jasper # clean cache 2053ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie delete($Cache{"getTypeAttr"}); 20546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines delete($Cache{"getTypeDeclId"}); 20556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 2056ba0513de93d2fab6db5ab30b6927209fcc883078Douglas Gregor # remove unused types 20576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($BinaryOnly and not $ExtendedCheck) 20586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { # --binary 20596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines removeUnused($Version, "All"); 2060dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth } 2061dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth else { 20626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines removeUnused($Version, "Derived"); 20636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 20646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 20656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($Debug) { 20666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines # debugMangling($Version); 20676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 20686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 2069dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 2070dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthsub readTUDump($) 20716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines{ 20726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my $DumpPath = $_[0]; 20736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 20746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines open(TU_DUMP, $DumpPath); 20756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines local $/ = undef; 2076dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth my $Content = <TU_DUMP>; 2077dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth close(TU_DUMP); 20786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 20796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines unlink($DumpPath); 20806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 20814967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $Content=~s/\n[ ]+/ /g; 20824967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar my @Lines = split("\n", $Content); 20836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 20846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines # clean memory 2085dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth undef $Content; 2086dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 20876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $MAX_ID = $#Lines+1; 20886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 20896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines foreach (0 .. $#Lines) 20906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 20916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i) 2092facfc77487a890bfb7b5eee7e21cd2b395a9faafChandler Carruth { # get a number and attributes of a node 20936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines next if(not $NodeType{$2}); 20946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $LibInfo{$Version}{"info_type"}{$1}=$2; 20956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $LibInfo{$Version}{"info"}{$1}=$3; 20966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 20976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 2098facfc77487a890bfb7b5eee7e21cd2b395a9faafChandler Carruth # clean memory 2099dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth delete($Lines[$_]); 21006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 21016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 2102dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth # clean memory 2103dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth undef @Lines; 21046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 21056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 2106dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthsub simplifyNames() 2107dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth{ 21086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines foreach my $Base (keys(%{$Typedef_Tr{$Version}})) 21096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 2110dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth my @Translations = keys(%{$Typedef_Tr{$Version}{$Base}}); 2111dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth if($#Translations==0 and length($Translations[0])<=length($Base)) { 21126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Typedef_Eq{$Version}{$Base} = $Translations[0]; 21136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 2114dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth } 2115dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth foreach my $TypeId (keys(%{$TypeInfo{$Version}})) 21166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 21176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"}; 2118dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth if(not $TypeName) { 2119dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth next; 21206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 21216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines next if(index($TypeName,"<")==-1);# template instances only 2122dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth if($TypeName=~/>(::\w+)+\Z/) 21236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { # skip unused types 212487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar next; 212587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar }; 212687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar foreach my $Base (sort {length($b)<=>length($a)} 21274967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}})) 21284967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar { 21294967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar next if(not $Base); 21304967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar next if(index($TypeName,$Base)==-1); 21314967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar next if(length($TypeName) - length($Base) <= 3); 21320e2c34f92f00628d48968dfea096d36381f494cbStephen Hines my $Typedef = $Typedef_Eq{$Version}{$Base}; 213387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g; 213487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g; 21350e2c34f92f00628d48968dfea096d36381f494cbStephen Hines if(defined $TypeInfo{$Version}{$TypeId}{"TParam"}) 2136ea245e0ba48caf7e7acf870880c030d7ddc76667Craig Silverstein { 2137ea245e0ba48caf7e7acf870880c030d7ddc76667Craig Silverstein foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}})) 2138ea245e0ba48caf7e7acf870880c030d7ddc76667Craig Silverstein { 2139ea245e0ba48caf7e7acf870880c030d7ddc76667Craig Silverstein my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"}; 214087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g; 214187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName); 214287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 214387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 214487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 214587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $TypeName = formatName($TypeName); 214687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName; 214787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $TName_Tid{$Version}{$TypeName} = $TypeId; 214887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 214987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar} 215087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 21514967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarsub setTemplateParams_All() 215287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar{ 215387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar foreach (keys(%{$LibInfo{$Version}{"info"}})) 2154f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne { 2155f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") { 2156f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne setTemplateParams($_); 215787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 215886b32fd702d794bb655c59a1238bf7422869f506Ted Kremenek } 2159f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne} 2160f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne 2161f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbournesub setTemplateParams($) 216287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar{ 2163f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne if(my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 21644967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar { 216587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /) 2166f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne { 216787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar my $TmplInst_Id = $2; 21684b9c2d235fb9449e249d74f48ecfec601650de93John McCall setTemplateInstParams($TmplInst_Id); 216987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar while($TmplInst_Id = getNextElem($TmplInst_Id)) { 217087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar setTemplateInstParams($TmplInst_Id); 21716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 21726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 21736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 21744b9c2d235fb9449e249d74f48ecfec601650de93John McCall if(my $TypeId = getTreeAttr_Type($_[0])) 21754b9c2d235fb9449e249d74f48ecfec601650de93John McCall { 21764b9c2d235fb9449e249d74f48ecfec601650de93John McCall if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId}) 217787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar { 21784b9c2d235fb9449e249d74f48ecfec601650de93John McCall if($IType eq "record_type") { 21794967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $TemplateDecl{$Version}{$TypeId}=1; 218087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 21814b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 2182ed8abf18329df67b0abcbb3a10458bd8c1d2a595Douglas Gregor } 21836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 21846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 21856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinessub setTemplateInstParams($) 21866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines{ 2187ea245e0ba48caf7e7acf870880c030d7ddc76667Craig Silverstein if(my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 2188ea245e0ba48caf7e7acf870880c030d7ddc76667Craig Silverstein { 21891bb2a93ab7b1499dda6f6b58865bd0dce1864228Douglas Gregor my ($Params_InfoId, $ElemId) = (); 21901bb2a93ab7b1499dda6f6b58865bd0dce1864228Douglas Gregor if($Info=~/purp[ ]*:[ ]*@(\d+) /) { 21916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Params_InfoId = $1; 2192ea245e0ba48caf7e7acf870880c030d7ddc76667Craig Silverstein } 2193cf4679e60a5c5fa13e4bfe69f8186658c828af49Craig Silverstein if($Info=~/valu[ ]*:[ ]*@(\d+) /) { 21946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $ElemId = $1; 21956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 21966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($Params_InfoId and $ElemId) 21976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 21986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId}; 21996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /) 2200cf4679e60a5c5fa13e4bfe69f8186658c828af49Craig Silverstein { 2201f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne my ($PPos, $PTypeId) = ($1, $2); 22026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId}) 22036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 22046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($PType eq "template_type_parm") 22056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 22066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $TemplateDecl{$Version}{$ElemId}=1; 2207cf4679e60a5c5fa13e4bfe69f8186658c828af49Craig Silverstein return; 220827de0f2cb3e8c26c37f31e61929b0e442c809ca5Craig Silverstein } 22096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 22106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl") 22116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { # functions 22126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId; 22136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 221401b7c3028da5bbcb9f8e52ba67e4613070de0e60Francois Pichet else 221576da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall { # types 221676da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId; 221776da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall } 221876da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall } 221987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 222087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 222101b7c3028da5bbcb9f8e52ba67e4613070de0e60Francois Pichet} 22226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 22236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinessub getTypeDeclId($) 22246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines{ 22256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($_[0]) 22266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 222727de0f2cb3e8c26c37f31e61929b0e442c809ca5Craig Silverstein if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) { 22284ca8ac2e61c37ddadf37024af86f3e1019af8532Douglas Gregor return $Cache{"getTypeDeclId"}{$Version}{$_[0]}; 22294ca8ac2e61c37ddadf37024af86f3e1019af8532Douglas Gregor } 22304ca8ac2e61c37ddadf37024af86f3e1019af8532Douglas Gregor if(my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 22314ca8ac2e61c37ddadf37024af86f3e1019af8532Douglas Gregor { 22324ca8ac2e61c37ddadf37024af86f3e1019af8532Douglas Gregor if($Info=~/name[ ]*:[ ]*@(\d+)/) { 223321ff2e516b0e0bc8c1dbf965cb3d44bac3c64330John Wiegley return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1); 22346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 22356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 223621ff2e516b0e0bc8c1dbf965cb3d44bac3c64330John Wiegley } 22376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0); 223887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar} 2239552622067dc45013d240f73952fece703f5e63bdJohn Wiegley 2240ac45ad57f0641b0d556ca27d19a59930925d6addCraig Silversteinsub getTypeInfo_All() 22416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines{ 22426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if(not check_gcc($GCC_PATH, "4.5")) 22436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { # support for GCC < 4.5 2244ac45ad57f0641b0d556ca27d19a59930925d6addCraig Silverstein # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag> 2245ac45ad57f0641b0d556ca27d19a59930925d6addCraig Silverstein # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump 22466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines # FIXME: check GCC versions 22476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines addMissedTypes_Pre(); 22486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 2249ac45ad57f0641b0d556ca27d19a59930925d6addCraig Silverstein 22506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}})) 225187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar { # forward order only 2252011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor my $IType = $LibInfo{$Version}{"info_type"}{$_}; 22536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($IType=~/_type\Z/ and $IType ne "function_type" 2254011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor and $IType ne "method_type") { 22550d8e9646bc000bab521ce52ed294209a92298cefRichard Smith getTypeInfo("$_"); 2256011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor } 2257011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor } 2258176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 2259176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines # add "..." type 2260176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines $TypeInfo{$Version}{-1} = { 2261176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines "Name" => "...", 2262176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines "Type" => "Intrinsic", 2263176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines "Tid" => -1 2264176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines }; 2265176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines $TName_Tid{$Version}{"..."} = -1; 2266176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 2267176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if(not check_gcc($GCC_PATH, "4.5")) 2268176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines { # support for GCC < 4.5 22696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines addMissedTypes_Post(); 2270176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2271176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines} 2272011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor 2273176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinessub addMissedTypes_Pre() 2274176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines{ 2275176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines my %MissedTypes = (); 2276176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}})) 2277176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines { # detecting missed typedefs 2278176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl") 2279176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines { 228087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar my $TypeId = getTreeAttr_Type($MissedTDid); 2281011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor next if(not $TypeId); 2282011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor my $TypeType = getTypeType($TypeId); 22834967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if($TypeType eq "Unknown") 22844967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar { # template_type_parm 228587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar next; 228601d08018b7cf5ce1601707cfd7a84d22015fc04eDouglas Gregor } 2287ac45ad57f0641b0d556ca27d19a59930925d6addCraig Silverstein my $TypeDeclId = getTypeDeclId($TypeId); 22886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId 22896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my $TypedefName = getNameByInfo($MissedTDid); 22906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines next if(not $TypedefName); 2291ac45ad57f0641b0d556ca27d19a59930925d6addCraig Silverstein next if($TypedefName eq "__float80"); 2292ac45ad57f0641b0d556ca27d19a59930925d6addCraig Silverstein next if(isAnon($TypedefName)); 2293ac45ad57f0641b0d556ca27d19a59930925d6addCraig Silverstein if(not $TypeDeclId 22946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines or getNameByInfo($TypeDeclId) ne $TypedefName) { 22956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1; 22966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 2297ac45ad57f0641b0d556ca27d19a59930925d6addCraig Silverstein } 2298dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth } 2299dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth my %AddTypes = (); 23006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines foreach my $Tid (keys(%{$MissedTypes{$Version}})) 23016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { # add missed typedefs 230287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar my @Missed = keys(%{$MissedTypes{$Version}{$Tid}}); 2303336f51e463340dc7b159bc38517ac4a68081302dArgyrios Kyrtzidis if(not @Missed or $#Missed>=1) { 2304336f51e463340dc7b159bc38517ac4a68081302dArgyrios Kyrtzidis next; 2305336f51e463340dc7b159bc38517ac4a68081302dArgyrios Kyrtzidis } 2306336f51e463340dc7b159bc38517ac4a68081302dArgyrios Kyrtzidis my $MissedTDid = $Missed[0]; 23076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid); 230882b4550fb25ad578b6c8143b87a003fae7106caeRichard Smith if(not $TypedefName) { 230982b4550fb25ad578b6c8143b87a003fae7106caeRichard Smith next; 231082b4550fb25ad578b6c8143b87a003fae7106caeRichard Smith } 23116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $MAX_ID++; 23126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my %MissedInfo = ( # typedef info 23136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "Name" => $TypedefName, 23146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "NameSpace" => $TypedefNS, 23156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "BaseType" => { 23166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "Tid" => $Tid 23174967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar }, 23186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "Type" => "Typedef", 23196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines "Tid" => "$MAX_ID" ); 2320ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie my ($H, $L) = getLocation($MissedTDid); 2321f3db29fff6a583ecda823cf909ab7737d8d30129Douglas Gregor $MissedInfo{"Header"} = $H; 232210ffc00e2177f042808f507c8dd50b744ed6f738Douglas Gregor $MissedInfo{"Line"} = $L; 232310ffc00e2177f042808f507c8dd50b744ed6f738Douglas Gregor if($TypedefName=~/\*|\&|\s/) 232410ffc00e2177f042808f507c8dd50b744ed6f738Douglas Gregor { # other types 232510ffc00e2177f042808f507c8dd50b744ed6f738Douglas Gregor next; 232610ffc00e2177f042808f507c8dd50b744ed6f738Douglas Gregor } 23276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($TypedefName=~/>(::\w+)+\Z/) 23286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { # QFlags<Qt::DropAction>::enum_type 23296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines next; 23306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 2331b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/) 23326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { # double-check for the name of typedef 23336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info 23346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines next if(not $TName); 2335b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar if(length($TypedefName)>=length($TName)) 23366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { # too long typedef 233787014f33f123461a012995b2f7eb5e6ecf6dc461Argyrios Kyrtzidis next; 233887014f33f123461a012995b2f7eb5e6ecf6dc461Argyrios Kyrtzidis } 233987014f33f123461a012995b2f7eb5e6ecf6dc461Argyrios Kyrtzidis if($TName=~/\A\Q$TypedefName\E</) { 234087014f33f123461a012995b2f7eb5e6ecf6dc461Argyrios Kyrtzidis next; 23416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 23426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($TypedefName=~/\A\Q$TName\E/) 23431270673bf5208a140b397419c8c34e7bdcce2339Argyrios Kyrtzidis { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type 23441270673bf5208a140b397419c8c34e7bdcce2339Argyrios Kyrtzidis next; 23451270673bf5208a140b397419c8c34e7bdcce2339Argyrios Kyrtzidis } 23461270673bf5208a140b397419c8c34e7bdcce2339Argyrios Kyrtzidis if(get_depth($TypedefName)==0 and get_depth($TName)!=0) 23476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { # std::_Vector_base and std::vector::_Base 23486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines next; 23496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 23506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 23516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 2352f85e193739c953358c865005855253af4f68a497John McCall $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo; 2353f85e193739c953358c865005855253af4f68a497John McCall 2354f85e193739c953358c865005855253af4f68a497John McCall # register typedef 23556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"}; 23566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid; 23576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"}; 23586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 23596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 23606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines # add missed & remove other 2361d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor $TypeInfo{$Version} = \%AddTypes; 23624c9be89bb615ec07eb3ed507c8fa9d0baa8a5ad7Douglas Gregor delete($Cache{"getTypeAttr"}{$Version}); 236366cf92a9670d57da61842adb69f9b038ce29dca5Matt Beaumont-Gay} 2364ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie 236566cf92a9670d57da61842adb69f9b038ce29dca5Matt Beaumont-Gaysub addMissedTypes_Post() 236666cf92a9670d57da61842adb69f9b038ce29dca5Matt Beaumont-Gay{ 2367d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor foreach my $BaseId (keys(%{$MissedTypedef{$Version}})) 2368ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie { 2369d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"}) 23704c9be89bb615ec07eb3ed507c8fa9d0baa8a5ad7Douglas Gregor { 237166cf92a9670d57da61842adb69f9b038ce29dca5Matt Beaumont-Gay $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"}; 2372ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) { 237366cf92a9670d57da61842adb69f9b038ce29dca5Matt Beaumont-Gay $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"}; 237466cf92a9670d57da61842adb69f9b038ce29dca5Matt Beaumont-Gay } 2375d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor } 2376d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor } 237728bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley} 237828bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 23796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinessub getTypeInfo($) 2380c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines{ 23816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my $TypeId = $_[0]; 238228bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId); 23836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my $TName = $TypeInfo{$Version}{$TypeId}{"Name"}; 23846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if(not $TName) { 2385176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines delete($TypeInfo{$Version}{$TypeId}); 23866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 2387dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth} 2388dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 2389dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthsub getArraySize($$) 23906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines{ 23916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my ($TypeId, $BaseName) = @_; 23926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if(my $Size = getSize($TypeId)) 23936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 23946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my $Elems = $Size/$BYTE_SIZE; 23956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines while($BaseName=~s/\s*\[(\d+)\]//) { 23966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Elems/=$1; 23976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 23986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if(my $BasicId = $TName_Tid{$Version}{$BaseName}) 23996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 24006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) { 24016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Elems/=$BasicSize; 2402176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 24036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 2404dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth return $Elems; 240587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 240687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return 0; 240787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar} 240887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 240987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarsub getTParams($$) 241087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar{ 24114967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar my ($TypeId, $Kind) = @_; 241287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar my @TmplParams = (); 241387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}}); 241487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar foreach my $Pos (@Positions) 241587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar { 241687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos}; 24174967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId}; 241887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if(not $NodeType) 241987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar { # typename_type 242087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return (); 242187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 242287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if($NodeType eq "tree_vec") 24234967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar { 242487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if($Pos!=$#Positions) 242587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar { # select last vector of parameters ( ns<P1>::type<P2> ) 242687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar next; 242787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 242887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 24294967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar my @Params = get_TemplateParam($Pos, $Param_TypeId); 243087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar foreach my $P (@Params) 243187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar { 243287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if($P eq "") { 2433dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth return (); 24346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 24356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines elsif($P ne "\@skip\@") { 24366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines @TmplParams = (@TmplParams, $P); 24376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 24386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 24396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 24406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return @TmplParams; 24416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 24426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 24436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinessub getTypeAttr($) 244461eee0ca33b29e102f11bab77c8b74cc00e2392bTanya Lattner{ 24456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my $TypeId = $_[0]; 2446dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth my %TypeAttr = (); 24474fa7eab771ab8212e1058bd1a91061ff120c8fbbAlexey Bataev if(defined $TypeInfo{$Version}{$TypeId} 24486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines and $TypeInfo{$Version}{$TypeId}{"Name"}) 2449651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines { # already created 24506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return %{$TypeInfo{$Version}{$TypeId}}; 2451c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 2452c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines elsif($Cache{"getTypeAttr"}{$Version}{$TypeId}) 2453c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines { # incomplete type 2454651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return (); 2455651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2456651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1; 2457176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 2458176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines my $TypeDeclId = getTypeDeclId($TypeId); 2459176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines $TypeAttr{"Tid"} = $TypeId; 2460176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 2461176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId)) 2462176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines { 2463c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if(my $Info = $LibInfo{$Version}{"info"}{$TypeId}) 2464c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines { 2465651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if($Info=~/qual[ ]*:/) 2466c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines { 2467c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if(my $NID = ++$MAX_ID) 2468c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines { 2469c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines $MissedBase{$Version}{$TypeId}="$NID"; 2470c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines $MissedBase_R{$Version}{$NID}=$TypeId; 2471c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines $LibInfo{$Version}{"info"}{$NID} = $LibInfo{$Version}{"info"}{$TypeId}; 2472176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines $LibInfo{$Version}{"info_type"}{$NID} = $LibInfo{$Version}{"info_type"}{$TypeId}; 2473176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2474176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2475c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 2476c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines $TypeAttr{"Type"} = "Typedef"; 2477c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 2478c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else { 2479c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines $TypeAttr{"Type"} = getTypeType($TypeId); 2480c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 2481c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2482c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if($TypeAttr{"Type"} eq "Unknown") { 2483c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return (); 2484176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2485176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/) 2486176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines { 2487176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"}); 2488176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if(my $TName = $TypeAttr{"Name"}) 2489176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines { 2490176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr; 2491176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines $TName_Tid{$Version}{$TName} = $TypeId; 2492c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return %TypeAttr; 2493c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 2494c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else { 2495176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return (); 2496176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2497176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2498c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines elsif($TypeAttr{"Type"} eq "Array") 2499c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines { 25004fa7eab771ab8212e1058bd1a91061ff120c8fbbAlexey Bataev my ($BTid, $BTSpec) = selectBaseType($TypeId); 2501176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if(not $BTid) { 2502176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return (); 2503176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2504176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines $TypeAttr{"BaseType"}{"Tid"} = $BTid; 2505176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if(my %BTAttr = getTypeAttr($BTid)) 2506176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines { 2507176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if(not $BTAttr{"Name"}) { 2508176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return (); 2509176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2510176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"})) 2511176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines { 2512176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if(my $Size = getSize($TypeId)) { 251387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $TypeAttr{"Size"} = $Size/$BYTE_SIZE; 251487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 251587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) { 251687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $TypeAttr{"Name"} = $1."[$NElems]".$2; 251787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 251887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar else { 251987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]"; 252087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 252187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 2522176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines else 2523176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines { 2524176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer 2525176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) { 2526176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines $TypeAttr{"Name"} = $1."[]".$2; 2527176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2528176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines else { 2529176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines $TypeAttr{"Name"} = $BTAttr{"Name"}."[]"; 2530176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2531176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2532176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}); 2533176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if($BTAttr{"Header"}) { 253487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $TypeAttr{"Header"} = $BTAttr{"Header"}; 253587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 253687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr; 25374967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId; 25384967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return %TypeAttr; 25394967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 25404967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return (); 25414967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 25424967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/) 25434967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar { 25444967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar %TypeAttr = getTrivialTypeAttr($TypeId); 25454967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if($TypeAttr{"Name"}) 25464967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar { 25474967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr; 25484967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if($TypeAttr{"Name"} ne "int" or getTypeDeclId($TypeAttr{"Tid"})) 2549176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines { # NOTE: register only one int: with built-in decl 2550176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) { 2551176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId; 25524967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 25534967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 25544967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return %TypeAttr; 255587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 255687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar else { 255787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return (); 255887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 255987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 256087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar else 256187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar { # derived types 256287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar my ($BTid, $BTSpec) = selectBaseType($TypeId); 256387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if(not $BTid) { 25644967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return (); 25654967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 25664967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $TypeAttr{"BaseType"}{"Tid"} = $BTid; 25674967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if(defined $MissedTypedef{$Version}{$BTid}) 25684967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar { 25694967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"}) 25704967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar { 25714967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if($MissedTDid ne $TypeDeclId) { 25724967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $TypeAttr{"BaseType"}{"Tid"} = $MissedTypedef{$Version}{$BTid}{"Tid"}; 25734967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 25744967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 25754967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 25764fa7eab771ab8212e1058bd1a91061ff120c8fbbAlexey Bataev my %BTAttr = getTypeAttr($TypeAttr{"BaseType"}{"Tid"}); 25776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if(not $BTAttr{"Name"}) 25784fa7eab771ab8212e1058bd1a91061ff120c8fbbAlexey Bataev { # templates 25796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return (); 25806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 25814fa7eab771ab8212e1058bd1a91061ff120c8fbbAlexey Bataev if($BTAttr{"Type"} eq "Typedef") 25826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { # relinking typedefs 25836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines my %BaseBase = get_Type($BTAttr{"BaseType"}{"Tid"}, $Version); 2584c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if($BTAttr{"Name"} eq $BaseBase{"Name"}) { 2585c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines $TypeAttr{"BaseType"}{"Tid"} = $BaseBase{"Tid"}; 25864fa7eab771ab8212e1058bd1a91061ff120c8fbbAlexey Bataev } 2587c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 25884967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if($BTSpec) 2589c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines { 25906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($TypeAttr{"Type"} eq "Pointer" 25914fa7eab771ab8212e1058bd1a91061ff120c8fbbAlexey Bataev and $BTAttr{"Name"}=~/\([\*]+\)/) 25924fa7eab771ab8212e1058bd1a91061ff120c8fbbAlexey Bataev { 25934fa7eab771ab8212e1058bd1a91061ff120c8fbbAlexey Bataev $TypeAttr{"Name"} = $BTAttr{"Name"}; 25944fa7eab771ab8212e1058bd1a91061ff120c8fbbAlexey Bataev $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g; 25956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 25964967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar else { 25974967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec; 25984967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 25994967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 26004967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar else { 26014967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $TypeAttr{"Name"} = $BTAttr{"Name"}; 26024967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 26034967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if($TypeAttr{"Type"} eq "Typedef") 26044967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar { 26054967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar $TypeAttr{"Name"} = getNameByInfo($TypeDeclId); 26064967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if(isAnon($TypeAttr{"Name"})) 26074967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar { # anon typedef to anon type: ._N 26084967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return (); 26094967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 26104967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if(my $NS = getNameSpace($TypeDeclId)) 2611651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines { 2612c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines my $TypeName = $TypeAttr{"Name"}; 2613651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/) 2614651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines { # "some_type" is the typedef to "struct some_type" in C++ 2615651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if($3) { 26166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $TypeAttr{"Name"} = $3."::".$TypeName; 2617176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2618176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2619176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines else 2620176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines { 2621176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines $TypeAttr{"NameSpace"} = $NS; 2622176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"}; 26236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 26246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/ 2625c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines and $TypeAttr{"Name"}!~/>(::\w+)+\Z/) 2626651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines { 2627651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if($BTAttr{"NameSpace"} 2628651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</) 2629c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines { # types like "std::fpos<__mbstate_t>" are 2630651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines # not covered by typedefs in the TU dump 2631c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines # so trying to add such typedefs manually 2632c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1; 2633c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"})) 2634c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines { 2635c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) 263687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar { # skip "other" in "std" and "type" in "boost" 263787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"}; 263887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 263987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 264087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 264187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 2642c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 2643c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 2644c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if($TypeAttr{"Name"} ne $BTAttr{"Name"} 2645651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/) 2646651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines { 2647651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}}) 26486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { # typedef int*const TYPEDEF; // first 2649c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines # int foo(TYPEDEF p); // const is optimized out 26506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"}; 26516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($BTAttr{"Name"}=~/</) 26526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { 2653c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) { 2654c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1; 26554fa7eab771ab8212e1058bd1a91061ff120c8fbbAlexey Bataev } 26564fa7eab771ab8212e1058bd1a91061ff120c8fbbAlexey Bataev } 26574fa7eab771ab8212e1058bd1a91061ff120c8fbbAlexey Bataev } 26586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 26596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId); 2660c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 26614967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if(not $TypeAttr{"Size"}) 2662c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines { 2663c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if($TypeAttr{"Type"} eq "Pointer") { 2664c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines $TypeAttr{"Size"} = $WORD_SIZE{$Version}; 2665c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 2666c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines elsif($BTAttr{"Size"}) { 266787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $TypeAttr{"Size"} = $BTAttr{"Size"}; 266887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 2669c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 2670c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}); 2671c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) { 2672c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines $TypeAttr{"Header"} = $BTAttr{"Header"}; 2673c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 26746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr; 26756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if($TypeAttr{"Name"} ne $BTAttr{"Name"}) 26766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines { # typedef to "class Class" 26776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines # should not be registered in TName_Tid 2678176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) { 2679176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId; 2680176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2681176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2682176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return %TypeAttr; 2683176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2684176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines} 2685176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 2686176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinessub getTreeVec($) 2687176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines{ 2688176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines my %Vector = (); 2689176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 2690176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines { 2691176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /) 2692176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines { # string length is N-1 because of the null terminator 2693176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines $Vector{$1} = $2; 2694176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2695176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2696176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return \%Vector; 2697176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines} 2698176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 2699176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinessub get_TemplateParam($$) 2700176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines{ 2701176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines my ($Pos, $Type_Id) = @_; 2702176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return () if(not $Type_Id); 2703176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id}; 2704176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return () if(not $NodeType); 2705176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if($NodeType eq "integer_cst") 2706176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines { # int (1), unsigned (2u), char ('c' as 99), ... 2707176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines my $CstTid = getTreeAttr_Type($Type_Id); 2708176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines my %CstType = getTypeAttr($CstTid); # without recursion 2709176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines my $Num = getNodeIntCst($Type_Id); 2710176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) { 2711176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return ($Num.$CstSuffix); 2712176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2713176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines else { 271487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return ("(".$CstType{"Name"}.")".$Num); 271587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 271687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 271787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar elsif($NodeType eq "string_cst") { 271887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return (getNodeStrCst($Type_Id)); 271987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 272087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar elsif($NodeType eq "tree_vec") 272187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar { 272287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar my $Vector = getTreeVec($Type_Id); 272387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar my @Params = (); 272487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector})) 272587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar { 272687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) { 272787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar push(@Params, $P2); 272887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 27296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 2730c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return @Params; 2731c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 2732c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else 2733c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines { 2734c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines my %ParamAttr = getTypeAttr($Type_Id); 2735543c4ae954f2bce5ac58ed22080f23cbd94794d2Alexey Bataev my $PName = $ParamAttr{"Name"}; 27364fa7eab771ab8212e1058bd1a91061ff120c8fbbAlexey Bataev if(not $PName) { 27376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return (); 27380c018357b8bbb1f96bbf622a5807421e626b4228Alexey Bataev } 2739c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if($PName=~/\>/) 2740176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines { 2741176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if(my $Cover = cover_stdcxx_typedef($PName)) { 2742176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines $PName = $Cover; 27434fa7eab771ab8212e1058bd1a91061ff120c8fbbAlexey Bataev } 27444fa7eab771ab8212e1058bd1a91061ff120c8fbbAlexey Bataev } 27454fa7eab771ab8212e1058bd1a91061ff120c8fbbAlexey Bataev if($Pos>=1 and 27466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines $PName=~/\Astd::(allocator|less|((char|regex)_traits)|((i|o)streambuf_iterator))\</) 2747d195bc38fd424b0c928e3c354038a8ca6e2ccac3Alexey Bataev { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> > 27486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines # template<typename _Key, typename _Compare = std::less<_Key> 2749c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines # template<typename _CharT, typename _Traits = std::char_traits<_CharT> > 27504967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> > 2751176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> > 2752176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> > 2753176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return ("\@skip\@"); 2754176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2755176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return ($PName); 2756176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 2757c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} 2758c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2759c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinessub cover_stdcxx_typedef($) 2760c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines{ 2761c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines my $TypeName = $_[0]; 2762c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if(my @Covers = sort {length($a)<=>length($b)} 2763c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines sort keys(%{$StdCxxTypedef{$Version}{$TypeName}})) 27644967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar { # take the shortest typedef 276558878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar # FIXME: there may be more than 276658878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar # one typedefs to the same type 276758878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar return $Covers[0]; 276858878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar } 276958878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar my $TypeName_Covered = $TypeName; 277058878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){}; 277158878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}})) 277258878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar { 277358878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar my $Cover = $Covers[0]; 277458878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar $TypeName_Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g; 277558878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar $TypeName_Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g; 277658878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar } 2777d195bc38fd424b0c928e3c354038a8ca6e2ccac3Alexey Bataev return formatName($TypeName_Covered); 2778d195bc38fd424b0c928e3c354038a8ca6e2ccac3Alexey Bataev} 2779d195bc38fd424b0c928e3c354038a8ca6e2ccac3Alexey Bataev 27806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinessub getNodeIntCst($) 27810c018357b8bbb1f96bbf622a5807421e626b4228Alexey Bataev{ 2782c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines my $CstId = $_[0]; 27830c018357b8bbb1f96bbf622a5807421e626b4228Alexey Bataev my $CstTypeId = getTreeAttr_Type($CstId); 27840c018357b8bbb1f96bbf622a5807421e626b4228Alexey Bataev if($EnumMembName_Id{$Version}{$CstId}) { 27850c018357b8bbb1f96bbf622a5807421e626b4228Alexey Bataev return $EnumMembName_Id{$Version}{$CstId}; 27866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 27876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines elsif((my $Value = getTreeValue($CstId)) ne "") 2788c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines { 27893ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if($Value eq "0") 2790c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines { 27914967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") { 279287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return "false"; 279387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 279487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar else { 27953ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return "0"; 27963ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 27973ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 27983ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar elsif($Value eq "1") 27993ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar { 28003ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") { 28013ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return "true"; 28023ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 28033ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar else { 2804c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return "1"; 2805c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 2806c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 2807c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines else { 2808c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return $Value; 2809c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 2810c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 28116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return ""; 28126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 28136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 28146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinessub getNodeStrCst($) 2815651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines{ 2816c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 281758878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar { 281858878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/) 281958878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar { # string length is N-1 because of the null terminator 282058878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar return substr($1, 0, $2-1); 282158878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar } 282258878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar } 282358878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar return ""; 282458878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar} 282558878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar 2826c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinessub getMemPtrAttr($$$) 2827c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines{ # function, method and field pointers 2828c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines my ($PtrId, $TypeId, $Type) = @_; 2829c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId}; 2830c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if($Type eq "FieldPtr") { 2831c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines $MemInfo = $LibInfo{$Version}{"info"}{$TypeId}; 2832c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 28333ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId}; 28343ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar my $MemPtrName = ""; 28353ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId); 28363ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if($Type eq "MethodPtr") 28373ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar { # size of "method pointer" may be greater than WORD size 28383ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if(my $Size = getSize($TypeId)) { 28393ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar $TypeAttr{"Size"} = $Size/$BYTE_SIZE; 28403ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 28413ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 2842c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines # Return 2843c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if($Type eq "FieldPtr") 2844c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines { 2845c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines my %ReturnAttr = getTypeAttr($PtrId); 2846c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if($ReturnAttr{"Name"}) { 2847c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines $MemPtrName .= $ReturnAttr{"Name"}; 2848c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 2849c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines $TypeAttr{"Return"} = $PtrId; 2850c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines } 28514967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar else 285287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar { 285387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /) 285487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar { 285558878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar my $ReturnTypeId = $1; 285658878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar my %ReturnAttr = getTypeAttr($ReturnTypeId); 285758878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar if(not $ReturnAttr{"Name"}) 285858878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar { # templates 285958878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar return (); 286058878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar } 286158878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar $MemPtrName .= $ReturnAttr{"Name"}; 286258878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar $TypeAttr{"Return"} = $ReturnTypeId; 286358878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar } 2864651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2865651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines # Class 2866651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /) 2867176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines { 2868176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines $TypeAttr{"Class"} = $2; 2869176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines my %Class = getTypeAttr($TypeAttr{"Class"}); 2870176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if($Class{"Name"}) { 2871176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines $MemPtrName .= " (".$Class{"Name"}."\:\:*)"; 2872176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 287387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar else { 287487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $MemPtrName .= " (*)"; 287587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 287687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 287787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar else { 287887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $MemPtrName .= " (*)"; 287987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 288087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar # Parameters 288187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if($Type eq "FuncPtr" 288287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar or $Type eq "MethodPtr") 288387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar { 288487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar my @ParamTypeName = (); 288587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /) 288687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar { 288787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar my $PTypeInfoId = $1; 288887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar my $Pos = 0; 288987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar while($PTypeInfoId) 289087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar { 289187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId}; 289287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /) 289387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar { 289487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar my $PTypeId = $1; 289587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar my %ParamAttr = getTypeAttr($PTypeId); 289687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if(not $ParamAttr{"Name"}) 289787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar { # templates (template_type_parm), etc. 289887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return (); 289987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 290087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if($ParamAttr{"Name"} eq "void") { 290187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar last; 290287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 290387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if($Pos!=0 or $Type ne "MethodPtr") 290487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar { 290587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $TypeAttr{"Param"}{$Pos}{"type"} = $PTypeId; 290687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar push(@ParamTypeName, $ParamAttr{"Name"}); 290787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 290887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if($PTypeInfoId = getNextElem($PTypeInfoId)) { 290987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $Pos+=1; 291087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 291187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar else { 291287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar last; 291387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 291487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 291587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar else { 291687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar last; 291787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 291887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 291987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 292087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $MemPtrName .= " (".join(", ", @ParamTypeName).")"; 292187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 292287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar $TypeAttr{"Name"} = formatName($MemPtrName); 292387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return %TypeAttr; 292487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar} 292587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 292687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarsub getTreeTypeName($) 292787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar{ 292887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar my $TypeId = $_[0]; 292987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if(my $Info = $LibInfo{$Version}{"info"}{$TypeId}) 293087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar { 293187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type") 29324967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar { 29334967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if(my $Name = getNameByInfo($TypeId)) 29344967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar { # bit_size_type 29354967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return $Name; 29364967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 29374967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar elsif($Info=~/unsigned/) { 29384967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return "unsigned int"; 29394967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 29404967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar else { 29414967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return "int"; 29424967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 29434967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 29444967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar elsif($Info=~/name[ ]*:[ ]*@(\d+) /) 29454967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar { 29464967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return getNameByInfo($1); 29474967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 29484967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 29494967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return ""; 29504967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar} 29514967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 29524967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarsub isFuncPtr($) 29534967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar{ 29544967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar my $Ptd = pointTo($_[0]); 29554967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return 0 if(not $Ptd); 29564967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if(my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 29574967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar { 29584967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) { 29594967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return 0; 29604967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 29614967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 29624967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]} 29634967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd}) 29644967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar { 29654967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if($InfoT1 eq "pointer_type" 29664967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar and $InfoT2 eq "function_type") { 29674967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return 1; 29684967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 29694967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 29704967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return 0; 29714967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar} 2972dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 2973dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthsub isMethodPtr($) 2974dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth{ 2975dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth my $Ptd = pointTo($_[0]); 2976dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth return 0 if(not $Ptd); 2977dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth if(my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 2978dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth { 2979dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type" 2980dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type" 2981dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth and $Info=~/ ptrmem /) { 2982dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth return 1; 29832ac54ec0a8ad305fdd76847c2fd6631cfb7baa82Zhanyong Wan } 2984dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth } 2985f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne return 0; 2986dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth} 2987dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth 2988dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruthsub isFieldPtr($) 2989dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth{ 299087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 299187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar { 2992dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type" 2993dfc35e33177a433b56454f1d2b5e53734f65b288Chandler Carruth and $Info=~/ ptrmem /) { 2994facfc77487a890bfb7b5eee7e21cd2b395a9faafChandler Carruth return 1; 2995d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor } 2996d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor } 2997d30bf2eb6d6bbebd41236bf205d3a6dfc51a3659Douglas Gregor return 0; 2998} 2999 3000sub pointTo($) 3001{ 3002 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 3003 { 3004 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) { 3005 return $1; 3006 } 3007 } 3008 return ""; 3009} 3010 3011sub getTypeTypeByTypeId($) 3012{ 3013 my $TypeId = $_[0]; 3014 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId}) 3015 { 3016 my $NType = $NodeType{$TType}; 3017 if($NType eq "Intrinsic") { 3018 return $NType; 3019 } 3020 elsif(isFuncPtr($TypeId)) { 3021 return "FuncPtr"; 3022 } 3023 elsif(isMethodPtr($TypeId)) { 3024 return "MethodPtr"; 3025 } 3026 elsif(isFieldPtr($TypeId)) { 3027 return "FieldPtr"; 3028 } 3029 elsif($NType ne "Other") { 3030 return $NType; 3031 } 3032 } 3033 return "Unknown"; 3034} 3035 3036sub getQual($) 3037{ 3038 my $TypeId = $_[0]; 3039 my %UnQual = ( 3040 "r"=>"restrict", 3041 "v"=>"volatile", 3042 "c"=>"const", 3043 "cv"=>"const volatile" 3044 ); 3045 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId}) 3046 { 3047 my ($Qual, $To) = (); 3048 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) { 3049 $Qual = $UnQual{$1}; 3050 } 3051 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) { 3052 $To = $1; 3053 } 3054 if($Qual and $To) { 3055 return ($Qual, $To); 3056 } 3057 } 3058 return (); 3059} 3060 3061sub getQualType($) 3062{ 3063 if($_[0] eq "const volatile") { 3064 return "ConstVolatile"; 3065 } 3066 return ucfirst($_[0]); 3067} 3068 3069sub getTypeType($) 3070{ 3071 my $TypeId = $_[0]; 3072 my $TypeDeclId = getTypeDeclId($TypeId); 3073 if(defined $MissedTypedef{$Version}{$TypeId}) 3074 { # support for old GCC versions 3075 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) { 3076 return "Typedef"; 3077 } 3078 } 3079 my $Info = $LibInfo{$Version}{"info"}{$TypeId}; 3080 my ($Qual, $To) = getQual($TypeId); 3081 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) / 3082 and (getTypeId($1) ne $TypeId)) 3083 { # qualified types (special) 3084 return getQualType($Qual); 3085 } 3086 elsif(not $MissedBase_R{$Version}{$TypeId} 3087 and isTypedef($TypeId)) { 3088 return "Typedef"; 3089 } 3090 elsif($Qual) 3091 { # qualified types 3092 return getQualType($Qual); 3093 } 3094 my $TypeType = getTypeTypeByTypeId($TypeId); 3095 if($TypeType eq "Struct") 3096 { 3097 if($TypeDeclId 3098 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") { 3099 return "Template"; 3100 } 3101 } 3102 return $TypeType; 3103} 3104 3105sub isTypedef($) 3106{ 3107 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 3108 { 3109 my $TDid = getTypeDeclId($_[0]); 3110 if(getNameByInfo($TDid) 3111 and $Info=~/unql[ ]*:[ ]*\@(\d+) / 3112 and getTypeId($TDid) eq $_[0]) { 3113 return $1; 3114 } 3115 } 3116 return 0; 3117} 3118 3119sub selectBaseType($) 3120{ 3121 my $TypeId = $_[0]; 3122 if(defined $MissedTypedef{$Version}{$TypeId}) 3123 { # add missed typedefs 3124 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) { 3125 return ($TypeId, ""); 3126 } 3127 } 3128 my $Info = $LibInfo{$Version}{"info"}{$TypeId}; 3129 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId}; 3130 3131 my $MB_R = $MissedBase_R{$Version}{$TypeId}; 3132 my $MB = $MissedBase{$Version}{$TypeId}; 3133 3134 my ($Qual, $To) = getQual($TypeId); 3135 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) / 3136 and (getTypeId($1) ne $TypeId) 3137 and (not $MB_R or getTypeId($1) ne $MB_R)) 3138 { # qualified types (special) 3139 return (getTypeId($1), $Qual); 3140 } 3141 elsif($MB) 3142 { # add base 3143 return ($MB, ""); 3144 } 3145 elsif(not $MB_R and my $Bid = isTypedef($TypeId)) 3146 { # typedefs 3147 return ($Bid, ""); 3148 } 3149 elsif($Qual or $To) 3150 { # qualified types 3151 return ($To, $Qual); 3152 } 3153 elsif($InfoType eq "reference_type") 3154 { 3155 if($Info=~/refd[ ]*:[ ]*@(\d+) /) { 3156 return ($1, "&"); 3157 } 3158 else { 3159 return (0, ""); 3160 } 3161 } 3162 elsif($InfoType eq "array_type") 3163 { 3164 if($Info=~/elts[ ]*:[ ]*@(\d+) /) { 3165 return ($1, ""); 3166 } 3167 else { 3168 return (0, ""); 3169 } 3170 } 3171 elsif($InfoType eq "pointer_type") 3172 { 3173 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) { 3174 return ($1, "*"); 3175 } 3176 else { 3177 return (0, ""); 3178 } 3179 } 3180 else { 3181 return (0, ""); 3182 } 3183} 3184 3185sub getSymbolInfo_All() 3186{ 3187 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}})) 3188 { # reverse order 3189 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") { 3190 getSymbolInfo($_); 3191 } 3192 } 3193} 3194 3195sub getVarInfo_All() 3196{ 3197 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}})) 3198 { # reverse order 3199 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") { 3200 getVarInfo($_); 3201 } 3202 } 3203} 3204 3205sub isBuiltIn($) { 3206 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./); 3207} 3208 3209sub getVarInfo($) 3210{ 3211 my $InfoId = $_[0]; 3212 if(my $NSid = getNameSpaceId($InfoId)) 3213 { 3214 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid}; 3215 if($NSInfoType and $NSInfoType eq "function_decl") { 3216 return; 3217 } 3218 } 3219 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId); 3220 if(not $SymbolInfo{$Version}{$InfoId}{"Header"} 3221 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) { 3222 delete($SymbolInfo{$Version}{$InfoId}); 3223 return; 3224 } 3225 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId)); 3226 if(not $ShortName) { 3227 delete($SymbolInfo{$Version}{$InfoId}); 3228 return; 3229 } 3230 if($ShortName=~/\Atmp_add_class_\d+\Z/) { 3231 delete($SymbolInfo{$Version}{$InfoId}); 3232 return; 3233 } 3234 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName; 3235 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = getTreeStr(getTreeAttr_Mngl($InfoId)); 3236 if($SymbolInfo{$Version}{$InfoId}{"MnglName"} 3237 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A_Z/) 3238 { # validate mangled name 3239 delete($SymbolInfo{$Version}{$InfoId}); 3240 return; 3241 } 3242 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"} 3243 and $ShortName=~/\A_Z/) 3244 { # _ZTS, etc. 3245 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName; 3246 } 3247 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"})) 3248 { # non-public global data 3249 delete($SymbolInfo{$Version}{$InfoId}); 3250 return; 3251 } 3252 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1; 3253 if(my $Rid = getTypeId($InfoId)) 3254 { 3255 if(not $TypeInfo{$Version}{$Rid}{"Name"}) 3256 { # typename_type 3257 delete($SymbolInfo{$Version}{$InfoId}); 3258 return; 3259 } 3260 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid; 3261 my $Val = getDataVal($InfoId, $Rid); 3262 if(defined $Val) { 3263 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val; 3264 } 3265 } 3266 set_Class_And_Namespace($InfoId); 3267 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"}) 3268 { 3269 if(not $TypeInfo{$Version}{$ClassId}{"Name"}) 3270 { # templates 3271 delete($SymbolInfo{$Version}{$InfoId}); 3272 return; 3273 } 3274 } 3275 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i) 3276 { # extern "C" 3277 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C"; 3278 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName; 3279 } 3280 if($UserLang and $UserLang eq "C") 3281 { # --lang=C option 3282 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName; 3283 } 3284 if(not $CheckHeadersOnly) 3285 { 3286 if(not $SymbolInfo{$Version}{$InfoId}{"Class"}) 3287 { 3288 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"} 3289 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps")) 3290 { 3291 if(link_symbol($ShortName, $Version, "-Deps")) 3292 { # "const" global data is mangled as _ZL... in the TU dump 3293 # but not mangled when compiling a C shared library 3294 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName; 3295 } 3296 } 3297 } 3298 } 3299 if($COMMON_LANGUAGE{$Version} eq "C++") 3300 { 3301 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) 3302 { # for some symbols (_ZTI) the short name is the mangled name 3303 if($ShortName=~/\A_Z/) { 3304 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName; 3305 } 3306 } 3307 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) 3308 { # try to mangle symbol (link with libraries) 3309 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId); 3310 } 3311 if($OStarget eq "windows") 3312 { 3313 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")}) 3314 { # link MS C++ symbols from library with GCC symbols from headers 3315 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled; 3316 } 3317 } 3318 } 3319 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) { 3320 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName; 3321 } 3322 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"}) 3323 { 3324 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version)) 3325 { # non-target symbols 3326 delete($SymbolInfo{$Version}{$InfoId}); 3327 return; 3328 } 3329 } 3330 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"}) 3331 { 3332 if(defined $MissedTypedef{$Version}{$Rid}) 3333 { 3334 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) { 3335 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid; 3336 } 3337 } 3338 } 3339 setFuncAccess($InfoId); 3340 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZTV/) { 3341 delete($SymbolInfo{$Version}{$InfoId}{"Return"}); 3342 } 3343 if($ShortName=~/\A(_Z|\?)/) { 3344 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"}); 3345 } 3346} 3347 3348sub isConstType($$) 3349{ 3350 my ($TypeId, $LibVersion) = @_; 3351 my %Base = get_Type($TypeId, $LibVersion); 3352 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") { 3353 %Base = get_OneStep_BaseType($Base{"Tid"}, $LibVersion); 3354 } 3355 return ($Base{"Type"} eq "Const"); 3356} 3357 3358sub getTrivialName($$) 3359{ 3360 my ($TypeInfoId, $TypeId) = @_; 3361 my %TypeAttr = (); 3362 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId); 3363 if(not $TypeAttr{"Name"}) { 3364 $TypeAttr{"Name"} = getTreeTypeName($TypeId); 3365 } 3366 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId); 3367 $TypeAttr{"Type"} = getTypeType($TypeId); 3368 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name 3369 if(isAnon($TypeAttr{"Name"})) 3370 { 3371 my $NameSpaceId = $TypeId; 3372 while(my $NSId = getNameSpaceId(getTypeDeclId($NameSpaceId))) 3373 { # searching for a first not anon scope 3374 if($NSId eq $NameSpaceId) { 3375 last; 3376 } 3377 else 3378 { 3379 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId)); 3380 if(not $TypeAttr{"NameSpace"} 3381 or isNotAnon($TypeAttr{"NameSpace"})) { 3382 last; 3383 } 3384 } 3385 $NameSpaceId=$NSId; 3386 } 3387 } 3388 else 3389 { 3390 if(my $NameSpaceId = getNameSpaceId($TypeInfoId)) 3391 { 3392 if($NameSpaceId ne $TypeId) { 3393 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId); 3394 } 3395 } 3396 } 3397 if($TypeAttr{"NameSpace"} and isNotAnon($TypeAttr{"Name"})) { 3398 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"}; 3399 } 3400 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}); 3401 if(isAnon($TypeAttr{"Name"})) 3402 { # anon-struct-header.h-line 3403 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-"; 3404 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"}; 3405 if($TypeAttr{"NameSpace"}) { 3406 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"}; 3407 } 3408 } 3409 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId} 3410 and getTypeDeclId($TypeId) eq $TypeInfoId) 3411 { 3412 my @TParams = getTParams($TypeId, "Type"); 3413 if(not @TParams) 3414 { # template declarations with abstract params 3415 return ("", ""); 3416 } 3417 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >"); 3418 } 3419 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}); 3420} 3421 3422sub getTrivialTypeAttr($) 3423{ 3424 my $TypeId = $_[0]; 3425 my $TypeInfoId = getTypeDeclId($_[0]); 3426 3427 if($TemplateDecl{$Version}{$TypeId}) 3428 { # template_decl 3429 return (); 3430 } 3431 if(my $ScopeId = getTreeAttr_Scpe($TypeInfoId)) 3432 { 3433 if($TemplateDecl{$Version}{$ScopeId}) 3434 { # template_decl 3435 return (); 3436 } 3437 } 3438 3439 my %TypeAttr = (); 3440 if(getTypeTypeByTypeId($TypeId)!~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/) { 3441 return (); 3442 } 3443 setTypeAccess($TypeId, \%TypeAttr); 3444 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId); 3445 if(isBuiltIn($TypeAttr{"Header"})) 3446 { 3447 delete($TypeAttr{"Header"}); 3448 delete($TypeAttr{"Line"}); 3449 } 3450 $TypeAttr{"Type"} = getTypeType($TypeId); 3451 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId); 3452 if(not $TypeAttr{"Name"}) { 3453 return (); 3454 } 3455 if(not $TypeAttr{"NameSpace"}) { 3456 delete($TypeAttr{"NameSpace"}); 3457 } 3458 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}) 3459 { 3460 if(my @TParams = getTParams($TypeId, "Type")) 3461 { 3462 foreach my $Pos (0 .. $#TParams) { 3463 $TypeAttr{"TParam"}{$Pos}{"name"}=$TParams[$Pos]; 3464 } 3465 } 3466 } 3467 if(my $Size = getSize($TypeId)) { 3468 $TypeAttr{"Size"} = $Size/$BYTE_SIZE; 3469 } 3470 if($TypeAttr{"Type"} eq "Struct" 3471 and detect_lang($TypeId)) 3472 { 3473 $TypeAttr{"Type"} = "Class"; 3474 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo() 3475 } 3476 if($TypeAttr{"Type"} eq "Struct" 3477 or $TypeAttr{"Type"} eq "Class") 3478 { 3479 my $Skip = setBaseClasses($TypeId, \%TypeAttr); 3480 if($Skip) { 3481 return (); 3482 } 3483 } 3484 setSpec($TypeId, \%TypeAttr); 3485 setTypeMemb($TypeId, \%TypeAttr); 3486 $TypeAttr{"Tid"} = $TypeId; 3487 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}}) 3488 { 3489 my @Entries = split(/\n/, $VTable); 3490 foreach (1 .. $#Entries) 3491 { 3492 my $Entry = $Entries[$_]; 3493 if($Entry=~/\A(\d+)\s+(.+)\Z/) { 3494 $TypeAttr{"VTable"}{$1} = $2; 3495 } 3496 } 3497 } 3498 return %TypeAttr; 3499} 3500 3501sub detect_lang($) 3502{ 3503 my $TypeId = $_[0]; 3504 my $Info = $LibInfo{$Version}{"info"}{$TypeId}; 3505 if(check_gcc($GCC_PATH, "4")) 3506 { # GCC 4 fncs-node points to only non-artificial methods 3507 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /); 3508 } 3509 else 3510 { # GCC 3 3511 my $Fncs = getTreeAttr_Fncs($TypeId); 3512 while($Fncs) 3513 { 3514 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) { 3515 return 1; 3516 } 3517 $Fncs = getTreeAttr_Chan($Fncs); 3518 } 3519 } 3520 return 0; 3521} 3522 3523sub setSpec($$) 3524{ 3525 my ($TypeId, $TypeAttr) = @_; 3526 my $Info = $LibInfo{$Version}{"info"}{$TypeId}; 3527 if($Info=~/\s+spec\s+/) { 3528 $TypeAttr->{"Spec"} = 1; 3529 } 3530} 3531 3532sub setBaseClasses($$) 3533{ 3534 my ($TypeId, $TypeAttr) = @_; 3535 my $Info = $LibInfo{$Version}{"info"}{$TypeId}; 3536 if($Info=~/binf[ ]*:[ ]*@(\d+) /) 3537 { 3538 $Info = $LibInfo{$Version}{"info"}{$1}; 3539 my $Pos = 0; 3540 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //) 3541 { 3542 my ($Access, $BInfoId) = ($1, $2); 3543 my $ClassId = getBinfClassId($BInfoId); 3544 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId}; 3545 if(not $CType or $CType eq "template_type_parm" 3546 or $CType eq "typename_type") 3547 { # skip 3548 return 1; 3549 } 3550 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId}; 3551 if($Access=~/prot/) 3552 { 3553 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected"; 3554 } 3555 elsif($Access=~/priv/) 3556 { 3557 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private"; 3558 } 3559 $TypeAttr->{"Base"}{$ClassId}{"pos"} = $Pos++; 3560 if($BaseInfo=~/virt/) 3561 { # virtual base 3562 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1; 3563 } 3564 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1; 3565 } 3566 } 3567 return 0; 3568} 3569 3570sub getBinfClassId($) 3571{ 3572 my $Info = $LibInfo{$Version}{"info"}{$_[0]}; 3573 $Info=~/type[ ]*:[ ]*@(\d+) /; 3574 return $1; 3575} 3576 3577sub unmangledFormat($$) 3578{ 3579 my ($Name, $LibVersion) = @_; 3580 $Name = uncover_typedefs($Name, $LibVersion); 3581 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){}; 3582 $Name=~s/\(\w+\)(\d)/$1/; 3583 return $Name; 3584} 3585 3586sub modelUnmangled($$) 3587{ 3588 my ($InfoId, $Compiler) = @_; 3589 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) { 3590 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}; 3591 } 3592 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"}; 3593 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) { 3594 $PureSignature = "~".$PureSignature; 3595 } 3596 if(not $SymbolInfo{$Version}{$InfoId}{"Data"}) 3597 { 3598 my (@Params, @ParamTypes) = (); 3599 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"} 3600 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) { 3601 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}}); 3602 } 3603 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params) 3604 { # checking parameters 3605 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"}; 3606 my %PType = get_PureType($PId, $Version); 3607 my $PTName = unmangledFormat($PType{"Name"}, $Version); 3608 $PTName=~s/\b(restrict|register)\b//g; 3609 if($Compiler eq "MSVC") { 3610 $PTName=~s/\blong long\b/__int64/; 3611 } 3612 @ParamTypes = (@ParamTypes, $PTName); 3613 } 3614 if(@ParamTypes) { 3615 $PureSignature .= "(".join(", ", @ParamTypes).")"; 3616 } 3617 else 3618 { 3619 if($Compiler eq "MSVC") 3620 { 3621 $PureSignature .= "(void)"; 3622 } 3623 else 3624 { # GCC 3625 $PureSignature .= "()"; 3626 } 3627 } 3628 $PureSignature = delete_keywords($PureSignature); 3629 } 3630 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"}) 3631 { 3632 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version); 3633 $PureSignature = $ClassName."::".$PureSignature; 3634 } 3635 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) { 3636 $PureSignature = $NS."::".$PureSignature; 3637 } 3638 if($SymbolInfo{$Version}{$InfoId}{"Const"}) { 3639 $PureSignature .= " const"; 3640 } 3641 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) { 3642 $PureSignature .= " volatile"; 3643 } 3644 my $ShowReturn = 0; 3645 if($Compiler eq "MSVC" 3646 and $SymbolInfo{$Version}{$InfoId}{"Data"}) 3647 { 3648 $ShowReturn=1; 3649 } 3650 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId} 3651 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}})) 3652 { 3653 $ShowReturn=1; 3654 } 3655 if($ShowReturn) 3656 { # mangled names for template function specializations include return value 3657 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"}) 3658 { 3659 my %RType = get_PureType($ReturnId, $Version); 3660 my $ReturnName = unmangledFormat($RType{"Name"}, $Version); 3661 $PureSignature = $ReturnName." ".$PureSignature; 3662 } 3663 } 3664 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature)); 3665} 3666 3667sub mangle_symbol($$$) 3668{ # mangling for simple methods 3669 # see gcc-4.6.0/gcc/cp/mangle.c 3670 my ($InfoId, $LibVersion, $Compiler) = @_; 3671 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) { 3672 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}; 3673 } 3674 my $Mangled = ""; 3675 if($Compiler eq "GCC") { 3676 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion); 3677 } 3678 elsif($Compiler eq "MSVC") { 3679 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion); 3680 } 3681 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled); 3682} 3683 3684sub mangle_symbol_MSVC($$) 3685{ 3686 my ($InfoId, $LibVersion) = @_; 3687 return ""; 3688} 3689 3690sub mangle_symbol_GCC($$) 3691{ # see gcc-4.6.0/gcc/cp/mangle.c 3692 my ($InfoId, $LibVersion) = @_; 3693 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, ""); 3694 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"}; 3695 my %Repl = ();# SN_ replacements 3696 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}) 3697 { 3698 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl); 3699 if($MangledClass!~/\AN/) { 3700 $MangledClass = "N".$MangledClass; 3701 } 3702 else { 3703 $MangledClass=~s/E\Z//; 3704 } 3705 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) { 3706 $MangledClass=~s/\AN/NV/; 3707 } 3708 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) { 3709 $MangledClass=~s/\AN/NK/; 3710 } 3711 $Mangled .= $MangledClass; 3712 } 3713 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"}) 3714 { # mangled by name due to the absence of structured info 3715 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl); 3716 if($MangledNS!~/\AN/) { 3717 $MangledNS = "N".$MangledNS; 3718 } 3719 else { 3720 $MangledNS=~s/E\Z//; 3721 } 3722 $Mangled .= $MangledNS; 3723 } 3724 my ($ShortName, $TmplParams) = template_base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"}); 3725 my @TParams = (); 3726 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) 3727 { # parsing mode 3728 foreach (@TPos) { 3729 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"}); 3730 } 3731 } 3732 elsif($TmplParams) 3733 { # remangling mode 3734 # support for old ABI dumps 3735 @TParams = separate_params($TmplParams, 0); 3736 } 3737 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) { 3738 $Mangled .= "C1"; 3739 } 3740 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) { 3741 $Mangled .= "D0"; 3742 } 3743 elsif($ShortName) 3744 { 3745 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"}) 3746 { 3747 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"} 3748 and isConstType($Return, $LibVersion)) 3749 { # "const" global data is mangled as _ZL... 3750 $Mangled .= "L"; 3751 } 3752 } 3753 if($ShortName=~/\Aoperator(\W.*)\Z/) 3754 { 3755 my $Op = $1; 3756 $Op=~s/\A[ ]+//g; 3757 if(my $OpMngl = $OperatorMangling{$Op}) { 3758 $Mangled .= $OpMngl; 3759 } 3760 else { # conversion operator 3761 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl); 3762 } 3763 } 3764 else { 3765 $Mangled .= length($ShortName).$ShortName; 3766 } 3767 if(@TParams) 3768 { # templates 3769 $Mangled .= "I"; 3770 foreach my $TParam (@TParams) { 3771 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl); 3772 } 3773 $Mangled .= "E"; 3774 } 3775 if(not $ClassId and @TParams) { 3776 add_substitution($ShortName, \%Repl, 0); 3777 } 3778 } 3779 if($ClassId or $NameSpace) { 3780 $Mangled .= "E"; 3781 } 3782 if(@TParams) 3783 { 3784 if($Return) { 3785 $Mangled .= mangle_param($Return, $LibVersion, \%Repl); 3786 } 3787 } 3788 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"}) 3789 { 3790 my @Params = (); 3791 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"} 3792 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) { 3793 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}); 3794 } 3795 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params) 3796 { # checking parameters 3797 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"}; 3798 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl); 3799 } 3800 if(not @Params) { 3801 $Mangled .= "v"; 3802 } 3803 } 3804 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled); 3805 $Mangled = write_stdcxx_substitution($Mangled); 3806 if($Mangled eq "_Z") { 3807 return ""; 3808 } 3809 return $Mangled; 3810} 3811 3812sub correct_incharge($$$) 3813{ 3814 my ($InfoId, $LibVersion, $Mangled) = @_; 3815 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) 3816 { 3817 if($MangledNames{$LibVersion}{$Mangled}) { 3818 $Mangled=~s/C1E/C2E/; 3819 } 3820 } 3821 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) 3822 { 3823 if($MangledNames{$LibVersion}{$Mangled}) { 3824 $Mangled=~s/D0E/D1E/; 3825 } 3826 if($MangledNames{$LibVersion}{$Mangled}) { 3827 $Mangled=~s/D1E/D2E/; 3828 } 3829 } 3830 return $Mangled; 3831} 3832 3833sub template_base($) 3834{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl 3835 # NOTE: operators: >>, << 3836 my $Name = $_[0]; 3837 if($Name!~/>\Z/ or $Name!~/</) { 3838 return $Name; 3839 } 3840 my $TParams = $Name; 3841 while(my $CPos = find_center($TParams, "<")) 3842 { # search for the last <T> 3843 $TParams = substr($TParams, $CPos); 3844 } 3845 if($TParams=~s/\A<(.+)>\Z/$1/) { 3846 $Name=~s/<\Q$TParams\E>\Z//; 3847 } 3848 else 3849 { # error 3850 $TParams = ""; 3851 } 3852 return ($Name, $TParams); 3853} 3854 3855sub get_sub_ns($) 3856{ 3857 my $Name = $_[0]; 3858 my @NS = (); 3859 while(my $CPos = find_center($Name, ":")) 3860 { 3861 push(@NS, substr($Name, 0, $CPos)); 3862 $Name = substr($Name, $CPos); 3863 $Name=~s/\A:://; 3864 } 3865 return (join("::", @NS), $Name); 3866} 3867 3868sub mangle_ns($$$) 3869{ 3870 my ($Name, $LibVersion, $Repl) = @_; 3871 if(my $Tid = $TName_Tid{$LibVersion}{$Name}) 3872 { 3873 my $Mangled = mangle_param($Tid, $LibVersion, $Repl); 3874 $Mangled=~s/\AN(.+)E\Z/$1/; 3875 return $Mangled; 3876 3877 } 3878 else 3879 { 3880 my ($MangledNS, $SubNS) = ("", ""); 3881 ($SubNS, $Name) = get_sub_ns($Name); 3882 if($SubNS) { 3883 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl); 3884 } 3885 $MangledNS .= length($Name).$Name; 3886 add_substitution($MangledNS, $Repl, 0); 3887 return $MangledNS; 3888 } 3889} 3890 3891sub mangle_param($$$) 3892{ 3893 my ($PTid, $LibVersion, $Repl) = @_; 3894 my ($MPrefix, $Mangled) = ("", ""); 3895 my %ReplCopy = %{$Repl}; 3896 my %BaseType = get_BaseType($PTid, $LibVersion); 3897 my $BaseType_Name = $BaseType{"Name"}; 3898 if(not $BaseType_Name) { 3899 return ""; 3900 } 3901 my ($ShortName, $TmplParams) = template_base($BaseType_Name); 3902 my $Suffix = get_BaseTypeQual($PTid, $LibVersion); 3903 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){}; 3904 while($Suffix=~/(&|\*|const)\Z/) 3905 { 3906 if($Suffix=~s/[ ]*&\Z//) { 3907 $MPrefix .= "R"; 3908 } 3909 if($Suffix=~s/[ ]*\*\Z//) { 3910 $MPrefix .= "P"; 3911 } 3912 if($Suffix=~s/[ ]*const\Z//) 3913 { 3914 if($MPrefix=~/R|P/ 3915 or $Suffix=~/&|\*/) { 3916 $MPrefix .= "K"; 3917 } 3918 } 3919 if($Suffix=~s/[ ]*volatile\Z//) { 3920 $MPrefix .= "V"; 3921 } 3922 #if($Suffix=~s/[ ]*restrict\Z//) { 3923 #$MPrefix .= "r"; 3924 #} 3925 } 3926 if(my $Token = $IntrinsicMangling{$BaseType_Name}) { 3927 $Mangled .= $Token; 3928 } 3929 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/) 3930 { 3931 my @TParams = (); 3932 if(my @TPos = keys(%{$BaseType{"TParam"}})) 3933 { # parsing mode 3934 foreach (@TPos) { 3935 push(@TParams, $BaseType{"TParam"}{$_}{"name"}); 3936 } 3937 } 3938 elsif($TmplParams) 3939 { # remangling mode 3940 # support for old ABI dumps 3941 @TParams = separate_params($TmplParams, 0); 3942 } 3943 my $MangledNS = ""; 3944 my ($SubNS, $SName) = get_sub_ns($ShortName); 3945 if($SubNS) { 3946 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl); 3947 } 3948 $MangledNS .= length($SName).$SName; 3949 if(@TParams) { 3950 add_substitution($MangledNS, $Repl, 0); 3951 } 3952 $Mangled .= "N".$MangledNS; 3953 if(@TParams) 3954 { # templates 3955 $Mangled .= "I"; 3956 foreach my $TParam (@TParams) { 3957 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl); 3958 } 3959 $Mangled .= "E"; 3960 } 3961 $Mangled .= "E"; 3962 } 3963 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/) 3964 { 3965 if($BaseType{"Type"} eq "MethodPtr") { 3966 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F"; 3967 } 3968 else { 3969 $Mangled .= "PF"; 3970 } 3971 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl); 3972 my @Params = keys(%{$BaseType{"Param"}}); 3973 foreach my $Num (sort {int($a)<=>int($b)} @Params) { 3974 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl); 3975 } 3976 if(not @Params) { 3977 $Mangled .= "v"; 3978 } 3979 $Mangled .= "E"; 3980 } 3981 elsif($BaseType{"Type"} eq "FieldPtr") 3982 { 3983 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl); 3984 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl); 3985 } 3986 $Mangled = $MPrefix.$Mangled;# add prefix (RPK) 3987 if(my $Optimized = write_substitution($Mangled, \%ReplCopy)) 3988 { 3989 if($Mangled eq $Optimized) 3990 { 3991 if($ShortName!~/::/) 3992 { # remove "N ... E" 3993 if($MPrefix) { 3994 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g; 3995 } 3996 else { 3997 $Mangled=~s/\AN(.+)E\Z/$1/g; 3998 } 3999 } 4000 } 4001 else { 4002 $Mangled = $Optimized; 4003 } 4004 } 4005 add_substitution($Mangled, $Repl, 1); 4006 return $Mangled; 4007} 4008 4009sub mangle_template_param($$$) 4010{ # types + literals 4011 my ($TParam, $LibVersion, $Repl) = @_; 4012 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) { 4013 return mangle_param($TPTid, $LibVersion, $Repl); 4014 } 4015 elsif($TParam=~/\A(\d+)(\w+)\Z/) 4016 { # class_name<1u>::method(...) 4017 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E"; 4018 } 4019 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/) 4020 { # class_name<(signed char)1>::method(...) 4021 return "L".$IntrinsicMangling{$1}.$2."E"; 4022 } 4023 elsif($TParam eq "true") 4024 { # class_name<true>::method(...) 4025 return "Lb1E"; 4026 } 4027 elsif($TParam eq "false") 4028 { # class_name<true>::method(...) 4029 return "Lb0E"; 4030 } 4031 else { # internal error 4032 return length($TParam).$TParam; 4033 } 4034} 4035 4036sub add_substitution($$$) 4037{ 4038 my ($Value, $Repl, $Rec) = @_; 4039 if($Rec) 4040 { # subtypes 4041 my @Subs = ($Value); 4042 while($Value=~s/\A(R|P|K)//) { 4043 push(@Subs, $Value); 4044 } 4045 foreach (reverse(@Subs)) { 4046 add_substitution($_, $Repl, 0); 4047 } 4048 return; 4049 } 4050 return if($Value=~/\AS(\d*)_\Z/); 4051 $Value=~s/\AN(.+)E\Z/$1/g; 4052 return if(defined $Repl->{$Value}); 4053 return if(length($Value)<=1); 4054 return if($StdcxxMangling{$Value}); 4055 # check for duplicates 4056 my $Base = $Value; 4057 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl})) 4058 { 4059 my $Num = $Repl->{$Type}; 4060 my $Replace = macro_mangle($Num); 4061 $Base=~s/\Q$Replace\E/$Type/; 4062 } 4063 if(my $OldNum = $Repl->{$Base}) 4064 { 4065 $Repl->{$Value} = $OldNum; 4066 return; 4067 } 4068 my @Repls = sort {$b<=>$a} values(%{$Repl}); 4069 if(@Repls) { 4070 $Repl->{$Value} = $Repls[0]+1; 4071 } 4072 else { 4073 $Repl->{$Value} = -1; 4074 } 4075 # register duplicates 4076 # upward 4077 $Base = $Value; 4078 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl})) 4079 { 4080 next if($Base eq $Type); 4081 my $Num = $Repl->{$Type}; 4082 my $Replace = macro_mangle($Num); 4083 $Base=~s/\Q$Type\E/$Replace/; 4084 $Repl->{$Base} = $Repl->{$Value}; 4085 } 4086} 4087 4088sub macro_mangle($) 4089{ 4090 my $Num = $_[0]; 4091 if($Num==-1) { 4092 return "S_"; 4093 } 4094 else 4095 { 4096 my $Code = ""; 4097 if($Num<10) 4098 { # S0_, S1_, S2_, ... 4099 $Code = $Num; 4100 } 4101 elsif($Num>=10 and $Num<=35) 4102 { # SA_, SB_, SC_, ... 4103 $Code = chr(55+$Num); 4104 } 4105 else 4106 { # S10_, S11_, S12_ 4107 $Code = $Num-26; # 26 is length of english alphabet 4108 } 4109 return "S".$Code."_"; 4110 } 4111} 4112 4113sub write_stdcxx_substitution($) 4114{ 4115 my $Mangled = $_[0]; 4116 if($StdcxxMangling{$Mangled}) { 4117 return $StdcxxMangling{$Mangled}; 4118 } 4119 else 4120 { 4121 my @Repls = keys(%StdcxxMangling); 4122 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls; 4123 foreach my $MangledType (@Repls) 4124 { 4125 my $Replace = $StdcxxMangling{$MangledType}; 4126 #if($Mangled!~/$Replace/) { 4127 $Mangled=~s/N\Q$MangledType\EE/$Replace/g; 4128 $Mangled=~s/\Q$MangledType\E/$Replace/g; 4129 #} 4130 } 4131 } 4132 return $Mangled; 4133} 4134 4135sub write_substitution($$) 4136{ 4137 my ($Mangled, $Repl) = @_; 4138 if(defined $Repl->{$Mangled} 4139 and my $MnglNum = $Repl->{$Mangled}) { 4140 $Mangled = macro_mangle($MnglNum); 4141 } 4142 else 4143 { 4144 my @Repls = keys(%{$Repl}); 4145 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls; 4146 # FIXME: how to apply replacements? by num or by pos 4147 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls; 4148 foreach my $MangledType (@Repls) 4149 { 4150 my $Replace = macro_mangle($Repl->{$MangledType}); 4151 if($Mangled!~/$Replace/) { 4152 $Mangled=~s/N\Q$MangledType\EE/$Replace/g; 4153 $Mangled=~s/\Q$MangledType\E/$Replace/g; 4154 } 4155 } 4156 } 4157 return $Mangled; 4158} 4159 4160sub delete_keywords($) 4161{ 4162 my $TypeName = $_[0]; 4163 $TypeName=~s/\b(enum|struct|union|class) //g; 4164 return $TypeName; 4165} 4166 4167sub uncover_typedefs($$) 4168{ 4169 my ($TypeName, $LibVersion) = @_; 4170 return "" if(not $TypeName); 4171 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) { 4172 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}; 4173 } 4174 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName), ""); 4175 while($TypeName_New ne $TypeName_Pre) 4176 { 4177 $TypeName_Pre = $TypeName_New; 4178 my $TypeName_Copy = $TypeName_New; 4179 my %Words = (); 4180 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io) 4181 { 4182 if(not $Intrinsic_Keywords{$1}) { 4183 $Words{$1} = 1; 4184 } 4185 } 4186 foreach my $Word (keys(%Words)) 4187 { 4188 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word}; 4189 next if(not $BaseType_Name); 4190 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/); 4191 if($BaseType_Name=~/\([\*]+\)/) 4192 { # FuncPtr 4193 if($TypeName_New=~/\Q$Word\E(.*)\Z/) 4194 { 4195 my $Type_Suffix = $1; 4196 $TypeName_New = $BaseType_Name; 4197 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) { 4198 $TypeName_New = formatName($TypeName_New); 4199 } 4200 } 4201 } 4202 else 4203 { 4204 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) { 4205 $TypeName_New = formatName($TypeName_New); 4206 } 4207 } 4208 } 4209 } 4210 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New); 4211} 4212 4213sub isInternal($) 4214{ 4215 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 4216 { 4217 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) 4218 { 4219 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/) 4220 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL* 4221 return 1; 4222 } 4223 } 4224 } 4225 return 0; 4226} 4227 4228sub getDataVal($$) 4229{ 4230 my ($InfoId, $TypeId) = @_; 4231 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId}) 4232 { 4233 if($Info=~/init[ ]*:[ ]*@(\d+) /) 4234 { 4235 if(defined $LibInfo{$Version}{"info_type"}{$1} 4236 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr") 4237 { # char const* data = "str" 4238 # NOTE: disabled 4239 if(my $NopExpr = $LibInfo{$Version}{"info"}{$1}) 4240 { 4241 if($NopExpr=~/op 0[ ]*:[ ]*@(\d+) /) 4242 { 4243 if(defined $LibInfo{$Version}{"info_type"}{$1} 4244 and $LibInfo{$Version}{"info_type"}{$1} eq "addr_expr") 4245 { 4246 if(my $AddrExpr = $LibInfo{$Version}{"info"}{$1}) 4247 { 4248 if($AddrExpr=~/op 0[ ]*:[ ]*@(\d+) /) 4249 { 4250 return getInitVal($1, $TypeId); 4251 } 4252 } 4253 } 4254 } 4255 } 4256 } 4257 else { 4258 return getInitVal($1, $TypeId); 4259 } 4260 } 4261 } 4262 return undef; 4263} 4264 4265sub getInitVal($$) 4266{ 4267 my ($InfoId, $TypeId) = @_; 4268 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId}) 4269 { 4270 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId}) 4271 { 4272 if($InfoType eq "integer_cst") 4273 { 4274 my $Val = getNodeIntCst($InfoId); 4275 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/) 4276 { # characters 4277 $Val = chr($Val); 4278 } 4279 return $Val; 4280 } 4281 elsif($InfoType eq "string_cst") { 4282 return getNodeStrCst($InfoId); 4283 } 4284 } 4285 } 4286 return undef; 4287} 4288 4289sub set_Class_And_Namespace($) 4290{ 4291 my $InfoId = $_[0]; 4292 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId}) 4293 { 4294 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) 4295 { 4296 my $NSInfoId = $1; 4297 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId}) 4298 { 4299 if($InfoType eq "namespace_decl") { 4300 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId); 4301 } 4302 elsif($InfoType eq "record_type") { 4303 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId; 4304 } 4305 } 4306 } 4307 } 4308 if($SymbolInfo{$Version}{$InfoId}{"Class"} 4309 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) 4310 { # identify language 4311 setLanguage($Version, "C++"); 4312 } 4313} 4314 4315sub debugType($$) 4316{ 4317 my ($Tid, $LibVersion) = @_; 4318 my %Type = get_Type($Tid, $LibVersion); 4319 printMsg("INFO", Dumper(\%Type)); 4320} 4321 4322sub debugMangling($) 4323{ 4324 my $LibVersion = $_[0]; 4325 my %Mangled = (); 4326 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}})) 4327 { 4328 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"}) 4329 { 4330 if($Mngl=~/\A(_Z|\?)/) { 4331 $Mangled{$Mngl}=$InfoId; 4332 } 4333 } 4334 } 4335 translateSymbols(keys(%Mangled), $LibVersion); 4336 foreach my $Mngl (keys(%Mangled)) 4337 { 4338 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC"); 4339 my $U2 = $tr_name{$Mngl}; 4340 if($U1 ne $U2) { 4341 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n"); 4342 } 4343 } 4344} 4345 4346sub linkSymbol($) 4347{ # link symbols from shared libraries 4348 # with the symbols from header files 4349 my $InfoId = $_[0]; 4350 # try to mangle symbol 4351 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"}) 4352 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})) 4353 { # 1. GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data) 4354 # 2. GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions 4355 if(not $CheckHeadersOnly) 4356 { 4357 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) { 4358 return correct_incharge($InfoId, $Version, $Mangled); 4359 } 4360 } 4361 if($CheckHeadersOnly 4362 or not $BinaryOnly) 4363 { # 1. --headers-only mode 4364 # 2. not mangled src-only symbols 4365 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) { 4366 return $Mangled; 4367 } 4368 } 4369 } 4370 return ""; 4371} 4372 4373sub setLanguage($$) 4374{ 4375 my ($LibVersion, $Lang) = @_; 4376 if(not $UserLang) { 4377 $COMMON_LANGUAGE{$LibVersion} = $Lang; 4378 } 4379} 4380 4381sub getSymbolInfo($) 4382{ 4383 my $InfoId = $_[0]; 4384 if(isInternal($InfoId)) { 4385 return; 4386 } 4387 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId); 4388 if(not $SymbolInfo{$Version}{$InfoId}{"Header"} 4389 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) 4390 { 4391 delete($SymbolInfo{$Version}{$InfoId}); 4392 return; 4393 } 4394 setFuncAccess($InfoId); 4395 setFuncKind($InfoId); 4396 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"}) 4397 { 4398 delete($SymbolInfo{$Version}{$InfoId}); 4399 return; 4400 } 4401 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId); 4402 if($SymbolInfo{$Version}{$InfoId}{"Return"} = getFuncReturn($InfoId)) 4403 { 4404 if(not $TypeInfo{$Version}{$SymbolInfo{$Version}{$InfoId}{"Return"}}{"Name"}) 4405 { # templates 4406 delete($SymbolInfo{$Version}{$InfoId}); 4407 return; 4408 } 4409 } 4410 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"}) 4411 { 4412 if(defined $MissedTypedef{$Version}{$Rid}) 4413 { 4414 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) { 4415 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid; 4416 } 4417 } 4418 } 4419 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) { 4420 delete($SymbolInfo{$Version}{$InfoId}{"Return"}); 4421 } 4422 my $Orig = getFuncOrig($InfoId); 4423 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig); 4424 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\._/) 4425 { 4426 delete($SymbolInfo{$Version}{$InfoId}); 4427 return; 4428 } 4429 4430 if(defined $TemplateInstance{$Version}{"Func"}{$Orig}) 4431 { 4432 my @TParams = getTParams($Orig, "Func"); 4433 if(not @TParams) 4434 { 4435 delete($SymbolInfo{$Version}{$InfoId}); 4436 return; 4437 } 4438 foreach my $Pos (0 .. $#TParams) { 4439 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"}=$TParams[$Pos]; 4440 } 4441 my $PrmsInLine = join(", ", @TParams); 4442 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/) 4443 { # operator<< <T>, operator>> <T> 4444 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " "; 4445 } 4446 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".$PrmsInLine.">"; 4447 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}); 4448 } 4449 else 4450 { # support for GCC 3.4 4451 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//; 4452 } 4453 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = getTreeStr(getTreeAttr_Mngl($InfoId)); 4454 # NOTE: mangling of some symbols may change depending on GCC version 4455 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E 4456 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_ 4457 4458 if($SymbolInfo{$Version}{$InfoId}{"MnglName"} 4459 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A_Z/) 4460 { 4461 delete($SymbolInfo{$Version}{$InfoId}); 4462 return; 4463 } 4464 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) 4465 { # destructors have an empty parameter list 4466 my $Skip = setFuncParams($InfoId); 4467 if($Skip) { 4468 delete($SymbolInfo{$Version}{$InfoId}); 4469 return; 4470 } 4471 } 4472 set_Class_And_Namespace($InfoId); 4473 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"}) 4474 { 4475 if(not $TypeInfo{$Version}{$ClassId}{"Name"}) 4476 { # templates 4477 delete($SymbolInfo{$Version}{$InfoId}); 4478 return; 4479 } 4480 } 4481 if(not $CheckHeadersOnly) 4482 { 4483 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function" 4484 and not $SymbolInfo{$Version}{$InfoId}{"Class"} 4485 and link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) 4486 { # functions (C++): not mangled in library, but are mangled in TU dump 4487 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"} 4488 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps")) { 4489 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"}; 4490 } 4491 } 4492 } 4493 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i) 4494 { # extern "C" 4495 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C"; 4496 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"}; 4497 } 4498 if($UserLang and $UserLang eq "C") 4499 { # --lang=C option 4500 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"}; 4501 } 4502 if($COMMON_LANGUAGE{$Version} eq "C++") 4503 { # correct mangled & short names 4504 # C++ or --headers-only mode 4505 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/) 4506 { # support for old GCC versions: reconstruct real names for constructors and destructors 4507 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"})); 4508 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//; 4509 } 4510 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) 4511 { # try to mangle symbol (link with libraries) 4512 if(my $Mangled = linkSymbol($InfoId)) { 4513 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled; 4514 } 4515 } 4516 if($OStarget eq "windows") 4517 { # link MS C++ symbols from library with GCC symbols from headers 4518 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")}) 4519 { # exported symbols 4520 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1; 4521 } 4522 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC")) 4523 { # pure virtual symbols 4524 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2; 4525 } 4526 } 4527 } 4528 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) 4529 { # can't detect symbol name 4530 delete($SymbolInfo{$Version}{$InfoId}); 4531 return; 4532 } 4533 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"} 4534 and my $Spec = getVirtSpec($Orig)) 4535 { # identify virtual and pure virtual functions 4536 # NOTE: constructors cannot be virtual 4537 # NOTE: in GCC 4.7 D1 destructors have no virtual spec 4538 # in the TU dump, so taking it from the original symbol 4539 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"} 4540 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/)) 4541 { # NOTE: D2 destructors are not present in a v-table 4542 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1; 4543 } 4544 } 4545 if(isInline($InfoId)) { 4546 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1; 4547 } 4548 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) { 4549 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1; 4550 } 4551 if($SymbolInfo{$Version}{$InfoId}{"Constructor"} 4552 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"}) 4553 { 4554 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"} 4555 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"}) 4556 { # inline or auto-generated constructor 4557 delete($TypeInfo{$Version}{$ClassId}{"Copied"}); 4558 } 4559 } 4560 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"}) 4561 { 4562 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version)) 4563 { # non-target symbols 4564 delete($SymbolInfo{$Version}{$InfoId}); 4565 return; 4566 } 4567 } 4568 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method" 4569 or $SymbolInfo{$Version}{$InfoId}{"Constructor"} 4570 or $SymbolInfo{$Version}{$InfoId}{"Destructor"} 4571 or $SymbolInfo{$Version}{$InfoId}{"Class"}) 4572 { 4573 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/) { 4574 delete($SymbolInfo{$Version}{$InfoId}); 4575 return; 4576 } 4577 } 4578 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}) 4579 { 4580 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) 4581 { # one instance for one mangled name only 4582 delete($SymbolInfo{$Version}{$InfoId}); 4583 return; 4584 } 4585 else { 4586 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1; 4587 } 4588 } 4589 if($SymbolInfo{$Version}{$InfoId}{"Constructor"} 4590 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) { 4591 delete($SymbolInfo{$Version}{$InfoId}{"Return"}); 4592 } 4593 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/ 4594 and $SymbolInfo{$Version}{$InfoId}{"Class"}) 4595 { 4596 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function") 4597 { # static methods 4598 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1; 4599 } 4600 } 4601 if(getFuncLink($InfoId) eq "Static") { 4602 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1; 4603 } 4604 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/) 4605 { 4606 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) 4607 { 4608 if($Unmangled=~/\.\_\d/) { 4609 delete($SymbolInfo{$Version}{$InfoId}); 4610 return; 4611 } 4612 } 4613 } 4614 delete($SymbolInfo{$Version}{$InfoId}{"Type"}); 4615 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) { 4616 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1; 4617 } 4618 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) { 4619 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1; 4620 } 4621} 4622 4623sub isInline($) 4624{ # "body: undefined" in the tree 4625 # -fkeep-inline-functions GCC option should be specified 4626 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 4627 { 4628 if($Info=~/ undefined /i) { 4629 return 0; 4630 } 4631 } 4632 return 1; 4633} 4634 4635sub getTypeId($) 4636{ 4637 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 4638 { 4639 if($Info=~/type[ ]*:[ ]*@(\d+) /) { 4640 return $1; 4641 } 4642 } 4643 return ""; 4644} 4645 4646sub setTypeMemb($$) 4647{ 4648 my ($TypeId, $TypeAttr) = @_; 4649 my $TypeType = $TypeAttr->{"Type"}; 4650 my ($Pos, $UnnamedPos) = (0, 0); 4651 if($TypeType eq "Enum") 4652 { 4653 my $TypeMembInfoId = getTreeAttr_Csts($TypeId); 4654 while($TypeMembInfoId) 4655 { 4656 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($TypeMembInfoId); 4657 my $MembName = getTreeStr(getTreeAttr_Purp($TypeMembInfoId)); 4658 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName; 4659 $EnumMembName_Id{$Version}{getTreeAttr_Valu($TypeMembInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName; 4660 $TypeMembInfoId = getNextElem($TypeMembInfoId); 4661 $Pos += 1; 4662 } 4663 } 4664 elsif($TypeType=~/\A(Struct|Class|Union)\Z/) 4665 { 4666 my $TypeMembInfoId = getTreeAttr_Flds($TypeId); 4667 while($TypeMembInfoId) 4668 { 4669 my $IType = $LibInfo{$Version}{"info_type"}{$TypeMembInfoId}; 4670 my $MInfo = $LibInfo{$Version}{"info"}{$TypeMembInfoId}; 4671 if(not $IType or $IType ne "field_decl") 4672 { # search for fields, skip other stuff in the declaration 4673 $TypeMembInfoId = getNextElem($TypeMembInfoId); 4674 next; 4675 } 4676 my $StructMembName = getStructMembName($TypeMembInfoId); 4677 if($StructMembName=~/_vptr\./) 4678 { # virtual tables 4679 $TypeMembInfoId = getNextElem($TypeMembInfoId); 4680 next; 4681 } 4682 if(not $StructMembName) 4683 { # unnamed fields 4684 if($TypeAttr->{"Name"}!~/_type_info_pseudo/) 4685 { 4686 my $UnnamedTid = getTreeAttr_Type($TypeMembInfoId); 4687 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid)); 4688 if(isAnon($UnnamedTName)) 4689 { # rename unnamed fields to unnamed0, unnamed1, ... 4690 $StructMembName = "unnamed".($UnnamedPos++); 4691 } 4692 } 4693 } 4694 if(not $StructMembName) 4695 { # unnamed fields and base classes 4696 $TypeMembInfoId = getNextElem($TypeMembInfoId); 4697 next; 4698 } 4699 my $MembTypeId = getTreeAttr_Type($TypeMembInfoId); 4700 if(defined $MissedTypedef{$Version}{$MembTypeId}) 4701 { 4702 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) { 4703 $MembTypeId = $AddedTid; 4704 } 4705 } 4706 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId; 4707 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName; 4708 if((my $Access = getTreeAccess($TypeMembInfoId)) ne "public") 4709 { # marked only protected and private, public by default 4710 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access; 4711 } 4712 if($MInfo=~/spec:\s*mutable /) 4713 { # mutable fields 4714 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1; 4715 } 4716 if(my $BFSize = getStructMembBitFieldSize($TypeMembInfoId)) { 4717 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize; 4718 } 4719 else 4720 { # set alignment for non-bit fields 4721 # alignment for bitfields is always equal to 1 bit 4722 if(my $Algn = getAlgn($TypeMembInfoId)) { 4723 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE; 4724 } 4725 } 4726 $TypeMembInfoId = getNextElem($TypeMembInfoId); 4727 $Pos += 1; 4728 } 4729 } 4730} 4731 4732sub setFuncParams($) 4733{ 4734 my $InfoId = $_[0]; 4735 my $ParamInfoId = getTreeAttr_Args($InfoId); 4736 if(getFuncType($InfoId) eq "Method") 4737 { # check type of "this" pointer 4738 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId); 4739 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"}) 4740 { 4741 if($ObjectName=~/\bconst(| volatile)\*const\b/) { 4742 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1; 4743 } 4744 if($ObjectName=~/\bvolatile\b/) { 4745 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1; 4746 } 4747 } 4748 else 4749 { # skip 4750 return 1; 4751 } 4752 $ParamInfoId = getNextElem($ParamInfoId); 4753 } 4754 my ($Pos, $Vtt_Pos) = (0, -1); 4755 while($ParamInfoId) 4756 { # formal args 4757 my $ParamTypeId = getTreeAttr_Type($ParamInfoId); 4758 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId)); 4759 if(not $ParamName) 4760 { # unnamed 4761 $ParamName = "p".($Pos+1); 4762 } 4763 if(defined $MissedTypedef{$Version}{$ParamTypeId}) 4764 { 4765 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) { 4766 $ParamTypeId = $AddedTid; 4767 } 4768 } 4769 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"}; 4770 if(not $PType or $PType eq "Unknown") { 4771 return 1; 4772 } 4773 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"}; 4774 if(not $PTName) { 4775 return 1; 4776 } 4777 if($PTName eq "void") { 4778 last; 4779 } 4780 if($ParamName eq "__vtt_parm" 4781 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**") 4782 { 4783 $Vtt_Pos = $Pos; 4784 $ParamInfoId = getNextElem($ParamInfoId); 4785 next; 4786 } 4787 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId; 4788 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName; 4789 if(my $Algn = getAlgn($ParamInfoId)) { 4790 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE; 4791 } 4792 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"}) { 4793 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($Pos+1); 4794 } 4795 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /) 4796 { # foo(register type arg) 4797 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1; 4798 } 4799 $ParamInfoId = getNextElem($ParamInfoId); 4800 $Pos += 1; 4801 } 4802 if(setFuncArgs($InfoId, $Vtt_Pos)) { 4803 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = -1; 4804 } 4805 return 0; 4806} 4807 4808sub setFuncArgs($$) 4809{ 4810 my ($InfoId, $Vtt_Pos) = @_; 4811 my $FuncTypeId = getFuncTypeId($InfoId); 4812 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId); 4813 if(getFuncType($InfoId) eq "Method") { 4814 $ParamListElemId = getNextElem($ParamListElemId); 4815 } 4816 if(not $ParamListElemId) 4817 { # foo(...) 4818 return 1; 4819 } 4820 my $HaveVoid = 0; 4821 my $Pos = 0; 4822 while($ParamListElemId) 4823 { # actual params: may differ from formal args 4824 # formal int*const 4825 # actual: int* 4826 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos) 4827 { 4828 $Vtt_Pos=-1; 4829 $ParamListElemId = getNextElem($ParamListElemId); 4830 next; 4831 } 4832 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId); 4833 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void") 4834 { 4835 $HaveVoid = 1; 4836 last; 4837 } 4838 elsif(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"}) 4839 { 4840 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId; 4841 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"}) 4842 { # unnamed 4843 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($Pos+1); 4844 } 4845 } 4846 if(my $PurpId = getTreeAttr_Purp($ParamListElemId)) 4847 { # default arguments 4848 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId}) { 4849 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = getInitVal($PurpId, $ParamTypeId); 4850 } 4851 } 4852 $ParamListElemId = getNextElem($ParamListElemId); 4853 $Pos += 1; 4854 } 4855 return ($Pos>=1 and not $HaveVoid); 4856} 4857 4858sub getTreeAttr_Chan($) 4859{ 4860 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 4861 { 4862 if($Info=~/chan[ ]*:[ ]*@(\d+) /) { 4863 return $1; 4864 } 4865 } 4866 return ""; 4867} 4868 4869sub getTreeAttr_Chain($) 4870{ 4871 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 4872 { 4873 if($Info=~/chain[ ]*:[ ]*@(\d+) /) { 4874 return $1; 4875 } 4876 } 4877 return ""; 4878} 4879 4880sub getTreeAttr_Scpe($) 4881{ 4882 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 4883 { 4884 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) { 4885 return $1; 4886 } 4887 } 4888 return ""; 4889} 4890 4891sub getTreeAttr_Type($) 4892{ 4893 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 4894 { 4895 if($Info=~/type[ ]*:[ ]*@(\d+) /) { 4896 return $1; 4897 } 4898 } 4899 return ""; 4900} 4901 4902sub getTreeAttr_Name($) 4903{ 4904 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 4905 { 4906 if($Info=~/name[ ]*:[ ]*@(\d+) /) { 4907 return $1; 4908 } 4909 } 4910 return ""; 4911} 4912 4913sub getTreeAttr_Mngl($) 4914{ 4915 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 4916 { 4917 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) { 4918 return $1; 4919 } 4920 } 4921 return ""; 4922} 4923 4924sub getTreeAttr_Prms($) 4925{ 4926 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 4927 { 4928 if($Info=~/prms[ ]*:[ ]*@(\d+) /) { 4929 return $1; 4930 } 4931 } 4932 return ""; 4933} 4934 4935sub getTreeAttr_Fncs($) 4936{ 4937 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 4938 { 4939 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) { 4940 return $1; 4941 } 4942 } 4943 return ""; 4944} 4945 4946sub getTreeAttr_Csts($) 4947{ 4948 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 4949 { 4950 if($Info=~/csts[ ]*:[ ]*@(\d+) /) { 4951 return $1; 4952 } 4953 } 4954 return ""; 4955} 4956 4957sub getTreeAttr_Purp($) 4958{ 4959 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 4960 { 4961 if($Info=~/purp[ ]*:[ ]*@(\d+) /) { 4962 return $1; 4963 } 4964 } 4965 return ""; 4966} 4967 4968sub getTreeAttr_Valu($) 4969{ 4970 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 4971 { 4972 if($Info=~/valu[ ]*:[ ]*@(\d+) /) { 4973 return $1; 4974 } 4975 } 4976 return ""; 4977} 4978 4979sub getTreeAttr_Flds($) 4980{ 4981 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 4982 { 4983 if($Info=~/flds[ ]*:[ ]*@(\d+) /) { 4984 return $1; 4985 } 4986 } 4987 return ""; 4988} 4989 4990sub getTreeAttr_Args($) 4991{ 4992 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 4993 { 4994 if($Info=~/args[ ]*:[ ]*@(\d+) /) { 4995 return $1; 4996 } 4997 } 4998 return ""; 4999} 5000 5001sub getTreeValue($) 5002{ 5003 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 5004 { 5005 if($Info=~/low[ ]*:[ ]*([^ ]+) /) { 5006 return $1; 5007 } 5008 } 5009 return ""; 5010} 5011 5012sub getTreeAccess($) 5013{ 5014 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 5015 { 5016 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /) 5017 { 5018 my $Access = $1; 5019 if($Access eq "prot") { 5020 return "protected"; 5021 } 5022 elsif($Access eq "priv") { 5023 return "private"; 5024 } 5025 } 5026 elsif($Info=~/ protected /) 5027 { # support for old GCC versions 5028 return "protected"; 5029 } 5030 elsif($Info=~/ private /) 5031 { # support for old GCC versions 5032 return "private"; 5033 } 5034 } 5035 return "public"; 5036} 5037 5038sub setFuncAccess($) 5039{ 5040 my $Access = getTreeAccess($_[0]); 5041 if($Access eq "protected") { 5042 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1; 5043 } 5044 elsif($Access eq "private") { 5045 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1; 5046 } 5047} 5048 5049sub setTypeAccess($$) 5050{ 5051 my ($TypeId, $TypeAttr) = @_; 5052 my $Access = getTreeAccess($TypeId); 5053 if($Access eq "protected") { 5054 $TypeAttr->{"Protected"} = 1; 5055 } 5056 elsif($Access eq "private") { 5057 $TypeAttr->{"Private"} = 1; 5058 } 5059} 5060 5061sub setFuncKind($) 5062{ 5063 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 5064 { 5065 if($Info=~/pseudo tmpl/) { 5066 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1; 5067 } 5068 elsif($Info=~/ constructor /) { 5069 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1; 5070 } 5071 elsif($Info=~/ destructor /) { 5072 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1; 5073 } 5074 } 5075} 5076 5077sub getVirtSpec($) 5078{ 5079 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 5080 { 5081 if($Info=~/spec[ ]*:[ ]*pure /) { 5082 return "PureVirt"; 5083 } 5084 elsif($Info=~/spec[ ]*:[ ]*virt /) { 5085 return "Virt"; 5086 } 5087 elsif($Info=~/ pure\s+virtual /) 5088 { # support for old GCC versions 5089 return "PureVirt"; 5090 } 5091 elsif($Info=~/ virtual /) 5092 { # support for old GCC versions 5093 return "Virt"; 5094 } 5095 } 5096 return ""; 5097} 5098 5099sub getFuncLink($) 5100{ 5101 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 5102 { 5103 if($Info=~/link[ ]*:[ ]*static /) { 5104 return "Static"; 5105 } 5106 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) { 5107 return $1; 5108 } 5109 } 5110 return ""; 5111} 5112 5113sub get_IntNameSpace($$) 5114{ 5115 my ($Interface, $LibVersion) = @_; 5116 return "" if(not $Interface or not $LibVersion); 5117 if(defined $Cache{"get_IntNameSpace"}{$Interface}{$LibVersion}) { 5118 return $Cache{"get_IntNameSpace"}{$Interface}{$LibVersion}; 5119 } 5120 my $Signature = get_Signature($Interface, $LibVersion); 5121 if($Signature=~/\:\:/) 5122 { 5123 my $FounNameSpace = 0; 5124 foreach my $NameSpace (sort {get_depth($b)<=>get_depth($a)} keys(%{$NestedNameSpaces{$LibVersion}})) 5125 { 5126 if($Signature=~/(\A|\s+for\s+)\Q$NameSpace\E\:\:/) { 5127 return ($Cache{"get_IntNameSpace"}{$Interface}{$LibVersion} = $NameSpace); 5128 } 5129 } 5130 } 5131 else { 5132 return ($Cache{"get_IntNameSpace"}{$Interface}{$LibVersion} = ""); 5133 } 5134} 5135 5136sub parse_TypeNameSpace($$) 5137{ 5138 my ($TypeName, $LibVersion) = @_; 5139 return "" if(not $TypeName or not $LibVersion); 5140 if(defined $Cache{"parse_TypeNameSpace"}{$TypeName}{$LibVersion}) { 5141 return $Cache{"parse_TypeNameSpace"}{$TypeName}{$LibVersion}; 5142 } 5143 if($TypeName=~/\:\:/) 5144 { 5145 my $FounNameSpace = 0; 5146 foreach my $NameSpace (sort {get_depth($b)<=>get_depth($a)} keys(%{$NestedNameSpaces{$LibVersion}})) 5147 { 5148 if($TypeName=~/\A\Q$NameSpace\E\:\:/) { 5149 return ($Cache{"parse_TypeNameSpace"}{$TypeName}{$LibVersion} = $NameSpace); 5150 } 5151 } 5152 } 5153 else { 5154 return ($Cache{"parse_TypeNameSpace"}{$TypeName}{$LibVersion} = ""); 5155 } 5156} 5157 5158sub getNameSpace($) 5159{ 5160 my $TypeInfoId = $_[0]; 5161 if(my $NSInfoId = getTreeAttr_Scpe($TypeInfoId)) 5162 { 5163 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId}) 5164 { 5165 if($InfoType eq "namespace_decl") 5166 { 5167 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /) 5168 { 5169 my $NameSpace = getTreeStr($1); 5170 if($NameSpace eq "::") 5171 { # global namespace 5172 return ""; 5173 } 5174 if(my $BaseNameSpace = getNameSpace($NSInfoId)) { 5175 $NameSpace = $BaseNameSpace."::".$NameSpace; 5176 } 5177 $NestedNameSpaces{$Version}{$NameSpace} = 1; 5178 return $NameSpace; 5179 } 5180 else { 5181 return ""; 5182 } 5183 } 5184 elsif($InfoType eq "record_type") 5185 { # inside data type 5186 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId); 5187 return $Name; 5188 } 5189 } 5190 } 5191 return ""; 5192} 5193 5194sub getNameSpaceId($) 5195{ 5196 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 5197 { 5198 if($Info=~/scpe[ ]*:[ ]*\@(\d+)/) { 5199 return $1; 5200 } 5201 } 5202 return ""; 5203} 5204 5205sub getStructMembName($) 5206{ 5207 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 5208 { 5209 if($Info=~/name[ ]*:[ ]*\@(\d+)/) { 5210 return getTreeStr($1); 5211 } 5212 } 5213 return ""; 5214} 5215 5216sub getEnumMembVal($) 5217{ 5218 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 5219 { 5220 if($Info=~/valu[ ]*:[ ]*\@(\d+)/) 5221 { 5222 if(my $VInfo = $LibInfo{$Version}{"info"}{$1}) 5223 { 5224 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/) 5225 { # in newer versions of GCC the value is in the "const_decl->cnst" node 5226 return getTreeValue($1); 5227 } 5228 else 5229 { # some old versions of GCC (3.3) have the value in the "integer_cst" node 5230 return getTreeValue($1); 5231 } 5232 } 5233 } 5234 } 5235 return ""; 5236} 5237 5238sub getSize($) 5239{ 5240 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 5241 { 5242 if($Info=~/size[ ]*:[ ]*\@(\d+)/) { 5243 return getTreeValue($1); 5244 } 5245 } 5246 return 0; 5247} 5248 5249sub getAlgn($) 5250{ 5251 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 5252 { 5253 if($Info=~/algn[ ]*:[ ]*(\d+) /) { 5254 return $1; 5255 } 5256 } 5257 return ""; 5258} 5259 5260sub getStructMembBitFieldSize($) 5261{ 5262 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 5263 { 5264 if($Info=~/ bitfield /) { 5265 return getSize($_[0]); 5266 } 5267 } 5268 return 0; 5269} 5270 5271sub getNextElem($) 5272{ 5273 if(my $Chan = getTreeAttr_Chan($_[0])) { 5274 return $Chan; 5275 } 5276 elsif(my $Chain = getTreeAttr_Chain($_[0])) { 5277 return $Chain; 5278 } 5279 return ""; 5280} 5281 5282sub registerHeader($$) 5283{ # input: absolute path of header, relative path or name 5284 my ($Header, $LibVersion) = @_; 5285 if(not $Header) { 5286 return ""; 5287 } 5288 if(is_abs($Header) and not -f $Header) 5289 { # incorrect absolute path 5290 exitStatus("Access_Error", "can't access \'$Header\'"); 5291 } 5292 if(skipHeader($Header, $LibVersion)) 5293 { # skip 5294 return ""; 5295 } 5296 if(my $Header_Path = identifyHeader($Header, $LibVersion)) 5297 { 5298 detect_header_includes($Header_Path, $LibVersion); 5299 5300 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path}) 5301 { # redirect 5302 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"} 5303 or skipHeader($RHeader_Path, $LibVersion)) 5304 { # skip 5305 return ""; 5306 } 5307 $Header_Path = $RHeader_Path; 5308 } 5309 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path}) 5310 { # skip 5311 return ""; 5312 } 5313 5314 if(my $HName = get_filename($Header_Path)) 5315 { # register 5316 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName; 5317 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1; 5318 } 5319 5320 if(($Header=~/\.(\w+)\Z/ and $1 ne "h") 5321 or $Header!~/\.(\w+)\Z/) 5322 { # hpp, hh 5323 setLanguage($LibVersion, "C++"); 5324 } 5325 5326 if($CheckHeadersOnly 5327 and $Header=~/(\A|\/)c\+\+(\/|\Z)/) 5328 { # /usr/include/c++/4.6.1/... 5329 $STDCXX_TESTING = 1; 5330 } 5331 5332 return $Header_Path; 5333 } 5334 return ""; 5335} 5336 5337sub register_directory($$$) 5338{ 5339 my ($Dir, $WithDeps, $LibVersion) = @_; 5340 $Dir=~s/[\/\\]+\Z//g; 5341 return if(not $LibVersion or not $Dir or not -d $Dir); 5342 return if(skipHeader($Dir, $LibVersion)); 5343 $Dir = get_abs_path($Dir); 5344 my $Mode = "All"; 5345 if($WithDeps) 5346 { 5347 if($RegisteredDirs{$LibVersion}{$Dir}{1}) { 5348 return; 5349 } 5350 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) { 5351 $Mode = "DepsOnly"; 5352 } 5353 } 5354 else 5355 { 5356 if($RegisteredDirs{$LibVersion}{$Dir}{1} 5357 or $RegisteredDirs{$LibVersion}{$Dir}{0}) { 5358 return; 5359 } 5360 } 5361 $Header_Dependency{$LibVersion}{$Dir} = 1; 5362 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1; 5363 if($Mode eq "DepsOnly") 5364 { 5365 foreach my $Path (cmd_find($Dir,"d","","")) { 5366 $Header_Dependency{$LibVersion}{$Path} = 1; 5367 } 5368 return; 5369 } 5370 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f","","")) 5371 { 5372 if($WithDeps) 5373 { 5374 my $SubDir = $Path; 5375 while(($SubDir = get_dirname($SubDir)) ne $Dir) 5376 { # register all sub directories 5377 $Header_Dependency{$LibVersion}{$SubDir} = 1; 5378 } 5379 } 5380 next if(is_not_header($Path)); 5381 next if(ignore_path($Path)); 5382 next if(skipHeader($Path, $LibVersion)); 5383 # Neighbors 5384 foreach my $Part (get_path_prefixes($Path)) { 5385 $Include_Neighbors{$LibVersion}{$Part} = $Path; 5386 } 5387 } 5388 if(get_filename($Dir) eq "include") 5389 { # search for "lib/include/" directory 5390 my $LibDir = $Dir; 5391 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) { 5392 register_directory($LibDir, $WithDeps, $LibVersion); 5393 } 5394 } 5395} 5396 5397sub parse_redirect($$$) 5398{ 5399 my ($Content, $Path, $LibVersion) = @_; 5400 my @Errors = (); 5401 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) { 5402 push(@Errors, $1); 5403 } 5404 my $Redirect = ""; 5405 foreach (@Errors) 5406 { 5407 s/\s{2,}/ /g; 5408 if(/(only|must\ include 5409 |update\ to\ include 5410 |replaced\ with 5411 |replaced\ by|renamed\ to 5412 |is\ in|use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix) 5413 { 5414 $Redirect = $2; 5415 last; 5416 } 5417 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i) 5418 { 5419 $Redirect = $2; 5420 last; 5421 } 5422 elsif(/this\ header\ should\ not\ be\ used 5423 |programs\ should\ not\ directly\ include 5424 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header)) 5425 |is\ not\ supported\ API\ for\ general\ use 5426 |do\ not\ use 5427 |should\ not\ be\ used 5428 |cannot\ be\ included\ directly/ix and not /\ from\ /i) { 5429 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1; 5430 } 5431 } 5432 if($Redirect) 5433 { 5434 $Redirect=~s/\A<//g; 5435 $Redirect=~s/>\Z//g; 5436 } 5437 return $Redirect; 5438} 5439 5440sub parse_includes($$) 5441{ 5442 my ($Content, $Path) = @_; 5443 my %Includes = (); 5444 while($Content=~s/#([ \t]*)(include|include_next|import)([ \t]*)(<|")([^<>"]+)(>|")//) 5445 { # C/C++: include, Objective C/C++: import directive 5446 my ($Header, $Method) = ($5, $4); 5447 $Header = path_format($Header, $OSgroup); 5448 if($Method eq "\"" or is_abs($Header)) 5449 { 5450 if(-e joinPath(get_dirname($Path), $Header)) 5451 { # relative path exists 5452 $Includes{$Header} = -1; 5453 } 5454 else 5455 { # include "..." that doesn't exist is equal to include <...> 5456 $Includes{$Header} = 2; 5457 } 5458 } 5459 else { 5460 $Includes{$Header} = 1; 5461 } 5462 } 5463 return \%Includes; 5464} 5465 5466sub ignore_path($) 5467{ 5468 my $Path = $_[0]; 5469 if($Path=~/\~\Z/) 5470 {# skipping system backup files 5471 return 1; 5472 } 5473 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/) 5474 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories 5475 return 1; 5476 } 5477 return 0; 5478} 5479 5480sub sort_by_word($$) 5481{ 5482 my ($ArrRef, $W) = @_; 5483 return if(length($W)<2); 5484 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef}; 5485} 5486 5487sub natural_sorting($$) 5488{ 5489 my ($H1, $H2) = @_; 5490 $H1=~s/\.[a-z]+\Z//ig; 5491 $H2=~s/\.[a-z]+\Z//ig; 5492 my ($HDir1, $Hname1) = separate_path($H1); 5493 my ($HDir2, $Hname2) = separate_path($H2); 5494 my $Dirname1 = get_filename($HDir1); 5495 my $Dirname2 = get_filename($HDir2); 5496 if($H1 eq $H2) { 5497 return 0; 5498 } 5499 elsif($H1=~/\A\Q$H2\E/) { 5500 return 1; 5501 } 5502 elsif($H2=~/\A\Q$H1\E/) { 5503 return -1; 5504 } 5505 elsif($HDir1=~/\Q$Hname1\E/i 5506 and $HDir2!~/\Q$Hname2\E/i) 5507 {# include/glib-2.0/glib.h 5508 return -1; 5509 } 5510 elsif($HDir2=~/\Q$Hname2\E/i 5511 and $HDir1!~/\Q$Hname1\E/i) 5512 {# include/glib-2.0/glib.h 5513 return 1; 5514 } 5515 elsif($Hname1=~/\Q$Dirname1\E/i 5516 and $Hname2!~/\Q$Dirname2\E/i) 5517 {# include/hildon-thumbnail/hildon-thumbnail-factory.h 5518 return -1; 5519 } 5520 elsif($Hname2=~/\Q$Dirname2\E/i 5521 and $Hname1!~/\Q$Dirname1\E/i) 5522 {# include/hildon-thumbnail/hildon-thumbnail-factory.h 5523 return 1; 5524 } 5525 elsif($Hname1=~/(config|lib)/i 5526 and $Hname2!~/(config|lib)/i) 5527 {# include/alsa/asoundlib.h 5528 return -1; 5529 } 5530 elsif($Hname2=~/(config|lib)/i 5531 and $Hname1!~/(config|lib)/i) 5532 {# include/alsa/asoundlib.h 5533 return 1; 5534 } 5535 elsif(checkRelevance($H1) 5536 and not checkRelevance($H2)) 5537 {# libebook/e-book.h 5538 return -1; 5539 } 5540 elsif(checkRelevance($H2) 5541 and not checkRelevance($H1)) 5542 {# libebook/e-book.h 5543 return 1; 5544 } 5545 else { 5546 return (lc($H1) cmp lc($H2)); 5547 } 5548} 5549 5550sub searchForHeaders($) 5551{ 5552 my $LibVersion = $_[0]; 5553 # gcc standard include paths 5554 find_gcc_cxx_headers($LibVersion); 5555 # processing header paths 5556 foreach my $Path (keys(%{$Descriptor{$LibVersion}{"IncludePaths"}}), 5557 keys(%{$Descriptor{$LibVersion}{"AddIncludePaths"}})) 5558 { 5559 my $IPath = $Path; 5560 if($SystemRoot) 5561 { 5562 if(is_abs($Path)) { 5563 $Path = $SystemRoot.$Path; 5564 } 5565 } 5566 if(not -e $Path) { 5567 exitStatus("Access_Error", "can't access \'$Path\'"); 5568 } 5569 elsif(-f $Path) { 5570 exitStatus("Access_Error", "\'$Path\' - not a directory"); 5571 } 5572 elsif(-d $Path) 5573 { 5574 $Path = get_abs_path($Path); 5575 register_directory($Path, 0, $LibVersion); 5576 if($Descriptor{$LibVersion}{"AddIncludePaths"}{$IPath}) { 5577 $Add_Include_Paths{$LibVersion}{$Path} = 1; 5578 } 5579 else { 5580 $Include_Paths{$LibVersion}{$Path} = 1; 5581 } 5582 } 5583 } 5584 if(keys(%{$Include_Paths{$LibVersion}})) { 5585 $INC_PATH_AUTODETECT{$LibVersion} = 0; 5586 } 5587 # registering directories 5588 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"})) 5589 { 5590 next if(not -e $Path); 5591 $Path = get_abs_path($Path); 5592 $Path = path_format($Path, $OSgroup); 5593 if(-d $Path) { 5594 register_directory($Path, 1, $LibVersion); 5595 } 5596 elsif(-f $Path) 5597 { 5598 my $Dir = get_dirname($Path); 5599 if(not $SystemPaths{"include"}{$Dir} 5600 and not $LocalIncludes{$Dir}) 5601 { 5602 register_directory($Dir, 1, $LibVersion); 5603 if(my $OutDir = get_dirname($Dir)) 5604 { # registering the outer directory 5605 if(not $SystemPaths{"include"}{$OutDir} 5606 and not $LocalIncludes{$OutDir}) { 5607 register_directory($OutDir, 0, $LibVersion); 5608 } 5609 } 5610 } 5611 } 5612 } 5613 5614 # clean memory 5615 %RegisteredDirs = (); 5616 5617 # registering headers 5618 my $Position = 0; 5619 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"})) 5620 { 5621 if(is_abs($Dest) and not -e $Dest) { 5622 exitStatus("Access_Error", "can't access \'$Dest\'"); 5623 } 5624 $Dest = path_format($Dest, $OSgroup); 5625 if(is_header($Dest, 1, $LibVersion)) 5626 { 5627 if(my $HPath = registerHeader($Dest, $LibVersion)) { 5628 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++; 5629 } 5630 } 5631 elsif(-d $Dest) 5632 { 5633 my @Registered = (); 5634 foreach my $Path (cmd_find($Dest,"f","","")) 5635 { 5636 next if(ignore_path($Path)); 5637 next if(not is_header($Path, 0, $LibVersion)); 5638 if(my $HPath = registerHeader($Path, $LibVersion)) { 5639 push(@Registered, $HPath); 5640 } 5641 } 5642 @Registered = sort {natural_sorting($a, $b)} @Registered; 5643 sort_by_word(\@Registered, $TargetLibraryShortName); 5644 foreach my $Path (@Registered) { 5645 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++; 5646 } 5647 } 5648 else { 5649 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file"); 5650 } 5651 } 5652 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"}) 5653 { # preparing preamble headers 5654 my $PPos=0; 5655 foreach my $Header (split(/\s*\n\s*/, $HList)) 5656 { 5657 if(is_abs($Header) and not -f $Header) { 5658 exitStatus("Access_Error", "can't access file \'$Header\'"); 5659 } 5660 $Header = path_format($Header, $OSgroup); 5661 if(my $Header_Path = is_header($Header, 1, $LibVersion)) 5662 { 5663 next if(skipHeader($Header_Path, $LibVersion)); 5664 $Include_Preamble{$LibVersion}{$Header_Path}{"Position"} = $PPos++; 5665 } 5666 else { 5667 exitStatus("Access_Error", "can't identify \'$Header\' as a header file"); 5668 } 5669 } 5670 } 5671 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}})) 5672 { # set relative paths (for duplicates) 5673 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2) 5674 { # search for duplicates 5675 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0]; 5676 my $Prefix = get_dirname($FirstPath); 5677 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/) 5678 { # detect a shortest distinguishing prefix 5679 my $NewPrefix = $1; 5680 my %Identity = (); 5681 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) 5682 { 5683 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) { 5684 $Identity{$Path} = $1; 5685 } 5686 } 5687 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) 5688 { # all names are differend with current prefix 5689 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) { 5690 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path}; 5691 } 5692 last; 5693 } 5694 $Prefix = $NewPrefix; # increase prefix 5695 } 5696 } 5697 } 5698 5699 # clean memory 5700 %HeaderName_Paths = (); 5701 5702 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}})) 5703 { # ordering headers according to descriptor 5704 my $PairName=$Include_Order{$LibVersion}{$HeaderName}; 5705 my ($Pos, $PairPos) = (-1, -1); 5706 my ($Path, $PairPath) = (); 5707 my @Paths = keys(%{$Registered_Headers{$LibVersion}}); 5708 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths; 5709 foreach my $Header_Path (@Paths) 5710 { 5711 if(get_filename($Header_Path) eq $PairName) 5712 { 5713 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"}; 5714 $PairPath = $Header_Path; 5715 } 5716 if(get_filename($Header_Path) eq $HeaderName) 5717 { 5718 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"}; 5719 $Path = $Header_Path; 5720 } 5721 } 5722 if($PairPos!=-1 and $Pos!=-1 5723 and int($PairPos)<int($Pos)) 5724 { 5725 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}}; 5726 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}}; 5727 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp; 5728 } 5729 } 5730 if(not keys(%{$Registered_Headers{$LibVersion}})) { 5731 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"}); 5732 } 5733} 5734 5735sub detect_real_includes($$) 5736{ 5737 my ($AbsPath, $LibVersion) = @_; 5738 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath); 5739 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath} 5740 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) { 5741 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}); 5742 } 5743 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1; 5744 5745 my $Path = callPreprocessor($AbsPath, "", $LibVersion); 5746 return () if(not $Path); 5747 open(PREPROC, $Path); 5748 while(<PREPROC>) 5749 { 5750 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/) 5751 { 5752 my $Include = path_format($1, $OSgroup); 5753 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) { 5754 next; 5755 } 5756 if($Include eq $AbsPath) { 5757 next; 5758 } 5759 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1; 5760 } 5761 } 5762 close(PREPROC); 5763 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}); 5764} 5765 5766sub detect_header_includes($$) 5767{ 5768 my ($Path, $LibVersion) = @_; 5769 return if(not $LibVersion or not $Path); 5770 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) { 5771 return; 5772 } 5773 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1; 5774 5775 if(not -e $Path) { 5776 return; 5777 } 5778 5779 my $Content = readFile($Path); 5780 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion)) 5781 { # detect error directive in headers 5782 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion)) 5783 { 5784 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) { 5785 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion); 5786 } 5787 if($RedirectPath ne $Path) { 5788 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath; 5789 } 5790 } 5791 } 5792 if(my $Inc = parse_includes($Content, $Path)) 5793 { 5794 foreach my $Include (keys(%{$Inc})) 5795 { # detect includes 5796 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include}; 5797 } 5798 } 5799} 5800 5801sub simplify_path($) 5802{ 5803 my $Path = $_[0]; 5804 while($Path=~s&([\/\\])[^\/\\]+[\/\\]\.\.[\/\\]&$1&){}; 5805 return $Path; 5806} 5807 5808sub fromLibc($) 5809{ # GLIBC header 5810 my $Path = $_[0]; 5811 my ($Dir, $Name) = separate_path($Path); 5812 if(get_filename($Dir)=~/\A(include|libc)\Z/ and $GlibcHeader{$Name}) 5813 { # /usr/include/{stdio, ...}.h 5814 # epoc32/include/libc/{stdio, ...}.h 5815 return 1; 5816 } 5817 if(isLibcDir($Dir)) { 5818 return 1; 5819 } 5820 return 0; 5821} 5822 5823sub isLibcDir($) 5824{ # GLIBC directory 5825 my $Dir = $_[0]; 5826 my ($OutDir, $Name) = separate_path($Dir); 5827 if(get_filename($OutDir)=~/\A(include|libc)\Z/ 5828 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name})) 5829 { # /usr/include/{sys,bits,asm,asm-*}/*.h 5830 return 1; 5831 } 5832 return 0; 5833} 5834 5835sub detect_recursive_includes($$) 5836{ 5837 my ($AbsPath, $LibVersion) = @_; 5838 return () if(not $AbsPath); 5839 if(isCyclical(\@RecurInclude, $AbsPath)) { 5840 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}); 5841 } 5842 my ($AbsDir, $Name) = separate_path($AbsPath); 5843 if(isLibcDir($AbsDir)) 5844 { # GLIBC internals 5845 return (); 5846 } 5847 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) { 5848 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}); 5849 } 5850 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i); 5851 return () if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING); 5852 push(@RecurInclude, $AbsPath); 5853 if($DefaultGccPaths{$AbsDir} 5854 or fromLibc($AbsPath)) 5855 { # check "real" (non-"model") include paths 5856 my @Paths = detect_real_includes($AbsPath, $LibVersion); 5857 pop(@RecurInclude); 5858 return @Paths; 5859 } 5860 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) { 5861 detect_header_includes($AbsPath, $LibVersion); 5862 } 5863 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) 5864 { 5865 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include}; 5866 my $HPath = ""; 5867 if($IncType<0) 5868 { # for #include "..." 5869 my $Candidate = joinPath($AbsDir, $Include); 5870 if(-f $Candidate) { 5871 $HPath = simplify_path($Candidate); 5872 } 5873 } 5874 elsif($IncType>0 5875 and $Include=~/[\/\\]/) # and not find_in_defaults($Include) 5876 { # search for the nearest header 5877 # QtCore/qabstractanimation.h includes <QtCore/qobject.h> 5878 my $Candidate = joinPath(get_dirname($AbsDir), $Include); 5879 if(-f $Candidate) { 5880 $HPath = $Candidate; 5881 } 5882 } 5883 if(not $HPath) { 5884 $HPath = identifyHeader($Include, $LibVersion); 5885 } 5886 next if(not $HPath); 5887 if($HPath eq $AbsPath) { 5888 next; 5889 } 5890 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType; 5891 if($IncType>0) 5892 { # only include <...>, skip include "..." prefixes 5893 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1; 5894 } 5895 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion)) 5896 { 5897 if($IncPath eq $AbsPath) { 5898 next; 5899 } 5900 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath}; 5901 if($RIncType==-1) 5902 { # include "..." 5903 $RIncType = $IncType; 5904 } 5905 elsif($RIncType==2) 5906 { 5907 if($IncType!=-1) { 5908 $RIncType = $IncType; 5909 } 5910 } 5911 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType; 5912 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) { 5913 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1; 5914 } 5915 } 5916 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}})) 5917 { 5918 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2 5919 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""}) 5920 { # distinguish math.h from glibc and math.h from the tested library 5921 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""}); 5922 last; 5923 } 5924 } 5925 } 5926 pop(@RecurInclude); 5927 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}); 5928} 5929 5930sub find_in_framework($$$) 5931{ 5932 my ($Header, $Framework, $LibVersion) = @_; 5933 return "" if(not $Header or not $Framework or not $LibVersion); 5934 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) { 5935 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}; 5936 } 5937 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}})) 5938 { 5939 if(get_filename($Dependency) eq $Framework 5940 and -f get_dirname($Dependency)."/".$Header) { 5941 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency)); 5942 } 5943 } 5944 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = ""); 5945} 5946 5947sub find_in_defaults($) 5948{ 5949 my $Header = $_[0]; 5950 return "" if(not $Header); 5951 if(defined $Cache{"find_in_defaults"}{$Header}) { 5952 return $Cache{"find_in_defaults"}{$Header}; 5953 } 5954 foreach my $Dir (sort {get_depth($a)<=>get_depth($b)} 5955 (keys(%DefaultIncPaths), keys(%DefaultGccPaths), keys(%DefaultCppPaths), keys(%UserIncPath))) 5956 { 5957 next if(not $Dir); 5958 if(-f $Dir."/".$Header) { 5959 return ($Cache{"find_in_defaults"}{$Header}=$Dir); 5960 } 5961 } 5962 return ($Cache{"find_in_defaults"}{$Header}=""); 5963} 5964 5965sub cmp_paths($$) 5966{ 5967 my ($Path1, $Path2) = @_; 5968 my @Parts1 = split(/[\/\\]/, $Path1); 5969 my @Parts2 = split(/[\/\\]/, $Path2); 5970 foreach my $Num (0 .. $#Parts1) 5971 { 5972 my $Part1 = $Parts1[$Num]; 5973 my $Part2 = $Parts2[$Num]; 5974 if($GlibcDir{$Part1} 5975 and not $GlibcDir{$Part2}) { 5976 return 1; 5977 } 5978 elsif($GlibcDir{$Part2} 5979 and not $GlibcDir{$Part1}) { 5980 return -1; 5981 } 5982 elsif($Part1=~/glib/ 5983 and $Part2!~/glib/) { 5984 return 1; 5985 } 5986 elsif($Part1!~/glib/ 5987 and $Part2=~/glib/) { 5988 return -1; 5989 } 5990 elsif(my $CmpRes = ($Part1 cmp $Part2)) { 5991 return $CmpRes; 5992 } 5993 } 5994 return 0; 5995} 5996 5997sub checkRelevance($) 5998{ 5999 my ($Path) = @_; 6000 return 0 if(not $Path); 6001 if($SystemRoot) { 6002 $Path = cut_path_prefix($Path, $SystemRoot); 6003 } 6004 my ($Dir, $Name) = separate_path($Path); 6005 $Name=~s/\.\w+\Z//g; # remove extension (.h) 6006 my @Tokens = split(/[_\d\W]+/, $Name); 6007 foreach (@Tokens) 6008 { 6009 next if(not $_); 6010 if($Dir=~/(\A|lib|[_\d\W])\Q$_\E([_\d\W]|lib|\Z)/i 6011 or length($_)>=4 and $Dir=~/\Q$_\E/i) 6012 { # include/gupnp-1.0/libgupnp/gupnp-context.h 6013 # include/evolution-data-server-1.4/libebook/e-book.h 6014 return 1; 6015 } 6016 } 6017 return 0; 6018} 6019 6020sub checkFamily(@) 6021{ 6022 my @Paths = @_; 6023 return 1 if($#Paths<=0); 6024 my %Prefix = (); 6025 foreach my $Path (@Paths) 6026 { 6027 if($SystemRoot) { 6028 $Path = cut_path_prefix($Path, $SystemRoot); 6029 } 6030 if(my $Dir = get_dirname($Path)) 6031 { 6032 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix 6033 $Prefix{$Dir} += 1; 6034 $Prefix{get_dirname($Dir)} += 1; 6035 } 6036 } 6037 foreach (sort keys(%Prefix)) 6038 { 6039 if(get_depth($_)>=3 6040 and $Prefix{$_}==$#Paths+1) { 6041 return 1; 6042 } 6043 } 6044 return 0; 6045} 6046 6047sub isAcceptable($$$) 6048{ 6049 my ($Header, $Candidate, $LibVersion) = @_; 6050 my $HName = get_filename($Header); 6051 if(get_dirname($Header)) 6052 { # with prefix 6053 return 1; 6054 } 6055 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/) 6056 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/ 6057 return 1; 6058 } 6059 if(checkRelevance($Candidate)) 6060 { # allow to search for atk.h in /usr/include/atk-1.0/atk/ 6061 return 1; 6062 } 6063 if(checkFamily(getSystemHeaders($HName, $LibVersion))) 6064 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h 6065 # /usr/include/qt4/Qt/qsslconfiguration.h 6066 return 1; 6067 } 6068 if($OStarget eq "symbian") 6069 { 6070 if($Candidate=~/[\/\\]stdapis[\/\\]/) { 6071 return 1; 6072 } 6073 } 6074 return 0; 6075} 6076 6077sub isRelevant($$$) 6078{ # disallow to search for "abstract" headers in too deep directories 6079 my ($Header, $Candidate, $LibVersion) = @_; 6080 my $HName = get_filename($Header); 6081 if($OStarget eq "symbian") 6082 { 6083 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) { 6084 return 0; 6085 } 6086 } 6087 if($OStarget ne "bsd") { 6088 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/) 6089 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h 6090 return 0; 6091 } 6092 } 6093 if(not get_dirname($Header) 6094 and $Candidate=~/[\/\\]wx[\/\\]/) 6095 { # do NOT search in system /wx/ directory 6096 # for headers without a prefix: sstream.h 6097 return 0; 6098 } 6099 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR 6100 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/) 6101 { # skip ../c++/3.3.3/ if using ../c++/4.5/ 6102 return 0; 6103 } 6104 if($Candidate=~/[\/\\]asm-/ 6105 and (my $Arch = getArch($LibVersion)) ne "unknown") 6106 { # arch-specific header files 6107 if($Candidate!~/[\/\\]asm-\Q$Arch\E/) 6108 {# skip ../asm-arm/ if using x86 architecture 6109 return 0; 6110 } 6111 } 6112 my @Candidates = getSystemHeaders($HName, $LibVersion); 6113 if($#Candidates==1) 6114 { # unique header 6115 return 1; 6116 } 6117 my @SCandidates = getSystemHeaders($Header, $LibVersion); 6118 if($#SCandidates==1) 6119 { # unique name 6120 return 1; 6121 } 6122 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0; 6123 if(get_depth($Candidate)-$SystemDepth>=5) 6124 { # abstract headers in too deep directories 6125 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/ 6126 if(not isAcceptable($Header, $Candidate, $LibVersion)) { 6127 return 0; 6128 } 6129 } 6130 if($Header eq "parser.h" 6131 and $Candidate!~/\/libxml2\//) 6132 { # select parser.h from xml2 library 6133 return 0; 6134 } 6135 if(not get_dirname($Header) 6136 and keys(%{$SystemHeaders{$HName}})>=3) 6137 { # many headers with the same name 6138 # like thread.h included without a prefix 6139 if(not checkFamily(@Candidates)) { 6140 return 0; 6141 } 6142 } 6143 return 1; 6144} 6145 6146sub selectSystemHeader($$) 6147{ # cache function 6148 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) { 6149 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}; 6150 } 6151 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_)); 6152} 6153 6154sub selectSystemHeader_I($$) 6155{ 6156 my ($Header, $LibVersion) = @_; 6157 if(-f $Header) { 6158 return $Header; 6159 } 6160 if(is_abs($Header) and not -f $Header) 6161 { # incorrect absolute path 6162 return ""; 6163 } 6164 if($Header=~/\A(atomic|config|configure|build|conf|setup)\.h\Z/i) 6165 { # too abstract configuration headers 6166 return ""; 6167 } 6168 if($OSgroup ne "windows") 6169 { 6170 if(get_filename($Header)=~/windows|win32|win64|\A(dos|process|winsock|config-win)\.h\Z/i) 6171 { # windows headers 6172 return ""; 6173 } 6174 elsif($Header=~/\A(mem)\.h\Z/) 6175 { # pngconf.h include mem.h for __MSDOS__ 6176 return ""; 6177 } 6178 } 6179 if($OSgroup ne "solaris") 6180 { 6181 if($Header=~/\A(thread)\.h\Z/) 6182 { # thread.h in Solaris 6183 return ""; 6184 } 6185 } 6186 6187 foreach my $Path (keys(%{$SystemPaths{"include"}})) 6188 { # search in default paths 6189 if(-f $Path."/".$Header) { 6190 return joinPath($Path,$Header); 6191 } 6192 } 6193 if(not keys(%SystemHeaders)) 6194 { # register all headers in system include dirs 6195 detectSystemHeaders(); 6196 } 6197 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)} 6198 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion)) 6199 { 6200 if(isRelevant($Header, $Candidate, $LibVersion)) { 6201 return $Candidate; 6202 } 6203 } 6204 # error 6205 return ""; 6206} 6207 6208sub getSystemHeaders($$) 6209{ 6210 my ($Header, $LibVersion) = @_; 6211 my @Candidates = (); 6212 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}})) 6213 { 6214 if(skipHeader($Candidate, $LibVersion)) { 6215 next; 6216 } 6217 push(@Candidates, $Candidate); 6218 } 6219 return @Candidates; 6220} 6221 6222sub cut_path_prefix($$) 6223{ 6224 my ($Path, $Prefix) = @_; 6225 return $Path if(not $Prefix); 6226 $Prefix=~s/[\/\\]+\Z//; 6227 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//; 6228 return $Path; 6229} 6230 6231sub is_default_include_dir($) 6232{ 6233 my $Dir = $_[0]; 6234 $Dir=~s/[\/\\]+\Z//; 6235 return ($DefaultGccPaths{$Dir} or $DefaultCppPaths{$Dir} or $DefaultIncPaths{$Dir}); 6236} 6237 6238sub identifyHeader($$) 6239{ # cache function 6240 my ($Header, $LibVersion) = @_; 6241 if(not $Header) { 6242 return ""; 6243 } 6244 $Header=~s/\A(\.\.[\\\/])+//g; 6245 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) { 6246 return $Cache{"identifyHeader"}{$LibVersion}{$Header}; 6247 } 6248 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion)); 6249} 6250 6251sub identifyHeader_I($$) 6252{ # search for header by absolute path, relative path or name 6253 my ($Header, $LibVersion) = @_; 6254 if(-f $Header) 6255 { # it's relative or absolute path 6256 return get_abs_path($Header); 6257 } 6258 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING 6259 and my $HeaderDir = find_in_defaults($Header)) 6260 { # search for libc headers in the /usr/include 6261 # for non-libc target library before searching 6262 # in the library paths 6263 return joinPath($HeaderDir,$Header); 6264 } 6265 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header}) 6266 { # search in the target library paths 6267 return $Path; 6268 } 6269 elsif($DefaultGccHeader{$Header}) 6270 { # search in the internal GCC include paths 6271 return $DefaultGccHeader{$Header}; 6272 } 6273 elsif(my $DefaultDir = find_in_defaults($Header)) 6274 { # search in the default GCC include paths 6275 return joinPath($DefaultDir,$Header); 6276 } 6277 elsif($DefaultCppHeader{$Header}) 6278 { # search in the default G++ include paths 6279 return $DefaultCppHeader{$Header}; 6280 } 6281 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion)) 6282 { # search everywhere in the system 6283 return $AnyPath; 6284 } 6285 elsif($OSgroup eq "macos") 6286 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h" 6287 if(my $Dir = get_dirname($Header)) 6288 { 6289 my $RelPath = "Headers\/".get_filename($Header); 6290 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) { 6291 return joinPath($HeaderDir, $RelPath); 6292 } 6293 } 6294 } 6295 # cannot find anything 6296 return ""; 6297} 6298 6299sub getLocation($) 6300{ 6301 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 6302 { 6303 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) { 6304 return ($1, $2); 6305 } 6306 } 6307 return (); 6308} 6309 6310sub getNameByInfo($) 6311{ 6312 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 6313 { 6314 if($Info=~/name[ ]*:[ ]*@(\d+) /) 6315 { 6316 if(my $NInfo = $LibInfo{$Version}{"info"}{$1}) 6317 { 6318 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/) 6319 { # short unsigned int (may include spaces) 6320 return $1; 6321 } 6322 } 6323 } 6324 } 6325 return ""; 6326} 6327 6328sub getTreeStr($) 6329{ 6330 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 6331 { 6332 if($Info=~/strg[ ]*:[ ]*([^ ]*)/) 6333 { 6334 my $Str = $1; 6335 if($C99Mode{$Version} 6336 and $Str=~/\Ac99_(.+)\Z/) { 6337 if($CppKeywords_A{$1}) { 6338 $Str=$1; 6339 } 6340 } 6341 return $Str; 6342 } 6343 } 6344 return ""; 6345} 6346 6347sub getFuncShortName($) 6348{ 6349 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 6350 { 6351 if($Info=~/ operator /) 6352 { 6353 if($Info=~/ conversion /) 6354 { 6355 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"}) 6356 { 6357 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) { 6358 return "operator ".$RName; 6359 } 6360 } 6361 } 6362 else 6363 { 6364 if($Info=~/ operator[ ]+([a-zA-Z]+) /) 6365 { 6366 if(my $Ind = $Operator_Indication{$1}) { 6367 return "operator".$Ind; 6368 } 6369 elsif(not $UnknownOperator{$1}) 6370 { 6371 printMsg("WARNING", "unknown operator $1"); 6372 $UnknownOperator{$1} = 1; 6373 } 6374 } 6375 } 6376 } 6377 else 6378 { 6379 if($Info=~/name[ ]*:[ ]*@(\d+) /) { 6380 return getTreeStr($1); 6381 } 6382 } 6383 } 6384 return ""; 6385} 6386 6387sub getFuncReturn($) 6388{ 6389 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 6390 { 6391 if($Info=~/type[ ]*:[ ]*@(\d+) /) 6392 { 6393 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) { 6394 return $1; 6395 } 6396 } 6397 } 6398 return ""; 6399} 6400 6401sub getFuncOrig($) 6402{ 6403 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 6404 { 6405 if($Info=~/orig[ ]*:[ ]*@(\d+) /) { 6406 return $1; 6407 } 6408 } 6409 return $_[0]; 6410} 6411 6412sub unmangleSymbol($) 6413{ 6414 my $Symbol = $_[0]; 6415 if(my @Unmngl = unmangleArray($Symbol)) { 6416 return $Unmngl[0]; 6417 } 6418 return ""; 6419} 6420 6421sub unmangleArray(@) 6422{ 6423 if($_[0]=~/\A\?/) 6424 { # MSVC mangling 6425 my $UndNameCmd = get_CmdPath("undname"); 6426 if(not $UndNameCmd) { 6427 exitStatus("Not_Found", "can't find \"undname\""); 6428 } 6429 writeFile("$TMP_DIR/unmangle", join("\n", @_)); 6430 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`); 6431 } 6432 else 6433 { # GCC mangling 6434 my $CppFiltCmd = get_CmdPath("c++filt"); 6435 if(not $CppFiltCmd) { 6436 exitStatus("Not_Found", "can't find c++filt in PATH"); 6437 } 6438 my $Info = `$CppFiltCmd -h 2>&1`; 6439 if($Info=~/\@<file>/) 6440 {# new version of c++filt can take a file 6441 my $NoStrip = ""; 6442 if($OSgroup eq "macos" 6443 or $OSgroup eq "windows") { 6444 $NoStrip = "-n"; 6445 } 6446 writeFile("$TMP_DIR/unmangle", join("\n", @_)); 6447 return split(/\n/, `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`); 6448 } 6449 else 6450 { # old-style unmangling 6451 if($#_>$MAX_COMMAND_LINE_ARGUMENTS) { 6452 my @Half = splice(@_, 0, ($#_+1)/2); 6453 return (unmangleArray(@Half), unmangleArray(@_)) 6454 } 6455 else 6456 { 6457 my $NoStrip = ""; 6458 if($OSgroup eq "macos" 6459 or $OSgroup eq "windows") { 6460 $NoStrip = "-n"; 6461 } 6462 my $Strings = join(" ", @_); 6463 return split(/\n/, `$CppFiltCmd $NoStrip $Strings`); 6464 } 6465 } 6466 } 6467} 6468 6469sub get_SignatureNoInfo($$) 6470{ 6471 my ($Symbol, $LibVersion) = @_; 6472 if($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol}) { 6473 return $Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol}; 6474 } 6475 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol); 6476 my $Signature = $tr_name{$MnglName}?$tr_name{$MnglName}:$MnglName; 6477 if($Symbol=~/\A(_Z|\?)/) 6478 { # C++ 6479 $Signature=~s/\Qstd::basic_string<char, std::char_traits<char>, std::allocator<char> >\E/std::string/g; 6480 $Signature=~s/\Qstd::map<std::string, std::string, std::less<std::string >, std::allocator<std::pair<std::string const, std::string > > >\E/std::map<std::string, std::string>/g; 6481 } 6482 if(not $CheckObjectsOnly or $OSgroup=~/linux|bsd|beos/) 6483 { # ELF format marks data as OBJECT 6484 if($GlobalDataObject{$LibVersion}{$Symbol}) { 6485 $Signature .= " [data]"; 6486 } 6487 elsif($Symbol!~/\A(_Z|\?)/) { 6488 $Signature .= " (...)"; 6489 } 6490 } 6491 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion)) 6492 { 6493 my $ShortName = substr($Signature, 0, find_center($Signature, "(")); 6494 $Signature=~s/\A\Q$ShortName\E/$ShortName $ChargeLevel/g; 6495 } 6496 if($SymbolVersion) { 6497 $Signature .= $VersionSpec.$SymbolVersion; 6498 } 6499 return ($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol} = $Signature); 6500} 6501 6502sub get_ChargeLevel($$) 6503{ 6504 my ($Symbol, $LibVersion) = @_; 6505 return "" if($Symbol!~/\A(_Z|\?)/); 6506 if(defined $CompleteSignature{$LibVersion}{$Symbol} 6507 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"}) 6508 { 6509 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}) 6510 { 6511 if($Symbol=~/C1E/) { 6512 return "[in-charge]"; 6513 } 6514 elsif($Symbol=~/C2E/) { 6515 return "[not-in-charge]"; 6516 } 6517 } 6518 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) 6519 { 6520 if($Symbol=~/D1E/) { 6521 return "[in-charge]"; 6522 } 6523 elsif($Symbol=~/D2E/) { 6524 return "[not-in-charge]"; 6525 } 6526 elsif($Symbol=~/D0E/) { 6527 return "[in-charge-deleting]"; 6528 } 6529 } 6530 } 6531 else 6532 { 6533 if($Symbol=~/C1E/) { 6534 return "[in-charge]"; 6535 } 6536 elsif($Symbol=~/C2E/) { 6537 return "[not-in-charge]"; 6538 } 6539 elsif($Symbol=~/D1E/) { 6540 return "[in-charge]"; 6541 } 6542 elsif($Symbol=~/D2E/) { 6543 return "[not-in-charge]"; 6544 } 6545 elsif($Symbol=~/D0E/) { 6546 return "[in-charge-deleting]"; 6547 } 6548 } 6549 return ""; 6550} 6551 6552sub get_Signature_M($$) 6553{ 6554 my ($Symbol, $LibVersion) = @_; 6555 my $Signature_M = $tr_name{$Symbol}; 6556 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) 6557 { # add return type name 6558 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M; 6559 } 6560 return $Signature_M; 6561} 6562 6563sub get_Signature($$) 6564{ 6565 my ($Symbol, $LibVersion) = @_; 6566 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) { 6567 return $Cache{"get_Signature"}{$LibVersion}{$Symbol}; 6568 } 6569 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol); 6570 if(isPrivateData($MnglName) or not $CompleteSignature{$LibVersion}{$Symbol}{"Header"}) 6571 { # non-public global data 6572 return get_SignatureNoInfo($Symbol, $LibVersion); 6573 } 6574 my ($Func_Signature, @Param_Types_FromUnmangledName) = (); 6575 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}; 6576 if($Symbol=~/\A(_Z|\?)/) 6577 { 6578 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) { 6579 $Func_Signature = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".(($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})?"~":"").$ShortName; 6580 } 6581 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) { 6582 $Func_Signature = $NameSpace."::".$ShortName; 6583 } 6584 else { 6585 $Func_Signature = $ShortName; 6586 } 6587 @Param_Types_FromUnmangledName = get_s_params($tr_name{$MnglName}, 0); 6588 } 6589 else { 6590 $Func_Signature = $MnglName; 6591 } 6592 my @ParamArray = (); 6593 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}})) 6594 { 6595 next if($Pos eq ""); 6596 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"}; 6597 next if(not $ParamTypeId); 6598 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"}; 6599 if(not $ParamTypeName) { 6600 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos]; 6601 } 6602 foreach my $Typedef (keys(%ChangedTypedef)) 6603 { 6604 my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}; 6605 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g; 6606 } 6607 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"}) { 6608 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName)); 6609 } 6610 else { 6611 push(@ParamArray, $ParamTypeName); 6612 } 6613 } 6614 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"} 6615 or $GlobalDataObject{$LibVersion}{$Symbol}) { 6616 $Func_Signature .= " [data]"; 6617 } 6618 else 6619 { 6620 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion)) 6621 { # add [in-charge] 6622 $Func_Signature .= " ".$ChargeLevel; 6623 } 6624 $Func_Signature .= " (".join(", ", @ParamArray).")"; 6625 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"} 6626 or $Symbol=~/\A_ZN(V|)K/) { 6627 $Func_Signature .= " const"; 6628 } 6629 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"} 6630 or $Symbol=~/\A_ZN(K|)V/) { 6631 $Func_Signature .= " volatile"; 6632 } 6633 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"} 6634 and $Symbol=~/\A(_Z|\?)/) 6635 {# for static methods 6636 $Func_Signature .= " [static]"; 6637 } 6638 } 6639 if(defined $ShowRetVal 6640 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) { 6641 $Func_Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"}; 6642 } 6643 if($SymbolVersion) { 6644 $Func_Signature .= $VersionSpec.$SymbolVersion; 6645 } 6646 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Func_Signature); 6647} 6648 6649sub create_member_decl($$) 6650{ 6651 my ($TName, $Member) = @_; 6652 if($TName=~/\([\*]+\)/) 6653 { 6654 $TName=~s/\(([\*]+)\)/\($1$Member\)/; 6655 return $TName; 6656 } 6657 else 6658 { 6659 my @ArraySizes = (); 6660 while($TName=~s/(\[[^\[\]]*\])\Z//) { 6661 push(@ArraySizes, $1); 6662 } 6663 return $TName." ".$Member.join("", @ArraySizes); 6664 } 6665} 6666 6667sub getFuncType($) 6668{ 6669 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 6670 { 6671 if($Info=~/type[ ]*:[ ]*@(\d+) /) 6672 { 6673 if(my $Type = $LibInfo{$Version}{"info_type"}{$1}) 6674 { 6675 if($Type eq "method_type") { 6676 return "Method"; 6677 } 6678 elsif($Type eq "function_type") { 6679 return "Function"; 6680 } 6681 else { 6682 return "Other"; 6683 } 6684 } 6685 } 6686 } 6687 return "" 6688} 6689 6690sub getFuncTypeId($) 6691{ 6692 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]}) 6693 { 6694 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) { 6695 return $1; 6696 } 6697 } 6698 return 0; 6699} 6700 6701sub isNotAnon($) { 6702 return (not isAnon($_[0])); 6703} 6704 6705sub isAnon($) 6706{ # "._N" or "$_N" in older GCC versions 6707 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/); 6708} 6709 6710sub formatName($) 6711{ # type name correction 6712 if(defined $Cache{"formatName"}{$_[0]}) { 6713 return $Cache{"formatName"}{$_[0]}; 6714 } 6715 6716 $_ = $_[0]; 6717 6718 s/\A[ ]+|[ ]+\Z//g; 6719 s/[ ]{2,}/ /g; 6720 s/[ ]*(\W)[ ]*/$1/g; 6721 6722 s/\bvolatile const\b/const volatile/g; 6723 6724 s/\b(long long|short|long) unsigned\b/unsigned $1/g; 6725 s/\b(short|long) int\b/$1/g; 6726 6727 s/([\)\]])(const|volatile)\b/$1 $2/g; 6728 6729 while(s/>>/> >/g) {}; 6730 6731 s/\b(operator[ ]*)> >/$1>>/; 6732 6733 return ($Cache{"formatName"}{$_[0]}=$_); 6734} 6735 6736sub get_HeaderDeps($$) 6737{ 6738 my ($AbsPath, $LibVersion) = @_; 6739 return () if(not $AbsPath or not $LibVersion); 6740 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) { 6741 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}}; 6742 } 6743 my %IncDir = (); 6744 detect_recursive_includes($AbsPath, $LibVersion); 6745 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) 6746 { 6747 next if(not $HeaderPath); 6748 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/); 6749 my $Dir = get_dirname($HeaderPath); 6750 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}})) 6751 { 6752 my $Dep = $Dir; 6753 if($Prefix) 6754 { 6755 if($OSgroup eq "windows") 6756 { # case insensitive seach on windows 6757 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) { 6758 next; 6759 } 6760 } 6761 elsif($OSgroup eq "macos") 6762 { # seach in frameworks 6763 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g) 6764 { 6765 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/) 6766 {# frameworks 6767 my ($HFramework, $HName) = ($1, $2); 6768 $Dep = $HFramework; 6769 } 6770 else 6771 {# mismatch 6772 next; 6773 } 6774 } 6775 } 6776 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g) 6777 { # Linux, FreeBSD 6778 next; 6779 } 6780 } 6781 if(not $Dep) 6782 { # nothing to include 6783 next; 6784 } 6785 if(is_default_include_dir($Dep)) 6786 { # included by the compiler 6787 next; 6788 } 6789 if(get_depth($Dep)==1) 6790 { # too short 6791 next; 6792 } 6793 if(isLibcDir($Dep)) 6794 { # do NOT include /usr/include/{sys,bits} 6795 next; 6796 } 6797 $IncDir{$Dep}=1; 6798 } 6799 } 6800 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion); 6801 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}}; 6802} 6803 6804sub sortIncPaths($$) 6805{ 6806 my ($ArrRef, $LibVersion) = @_; 6807 if(not $ArrRef or $#{$ArrRef}<0) { 6808 return $ArrRef; 6809 } 6810 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef}; 6811 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef}; 6812 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef}; 6813 return $ArrRef; 6814} 6815 6816sub sortDeps($$$) 6817{ 6818 if($Header_Dependency{$_[2]}{$_[0]} 6819 and not $Header_Dependency{$_[2]}{$_[1]}) { 6820 return 1; 6821 } 6822 elsif(not $Header_Dependency{$_[2]}{$_[0]} 6823 and $Header_Dependency{$_[2]}{$_[1]}) { 6824 return -1; 6825 } 6826 return 0; 6827} 6828 6829sub joinPath($$) { 6830 return join($SLASH, @_); 6831} 6832 6833sub get_namespace_additions($) 6834{ 6835 my $NameSpaces = $_[0]; 6836 my ($Additions, $AddNameSpaceId) = ("", 1); 6837 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces})) 6838 { 6839 next if($SkipNameSpaces{$Version}{$NS}); 6840 next if(not $NS or $NameSpaces->{$NS}==-1); 6841 next if($NS=~/(\A|::)iterator(::|\Z)/i); 6842 next if($NS=~/\A__/i); 6843 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING); 6844 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports 6845 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = (); 6846 my @NS_Parts = split(/::/, $NS); 6847 next if($#NS_Parts==-1); 6848 next if($NS_Parts[0]=~/\A(random|or)\Z/); 6849 foreach my $NS_Part (@NS_Parts) 6850 { 6851 $TypeDecl_Prefix .= "namespace $NS_Part\{"; 6852 $TypeDecl_Suffix .= "}"; 6853 } 6854 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_$AddNameSpaceId;".$TypeDecl_Suffix; 6855 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};"; 6856 $Additions.=" $TypeDecl\n $FuncDecl\n"; 6857 $AddNameSpaceId+=1; 6858 } 6859 return $Additions; 6860} 6861 6862sub path_format($$) 6863{ # forward slash to pass into MinGW GCC 6864 my ($Path, $Fmt) = @_; 6865 if($Fmt eq "windows") 6866 { 6867 $Path=~s/\//\\/g; 6868 $Path=lc($Path); 6869 } 6870 else { 6871 $Path=~s/\\/\//g; 6872 } 6873 return $Path; 6874} 6875 6876sub inc_opt($$) 6877{ 6878 my ($Path, $Style) = @_; 6879 if($Style eq "GCC") 6880 { # GCC options 6881 if($OSgroup eq "windows") 6882 { # to MinGW GCC 6883 return "-I\"".path_format($Path, "unix")."\""; 6884 } 6885 elsif($OSgroup eq "macos" 6886 and $Path=~/\.framework\Z/) 6887 {# to Apple's GCC 6888 return "-F".esc(get_dirname($Path)); 6889 } 6890 else { 6891 return "-I".esc($Path); 6892 } 6893 } 6894 elsif($Style eq "CL") { 6895 return "/I \"".$Path."\""; 6896 } 6897 return ""; 6898} 6899 6900sub platformSpecs($) 6901{ 6902 my $LibVersion = $_[0]; 6903 my $Arch = getArch($LibVersion); 6904 if($OStarget eq "symbian") 6905 { # options for GCCE compiler 6906 my %Symbian_Opts = map {$_=>1} ( 6907 "-D__GCCE__", 6908 "-DUNICODE", 6909 "-fexceptions", 6910 "-D__SYMBIAN32__", 6911 "-D__MARM_INTERWORK__", 6912 "-D_UNICODE", 6913 "-D__S60_50__", 6914 "-D__S60_3X__", 6915 "-D__SERIES60_3X__", 6916 "-D__EPOC32__", 6917 "-D__MARM__", 6918 "-D__EABI__", 6919 "-D__MARM_ARMV5__", 6920 "-D__SUPPORT_CPP_EXCEPTIONS__", 6921 "-march=armv5t", 6922 "-mapcs", 6923 "-mthumb-interwork", 6924 "-DEKA2", 6925 "-DSYMBIAN_ENABLE_SPLIT_HEADERS" 6926 ); 6927 return join(" ", keys(%Symbian_Opts)); 6928 } 6929 elsif($OSgroup eq "windows" 6930 and get_dumpmachine($GCC_PATH)=~/mingw/i) 6931 { # add options to MinGW compiler 6932 # to simulate the MSVC compiler 6933 my %MinGW_Opts = map {$_=>1} ( 6934 "-D_WIN32", 6935 "-D_STDCALL_SUPPORTED", 6936 "-D__int64=\"long long\"", 6937 "-D__int32=int", 6938 "-D__int16=short", 6939 "-D__int8=char", 6940 "-D__possibly_notnullterminated=\" \"", 6941 "-D__nullterminated=\" \"", 6942 "-D__nullnullterminated=\" \"", 6943 "-D__w64=\" \"", 6944 "-D__ptr32=\" \"", 6945 "-D__ptr64=\" \"", 6946 "-D__forceinline=inline", 6947 "-D__inline=inline", 6948 "-D__uuidof(x)=IID()", 6949 "-D__try=", 6950 "-D__except(x)=", 6951 "-D__declspec(x)=__attribute__((x))", 6952 "-D__pragma(x)=", 6953 "-D_inline=inline", 6954 "-D__forceinline=__inline", 6955 "-D__stdcall=__attribute__((__stdcall__))", 6956 "-D__cdecl=__attribute__((__cdecl__))", 6957 "-D__fastcall=__attribute__((__fastcall__))", 6958 "-D__thiscall=__attribute__((__thiscall__))", 6959 "-D_stdcall=__attribute__((__stdcall__))", 6960 "-D_cdecl=__attribute__((__cdecl__))", 6961 "-D_fastcall=__attribute__((__fastcall__))", 6962 "-D_thiscall=__attribute__((__thiscall__))", 6963 "-DSHSTDAPI_(x)=x", 6964 "-D_MSC_EXTENSIONS", 6965 "-DSECURITY_WIN32", 6966 "-D_MSC_VER=1500", 6967 "-D_USE_DECLSPECS_FOR_SAL", 6968 "-D__noop=\" \"", 6969 "-DDECLSPEC_DEPRECATED=\" \"", 6970 "-D__builtin_alignof(x)=__alignof__(x)", 6971 "-DSORTPP_PASS"); 6972 if($Arch eq "x86") { 6973 $MinGW_Opts{"-D_M_IX86=300"}=1; 6974 } 6975 elsif($Arch eq "x86_64") { 6976 $MinGW_Opts{"-D_M_AMD64=300"}=1; 6977 } 6978 elsif($Arch eq "ia64") { 6979 $MinGW_Opts{"-D_M_IA64=300"}=1; 6980 } 6981 return join(" ", keys(%MinGW_Opts)); 6982 } 6983 return ""; 6984} 6985 6986my %C_Structure = map {$_=>1} ( 6987# FIXME: Can't separate union and struct data types before dumping, 6988# so it sometimes cause compilation errors for unknown reason 6989# when trying to declare TYPE* tmp_add_class_N 6990# This is a list of such structures + list of other C structures 6991 "sigval", 6992 "sigevent", 6993 "sigaction", 6994 "sigvec", 6995 "sigstack", 6996 "timeval", 6997 "timezone", 6998 "rusage", 6999 "rlimit", 7000 "wait", 7001 "flock", 7002 "stat", 7003 "_stat", 7004 "stat32", 7005 "_stat32", 7006 "stat64", 7007 "_stat64", 7008 "_stati64", 7009 "if_nameindex", 7010 "usb_device", 7011 "sigaltstack", 7012 "sysinfo", 7013 "timeLocale", 7014 "tcp_debug", 7015 "rpc_createerr", 7016# Other C structures appearing in every dump 7017 "timespec", 7018 "random_data", 7019 "drand48_data", 7020 "_IO_marker", 7021 "_IO_FILE", 7022 "lconv", 7023 "sched_param", 7024 "tm", 7025 "itimerspec", 7026 "_pthread_cleanup_buffer", 7027 "fd_set", 7028 "siginfo" 7029); 7030 7031sub getCompileCmd($$$) 7032{ 7033 my ($Path, $Opt, $Inc) = @_; 7034 my $GccCall = $GCC_PATH; 7035 if($Opt) { 7036 $GccCall .= " ".$Opt; 7037 } 7038 $GccCall .= " -x "; 7039 if($OSgroup eq "macos") { 7040 $GccCall .= "objective-"; 7041 } 7042 if(check_gcc($GCC_PATH, "4")) 7043 { # compile as "C++" header 7044 # to obtain complete dump using GCC 4.0 7045 $GccCall .= "c++-header"; 7046 } 7047 else 7048 { # compile as "C++" source 7049 # GCC 3.3 cannot compile headers 7050 $GccCall .= "c++"; 7051 } 7052 if(my $Opts = platformSpecs($Version)) 7053 {# platform-specific options 7054 $GccCall .= " ".$Opts; 7055 } 7056 # allow extra qualifications 7057 # and other nonconformant code 7058 $GccCall .= " -fpermissive -w"; 7059 if($NoStdInc) 7060 { 7061 $GccCall .= " -nostdinc"; 7062 $GccCall .= " -nostdinc++"; 7063 } 7064 if($CompilerOptions{$Version}) 7065 { # user-defined options 7066 $GccCall .= " ".$CompilerOptions{$Version}; 7067 } 7068 $GccCall .= " \"$Path\""; 7069 if($Inc) 7070 { # include paths 7071 $GccCall .= " ".$Inc; 7072 } 7073 return $GccCall; 7074} 7075 7076sub getDump() 7077{ 7078 if(not $GCC_PATH) { 7079 exitStatus("Error", "internal error - GCC path is not set"); 7080 } 7081 my %HeaderElems = ( 7082 # Types 7083 "stdio.h" => ["FILE", "va_list"], 7084 "stddef.h" => ["NULL", "ptrdiff_t"], 7085 "stdint.h" => ["uint32_t", "int32_t", "uint64_t"], 7086 "time.h" => ["time_t"], 7087 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char", 7088 "u_int", "off_t", "u_quad_t", "u_long", "size_t", "mode_t"], 7089 "unistd.h" => ["gid_t", "uid_t"], 7090 "stdbool.h" => ["_Bool"], 7091 "rpc/xdr.h" => ["bool_t"], 7092 "in_systm.h" => ["n_long", "n_short"], 7093 # Fields 7094 "arpa/inet.h" => ["fw_src", "ip_src"], 7095 # Functions 7096 "stdlib.h" => ["free", "malloc"], 7097 "string.h" => ["memmove", "strcmp"] 7098 ); 7099 my %AutoPreamble = (); 7100 foreach (keys(%HeaderElems)) 7101 { 7102 foreach my $Elem (@{$HeaderElems{$_}}) { 7103 $AutoPreamble{$Elem}=$_; 7104 } 7105 } 7106 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h"; 7107 my $MHeaderPath = $TmpHeaderPath; 7108 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n"); 7109 if(my $AddDefines = $Descriptor{$Version}{"Defines"}) 7110 { 7111 $AddDefines=~s/\n\s+/\n /g; 7112 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n"; 7113 } 7114 print TMP_HEADER "\n // add includes\n"; 7115 my @PreambleHeaders = keys(%{$Include_Preamble{$Version}}); 7116 @PreambleHeaders = sort {int($Include_Preamble{$Version}{$a}{"Position"})<=>int($Include_Preamble{$Version}{$b}{"Position"})} @PreambleHeaders; 7117 foreach my $Header_Path (@PreambleHeaders) { 7118 print TMP_HEADER " #include \"".path_format($Header_Path, "unix")."\"\n"; 7119 } 7120 my @Headers = keys(%{$Registered_Headers{$Version}}); 7121 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers; 7122 foreach my $Header_Path (@Headers) 7123 { 7124 next if($Include_Preamble{$Version}{$Header_Path}); 7125 print TMP_HEADER " #include \"".path_format($Header_Path, "unix")."\"\n"; 7126 } 7127 close(TMP_HEADER); 7128 my $IncludeString = getIncString(getIncPaths(@PreambleHeaders, @Headers), "GCC"); 7129 if($Debug) 7130 { # debug mode 7131 writeFile($DEBUG_PATH{$Version}."/headers/direct-includes.txt", Dumper($Header_Includes{$Version})); 7132 writeFile($DEBUG_PATH{$Version}."/headers/recursive-includes.txt", Dumper($RecursiveIncludes{$Version})); 7133 writeFile($DEBUG_PATH{$Version}."/headers/include-paths.txt", Dumper($Cache{"get_HeaderDeps"}{$Version})); 7134 writeFile($DEBUG_PATH{$Version}."/headers/default-paths.txt", Dumper(\%DefaultIncPaths)); 7135 } 7136 7137 if(not keys(%{$TargetHeaders{$Version}})) 7138 { # Target headers 7139 addTargetHeaders($Version); 7140 } 7141 7142 # clean memory 7143 %RecursiveIncludes = (); 7144 %Header_Include_Prefix = (); 7145 %Header_Includes = (); 7146 7147 # clean cache 7148 delete($Cache{"identifyHeader"}); 7149 delete($Cache{"detect_header_includes"}); 7150 delete($Cache{"selectSystemHeader"}); 7151 7152 # preprocessing stage 7153 checkPreprocessedUnit(callPreprocessor($TmpHeaderPath, $IncludeString, $Version)); 7154 7155 # clean memory 7156 delete($Include_Neighbors{$Version}); 7157 7158 my $MContent = ""; 7159 my $PreprocessCmd = getCompileCmd($TmpHeaderPath, "-E", $IncludeString); 7160 if($OStarget eq "windows" 7161 and get_dumpmachine($GCC_PATH)=~/mingw/i 7162 and $MinGWMode{$Version}!=-1) 7163 { # modify headers to compile by MinGW 7164 if(not $MContent) 7165 { # preprocessing 7166 $MContent = `$PreprocessCmd 2>\"$TMP_DIR/null\"`; 7167 } 7168 if($MContent=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g) 7169 { # __asm { ... } 7170 $MinGWMode{$Version}=1; 7171 } 7172 if($MContent=~s/\s+(\/ \/.*?)\n/\n/g) 7173 { # comments after preprocessing 7174 $MinGWMode{$Version}=1; 7175 } 7176 if($MContent=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g) 7177 { # 0xffui8 7178 $MinGWMode{$Version}=1; 7179 } 7180 if($MinGWMode{$Version}) 7181 { 7182 printMsg("INFO", "Using MinGW compatibility mode"); 7183 $MHeaderPath = $TMP_DIR."/dump$Version.i"; 7184 } 7185 } 7186 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly) 7187 and $C99Mode{$Version}!=-1 and not $Cpp2003) 7188 { # rename C++ keywords in C code 7189 if(not $MContent) 7190 { # preprocessing 7191 $MContent = `$PreprocessCmd 2>\"$TMP_DIR/null\"`; 7192 } 7193 my $RegExp_C = join("|", keys(%CppKeywords_C)); 7194 my $RegExp_F = join("|", keys(%CppKeywords_F)); 7195 my $RegExp_O = join("|", keys(%CppKeywords_O)); 7196 while($MContent=~s/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*(\,|\)|\;|\-\>|\.|\:\s*\d))/$1$2c99_$3$4/g) 7197 { # MATCH: 7198 # int foo(int new, int class, int (*new)(int)); 7199 # unsigned private: 8; 7200 # DO NOT MATCH: 7201 # #pragma GCC visibility push(default) 7202 $C99Mode{$Version} = 1; 7203 } 7204 if($MContent=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g) 7205 { # MATCH: 7206 # int delete(...); 7207 # int explicit(...); 7208 # DO NOT MATCH: 7209 # void operator delete(...) 7210 $C99Mode{$Version} = 1; 7211 } 7212 if($MContent=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g) 7213 { # MATCH: 7214 # int bool; 7215 # DO NOT MATCH: 7216 # bool X; 7217 # return *this; 7218 # throw; 7219 $C99Mode{$Version} = 1; 7220 } 7221 if($MContent=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g) 7222 { # MATCH: 7223 # int operator(...); 7224 # DO NOT MATCH: 7225 # int operator()(...); 7226 $C99Mode{$Version} = 1; 7227 } 7228 if($MContent=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g) 7229 { # MATCH: 7230 # int foo(int operator); 7231 # int foo(int operator, int other); 7232 # DO NOT MATCH: 7233 # int operator,(...); 7234 $C99Mode{$Version} = 1; 7235 } 7236 if($MContent=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g) 7237 { # MATCH: 7238 # int foo(gboolean *bool); 7239 # DO NOT MATCH: 7240 # void setTabEnabled(int index, bool); 7241 $C99Mode{$Version} = 1; 7242 } 7243 if($MContent=~s/(\w)([^\w\(\,\s]\s*|\s+)(this)(\s*(\,|\)))/$1$2c99_$3$4/g) 7244 { # MATCH: 7245 # int foo(int* this); 7246 # int bar(int this); 7247 # DO NOT MATCH: 7248 # baz(X, this); 7249 $C99Mode{$Version} = 1; 7250 } 7251 if($C99Mode{$Version}==1) 7252 { # try to change C++ "keyword" to "c99_keyword" 7253 printMsg("INFO", "Using C99 compatibility mode"); 7254 $MHeaderPath = $TMP_DIR."/dump$Version.i"; 7255 } 7256 } 7257 if($C99Mode{$Version}==1 7258 or $MinGWMode{$Version}==1) 7259 { # compile the corrected preprocessor output 7260 writeFile($MHeaderPath, $MContent); 7261 } 7262 7263 # clean memory 7264 undef $MContent; 7265 7266 if($COMMON_LANGUAGE{$Version} eq "C++") 7267 { # add classes and namespaces to the dump 7268 my $CHdump = "-fdump-class-hierarchy -c"; 7269 if($C99Mode{$Version}==1 7270 or $MinGWMode{$Version}==1) { 7271 $CHdump .= " -fpreprocessed"; 7272 } 7273 my $ClassHierarchyCmd = getCompileCmd($MHeaderPath, $CHdump, $IncludeString); 7274 chdir($TMP_DIR); 7275 system($ClassHierarchyCmd." >null 2>&1"); 7276 chdir($ORIG_DIR); 7277 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0]) 7278 { 7279 my %AddClasses = (); 7280 my $Content = readFile($ClassDump); 7281 foreach my $ClassInfo (split(/\n\n/, $Content)) 7282 { 7283 if($ClassInfo=~/\AClass\s+(.+)\s*/i) 7284 { 7285 my $CName = $1; 7286 next if($CName=~/\A(__|_objc_|_opaque_)/); 7287 $TUnit_NameSpaces{$Version}{$CName} = -1; 7288 if($CName=~/\A[\w:]+\Z/) 7289 { # classes 7290 $AddClasses{$CName} = 1; 7291 } 7292 if($CName=~/(\w[\w:]*)::/) 7293 { # namespaces 7294 my $NS = $1; 7295 if(not defined $TUnit_NameSpaces{$Version}{$NS}) { 7296 $TUnit_NameSpaces{$Version}{$NS} = 1; 7297 } 7298 } 7299 } 7300 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i) 7301 { # read v-tables (advanced approach) 7302 my ($CName, $VTable) = ($1, $2); 7303 $ClassVTable_Content{$Version}{$CName} = $VTable; 7304 } 7305 } 7306 foreach my $NS (keys(%{$AddNameSpaces{$Version}})) 7307 { # add user-defined namespaces 7308 $TUnit_NameSpaces{$Version}{$NS} = 1; 7309 } 7310 if($Debug) 7311 { # debug mode 7312 mkpath($DEBUG_PATH{$Version}); 7313 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt"); 7314 } 7315 unlink($ClassDump); 7316 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version})) 7317 { # GCC on all supported platforms does not include namespaces to the dump by default 7318 appendFile($MHeaderPath, "\n // add namespaces\n".$NS_Add); 7319 } 7320 # some GCC versions don't include class methods to the TU dump by default 7321 my ($AddClass, $ClassNum) = ("", 0); 7322 foreach my $CName (sort keys(%AddClasses)) 7323 { 7324 next if($C_Structure{$CName}); 7325 next if(not $STDCXX_TESTING and $CName=~/\Astd::/); 7326 next if(($CName=~tr![:]!!)>2); 7327 next if($SkipTypes{$Version}{$CName}); 7328 if($CName=~/\A(.+)::[^:]+\Z/ 7329 and $AddClasses{$1}) { 7330 next; 7331 } 7332 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n"; 7333 } 7334 appendFile($MHeaderPath, "\n // add classes\n".$AddClass); 7335 } 7336 } 7337 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n"); 7338 # create TU dump 7339 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c"; 7340 if($C99Mode{$Version}==1 7341 or $MinGWMode{$Version}==1) { 7342 $TUdump .= " -fpreprocessed"; 7343 } 7344 my $SyntaxTreeCmd = getCompileCmd($MHeaderPath, $TUdump, $IncludeString); 7345 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n"); 7346 chdir($TMP_DIR); 7347 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1"); 7348 if($?) 7349 { # failed to compile, but the TU dump still can be created 7350 my $Errors = readFile($TMP_DIR."/tu_errors"); 7351 if($Errors=~/c99_/) 7352 { # disable c99 mode 7353 $C99Mode{$Version}=-1; 7354 printMsg("INFO", "Disabling C99 compatibility mode"); 7355 resetLogging($Version); 7356 $TMP_DIR = tempdir(CLEANUP=>1); 7357 return getDump(); 7358 } 7359 elsif($AutoPreambleMode{$Version}!=-1 7360 and my $TErrors = $Errors) 7361 { 7362 my %Types = (); 7363 while($TErrors=~s/error\:\s*(field\s*|)\W+(.+?)\W+//) 7364 { # error: 'FILE' has not been declared 7365 $Types{$2}=1; 7366 } 7367 my %AddHeaders = (); 7368 foreach my $Type (keys(%Types)) 7369 { 7370 if(my $Header = $AutoPreamble{$Type}) { 7371 $AddHeaders{path_format($Header, $OSgroup)}=$Type; 7372 } 7373 } 7374 if(my @Headers = sort {$b cmp $a} keys(%AddHeaders)) 7375 { # sys/types.h should be the first 7376 foreach my $Num (0 .. $#Headers) 7377 { 7378 my $Name = $Headers[$Num]; 7379 if(my $Path = identifyHeader($Name, $Version)) 7380 { # add automatic preamble headers 7381 if(defined $Include_Preamble{$Version}{$Path}) 7382 { # already added 7383 next; 7384 } 7385 $Include_Preamble{$Version}{$Path}{"Position"} = keys(%{$Include_Preamble{$Version}}); 7386 my $Type = $AddHeaders{$Name}; 7387 printMsg("INFO", "Add \'$Name\' preamble header for \'$Type\'"); 7388 } 7389 } 7390 $AutoPreambleMode{$Version}=-1; 7391 resetLogging($Version); 7392 $TMP_DIR = tempdir(CLEANUP=>1); 7393 return getDump(); 7394 } 7395 } 7396 elsif($MinGWMode{$Version}!=-1) 7397 { 7398 $MinGWMode{$Version}=-1; 7399 resetLogging($Version); 7400 $TMP_DIR = tempdir(CLEANUP=>1); 7401 return getDump(); 7402 } 7403 # FIXME: handle other errors and try to recompile 7404 writeLog($Version, $Errors); 7405 printMsg("ERROR", "some errors occurred when compiling headers"); 7406 printErrorLog($Version); 7407 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"}; 7408 writeLog($Version, "\n");# new line 7409 } 7410 chdir($ORIG_DIR); 7411 unlink($TmpHeaderPath, $MHeaderPath); 7412 return (cmd_find($TMP_DIR,"f","*.tu",1))[0]; 7413} 7414 7415sub cmd_file($) 7416{ 7417 my $Path = $_[0]; 7418 return "" if(not $Path or not -e $Path); 7419 if(my $CmdPath = get_CmdPath("file")) { 7420 return `$CmdPath -b \"$Path\"`; 7421 } 7422 return ""; 7423} 7424 7425sub getIncString($$) 7426{ 7427 my ($ArrRef, $Style) = @_; 7428 return "" if(not $ArrRef or $#{$ArrRef}<0); 7429 my $String = ""; 7430 foreach (@{$ArrRef}) { 7431 $String .= " ".inc_opt($_, $Style); 7432 } 7433 return $String; 7434} 7435 7436sub getIncPaths(@) 7437{ 7438 my @HeaderPaths = @_; 7439 my @IncPaths = (); 7440 if($INC_PATH_AUTODETECT{$Version}) 7441 { # auto-detecting dependencies 7442 my %Includes = (); 7443 foreach my $HPath (@HeaderPaths) 7444 { 7445 foreach my $Dir (get_HeaderDeps($HPath, $Version)) 7446 { 7447 if($Skip_Include_Paths{$Version}{$Dir}) { 7448 next; 7449 } 7450 if($SystemRoot) 7451 { 7452 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) { 7453 next; 7454 } 7455 } 7456 $Includes{$Dir}=1; 7457 } 7458 } 7459 foreach my $Dir (keys(%{$Add_Include_Paths{$Version}})) 7460 { # added by user 7461 next if($Includes{$Dir}); 7462 push(@IncPaths, $Dir); 7463 } 7464 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) { 7465 push(@IncPaths, $Dir); 7466 } 7467 } 7468 else 7469 { # user-defined paths 7470 foreach my $Dir (sort {get_depth($a)<=>get_depth($b)} 7471 sort {$b cmp $a} keys(%{$Include_Paths{$Version}})) { 7472 push(@IncPaths, $Dir); 7473 } 7474 } 7475 return \@IncPaths; 7476} 7477 7478sub callPreprocessor($$$) 7479{ 7480 my ($Path, $Inc, $LibVersion) = @_; 7481 return "" if(not $Path or not -f $Path); 7482 my $IncludeString=$Inc; 7483 if(not $Inc) { 7484 $IncludeString = getIncString(getIncPaths($Path), "GCC"); 7485 } 7486 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString); 7487 my $Out = $TMP_DIR."/preprocessed"; 7488 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\""); 7489 return $Out; 7490} 7491 7492sub cmd_find($$$$) 7493{ # native "find" is much faster than File::Find (~6x) 7494 # also the File::Find doesn't support --maxdepth N option 7495 # so using the cross-platform wrapper for the native one 7496 my ($Path, $Type, $Name, $MaxDepth) = @_; 7497 return () if(not $Path or not -e $Path); 7498 if($OSgroup eq "windows") 7499 { 7500 my $DirCmd = get_CmdPath("dir"); 7501 if(not $DirCmd) { 7502 exitStatus("Not_Found", "can't find \"dir\" command"); 7503 } 7504 $Path=~s/[\\]+\Z//; 7505 $Path = get_abs_path($Path); 7506 $Path = path_format($Path, $OSgroup); 7507 my $Cmd = $DirCmd." \"$Path\" /B /O"; 7508 if($MaxDepth!=1) { 7509 $Cmd .= " /S"; 7510 } 7511 if($Type eq "d") { 7512 $Cmd .= " /AD"; 7513 } 7514 my @Files = (); 7515 if($Name) 7516 { # FIXME: how to search file names in MS shell? 7517 $Name=~s/\*/.*/g if($Name!~/\]/); 7518 foreach my $File (split(/\n/, `$Cmd`)) 7519 { 7520 if($File=~/$Name\Z/i) { 7521 push(@Files, $File); 7522 } 7523 } 7524 } 7525 else { 7526 @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`); 7527 } 7528 my @AbsPaths = (); 7529 foreach my $File (@Files) 7530 { 7531 if(not is_abs($File)) { 7532 $File = joinPath($Path, $File); 7533 } 7534 if($Type eq "f" and not -f $File) 7535 { # skip dirs 7536 next; 7537 } 7538 push(@AbsPaths, path_format($File, $OSgroup)); 7539 } 7540 if($Type eq "d") { 7541 push(@AbsPaths, $Path); 7542 } 7543 return @AbsPaths; 7544 } 7545 else 7546 { 7547 my $FindCmd = get_CmdPath("find"); 7548 if(not $FindCmd) { 7549 exitStatus("Not_Found", "can't find a \"find\" command"); 7550 } 7551 $Path = get_abs_path($Path); 7552 if(-d $Path and -l $Path 7553 and $Path!~/\/\Z/) 7554 { # for directories that are symlinks 7555 $Path.="/"; 7556 } 7557 my $Cmd = $FindCmd." \"$Path\""; 7558 if($MaxDepth) { 7559 $Cmd .= " -maxdepth $MaxDepth"; 7560 } 7561 if($Type) { 7562 $Cmd .= " -type $Type"; 7563 } 7564 if($Name) 7565 { # file name 7566 if($Name=~/\]/) { 7567 $Cmd .= " -regex \"$Name\""; 7568 } 7569 else { 7570 $Cmd .= " -name \"$Name\""; 7571 } 7572 } 7573 return split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`); 7574 } 7575} 7576 7577sub unpackDump($) 7578{ 7579 my $Path = $_[0]; 7580 return "" if(not $Path or not -e $Path); 7581 $Path = get_abs_path($Path); 7582 $Path = path_format($Path, $OSgroup); 7583 my ($Dir, $FileName) = separate_path($Path); 7584 my $UnpackDir = $TMP_DIR."/unpack"; 7585 rmtree($UnpackDir); 7586 mkpath($UnpackDir); 7587 if($FileName=~s/\Q.zip\E\Z//g) 7588 { # *.zip 7589 my $UnzipCmd = get_CmdPath("unzip"); 7590 if(not $UnzipCmd) { 7591 exitStatus("Not_Found", "can't find \"unzip\" command"); 7592 } 7593 chdir($UnpackDir); 7594 system("$UnzipCmd \"$Path\" >contents.txt"); 7595 if($?) { 7596 exitStatus("Error", "can't extract \'$Path\'"); 7597 } 7598 chdir($ORIG_DIR); 7599 my @Contents = (); 7600 foreach (split("\n", readFile("$UnpackDir/contents.txt"))) 7601 { 7602 if(/inflating:\s*([^\s]+)/) { 7603 push(@Contents, $1); 7604 } 7605 } 7606 if(not @Contents) { 7607 exitStatus("Error", "can't extract \'$Path\'"); 7608 } 7609 return joinPath($UnpackDir, $Contents[0]); 7610 } 7611 elsif($FileName=~s/\Q.tar.gz\E\Z//g) 7612 { # *.tar.gz 7613 if($OSgroup eq "windows") 7614 { # -xvzf option is not implemented in tar.exe (2003) 7615 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead 7616 my $TarCmd = get_CmdPath("tar"); 7617 if(not $TarCmd) { 7618 exitStatus("Not_Found", "can't find \"tar\" command"); 7619 } 7620 my $GzipCmd = get_CmdPath("gzip"); 7621 if(not $GzipCmd) { 7622 exitStatus("Not_Found", "can't find \"gzip\" command"); 7623 } 7624 chdir($UnpackDir); 7625 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k) 7626 if($?) { 7627 exitStatus("Error", "can't extract \'$Path\'"); 7628 } 7629 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >contents.txt"); 7630 if($?) { 7631 exitStatus("Error", "can't extract \'$Path\'"); 7632 } 7633 chdir($ORIG_DIR); 7634 unlink($Dir."/".$FileName.".tar"); 7635 my @Contents = split("\n", readFile("$UnpackDir/contents.txt")); 7636 if(not @Contents) { 7637 exitStatus("Error", "can't extract \'$Path\'"); 7638 } 7639 return joinPath($UnpackDir, $Contents[0]); 7640 } 7641 else 7642 { # Unix 7643 my $TarCmd = get_CmdPath("tar"); 7644 if(not $TarCmd) { 7645 exitStatus("Not_Found", "can't find \"tar\" command"); 7646 } 7647 chdir($UnpackDir); 7648 system("$TarCmd -xvzf \"$Path\" >contents.txt"); 7649 if($?) { 7650 exitStatus("Error", "can't extract \'$Path\'"); 7651 } 7652 chdir($ORIG_DIR); 7653 # The content file name may be different 7654 # from the package file name 7655 my @Contents = split("\n", readFile("$UnpackDir/contents.txt")); 7656 if(not @Contents) { 7657 exitStatus("Error", "can't extract \'$Path\'"); 7658 } 7659 return joinPath($UnpackDir, $Contents[0]); 7660 } 7661 } 7662} 7663 7664sub createArchive($$) 7665{ 7666 my ($Path, $To) = @_; 7667 if(not $To) { 7668 $To = "."; 7669 } 7670 if(not $Path or not -e $Path 7671 or not -d $To) { 7672 return ""; 7673 } 7674 my ($From, $Name) = separate_path($Path); 7675 if($OSgroup eq "windows") 7676 { # *.zip 7677 my $ZipCmd = get_CmdPath("zip"); 7678 if(not $ZipCmd) { 7679 exitStatus("Not_Found", "can't find \"zip\""); 7680 } 7681 my $Pkg = $To."/".$Name.".zip"; 7682 unlink($Pkg); 7683 chdir($To); 7684 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\""); 7685 if($?) 7686 { # cannot allocate memory (or other problems with "zip") 7687 unlink($Path); 7688 exitStatus("Error", "can't pack the ABI dump: ".$!); 7689 } 7690 chdir($ORIG_DIR); 7691 unlink($Path); 7692 return $Pkg; 7693 } 7694 else 7695 { # *.tar.gz 7696 my $TarCmd = get_CmdPath("tar"); 7697 if(not $TarCmd) { 7698 exitStatus("Not_Found", "can't find \"tar\""); 7699 } 7700 my $GzipCmd = get_CmdPath("gzip"); 7701 if(not $GzipCmd) { 7702 exitStatus("Not_Found", "can't find \"gzip\""); 7703 } 7704 my $Pkg = abs_path($To)."/".$Name.".tar.gz"; 7705 unlink($Pkg); 7706 chdir($From); 7707 system($TarCmd, "-czf", $Pkg, $Name); 7708 if($?) 7709 { # cannot allocate memory (or other problems with "tar") 7710 unlink($Path); 7711 exitStatus("Error", "can't pack the ABI dump: ".$!); 7712 } 7713 chdir($ORIG_DIR); 7714 unlink($Path); 7715 return $To."/".$Name.".tar.gz"; 7716 } 7717} 7718 7719sub is_header_file($) 7720{ 7721 if($_[0]=~/\.($HEADER_EXT)\Z/i) { 7722 return $_[0]; 7723 } 7724 return 0; 7725} 7726 7727sub is_not_header($) 7728{ 7729 if($_[0]=~/\.\w+\Z/ 7730 and $_[0]!~/\.($HEADER_EXT)\Z/i) { 7731 return 1; 7732 } 7733 return 0; 7734} 7735 7736sub is_header($$$) 7737{ 7738 my ($Header, $UserDefined, $LibVersion) = @_; 7739 return 0 if(-d $Header); 7740 if(-f $Header) { 7741 $Header = get_abs_path($Header); 7742 } 7743 else 7744 { 7745 if(is_abs($Header)) 7746 { # incorrect absolute path 7747 return 0; 7748 } 7749 if(my $HPath = identifyHeader($Header, $LibVersion)) { 7750 $Header = $HPath; 7751 } 7752 else 7753 { # can't find header 7754 return 0; 7755 } 7756 } 7757 if($Header=~/\.\w+\Z/) 7758 { # have an extension 7759 return is_header_file($Header); 7760 } 7761 else 7762 { 7763 if($UserDefined==2) 7764 { # specified on the command line 7765 if(cmd_file($Header)!~/HTML|XML/i) { 7766 return $Header; 7767 } 7768 } 7769 elsif($UserDefined) 7770 { # specified in the XML-descriptor 7771 # header file without an extension 7772 return $Header; 7773 } 7774 else 7775 { 7776 if($Header=~/\/include\// 7777 or cmd_file($Header)=~/C[\+]*\s+program/i) 7778 { # !~/HTML|XML|shared|dynamic/i 7779 return $Header; 7780 } 7781 } 7782 } 7783 return 0; 7784} 7785 7786sub addTargetHeaders($) 7787{ 7788 my $LibVersion = $_[0]; 7789 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}})) 7790 { 7791 my $RegDir = get_dirname($RegHeader); 7792 $TargetHeaders{$LibVersion}{get_filename($RegHeader)}=1; 7793 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}})) 7794 { 7795 my $Dir = get_dirname($RecInc); 7796 if($Dir=~/\A\Q$RegDir\E([\/\\]|\Z)/ 7797 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1) 7798 { # in the same directory or included by #include "..." 7799 $TargetHeaders{$LibVersion}{get_filename($RecInc)}=1; 7800 } 7801 } 7802 } 7803} 7804 7805sub readHeaders($) 7806{ 7807 $Version = $_[0]; 7808 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ..."); 7809 my $DumpPath = getDump(); 7810 if(not $DumpPath) { 7811 exitStatus("Cannot_Compile", "can't compile header(s)"); 7812 } 7813 if($Debug) 7814 { # debug mode 7815 mkpath($DEBUG_PATH{$Version}); 7816 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt"); 7817 } 7818 getInfo($DumpPath); 7819} 7820 7821sub prepareTypes($) 7822{ 7823 my $LibVersion = $_[0]; 7824 if(not checkDump($LibVersion, "2.0")) 7825 { # support for old ABI dumps 7826 # type names have been corrected in ACC 1.22 (dump 2.0 format) 7827 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}})) 7828 { 7829 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"}; 7830 if($TName=~/\A(\w+)::(\w+)/) { 7831 my ($P1, $P2) = ($1, $2); 7832 if($P1 eq $P2) { 7833 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/; 7834 } 7835 else { 7836 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/; 7837 } 7838 } 7839 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName; 7840 } 7841 } 7842 if(not checkDump($LibVersion, "2.5")) 7843 { # support for old ABI dumps 7844 # V < 2.5: array size == "number of elements" 7845 # V >= 2.5: array size in bytes 7846 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}})) 7847 { 7848 my %Type = get_PureType($TypeId, $LibVersion); 7849 if($Type{"Type"} eq "Array") 7850 { 7851 if($Type{"Size"}) 7852 { # array[N] 7853 my %Base = get_OneStep_BaseType($Type{"Tid"}, $LibVersion); 7854 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type{"Size"}*$Base{"Size"}; 7855 } 7856 else 7857 { # array[] is a pointer 7858 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion}; 7859 } 7860 } 7861 } 7862 } 7863 my $V2 = ($LibVersion==1)?2:1; 7864 if(not checkDump($LibVersion, "2.7")) 7865 { # support for old ABI dumps 7866 # size of "method ptr" corrected in 2.7 7867 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}})) 7868 { 7869 my %PureType = get_PureType($TypeId, $LibVersion); 7870 if($PureType{"Type"} eq "MethodPtr") 7871 { 7872 my %Type = get_Type($TypeId, $LibVersion); 7873 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2); 7874 my %Type2 = get_Type($TypeId_2, $V2); 7875 if($Type{"Size"} ne $Type2{"Size"}) { 7876 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"}; 7877 } 7878 } 7879 } 7880 } 7881} 7882 7883sub prepareSymbols($) 7884{ 7885 my $LibVersion = $_[0]; 7886 7887 if(not keys(%{$SymbolInfo{$LibVersion}})) 7888 { # check if input is valid 7889 if(not $ExtendedCheck and not $CheckObjectsOnly) 7890 { 7891 if($CheckHeadersOnly) { 7892 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")"); 7893 } 7894 else { 7895 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")"); 7896 } 7897 } 7898 } 7899 7900 my $Remangle = 0; 7901 if(not checkDump(1, "2.10") 7902 or not checkDump(2, "2.10")) 7903 { # different formats 7904 $Remangle = 1; 7905 } 7906 if($CheckHeadersOnly) 7907 { # different languages 7908 if($UserLang) 7909 { # --lang=LANG for both versions 7910 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"}) 7911 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"})) 7912 { 7913 if($UserLang eq "C++") 7914 { # remangle symbols 7915 $Remangle = 1; 7916 } 7917 elsif($UserLang eq "C") 7918 { # remove mangling 7919 $Remangle = -1; 7920 } 7921 } 7922 } 7923 } 7924 7925 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}})) 7926 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2 7927 if(not checkDump($LibVersion, "2.13")) 7928 { # support for old ABI dumps 7929 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}) 7930 { 7931 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) 7932 { 7933 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"}; 7934 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"}; 7935 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"}; 7936 if(defined $DVal and $DVal ne "") 7937 { 7938 if($TName eq "char") { 7939 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal); 7940 } 7941 elsif($TName eq "bool") { 7942 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false"; 7943 } 7944 } 7945 } 7946 } 7947 } 7948 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) 7949 { 7950 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"} 7951 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}) 7952 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"}) 7953 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg) 7954 # + support for old ABI dumps 7955 next; 7956 } 7957 } 7958 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"}; 7959 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"}; 7960 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}; 7961 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"}; 7962 7963 if(not $MnglName) 7964 { # ABI dumps have no mangled names for C-functions 7965 $MnglName = $ShortName; 7966 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName; 7967 } 7968 7969 my $SRemangle = 0; 7970 if(not checkDump(1, "2.12") 7971 or not checkDump(2, "2.12")) 7972 { # support for old ABI dumps 7973 if($ShortName eq "operator>>") 7974 { 7975 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}) 7976 { # corrected mangling of operator>> 7977 $SRemangle = 1; 7978 } 7979 } 7980 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"}) 7981 { 7982 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"} 7983 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/) 7984 { # corrected mangling of const global data 7985 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8) 7986 # and incorrectly mangled by old ACC versions 7987 $SRemangle = 1; 7988 } 7989 } 7990 } 7991 if(not $CheckHeadersOnly) 7992 { # support for old ABI dumps 7993 if(not checkDump(1, "2.17") 7994 or not checkDump(2, "2.17")) 7995 { 7996 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"}) 7997 { 7998 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}) 7999 { 8000 if(link_symbol($ShortName, $LibVersion, "-Deps")) 8001 { 8002 $MnglName = $ShortName; 8003 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName; 8004 } 8005 } 8006 } 8007 } 8008 } 8009 if($Remangle==1 or $SRemangle==1) 8010 { # support for old ABI dumps: some symbols are not mangled in old dumps 8011 # mangle both sets of symbols (old and new) 8012 # NOTE: remangling all symbols by the same mangler 8013 if($MnglName=~/\A_ZN(V|)K/) 8014 { # mangling may be incorrect on old ABI dumps 8015 # because of absent "Const" attribute 8016 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1; 8017 } 8018 if($MnglName=~/\A_ZN(K|)V/) 8019 { # mangling may be incorrect on old ABI dumps 8020 # because of absent "Volatile" attribute 8021 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1; 8022 } 8023 if(($ClassID and $MnglName!~/\A(_Z|\?)/) 8024 or (not $ClassID and $CheckHeadersOnly) 8025 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps"))) 8026 { # support for old ABI dumps, GCC >= 4.0 8027 # remangling all manually mangled symbols 8028 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC")) 8029 { 8030 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName; 8031 $MangledNames{$LibVersion}{$MnglName} = 1; 8032 } 8033 } 8034 } 8035 elsif($Remangle==-1) 8036 { # remove mangling 8037 $MnglName = ""; 8038 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = ""; 8039 } 8040 if(not $MnglName) { 8041 next; 8042 } 8043 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"}) 8044 { # NOTE: global data may enter here twice 8045 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}}; 8046 8047 } 8048 if(not checkDump($LibVersion, "2.6")) 8049 { # support for old dumps 8050 # add "Volatile" attribute 8051 if($MnglName=~/_Z(K|)V/) { 8052 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1; 8053 } 8054 } 8055 # symbol and its symlink have same signatures 8056 if($SymVer{$LibVersion}{$MnglName}) { 8057 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}}; 8058 } 8059 8060 # clean memory 8061 delete($SymbolInfo{$LibVersion}{$InfoId}); 8062 } 8063 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") { 8064 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion); 8065 } 8066 if($ExtendedCheck) 8067 { # --ext option 8068 addExtension($LibVersion); 8069 } 8070 8071 # clean memory 8072 delete($SymbolInfo{$LibVersion}); 8073 8074 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}})) 8075 { # detect allocable classes with public exported constructors 8076 # or classes with auto-generated or inline-only constructors 8077 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) 8078 { 8079 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}; 8080 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"} 8081 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}) 8082 { # Class() { ... } will not be exported 8083 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"}) 8084 { 8085 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) { 8086 $AllocableClass{$LibVersion}{$ClassName} = 1; 8087 } 8088 } 8089 } 8090 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"}) 8091 { # all imported class methods 8092 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary")) 8093 { 8094 if($CheckHeadersOnly) 8095 { 8096 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"} 8097 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"}) 8098 { # all symbols except non-virtual inline 8099 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1; 8100 } 8101 } 8102 else { 8103 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1; 8104 } 8105 } 8106 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) { 8107 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1; 8108 } 8109 } 8110 $ClassNames{$LibVersion}{$ClassName} = 1; 8111 } 8112 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) 8113 { 8114 my %Base = get_BaseType($RetId, $LibVersion); 8115 if(defined $Base{"Type"} 8116 and $Base{"Type"}=~/Struct|Class/) 8117 { 8118 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"}; 8119 if($Name=~/<([^<>\s]+)>/) 8120 { 8121 if(my $Tid = getTypeIdByName($1, $LibVersion)) { 8122 $ReturnedClass{$LibVersion}{$Tid} = 1; 8123 } 8124 } 8125 else { 8126 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1; 8127 } 8128 } 8129 } 8130 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}})) 8131 { 8132 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"}; 8133 if(get_PLevel($PId, $LibVersion)>=1) 8134 { 8135 if(my %Base = get_BaseType($PId, $LibVersion)) 8136 { 8137 if($Base{"Type"}=~/Struct|Class/) 8138 { 8139 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1; 8140 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1)) 8141 { # mark all derived classes 8142 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1; 8143 } 8144 } 8145 } 8146 } 8147 } 8148 } 8149 foreach my $MnglName (keys(%VTableClass)) 8150 { # reconstruct header name for v-tables 8151 if($MnglName=~/\A_ZTV/) 8152 { 8153 if(my $ClassName = $VTableClass{$MnglName}) 8154 { 8155 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName}) { 8156 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"}; 8157 } 8158 } 8159 } 8160 } 8161 8162 # types 8163 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}})) 8164 { 8165 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"}) 8166 { 8167 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) { 8168 $ClassNames{$LibVersion}{$TName} = 1; 8169 } 8170 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"}) 8171 { 8172 $ClassNames{$LibVersion}{$TName} = 1; 8173 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}})) 8174 { 8175 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) { 8176 $ClassNames{$LibVersion}{$BName} = 1; 8177 } 8178 } 8179 } 8180 } 8181 } 8182} 8183 8184sub register_TypeUsage($$) 8185{ 8186 my ($TypeId, $LibVersion) = @_; 8187 if(not $TypeId) { 8188 return 0; 8189 } 8190 if($UsedType{$LibVersion}{$TypeId}) 8191 { # already registered 8192 return 1; 8193 } 8194 my %TInfo = get_Type($TypeId, $LibVersion); 8195 if($TInfo{"Type"}) 8196 { 8197 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|MethodPtr|FieldPtr|Enum)\Z/) 8198 { 8199 $UsedType{$LibVersion}{$TypeId} = 1; 8200 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/) 8201 { 8202 foreach my $BaseId (keys(%{$TInfo{"Base"}})) 8203 { # register base classes 8204 register_TypeUsage($BaseId, $LibVersion); 8205 } 8206 foreach my $TPos (keys(%{$TInfo{"TParam"}})) 8207 { 8208 my $TPName = $TInfo{"TParam"}{$TPos}{"name"}; 8209 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) { 8210 register_TypeUsage($TTid, $LibVersion); 8211 } 8212 } 8213 } 8214 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}})) 8215 { 8216 if(my $MTid = $TInfo{"Memb"}{$Memb_Pos}{"type"}) { 8217 register_TypeUsage($MTid, $LibVersion); 8218 } 8219 } 8220 if($TInfo{"Type"} eq "FuncPtr" 8221 or $TInfo{"Type"} eq "MethodPtr") 8222 { 8223 if(my $RTid = $TInfo{"Return"}) { 8224 register_TypeUsage($RTid, $LibVersion); 8225 } 8226 foreach my $Memb_Pos (keys(%{$TInfo{"Param"}})) 8227 { 8228 if(my $MTid = $TInfo{"Param"}{$Memb_Pos}{"type"}) { 8229 register_TypeUsage($MTid, $LibVersion); 8230 } 8231 } 8232 } 8233 return 1; 8234 } 8235 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/) 8236 { 8237 $UsedType{$LibVersion}{$TypeId} = 1; 8238 register_TypeUsage($TInfo{"BaseType"}{"Tid"}, $LibVersion); 8239 return 1; 8240 } 8241 elsif($TInfo{"Type"} eq "Intrinsic") 8242 { 8243 $UsedType{$LibVersion}{$TypeId} = 1; 8244 return 1; 8245 } 8246 } 8247 return 0; 8248} 8249 8250sub selectSymbol($$$$) 8251{ # select symbol to check or to dump 8252 my ($Symbol, $SInfo, $Level, $LibVersion) = @_; 8253 8254 if($Level eq "Dump") 8255 { 8256 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"}) 8257 { # TODO: check if this symbol is from 8258 # base classes of other target symbols 8259 return 1; 8260 } 8261 } 8262 8263 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/) 8264 { # stdc++ interfaces 8265 return 0; 8266 } 8267 8268 my $Target = 0; 8269 if(my $Header = $SInfo->{"Header"}) { 8270 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2)); 8271 } 8272 if($CheckHeadersOnly) 8273 { 8274 if($Target) 8275 { 8276 if($Level eq "Dump") 8277 { # dumped 8278 if($BinaryOnly) 8279 { 8280 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) { 8281 return 1; 8282 } 8283 } 8284 else { 8285 return 1; 8286 } 8287 } 8288 elsif($Level eq "Source") 8289 { # checked 8290 return 1; 8291 } 8292 elsif($Level eq "Binary") 8293 { # checked 8294 if(not $SInfo->{"InLine"} or $SInfo->{"Data"} 8295 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) { 8296 return 1; 8297 } 8298 } 8299 } 8300 } 8301 else 8302 { # library is available 8303 if(link_symbol($Symbol, $LibVersion, "-Deps")) 8304 { # exported symbols 8305 return 1; 8306 } 8307 if($Level eq "Dump") 8308 { # dumped 8309 if($BinaryOnly) 8310 { 8311 if($SInfo->{"Data"}) 8312 { 8313 if($Target) { 8314 return 1; 8315 } 8316 } 8317 } 8318 else 8319 { # SrcBin 8320 if($Target) { 8321 return 1; 8322 } 8323 } 8324 } 8325 elsif($Level eq "Source") 8326 { # checked 8327 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}) 8328 { # skip LOCAL symbols 8329 if($Target) { 8330 return 1; 8331 } 8332 } 8333 } 8334 elsif($Level eq "Binary") 8335 { # checked 8336 if($SInfo->{"PureVirt"} or $SInfo->{"Data"}) 8337 { 8338 if($Target) { 8339 return 1; 8340 } 8341 } 8342 } 8343 } 8344 return 0; 8345} 8346 8347sub cleanDump($) 8348{ # clean data 8349 my $LibVersion = $_[0]; 8350 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}})) 8351 { 8352 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"}; 8353 if(not $MnglName) { 8354 delete($SymbolInfo{$LibVersion}{$InfoId}); 8355 next; 8356 } 8357 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"}; 8358 if(not $ShortName) { 8359 delete($SymbolInfo{$LibVersion}{$InfoId}); 8360 next; 8361 } 8362 if($MnglName eq $ShortName) 8363 { # remove duplicate data 8364 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"}); 8365 } 8366 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) { 8367 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"}); 8368 } 8369 } 8370 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}})) 8371 { 8372 foreach my $Attr ("Header", "Line", "Size", "NameSpace") 8373 { 8374 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) { 8375 delete($TypeInfo{$LibVersion}{$Tid}{$Attr}); 8376 } 8377 } 8378 } 8379} 8380 8381sub selectType($$) 8382{ 8383 my ($Tid, $LibVersion) = @_; 8384 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"}) 8385 { 8386 if(not isBuiltIn($THeader)) 8387 { 8388 if($TypeInfo{$LibVersion}{$Tid}{"Type"}=~/Class|Struct|Union|Enum|Typedef/) 8389 { 8390 if(not isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) 8391 { 8392 if(is_target_header($THeader, $LibVersion)) 8393 { # from target headers 8394 if(not selfTypedef($Tid, $LibVersion)) { 8395 return 1; 8396 } 8397 } 8398 } 8399 } 8400 } 8401 } 8402 return 0; 8403} 8404 8405sub removeUnused($$) 8406{ # remove unused data types from the ABI dump 8407 my ($LibVersion, $Kind) = @_; 8408 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}})) 8409 { 8410 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}}; 8411 if(my $RTid = $FuncInfo{"Return"}) { 8412 register_TypeUsage($RTid, $LibVersion); 8413 } 8414 if(my $FCid = $FuncInfo{"Class"}) 8415 { 8416 register_TypeUsage($FCid, $LibVersion); 8417 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion)) 8418 { # register "this" pointer 8419 $UsedType{$LibVersion}{$ThisId} = 1; 8420 if(my %ThisType = get_Type($ThisId, $LibVersion)) { 8421 register_TypeUsage($ThisType{"BaseType"}{"Tid"}, $LibVersion); 8422 } 8423 } 8424 } 8425 foreach my $PPos (keys(%{$FuncInfo{"Param"}})) 8426 { 8427 if(my $PTid = $FuncInfo{"Param"}{$PPos}{"type"}) { 8428 register_TypeUsage($PTid, $LibVersion); 8429 } 8430 } 8431 foreach my $TPos (keys(%{$FuncInfo{"TParam"}})) 8432 { 8433 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"}; 8434 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) { 8435 register_TypeUsage($TTid, $LibVersion); 8436 } 8437 } 8438 } 8439 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}})) 8440 { 8441 if($UsedType{$LibVersion}{$Tid}) 8442 { # All & Derived 8443 next; 8444 } 8445 8446 if($Kind eq "Derived") 8447 { 8448 if(selectType($Tid, $LibVersion)) { 8449 register_TypeUsage($Tid, $LibVersion); 8450 } 8451 } 8452 } 8453 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}})) 8454 { # remove unused types 8455 if($UsedType{$LibVersion}{$Tid}) 8456 { # All & Derived 8457 next; 8458 } 8459 # remove type 8460 delete($TypeInfo{$LibVersion}{$Tid}); 8461 } 8462 8463 # clean memory 8464 %UsedType = (); 8465} 8466 8467sub selfTypedef($$) 8468{ 8469 my ($TypeId, $LibVersion) = @_; 8470 my %Type = get_Type($TypeId, $LibVersion); 8471 if($Type{"Type"} eq "Typedef") 8472 { 8473 my %Base = get_OneStep_BaseType($TypeId, $LibVersion); 8474 if($Base{"Type"}=~/Class|Struct/) 8475 { 8476 if($Type{"Name"} eq $Base{"Name"}) { 8477 return 1; 8478 } 8479 elsif($Type{"Name"}=~/::(\w+)\Z/) 8480 { 8481 if($Type{"Name"} eq $Base{"Name"}."::".$1) 8482 { # QPointer<QWidget>::QPointer 8483 return 1; 8484 } 8485 } 8486 } 8487 } 8488 return 0; 8489} 8490 8491sub addExtension($) 8492{ 8493 my $LibVersion = $_[0]; 8494 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}})) 8495 { 8496 if(selectType($Tid, $LibVersion)) 8497 { 8498 my $Symbol = "external_func_".$TypeInfo{$LibVersion}{$Tid}{"Name"}; 8499 8500 %{$CompleteSignature{$LibVersion}{$Symbol}} = ( 8501 "Header" => "extended.h", 8502 "ShortName" => $Symbol, 8503 "MnglName" => $Symbol, 8504 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } } 8505 ); 8506 8507 $ExtendedSymbols{$Symbol}=1; 8508 $CheckedSymbols{"Binary"}{$Symbol}=1; 8509 $CheckedSymbols{"Source"}{$Symbol}=1; 8510 } 8511 } 8512 $ExtendedSymbols{"external_func_0"}=1; 8513 $CheckedSymbols{"Binary"}{"external_func_0"}=1; 8514 $CheckedSymbols{"Source"}{"external_func_0"}=1; 8515} 8516 8517sub findMethod($$$) 8518{ 8519 my ($VirtFunc, $ClassId, $LibVersion) = @_; 8520 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}})) 8521 { 8522 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) { 8523 return $VirtMethodInClass; 8524 } 8525 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) { 8526 return $VirtMethodInBaseClasses; 8527 } 8528 } 8529 return ""; 8530} 8531 8532sub findMethod_Class($$$) 8533{ 8534 my ($VirtFunc, $ClassId, $LibVersion) = @_; 8535 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}; 8536 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName}); 8537 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1); 8538 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"}; 8539 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}})) 8540 { # search for interface with the same parameters suffix (overridden) 8541 if($TargetSuffix eq get_symbol_suffix($Candidate, 1)) 8542 { 8543 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"}) { 8544 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"}) 8545 { 8546 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/) 8547 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/) 8548 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) { 8549 return $Candidate; 8550 } 8551 } 8552 } 8553 else { 8554 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) { 8555 return $Candidate; 8556 } 8557 } 8558 } 8559 } 8560 return ""; 8561} 8562 8563sub registerVTable($) 8564{ 8565 my $LibVersion = $_[0]; 8566 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}})) 8567 { 8568 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"} 8569 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"}) 8570 { 8571 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"}; 8572 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/); 8573 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"} 8574 and $Symbol=~/D2E/) 8575 { # pure virtual D2-destructors are marked as "virt" in the dump 8576 # virtual D2-destructors are NOT marked as "virt" in the dump 8577 # both destructors are not presented in the v-table 8578 next; 8579 } 8580 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol); 8581 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1; 8582 } 8583 } 8584} 8585 8586sub registerOverriding($) 8587{ 8588 my $LibVersion = $_[0]; 8589 my @Classes = keys(%{$VirtualTable{$LibVersion}}); 8590 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes; 8591 foreach my $ClassName (@Classes) 8592 { 8593 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}})) 8594 { 8595 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"}) 8596 { # pure virtuals 8597 next; 8598 } 8599 my $ClassId = $TName_Tid{$LibVersion}{$ClassName}; 8600 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion)) 8601 { 8602 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"} 8603 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"}) 8604 { # both overridden virtual methods 8605 # and implemented pure virtual methods 8606 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden; 8607 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1; 8608 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model 8609 } 8610 } 8611 } 8612 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) { 8613 delete($VirtualTable{$LibVersion}{$ClassName}); 8614 } 8615 } 8616} 8617 8618sub setVirtFuncPositions($) 8619{ 8620 my $LibVersion = $_[0]; 8621 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}})) 8622 { 8623 my ($Num, $RelPos, $AbsNum) = (1, 0, 1); 8624 foreach my $VirtFunc (sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} 8625 sort keys(%{$VirtualTable{$LibVersion}{$ClassName}})) 8626 { 8627 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}=$Num++; 8628 8629 # set relative positions 8630 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc} 8631 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc}) 8632 { # relative position excluding added and removed virtual functions 8633 if(not $CompleteSignature{1}{$VirtFunc}{"Override"} 8634 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) { 8635 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $RelPos++; 8636 } 8637 } 8638 } 8639 } 8640 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}})) 8641 { 8642 my $AbsNum = 1; 8643 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) { 8644 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc}=$AbsNum++; 8645 } 8646 } 8647} 8648 8649sub get_sub_classes($$$) 8650{ 8651 my ($ClassId, $LibVersion, $Recursive) = @_; 8652 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId}); 8653 my @Subs = (); 8654 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}})) 8655 { 8656 if($Recursive) 8657 { 8658 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) { 8659 push(@Subs, $SubSubId); 8660 } 8661 } 8662 push(@Subs, $SubId); 8663 } 8664 return @Subs; 8665} 8666 8667sub get_base_classes($$$) 8668{ 8669 my ($ClassId, $LibVersion, $Recursive) = @_; 8670 my %ClassType = get_Type($ClassId, $LibVersion); 8671 return () if(not defined $ClassType{"Base"}); 8672 my @Bases = (); 8673 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})} 8674 keys(%{$ClassType{"Base"}})) 8675 { 8676 if($Recursive) 8677 { 8678 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) { 8679 push(@Bases, $SubBaseId); 8680 } 8681 } 8682 push(@Bases, $BaseId); 8683 } 8684 return @Bases; 8685} 8686 8687sub getVTable_Model($$) 8688{ # return an ordered list of v-table elements 8689 my ($ClassId, $LibVersion) = @_; 8690 my @Bases = get_base_classes($ClassId, $LibVersion, 1); 8691 my @Elements = (); 8692 foreach my $BaseId (@Bases, $ClassId) 8693 { 8694 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"}) 8695 { 8696 if(defined $VirtualTable{$LibVersion}{$BName}) 8697 { 8698 my @VFunctions = keys(%{$VirtualTable{$LibVersion}{$BName}}); 8699 @VFunctions = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFunctions; 8700 foreach my $VFunc (@VFunctions) { 8701 push(@Elements, $VFunc); 8702 } 8703 } 8704 } 8705 } 8706 return @Elements; 8707} 8708 8709sub getVShift($$) 8710{ 8711 my ($ClassId, $LibVersion) = @_; 8712 my @Bases = get_base_classes($ClassId, $LibVersion, 1); 8713 my $VShift = 0; 8714 foreach my $BaseId (@Bases) 8715 { 8716 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"}) 8717 { 8718 if(defined $VirtualTable{$LibVersion}{$BName}) { 8719 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}}); 8720 } 8721 } 8722 } 8723 return $VShift; 8724} 8725 8726sub getShift($$) 8727{ 8728 my ($ClassId, $LibVersion) = @_; 8729 my @Bases = get_base_classes($ClassId, $LibVersion, 0); 8730 my $Shift = 0; 8731 foreach my $BaseId (@Bases) 8732 { 8733 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"}) 8734 { 8735 if($Size!=1) 8736 { # not empty base class 8737 $Shift+=$Size; 8738 } 8739 } 8740 } 8741 return $Shift; 8742} 8743 8744sub getVTable_Size($$) 8745{ # number of v-table elements 8746 my ($ClassName, $LibVersion) = @_; 8747 my $Size = 0; 8748 # three approaches 8749 if(not $Size) 8750 { # real size 8751 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) { 8752 $Size = keys(%VTable); 8753 } 8754 } 8755 if(not $Size) 8756 { # shared library symbol size 8757 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) { 8758 $Size /= $WORD_SIZE{$LibVersion}; 8759 } 8760 } 8761 if(not $Size) 8762 { # model size 8763 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) { 8764 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2; 8765 } 8766 } 8767 return $Size; 8768} 8769 8770sub isCopyingClass($$) 8771{ 8772 my ($TypeId, $LibVersion) = @_; 8773 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"}; 8774} 8775 8776sub isLeafClass($$) 8777{ 8778 my ($ClassId, $LibVersion) = @_; 8779 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}})); 8780} 8781 8782sub havePubFields($) 8783{ # check structured type for public fields 8784 return isAccessible($_[0], {}, 0, -1); 8785} 8786 8787sub isAccessible($$$$) 8788{ # check interval in structured type for public fields 8789 my ($TypePtr, $Skip, $Start, $End) = @_; 8790 return 0 if(not $TypePtr); 8791 if($End==-1) { 8792 $End = keys(%{$TypePtr->{"Memb"}})-1; 8793 } 8794 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}})) 8795 { 8796 if($Skip and $Skip->{$MemPos}) 8797 { # skip removed/added fields 8798 next; 8799 } 8800 if(int($MemPos)>=$Start and int($MemPos)<=$End) 8801 { 8802 if(isPublic($TypePtr, $MemPos)) { 8803 return ($MemPos+1); 8804 } 8805 } 8806 } 8807 return 0; 8808} 8809 8810sub getAlignment($$$) 8811{ 8812 my ($Pos, $TypePtr, $LibVersion) = @_; 8813 my $Tid = $TypePtr->{"Memb"}{$Pos}{"type"}; 8814 my %Type = get_PureType($Tid, $LibVersion); 8815 my $TSize = $Type{"Size"}*$BYTE_SIZE; 8816 my $MSize = $Type{"Size"}*$BYTE_SIZE; 8817 if(my $BSize = $TypePtr->{"Memb"}{$Pos}{"bitfield"}) 8818 { # bitfields 8819 ($TSize, $MSize) = ($WORD_SIZE{$LibVersion}*$BYTE_SIZE, $BSize); 8820 } 8821 elsif($Type{"Type"} eq "Array") 8822 { # in the context of function parameter 8823 # it's passed through the pointer 8824 } 8825 # alignment 8826 my $Alignment = $WORD_SIZE{$LibVersion}*$BYTE_SIZE; # default 8827 if(my $Computed = $TypePtr->{"Memb"}{$Pos}{"algn"}) 8828 { # computed by GCC 8829 $Alignment = $Computed*$BYTE_SIZE; 8830 } 8831 elsif($TypePtr->{"Memb"}{$Pos}{"bitfield"}) 8832 { # bitfields are 1 bit aligned 8833 $Alignment = 1; 8834 } 8835 elsif($TSize and $TSize<$WORD_SIZE{$LibVersion}*$BYTE_SIZE) 8836 { # model 8837 $Alignment = $TSize; 8838 } 8839 return ($Alignment, $MSize); 8840} 8841 8842sub getOffset($$$) 8843{ # offset of the field including padding 8844 my ($FieldPos, $TypePtr, $LibVersion) = @_; 8845 my $Offset = 0; 8846 foreach my $Pos (0 .. keys(%{$TypePtr->{"Memb"}})-1) 8847 { 8848 my ($Alignment, $MSize) = getAlignment($Pos, $TypePtr, $LibVersion); 8849 # padding 8850 my $Padding = 0; 8851 if($Offset % $Alignment!=0) 8852 { # not aligned, add padding 8853 $Padding = $Alignment - $Offset % $Alignment; 8854 } 8855 $Offset += $Padding; 8856 if($Pos==$FieldPos) 8857 { # after the padding 8858 # before the field 8859 return $Offset; 8860 } 8861 $Offset += $MSize; 8862 } 8863 return $FieldPos;# if something is going wrong 8864} 8865 8866sub isMemPadded($$$$$) 8867{ # check if the target field can be added/removed/changed 8868 # without shifting other fields because of padding bits 8869 my ($FieldPos, $Size, $TypePtr, $Skip, $LibVersion) = @_; 8870 return 0 if($FieldPos==0); 8871 if(defined $TypePtr->{"Memb"}{""}) 8872 { 8873 delete($TypePtr->{"Memb"}{""}); 8874 if($Debug) { 8875 printMsg("WARNING", "internal error detected"); 8876 } 8877 } 8878 my $Offset = 0; 8879 my (%Alignment, %MSize) = (); 8880 my $MaxAlgn = 0; 8881 my $End = keys(%{$TypePtr->{"Memb"}})-1; 8882 my $NextField = $FieldPos+1; 8883 foreach my $Pos (0 .. $End) 8884 { 8885 if($Skip and $Skip->{$Pos}) 8886 { # skip removed/added fields 8887 if($Pos > $FieldPos) 8888 { # after the target 8889 $NextField += 1; 8890 next; 8891 } 8892 } 8893 ($Alignment{$Pos}, $MSize{$Pos}) = getAlignment($Pos, $TypePtr, $LibVersion); 8894 if($Alignment{$Pos}>$MaxAlgn) { 8895 $MaxAlgn = $Alignment{$Pos}; 8896 } 8897 if($Pos==$FieldPos) 8898 { 8899 if($Size==-1) 8900 { # added/removed fields 8901 if($Pos!=$End) 8902 { # skip target field and see 8903 # if enough padding will be 8904 # created on the next step 8905 # to include this field 8906 next; 8907 } 8908 } 8909 } 8910 # padding 8911 my $Padding = 0; 8912 if($Offset % $Alignment{$Pos}!=0) 8913 { # not aligned, add padding 8914 $Padding = $Alignment{$Pos} - $Offset % $Alignment{$Pos}; 8915 } 8916 if($Pos==$NextField) 8917 { # try to place target field in the padding 8918 if($Size==-1) 8919 { # added/removed fields 8920 my $TPadding = 0; 8921 if($Offset % $Alignment{$FieldPos}!=0) 8922 {# padding of the target field 8923 $TPadding = $Alignment{$FieldPos} - $Offset % $Alignment{$FieldPos}; 8924 } 8925 if($TPadding+$MSize{$FieldPos}<=$Padding) 8926 { # enough padding to place target field 8927 return 1; 8928 } 8929 else { 8930 return 0; 8931 } 8932 } 8933 else 8934 { # changed fields 8935 my $Delta = $Size-$MSize{$FieldPos}; 8936 if($Delta>=0) 8937 { # increased 8938 if($Size-$MSize{$FieldPos}<=$Padding) 8939 { # enough padding to change target field 8940 return 1; 8941 } 8942 else { 8943 return 0; 8944 } 8945 } 8946 else 8947 { # decreased 8948 $Delta = abs($Delta); 8949 if($Delta+$Padding>=$MSize{$Pos}) 8950 { # try to place the next field 8951 if(($Offset-$Delta) % $Alignment{$Pos} != 0) 8952 { # padding of the next field in new place 8953 my $NPadding = $Alignment{$Pos} - ($Offset-$Delta) % $Alignment{$Pos}; 8954 if($NPadding+$MSize{$Pos}<=$Delta+$Padding) 8955 { # enough delta+padding to store next field 8956 return 0; 8957 } 8958 } 8959 else 8960 { 8961 return 0; 8962 } 8963 } 8964 return 1; 8965 } 8966 } 8967 } 8968 elsif($Pos==$End) 8969 { # target field is the last field 8970 if($Size==-1) 8971 { # added/removed fields 8972 if($Offset % $MaxAlgn!=0) 8973 { # tail padding 8974 my $TailPadding = $MaxAlgn - $Offset % $MaxAlgn; 8975 if($Padding+$MSize{$Pos}<=$TailPadding) 8976 { # enough tail padding to place the last field 8977 return 1; 8978 } 8979 } 8980 return 0; 8981 } 8982 else 8983 { # changed fields 8984 # scenario #1 8985 my $Offset1 = $Offset+$Padding+$MSize{$Pos}; 8986 if($Offset1 % $MaxAlgn != 0) 8987 { # tail padding 8988 $Offset1 += $MaxAlgn - $Offset1 % $MaxAlgn; 8989 } 8990 # scenario #2 8991 my $Offset2 = $Offset+$Padding+$Size; 8992 if($Offset2 % $MaxAlgn != 0) 8993 { # tail padding 8994 $Offset2 += $MaxAlgn - $Offset2 % $MaxAlgn; 8995 } 8996 if($Offset1!=$Offset2) 8997 { # different sizes of structure 8998 return 0; 8999 } 9000 return 1; 9001 } 9002 } 9003 $Offset += $Padding+$MSize{$Pos}; 9004 } 9005 return 0; 9006} 9007 9008sub isReserved($) 9009{ # reserved fields == private 9010 my $MName = $_[0]; 9011 if($MName=~/reserved|padding|f_spare/i) { 9012 return 1; 9013 } 9014 if($MName=~/\A[_]*(spare|pad|unused)[_]*\Z/i) { 9015 return 1; 9016 } 9017 if($MName=~/(pad\d+)/i) { 9018 return 1; 9019 } 9020 return 0; 9021} 9022 9023sub isPublic($$) 9024{ 9025 my ($TypePtr, $FieldPos) = @_; 9026 return 0 if(not $TypePtr); 9027 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}); 9028 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"}); 9029 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"}) 9030 { # by name in C language 9031 # FIXME: add other methods to detect private members 9032 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"}; 9033 if($MName=~/priv|abidata|parent_object/i) 9034 { # C-styled private data 9035 return 0; 9036 } 9037 if(lc($MName) eq "abi") 9038 { # ABI information/reserved field 9039 return 0; 9040 } 9041 if(isReserved($MName)) 9042 { # reserved fields 9043 return 0; 9044 } 9045 return 1; 9046 } 9047 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private") 9048 { # by access in C++ language 9049 return 1; 9050 } 9051 return 0; 9052} 9053 9054sub getVTable_Real($$) 9055{ 9056 my ($ClassName, $LibVersion) = @_; 9057 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName}) 9058 { 9059 my %Type = get_Type($ClassId, $LibVersion); 9060 if(defined $Type{"VTable"}) { 9061 return %{$Type{"VTable"}}; 9062 } 9063 } 9064 return (); 9065} 9066 9067sub cmpVTables($) 9068{ 9069 my $ClassName = $_[0]; 9070 my $Res = cmpVTables_Real($ClassName, 1); 9071 if($Res==-1) { 9072 $Res = cmpVTables_Model($ClassName); 9073 } 9074 return $Res; 9075} 9076 9077sub cmpVTables_Model($) 9078{ 9079 my $ClassName = $_[0]; 9080 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}})) 9081 { 9082 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) { 9083 return 1; 9084 } 9085 } 9086 return 0; 9087} 9088 9089sub cmpVTables_Real($$) 9090{ 9091 my ($ClassName, $Strong) = @_; 9092 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) { 9093 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}; 9094 } 9095 my %VTable_Old = getVTable_Real($ClassName, 1); 9096 my %VTable_New = getVTable_Real($ClassName, 2); 9097 if(not %VTable_Old or not %VTable_New) 9098 { # old ABI dumps 9099 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1); 9100 } 9101 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New)); 9102 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes)) 9103 { 9104 if(not defined $VTable_Old{$Offset}) 9105 { # v-table v.1 < v-table v.2 9106 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong); 9107 } 9108 my $Entry1 = $VTable_Old{$Offset}; 9109 if(not defined $VTable_New{$Offset}) 9110 { # v-table v.1 > v-table v.2 9111 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/)); 9112 } 9113 my $Entry2 = $VTable_New{$Offset}; 9114 $Entry1 = simpleVEntry($Entry1); 9115 $Entry2 = simpleVEntry($Entry2); 9116 if($Entry1 ne $Entry2) 9117 { # register as changed 9118 if($Entry1=~/::([^:]+)\Z/) 9119 { 9120 my $M1 = $1; 9121 if($Entry2=~/::([^:]+)\Z/) 9122 { 9123 my $M2 = $1; 9124 if($M1 eq $M2) 9125 { # overridden 9126 next; 9127 } 9128 } 9129 } 9130 if(differentDumps("G")) 9131 { 9132 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/) 9133 { 9134 # GCC 4.6.1: -0x00000000000000010 9135 # GCC 4.7.0: -16 9136 next; 9137 } 9138 } 9139 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1); 9140 } 9141 } 9142 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0); 9143} 9144 9145sub mergeVTables($) 9146{ # merging v-tables without diagnostics 9147 my $Level = $_[0]; 9148 foreach my $ClassName (keys(%{$VirtualTable{1}})) 9149 { 9150 if($VTableChanged_M{$ClassName}) 9151 { # already registered 9152 next; 9153 } 9154 if(cmpVTables_Real($ClassName, 0)==1) 9155 { 9156 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}})); 9157 foreach my $Symbol (@Affected) 9158 { 9159 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=( 9160 "Type_Name"=>$ClassName, 9161 "Type_Type"=>"Class", 9162 "Target"=>$ClassName); 9163 } 9164 } 9165 } 9166} 9167 9168sub mergeBases($) 9169{ 9170 my $Level = $_[0]; 9171 foreach my $ClassName (keys(%{$ClassNames{1}})) 9172 { # detect added and removed virtual functions 9173 my $ClassId = $TName_Tid{1}{$ClassName}; 9174 next if(not $ClassId); 9175 if(defined $VirtualTable{2}{$ClassName}) 9176 { 9177 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}})) 9178 { 9179 if($TName_Tid{1}{$ClassName} 9180 and not defined $VirtualTable{1}{$ClassName}{$Symbol}) 9181 { # added to v-table 9182 if(defined $CompleteSignature{1}{$Symbol} 9183 and $CompleteSignature{1}{$Symbol}{"Virt"}) 9184 { # override some method in v.1 9185 next; 9186 } 9187 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1; 9188 } 9189 } 9190 } 9191 if(defined $VirtualTable{1}{$ClassName}) 9192 { 9193 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}})) 9194 { 9195 if($TName_Tid{2}{$ClassName} 9196 and not defined $VirtualTable{2}{$ClassName}{$Symbol}) 9197 { # removed from v-table 9198 if(defined $CompleteSignature{2}{$Symbol} 9199 and $CompleteSignature{2}{$Symbol}{"Virt"}) 9200 { # override some method in v.2 9201 next; 9202 } 9203 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1; 9204 } 9205 } 9206 } 9207 if($Level eq "Binary") 9208 { # Binary-level 9209 my %Class_Type = get_Type($ClassId, 1); 9210 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}})) 9211 { # check replacements, including pure virtual methods 9212 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc}; 9213 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}})) 9214 { 9215 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc}; 9216 if($AddedPos==$RemovedPos) 9217 { 9218 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc; 9219 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc; 9220 last; # other methods will be reported as "added" or "removed" 9221 } 9222 } 9223 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc}) 9224 { 9225 if(lc($AddedVFunc) eq lc($RemovedVFunc)) 9226 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0) 9227 next; 9228 } 9229 my $ProblemType = "Virtual_Replacement"; 9230 my @Affected = ($RemovedVFunc); 9231 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) 9232 { # pure methods 9233 if(not isUsedClass($ClassId, 1, $Level)) 9234 { # not a parameter of some exported method 9235 next; 9236 } 9237 $ProblemType = "Pure_Virtual_Replacement"; 9238 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}})) 9239 } 9240 foreach my $AffectedInt (@Affected) 9241 { 9242 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"}) 9243 { # affected exported methods only 9244 next; 9245 } 9246 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=( 9247 "Type_Name"=>$Class_Type{"Name"}, 9248 "Type_Type"=>"Class", 9249 "Target"=>get_Signature($AddedVFunc, 2), 9250 "Old_Value"=>get_Signature($RemovedVFunc, 1)); 9251 } 9252 } 9253 } 9254 } 9255 } 9256 if(not checkDump(1, "2.0") 9257 or not checkDump(2, "2.0")) 9258 { # support for old ABI dumps 9259 # "Base" attribute introduced in ACC 1.22 (dump 2.0 format) 9260 return; 9261 } 9262 foreach my $ClassName (sort keys(%{$ClassNames{1}})) 9263 { 9264 my $ClassId_Old = $TName_Tid{1}{$ClassName}; 9265 next if(not $ClassId_Old); 9266 if(not isCreatable($ClassId_Old, 1)) 9267 { # skip classes without public constructors (including auto-generated) 9268 # example: class has only a private exported or private inline constructor 9269 next; 9270 } 9271 if($ClassName=~/>/) 9272 { # skip affected template instances 9273 next; 9274 } 9275 my %Class_Old = get_Type($ClassId_Old, 1); 9276 my $ClassId_New = $TName_Tid{2}{$ClassName}; 9277 if(not $ClassId_New) { 9278 next; 9279 } 9280 my %Class_New = get_Type($ClassId_New, 2); 9281 if($Class_New{"Type"}!~/Class|Struct/) 9282 { # became typedef 9283 if($Level eq "Binary") { 9284 next; 9285 } 9286 if($Level eq "Source") 9287 { 9288 %Class_New = get_PureType($ClassId_New, 2); 9289 if($Class_New{"Type"}!~/Class|Struct/) { 9290 next; 9291 } 9292 $ClassId_New = $Class_New{"Tid"}; 9293 } 9294 } 9295 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}}); 9296 my @Bases_New = sort {$Class_New{"Base"}{$a}{"pos"}<=>$Class_New{"Base"}{$b}{"pos"}} keys(%{$Class_New{"Base"}}); 9297 my ($BNum1, $BNum2) = (1, 1); 9298 my %BasePos_Old = map {$TypeInfo{1}{$_}{"Name"} => $BNum1++} @Bases_Old; 9299 my %BasePos_New = map {$TypeInfo{2}{$_}{"Name"} => $BNum2++} @Bases_New; 9300 my %ShortBase_Old = map {get_ShortType($_, 1) => 1} @Bases_Old; 9301 my %ShortBase_New = map {get_ShortType($_, 2) => 1} @Bases_New; 9302 my $Shift_Old = getShift($ClassId_Old, 1); 9303 my $Shift_New = getShift($ClassId_New, 2); 9304 my %BaseId_New = map {$TypeInfo{2}{$_}{"Name"} => $_} @Bases_New; 9305 my ($Added, $Removed) = (0, 0); 9306 my @StableBases_Old = (); 9307 foreach my $BaseId (@Bases_Old) 9308 { 9309 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"}; 9310 if($BasePos_New{$BaseName}) { 9311 push(@StableBases_Old, $BaseId); 9312 } 9313 elsif(not $ShortBase_New{$BaseName} 9314 and not $ShortBase_New{get_ShortType($BaseId, 1)}) 9315 { # removed base 9316 # excluding namespace::SomeClass to SomeClass renaming 9317 my $ProblemKind = "Removed_Base_Class"; 9318 if($Level eq "Binary") 9319 { # Binary-level 9320 if($Shift_Old ne $Shift_New) 9321 { # affected fields 9322 if(havePubFields(\%Class_Old)) { 9323 $ProblemKind .= "_And_Shift"; 9324 } 9325 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) { 9326 $ProblemKind .= "_And_Size"; 9327 } 9328 } 9329 if(keys(%{$VirtualTable_Model{1}{$BaseName}}) 9330 and cmpVTables($ClassName)==1) 9331 { # affected v-table 9332 $ProblemKind .= "_And_VTable"; 9333 $VTableChanged_M{$ClassName}=1; 9334 } 9335 } 9336 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}}); 9337 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1)) 9338 { 9339 my $SubName = $TypeInfo{1}{$SubId}{"Name"}; 9340 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}})); 9341 if($ProblemKind=~/VTable/) { 9342 $VTableChanged_M{$SubName}=1; 9343 } 9344 } 9345 foreach my $Interface (@Affected) 9346 { 9347 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=( 9348 "Type_Name"=>$ClassName, 9349 "Type_Type"=>"Class", 9350 "Target"=>$BaseName, 9351 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE, 9352 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE, 9353 "Shift"=>abs($Shift_New-$Shift_Old) ); 9354 } 9355 $Removed+=1; 9356 } 9357 } 9358 my @StableBases_New = (); 9359 foreach my $BaseId (@Bases_New) 9360 { 9361 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"}; 9362 if($BasePos_Old{$BaseName}) { 9363 push(@StableBases_New, $BaseId); 9364 } 9365 elsif(not $ShortBase_Old{$BaseName} 9366 and not $ShortBase_Old{get_ShortType($BaseId, 2)}) 9367 { # added base 9368 # excluding namespace::SomeClass to SomeClass renaming 9369 my $ProblemKind = "Added_Base_Class"; 9370 if($Level eq "Binary") 9371 { # Binary-level 9372 if($Shift_Old ne $Shift_New) 9373 { # affected fields 9374 if(havePubFields(\%Class_Old)) { 9375 $ProblemKind .= "_And_Shift"; 9376 } 9377 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) { 9378 $ProblemKind .= "_And_Size"; 9379 } 9380 } 9381 if(keys(%{$VirtualTable_Model{2}{$BaseName}}) 9382 and cmpVTables($ClassName)==1) 9383 { # affected v-table 9384 $ProblemKind .= "_And_VTable"; 9385 $VTableChanged_M{$ClassName}=1; 9386 } 9387 } 9388 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}}); 9389 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1)) 9390 { 9391 my $SubName = $TypeInfo{1}{$SubId}{"Name"}; 9392 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}})); 9393 if($ProblemKind=~/VTable/) { 9394 $VTableChanged_M{$SubName}=1; 9395 } 9396 } 9397 foreach my $Interface (@Affected) 9398 { 9399 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=( 9400 "Type_Name"=>$ClassName, 9401 "Type_Type"=>"Class", 9402 "Target"=>$BaseName, 9403 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE, 9404 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE, 9405 "Shift"=>abs($Shift_New-$Shift_Old) ); 9406 } 9407 $Added+=1; 9408 } 9409 } 9410 if($Level eq "Binary") 9411 { # Binary-level 9412 ($BNum1, $BNum2) = (1, 1); 9413 my %BaseRelPos_Old = map {$TypeInfo{1}{$_}{"Name"} => $BNum1++} @StableBases_Old; 9414 my %BaseRelPos_New = map {$TypeInfo{2}{$_}{"Name"} => $BNum2++} @StableBases_New; 9415 foreach my $BaseId (@Bases_Old) 9416 { 9417 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"}; 9418 if(my $NewPos = $BaseRelPos_New{$BaseName}) 9419 { 9420 my $BaseNewId = $BaseId_New{$BaseName}; 9421 my $OldPos = $BaseRelPos_Old{$BaseName}; 9422 if($NewPos!=$OldPos) 9423 { # changed position of the base class 9424 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}})) 9425 { 9426 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=( 9427 "Type_Name"=>$ClassName, 9428 "Type_Type"=>"Class", 9429 "Target"=>$BaseName, 9430 "Old_Value"=>$OldPos-1, 9431 "New_Value"=>$NewPos-1 ); 9432 } 9433 } 9434 if($Class_Old{"Base"}{$BaseId}{"virtual"} 9435 and not $Class_New{"Base"}{$BaseNewId}{"virtual"}) 9436 { # became non-virtual base 9437 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}})) 9438 { 9439 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=( 9440 "Type_Name"=>$ClassName, 9441 "Type_Type"=>"Class", 9442 "Target"=>$BaseName ); 9443 } 9444 } 9445 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"} 9446 and $Class_New{"Base"}{$BaseNewId}{"virtual"}) 9447 { # became virtual base 9448 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}})) 9449 { 9450 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=( 9451 "Type_Name"=>$ClassName, 9452 "Type_Type"=>"Class", 9453 "Target"=>$BaseName ); 9454 } 9455 } 9456 } 9457 } 9458 # detect size changes in base classes 9459 if($Shift_Old!=$Shift_New) 9460 { # size of allocable class 9461 foreach my $BaseId (@StableBases_Old) 9462 { # search for changed base 9463 my %BaseType = get_Type($BaseId, 1); 9464 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"}; 9465 my $Size_New = $TypeInfo{2}{$BaseId_New{$BaseType{"Name"}}}{"Size"}; 9466 if($Size_Old ne $Size_New 9467 and $Size_Old and $Size_New) 9468 { 9469 my $ProblemType = ""; 9470 if(isCopyingClass($BaseId, 1)) { 9471 $ProblemType = "Size_Of_Copying_Class"; 9472 } 9473 elsif($AllocableClass{1}{$BaseType{"Name"}}) 9474 { 9475 if($Size_New>$Size_Old) 9476 { # increased size 9477 $ProblemType = "Size_Of_Allocable_Class_Increased"; 9478 } 9479 else 9480 { # decreased size 9481 $ProblemType = "Size_Of_Allocable_Class_Decreased"; 9482 if(not havePubFields(\%Class_Old)) 9483 { # affected class has no public members 9484 next; 9485 } 9486 } 9487 } 9488 next if(not $ProblemType); 9489 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}})) 9490 { # base class size changes affecting current class 9491 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=( 9492 "Type_Name"=>$BaseType{"Name"}, 9493 "Type_Type"=>"Class", 9494 "Target"=>$BaseType{"Name"}, 9495 "Old_Size"=>$Size_Old*$BYTE_SIZE, 9496 "New_Size"=>$Size_New*$BYTE_SIZE ); 9497 } 9498 } 9499 } 9500 } 9501 if(defined $VirtualTable{1}{$ClassName} 9502 and cmpVTables_Real($ClassName, 1)==1 9503 and my @VFunctions = keys(%{$VirtualTable{1}{$ClassName}})) 9504 { # compare virtual tables size in base classes 9505 my $VShift_Old = getVShift($ClassId_Old, 1); 9506 my $VShift_New = getVShift($ClassId_New, 2); 9507 if($VShift_Old ne $VShift_New) 9508 { # changes in the base class or changes in the list of base classes 9509 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1); 9510 my @AllBases_New = get_base_classes($ClassId_New, 2, 1); 9511 ($BNum1, $BNum2) = (1, 1); 9512 my %StableBase = map {$TypeInfo{2}{$_}{"Name"} => $_} @AllBases_New; 9513 foreach my $BaseId (@AllBases_Old) 9514 { 9515 my %BaseType = get_Type($BaseId, 1); 9516 if(not $StableBase{$BaseType{"Name"}}) 9517 { # lost base 9518 next; 9519 } 9520 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1); 9521 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2); 9522 if($VSize_Old!=$VSize_New) 9523 { 9524 foreach my $Symbol (@VFunctions) 9525 { 9526 if(not defined $VirtualTable{2}{$ClassName}{$Symbol}) 9527 { # Removed_Virtual_Method, will be registered in mergeVirtualTables() 9528 next; 9529 } 9530 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0) 9531 { # skip interfaces that have not changed the absolute virtual position 9532 next; 9533 } 9534 if(not symbolFilter($Symbol, 1, "Affected", $Level)) { 9535 next; 9536 } 9537 $VTableChanged_M{$BaseType{"Name"}} = 1; 9538 $VTableChanged_M{$ClassName} = 1; 9539 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}})) 9540 { # the reason of the layout change: added virtual functions 9541 next if($VirtualReplacement{$VirtFunc}); 9542 my $ProblemType = "Added_Virtual_Method"; 9543 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) { 9544 $ProblemType = "Added_Pure_Virtual_Method"; 9545 } 9546 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=( 9547 "Type_Name"=>$BaseType{"Name"}, 9548 "Type_Type"=>"Class", 9549 "Target"=>get_Signature($VirtFunc, 2) ); 9550 } 9551 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}})) 9552 { # the reason of the layout change: removed virtual functions 9553 next if($VirtualReplacement{$VirtFunc}); 9554 my $ProblemType = "Removed_Virtual_Method"; 9555 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) { 9556 $ProblemType = "Removed_Pure_Virtual_Method"; 9557 } 9558 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=( 9559 "Type_Name"=>$BaseType{"Name"}, 9560 "Type_Type"=>"Class", 9561 "Target"=>get_Signature($VirtFunc, 1) ); 9562 } 9563 } 9564 } 9565 } 9566 } 9567 } 9568 } 9569 } 9570} 9571 9572sub isCreatable($$) 9573{ 9574 my ($ClassId, $LibVersion) = @_; 9575 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}} 9576 or isCopyingClass($ClassId, $LibVersion)) { 9577 return 1; 9578 } 9579 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}})) 9580 { # Fix for incomplete data: if this class has 9581 # a base class then it should also has a constructor 9582 return 1; 9583 } 9584 if($ReturnedClass{$LibVersion}{$ClassId}) 9585 { # returned by some method of this class 9586 # or any other class 9587 return 1; 9588 } 9589 return 0; 9590} 9591 9592sub isUsedClass($$$) 9593{ 9594 my ($ClassId, $LibVersion, $Level) = @_; 9595 if(keys(%{$ParamClass{$LibVersion}{$ClassId}})) 9596 { # parameter of some exported method 9597 return 1; 9598 } 9599 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}; 9600 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}})) 9601 { # method from target class 9602 return 1; 9603 } 9604 return 0; 9605} 9606 9607sub mergeVirtualTables($$) 9608{ # check for changes in the virtual table 9609 my ($Interface, $Level) = @_; 9610 # affected methods: 9611 # - virtual 9612 # - pure-virtual 9613 # - non-virtual 9614 if($CompleteSignature{1}{$Interface}{"Data"}) 9615 { # global data is not affected 9616 return; 9617 } 9618 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"}; 9619 if(not $Class_Id) { 9620 return; 9621 } 9622 my $CName = $TypeInfo{1}{$Class_Id}{"Name"}; 9623 if(cmpVTables_Real($CName, 1)==0) 9624 { # no changes 9625 return; 9626 } 9627 $CheckedTypes{$Level}{$CName} = 1; 9628 if($Level eq "Binary") 9629 { # Binary-level 9630 if($CompleteSignature{1}{$Interface}{"PureVirt"} 9631 and not isUsedClass($Class_Id, 1, $Level)) 9632 { # pure virtuals should not be affected 9633 # if there are no exported methods using this class 9634 return; 9635 } 9636 } 9637 foreach my $Func (keys(%{$VirtualTable{1}{$CName}})) 9638 { 9639 if(defined $VirtualTable{2}{$CName}{$Func} 9640 and defined $CompleteSignature{2}{$Func}) 9641 { 9642 if(not $CompleteSignature{1}{$Func}{"PureVirt"} 9643 and $CompleteSignature{2}{$Func}{"PureVirt"}) 9644 { # became pure virtual 9645 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=( 9646 "Type_Name"=>$CName, 9647 "Type_Type"=>"Class", 9648 "Target"=>get_Signature_M($Func, 1) ); 9649 $VTableChanged_M{$CName} = 1; 9650 } 9651 elsif($CompleteSignature{1}{$Func}{"PureVirt"} 9652 and not $CompleteSignature{2}{$Func}{"PureVirt"}) 9653 { # became non-pure virtual 9654 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=( 9655 "Type_Name"=>$CName, 9656 "Type_Type"=>"Class", 9657 "Target"=>get_Signature_M($Func, 1) ); 9658 $VTableChanged_M{$CName} = 1; 9659 } 9660 } 9661 } 9662 if($Level eq "Binary") 9663 { # Binary-level 9664 # check virtual table structure 9665 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}})) 9666 { 9667 next if($Interface eq $AddedVFunc); 9668 next if($VirtualReplacement{$AddedVFunc}); 9669 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc}; 9670 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"}) 9671 { # pure virtual methods affect all others (virtual and non-virtual) 9672 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=( 9673 "Type_Name"=>$CName, 9674 "Type_Type"=>"Class", 9675 "Target"=>get_Signature($AddedVFunc, 2) ); 9676 $VTableChanged_M{$CName} = 1; 9677 } 9678 elsif(not defined $VirtualTable{1}{$CName} 9679 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}})) 9680 { # added virtual function at the end of v-table 9681 if(not keys(%{$VirtualTable_Model{1}{$CName}})) 9682 { # became polymorphous class, added v-table pointer 9683 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=( 9684 "Type_Name"=>$CName, 9685 "Type_Type"=>"Class", 9686 "Target"=>get_Signature($AddedVFunc, 2) ); 9687 $VTableChanged_M{$CName} = 1; 9688 } 9689 else 9690 { 9691 my $VSize_Old = getVTable_Size($CName, 1); 9692 my $VSize_New = getVTable_Size($CName, 2); 9693 next if($VSize_Old==$VSize_New);# exception: register as removed and added virtual method 9694 if(isCopyingClass($Class_Id, 1)) 9695 { # class has no constructors and v-table will be copied by applications, this may affect all methods 9696 my $ProblemType = "Added_Virtual_Method"; 9697 if(isLeafClass($Class_Id, 1)) { 9698 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class"; 9699 } 9700 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=( 9701 "Type_Name"=>$CName, 9702 "Type_Type"=>"Class", 9703 "Target"=>get_Signature($AddedVFunc, 2) ); 9704 $VTableChanged_M{$CName} = 1; 9705 } 9706 else 9707 { 9708 my $ProblemType = "Added_Virtual_Method"; 9709 if(isLeafClass($Class_Id, 1)) { 9710 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class"; 9711 } 9712 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=( 9713 "Type_Name"=>$CName, 9714 "Type_Type"=>"Class", 9715 "Target"=>get_Signature($AddedVFunc, 2) ); 9716 $VTableChanged_M{$CName} = 1; 9717 } 9718 } 9719 } 9720 elsif($CompleteSignature{1}{$Interface}{"Virt"} 9721 or $CompleteSignature{1}{$Interface}{"PureVirt"}) 9722 { 9723 if(defined $VirtualTable{1}{$CName} 9724 and defined $VirtualTable{2}{$CName}) 9725 { 9726 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface}; 9727 my $VPos_New = $VirtualTable{2}{$CName}{$Interface}; 9728 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New) 9729 { 9730 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}})); 9731 foreach my $ASymbol (@Affected) 9732 { 9733 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"}) 9734 { 9735 if(symbolFilter($ASymbol, 1, "Affected", $Level)) { 9736 next; 9737 } 9738 } 9739 $CheckedSymbols{$Level}{$ASymbol} = 1; 9740 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=( 9741 "Type_Name"=>$CName, 9742 "Type_Type"=>"Class", 9743 "Target"=>get_Signature($AddedVFunc, 2) ); 9744 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1; 9745 } 9746 } 9747 } 9748 } 9749 else { 9750 # safe 9751 } 9752 } 9753 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}})) 9754 { 9755 next if($VirtualReplacement{$RemovedVFunc}); 9756 if($RemovedVFunc eq $Interface 9757 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) 9758 { # This case is for removed virtual methods 9759 # implemented in both versions of a library 9760 next; 9761 } 9762 if(not keys(%{$VirtualTable_Model{2}{$CName}})) 9763 { # became non-polymorphous class, removed v-table pointer 9764 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=( 9765 "Type_Name"=>$CName, 9766 "Type_Type"=>"Class", 9767 "Target"=>get_Signature($RemovedVFunc, 1) ); 9768 $VTableChanged_M{$CName} = 1; 9769 } 9770 elsif($CompleteSignature{1}{$Interface}{"Virt"} 9771 or $CompleteSignature{1}{$Interface}{"PureVirt"}) 9772 { 9773 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName}) 9774 { 9775 if(not defined $VirtualTable{1}{$CName}{$Interface}) { 9776 next; 9777 } 9778 my $VPos_New = -1; 9779 if(defined $VirtualTable{2}{$CName}{$Interface}) 9780 { 9781 $VPos_New = $VirtualTable{2}{$CName}{$Interface}; 9782 } 9783 else 9784 { 9785 if($Interface ne $RemovedVFunc) { 9786 next; 9787 } 9788 } 9789 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc}; 9790 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface}; 9791 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New) 9792 { 9793 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}})); 9794 foreach my $ASymbol (@Affected) 9795 { 9796 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"}) 9797 { 9798 if(symbolFilter($ASymbol, 1, "Affected", $Level)) { 9799 next; 9800 } 9801 } 9802 my $ProblemType = "Removed_Virtual_Method"; 9803 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) { 9804 $ProblemType = "Removed_Pure_Virtual_Method"; 9805 } 9806 $CheckedSymbols{$Level}{$ASymbol} = 1; 9807 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=( 9808 "Type_Name"=>$CName, 9809 "Type_Type"=>"Class", 9810 "Target"=>get_Signature($RemovedVFunc, 1) ); 9811 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1; 9812 } 9813 } 9814 } 9815 } 9816 } 9817 } 9818 else 9819 { # Source-level 9820 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}})) 9821 { 9822 next if($Interface eq $AddedVFunc); 9823 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"}) 9824 { 9825 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=( 9826 "Type_Name"=>$CName, 9827 "Type_Type"=>"Class", 9828 "Target"=>get_Signature($AddedVFunc, 2) ); 9829 } 9830 } 9831 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}})) 9832 { 9833 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) 9834 { 9835 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=( 9836 "Type_Name"=>$CName, 9837 "Type_Type"=>"Class", 9838 "Target"=>get_Signature($RemovedVFunc, 1) ); 9839 } 9840 } 9841 } 9842} 9843 9844sub find_MemberPair_Pos_byName($$) 9845{ 9846 my ($Member_Name, $Pair_Type) = @_; 9847 $Member_Name=~s/\A[_]+|[_]+\Z//g; 9848 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}})) 9849 { 9850 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}) 9851 { 9852 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"}; 9853 $Name=~s/\A[_]+|[_]+\Z//g; 9854 if($Name eq $Member_Name) { 9855 return $MemberPair_Pos; 9856 } 9857 } 9858 } 9859 return "lost"; 9860} 9861 9862sub find_MemberPair_Pos_byVal($$) 9863{ 9864 my ($Member_Value, $Pair_Type) = @_; 9865 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}})) 9866 { 9867 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos} 9868 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) { 9869 return $MemberPair_Pos; 9870 } 9871 } 9872 return "lost"; 9873} 9874 9875my %Severity_Val=( 9876 "High"=>3, 9877 "Medium"=>2, 9878 "Low"=>1, 9879 "Safe"=>-1 9880); 9881 9882sub maxSeverity($$) 9883{ 9884 my ($S1, $S2) = @_; 9885 if(cmpSeverities($S1, $S2)) { 9886 return $S1; 9887 } 9888 else { 9889 return $S2; 9890 } 9891} 9892 9893sub cmpSeverities($$) 9894{ 9895 my ($S1, $S2) = @_; 9896 if(not $S1) { 9897 return 0; 9898 } 9899 elsif(not $S2) { 9900 return 1; 9901 } 9902 return ($Severity_Val{$S1}>$Severity_Val{$S2}); 9903} 9904 9905sub getProblemSeverity($$) 9906{ 9907 my ($Level, $Kind) = @_; 9908 return $CompatRules{$Level}{$Kind}{"Severity"}; 9909} 9910 9911sub isRecurType($$) 9912{ 9913 foreach (@RecurTypes) 9914 { 9915 if( $_->{"T1"} eq $_[0] 9916 and $_->{"T2"} eq $_[1] ) 9917 { 9918 return 1; 9919 } 9920 } 9921 return 0; 9922} 9923 9924sub pushType($$) 9925{ 9926 my %TypeIDs=( 9927 "T1" => $_[0], #Tid1 9928 "T2" => $_[1] #Tid2 9929 ); 9930 push(@RecurTypes, \%TypeIDs); 9931} 9932 9933sub isRenamed($$$$$) 9934{ 9935 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_; 9936 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"}; 9937 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"}; 9938 my %MemberType_Pure = get_PureType($MemberType_Id, $LVersion1); 9939 if(not defined $Type2->{"Memb"}{$MemPos}) { 9940 return ""; 9941 } 9942 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"}; 9943 my %PairType_Pure = get_PureType($PairType_Id, $LVersion2); 9944 9945 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"}; 9946 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1); 9947 if($MemberPair_Pos_Rev eq "lost") 9948 { 9949 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"}) 9950 { # base type match 9951 return $Pair_Name; 9952 } 9953 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"}) 9954 { # exact type match 9955 return $Pair_Name; 9956 } 9957 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"}) 9958 { # size match 9959 return $Pair_Name; 9960 } 9961 if(isReserved($Pair_Name)) 9962 { # reserved fields 9963 return $Pair_Name; 9964 } 9965 } 9966 return ""; 9967} 9968 9969sub isLastElem($$) 9970{ 9971 my ($Pos, $TypeRef) = @_; 9972 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"}; 9973 if($Name=~/last|count|max|total/i) 9974 { # GST_LEVEL_COUNT, GST_RTSP_ELAST 9975 return 1; 9976 } 9977 elsif($Name=~/END|NLIMITS\Z/) 9978 { # __RLIMIT_NLIMITS 9979 return 1; 9980 } 9981 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/ 9982 and $Pos+1==keys(%{$TypeRef->{"Memb"}})) 9983 { # NImageFormats, NColorRoles 9984 return 1; 9985 } 9986 return 0; 9987} 9988 9989sub nonComparable($$) 9990{ 9991 my ($T1, $T2) = @_; 9992 if($T1->{"Name"} ne $T2->{"Name"} 9993 and not isAnon($T1->{"Name"}) 9994 and not isAnon($T2->{"Name"})) 9995 { # different names 9996 if($T1->{"Type"} ne "Pointer" 9997 or $T2->{"Type"} ne "Pointer") 9998 { # compare base types 9999 return 1; 10000 } 10001 if($T1->{"Name"}!~/\Avoid\s*\*/ 10002 and $T2->{"Name"}=~/\Avoid\s*\*/) 10003 { 10004 return 1; 10005 } 10006 } 10007 elsif($T1->{"Type"} ne $T2->{"Type"}) 10008 { # different types 10009 if($T1->{"Type"} eq "Class" 10010 and $T2->{"Type"} eq "Struct") 10011 { # "class" to "struct" 10012 return 0; 10013 } 10014 elsif($T2->{"Type"} eq "Class" 10015 and $T1->{"Type"} eq "Struct") 10016 { # "struct" to "class" 10017 return 0; 10018 } 10019 else 10020 { # "class" to "enum" 10021 # "union" to "class" 10022 # ... 10023 return 1; 10024 } 10025 } 10026 return 0; 10027} 10028 10029sub mergeTypes($$$) 10030{ 10031 my ($Type1_Id, $Type2_Id, $Level) = @_; 10032 return () if(not $Type1_Id or not $Type2_Id); 10033 my (%Sub_SubProblems, %SubProblems) = (); 10034 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}) 10035 { # already merged 10036 return %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}}; 10037 } 10038 my %Type1 = get_Type($Type1_Id, 1); 10039 my %Type2 = get_Type($Type2_Id, 2); 10040 if(not $Type1{"Name"} or not $Type2{"Name"}) { 10041 return (); 10042 } 10043 $CheckedTypes{$Level}{$Type1{"Name"}}=1; 10044 my %Type1_Pure = get_PureType($Type1_Id, 1); 10045 my %Type2_Pure = get_PureType($Type2_Id, 2); 10046 $CheckedTypes{$Level}{$Type1_Pure{"Name"}}=1; 10047 if(not $Type1_Pure{"Size"} or not $Type2_Pure{"Size"}) 10048 { # including a case when "class Class { ... };" changed to "class Class;" 10049 return (); 10050 } 10051 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"})) 10052 { # skip recursive declarations 10053 return (); 10054 } 10055 return () if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"}); 10056 return () if($SkipTypes{1}{$Type1_Pure{"Name"}}); 10057 return () if($SkipTypes{1}{$Type1{"Name"}}); 10058 10059 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef"); 10060 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef"); 10061 if(not $UseOldDumps and %Typedef_1 and %Typedef_2 10062 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef" 10063 and $Typedef_1{"Name"} eq $Typedef_2{"Name"}) 10064 { 10065 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, 1); 10066 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, 2); 10067 if($Base_1{"Name"} ne $Base_2{"Name"}) 10068 { 10069 if(differentDumps("G") 10070 or differentDumps("V")) 10071 { # different GCC versions or different dumps 10072 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1); 10073 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2); 10074 # std::__va_list and __va_list 10075 $Base_1{"Name"}=~s/\A(\w+::)+//; 10076 $Base_2{"Name"}=~s/\A(\w+::)+//; 10077 $Base_1{"Name"} = formatName($Base_1{"Name"}); 10078 $Base_2{"Name"} = formatName($Base_2{"Name"}); 10079 } 10080 } 10081 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/ 10082 and $Base_1{"Name"} ne $Base_2{"Name"}) 10083 { 10084 if($Level eq "Binary" 10085 and $Type1{"Size"} ne $Type2{"Size"}) 10086 { 10087 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=( 10088 "Target"=>$Typedef_1{"Name"}, 10089 "Type_Name"=>$Typedef_1{"Name"}, 10090 "Type_Type"=>"Typedef", 10091 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE, 10092 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE ); 10093 } 10094 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=( 10095 "Target"=>$Typedef_1{"Name"}, 10096 "Type_Name"=>$Typedef_1{"Name"}, 10097 "Type_Type"=>"Typedef", 10098 "Old_Value"=>$Base_1{"Name"}, 10099 "New_Value"=>$Base_2{"Name"} ); 10100 } 10101 } 10102 if(nonComparable(\%Type1_Pure, \%Type2_Pure)) 10103 { # different types (reported in detectTypeChange(...)) 10104 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"} 10105 and $Type1_Pure{"Type"} ne $Type2_Pure{"Type"} 10106 and $Type1_Pure{"Type"}!~/Intrinsic|Pointer|Ref|Typedef/) 10107 { # different type of the type 10108 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=( 10109 "Target"=>$Type1_Pure{"Name"}, 10110 "Type_Name"=>$Type1_Pure{"Name"}, 10111 "Type_Type"=>$Type1_Pure{"Type"}, 10112 "Old_Value"=>lc($Type1_Pure{"Type"}), 10113 "New_Value"=>lc($Type2_Pure{"Type"}) ); 10114 } 10115 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems; 10116 return %SubProblems; 10117 } 10118 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}); 10119 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"} 10120 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"}))) 10121 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/) 10122 { # checking size 10123 if($Level eq "Binary" 10124 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) 10125 { 10126 my $ProblemKind = "DataType_Size"; 10127 if($Type1_Pure{"Type"} eq "Class" 10128 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}})) 10129 { 10130 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) { 10131 $ProblemKind = "Size_Of_Copying_Class"; 10132 } 10133 elsif($AllocableClass{1}{$Type1_Pure{"Name"}}) 10134 { 10135 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) { 10136 $ProblemKind = "Size_Of_Allocable_Class_Increased"; 10137 } 10138 else { 10139 # descreased size of allocable class 10140 # it has no special effects 10141 } 10142 } 10143 } 10144 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=( 10145 "Target"=>$Type1_Pure{"Name"}, 10146 "Type_Name"=>$Type1_Pure{"Name"}, 10147 "Type_Type"=>$Type1_Pure{"Type"}, 10148 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE, 10149 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE, 10150 "InitialType_Type"=>$Type1_Pure{"Type"} ); 10151 } 10152 } 10153 if(defined $Type1_Pure{"BaseType"} and $Type1_Pure{"BaseType"}{"Tid"} 10154 and defined $Type2_Pure{"BaseType"} and $Type2_Pure{"BaseType"}{"Tid"}) 10155 { # checking base types 10156 %Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}{"Tid"}, $Type2_Pure{"BaseType"}{"Tid"}, $Level); 10157 foreach my $Sub_SubProblemType (keys(%Sub_SubProblems)) 10158 { 10159 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems{$Sub_SubProblemType}})) 10160 { 10161 foreach my $Attr (keys(%{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}})) { 10162 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr} = $Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr}; 10163 } 10164 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{"InitialType_Type"} = $Type1_Pure{"Type"}; 10165 } 10166 } 10167 } 10168 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = (); 10169 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}}); 10170 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}}); 10171 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}})) 10172 { # detect removed and renamed fields 10173 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"}; 10174 next if(not $Member_Name); 10175 my $MemberPair_Pos = (defined $Type2_Pure{"Memb"}{$Member_Pos} and $Type2_Pure{"Memb"}{$Member_Pos}{"name"} eq $Member_Name)?$Member_Pos:find_MemberPair_Pos_byName($Member_Name, \%Type2_Pure); 10176 if($MemberPair_Pos eq "lost") 10177 { 10178 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/) 10179 { 10180 if(isUnnamed($Member_Name)) 10181 { # support for old-version dumps 10182 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format) 10183 if(not checkDump(2, "2.1")) { 10184 next; 10185 } 10186 } 10187 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2)) 10188 { # renamed 10189 $RenamedField{$Member_Pos}=$RenamedTo; 10190 $RenamedField_Rev{$NameToPosB{$RenamedTo}}=$Member_Name; 10191 } 10192 else 10193 { # removed 10194 $RemovedField{$Member_Pos}=1; 10195 } 10196 } 10197 elsif($Type1_Pure{"Type"} eq "Enum") 10198 { 10199 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"}; 10200 next if($Member_Value1 eq ""); 10201 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure); 10202 if($MemberPair_Pos ne "lost") 10203 { # renamed 10204 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"}; 10205 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure); 10206 if($MemberPair_Pos_Rev eq "lost") 10207 { 10208 $RenamedField{$Member_Pos}=$RenamedTo; 10209 $RenamedField_Rev{$NameToPosB{$RenamedTo}}=$Member_Name; 10210 } 10211 else { 10212 $RemovedField{$Member_Pos}=1; 10213 } 10214 } 10215 else 10216 { # removed 10217 $RemovedField{$Member_Pos}=1; 10218 } 10219 } 10220 } 10221 else 10222 { # related 10223 $RelatedField{$Member_Pos} = $MemberPair_Pos; 10224 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos; 10225 } 10226 } 10227 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}})) 10228 { # detect added fields 10229 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"}; 10230 next if(not $Member_Name); 10231 my $MemberPair_Pos = (defined $Type1_Pure{"Memb"}{$Member_Pos} and $Type1_Pure{"Memb"}{$Member_Pos}{"name"} eq $Member_Name)?$Member_Pos:find_MemberPair_Pos_byName($Member_Name, \%Type1_Pure); 10232 if($MemberPair_Pos eq "lost") 10233 { 10234 if(isUnnamed($Member_Name)) 10235 { # support for old-version dumps 10236 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format) 10237 if(not checkDump(1, "2.1")) { 10238 next; 10239 } 10240 } 10241 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/) 10242 { 10243 if(not $RenamedField_Rev{$Member_Pos}) 10244 { # added 10245 $AddedField{$Member_Pos}=1; 10246 } 10247 } 10248 } 10249 } 10250 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/) 10251 { # detect moved fields 10252 my (%RelPos, %RelPosName, %AbsPos) = (); 10253 my $Pos = 0; 10254 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}})) 10255 { # relative positions in 1st version 10256 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"}; 10257 next if(not $Member_Name); 10258 if(not $RemovedField{$Member_Pos}) 10259 { # old type without removed fields 10260 $RelPos{1}{$Member_Name}=$Pos; 10261 $RelPosName{1}{$Pos} = $Member_Name; 10262 $AbsPos{1}{$Pos++} = $Member_Pos; 10263 } 10264 } 10265 $Pos = 0; 10266 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}})) 10267 { # relative positions in 2nd version 10268 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"}; 10269 next if(not $Member_Name); 10270 if(not $AddedField{$Member_Pos}) 10271 { # new type without added fields 10272 $RelPos{2}{$Member_Name}=$Pos; 10273 $RelPosName{2}{$Pos} = $Member_Name; 10274 $AbsPos{2}{$Pos++} = $Member_Pos; 10275 } 10276 } 10277 foreach my $Member_Name (keys(%{$RelPos{1}})) 10278 { 10279 my $RPos1 = $RelPos{1}{$Member_Name}; 10280 my $AbsPos1 = $NameToPosA{$Member_Name}; 10281 my $Member_Name2 = $Member_Name; 10282 if(my $RenamedTo = $RenamedField{$AbsPos1}) 10283 { # renamed 10284 $Member_Name2 = $RenamedTo; 10285 } 10286 my $RPos2 = $RelPos{2}{$Member_Name2}; 10287 if($RPos2 ne "" and $RPos1 ne $RPos2) 10288 { # different relative positions 10289 my $AbsPos2 = $NameToPosB{$Member_Name2}; 10290 if($AbsPos1 ne $AbsPos2) 10291 { # different absolute positions 10292 my $ProblemType = "Moved_Field"; 10293 if(not isPublic(\%Type1_Pure, $AbsPos1)) 10294 { # may change layout and size of type 10295 if($Level eq "Source") { 10296 next; 10297 } 10298 $ProblemType = "Moved_Private_Field"; 10299 } 10300 if($Level eq "Binary" 10301 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) 10302 { # affected size 10303 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"}; 10304 my $MovedAbsPos = $AbsPos{1}{$RPos2}; 10305 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"}; 10306 if($MemSize1 ne $MemSize2) { 10307 $ProblemType .= "_And_Size"; 10308 } 10309 } 10310 if($ProblemType eq "Moved_Private_Field") { 10311 next; 10312 } 10313 %{$SubProblems{$ProblemType}{$Member_Name}}=( 10314 "Target"=>$Member_Name, 10315 "Type_Name"=>$Type1_Pure{"Name"}, 10316 "Type_Type"=>$Type1_Pure{"Type"}, 10317 "Old_Value"=>$RPos1, 10318 "New_Value"=>$RPos2 ); 10319 } 10320 } 10321 } 10322 } 10323 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}})) 10324 { # check older fields, public and private 10325 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"}; 10326 next if(not $Member_Name); 10327 if(my $RenamedTo = $RenamedField{$Member_Pos}) 10328 { # renamed 10329 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/) 10330 { 10331 if(isPublic(\%Type1_Pure, $Member_Pos)) 10332 { 10333 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=( 10334 "Target"=>$Member_Name, 10335 "Type_Name"=>$Type1_Pure{"Name"}, 10336 "Type_Type"=>$Type1_Pure{"Type"}, 10337 "Old_Value"=>$Member_Name, 10338 "New_Value"=>$RenamedTo ); 10339 } 10340 } 10341 elsif($Type1_Pure{"Type"} eq "Enum") 10342 { 10343 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=( 10344 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"}, 10345 "Type_Name"=>$Type1_Pure{"Name"}, 10346 "Type_Type"=>$Type1_Pure{"Type"}, 10347 "Old_Value"=>$Member_Name, 10348 "New_Value"=>$RenamedTo ); 10349 } 10350 } 10351 elsif($RemovedField{$Member_Pos}) 10352 { # removed 10353 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/) 10354 { 10355 my $ProblemType = "Removed_Field"; 10356 if(not isPublic(\%Type1_Pure, $Member_Pos) 10357 or isUnnamed($Member_Name)) 10358 { 10359 if($Level eq "Source") { 10360 next; 10361 } 10362 $ProblemType = "Removed_Private_Field"; 10363 } 10364 if($Level eq "Binary" 10365 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, 1)) 10366 { 10367 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1)) 10368 { # affected fields 10369 if(getOffset($MNum-1, \%Type1_Pure, 1)!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, 2)) 10370 { # changed offset 10371 $ProblemType .= "_And_Layout"; 10372 } 10373 } 10374 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) 10375 { # affected size 10376 $ProblemType .= "_And_Size"; 10377 } 10378 } 10379 if($ProblemType eq "Removed_Private_Field") { 10380 next; 10381 } 10382 %{$SubProblems{$ProblemType}{$Member_Name}}=( 10383 "Target"=>$Member_Name, 10384 "Type_Name"=>$Type1_Pure{"Name"}, 10385 "Type_Type"=>$Type1_Pure{"Type"} ); 10386 } 10387 elsif($Type2_Pure{"Type"} eq "Union") 10388 { 10389 if($Level eq "Binary" 10390 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) 10391 { 10392 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=( 10393 "Target"=>$Member_Name, 10394 "Type_Name"=>$Type1_Pure{"Name"}, 10395 "Type_Type"=>$Type1_Pure{"Type"} ); 10396 } 10397 else 10398 { 10399 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=( 10400 "Target"=>$Member_Name, 10401 "Type_Name"=>$Type1_Pure{"Name"}, 10402 "Type_Type"=>$Type1_Pure{"Type"} ); 10403 } 10404 } 10405 elsif($Type1_Pure{"Type"} eq "Enum") 10406 { 10407 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=( 10408 "Target"=>$Member_Name, 10409 "Type_Name"=>$Type1_Pure{"Name"}, 10410 "Type_Type"=>$Type1_Pure{"Type"}, 10411 "Old_Value"=>$Member_Name ); 10412 } 10413 } 10414 else 10415 { # changed 10416 my $MemberPair_Pos = $RelatedField{$Member_Pos}; 10417 if($Type1_Pure{"Type"} eq "Enum") 10418 { 10419 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"}; 10420 next if($Member_Value1 eq ""); 10421 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"}; 10422 next if($Member_Value2 eq ""); 10423 if($Member_Value1 ne $Member_Value2) 10424 { 10425 my $ProblemType = "Enum_Member_Value"; 10426 if(isLastElem($Member_Pos, \%Type1_Pure)) { 10427 $ProblemType = "Enum_Last_Member_Value"; 10428 } 10429 %{$SubProblems{$ProblemType}{$Member_Name}}=( 10430 "Target"=>$Member_Name, 10431 "Type_Name"=>$Type1_Pure{"Name"}, 10432 "Type_Type"=>$Type1_Pure{"Type"}, 10433 "Old_Value"=>$Member_Value1, 10434 "New_Value"=>$Member_Value2 ); 10435 } 10436 } 10437 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/) 10438 { 10439 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"}; 10440 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"}; 10441 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE; 10442 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) { 10443 $SizeV1 = $BSize1; 10444 } 10445 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE; 10446 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) { 10447 $SizeV2 = $BSize2; 10448 } 10449 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"}; 10450 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"}; 10451 if($Level eq "Binary" 10452 and $SizeV1 ne $SizeV2) 10453 { 10454 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name)) 10455 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})) 10456 { # field size change (including anon-structures and unions) 10457 # - same types 10458 # - unnamed types 10459 # - bitfields 10460 my $ProblemType = "Field_Size"; 10461 if(not isPublic(\%Type1_Pure, $Member_Pos) 10462 or isUnnamed($Member_Name)) 10463 { # should not be accessed by applications, goes to "Low Severity" 10464 # example: "abidata" members in GStreamer types 10465 $ProblemType = "Private_".$ProblemType; 10466 } 10467 if(not isMemPadded($Member_Pos, $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE, \%Type1_Pure, \%RemovedField, 1)) 10468 { # check an effect 10469 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1)) 10470 { # public fields after the current 10471 if(getOffset($MNum-1, \%Type1_Pure, 1)!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, 2)) 10472 { # changed offset 10473 $ProblemType .= "_And_Layout"; 10474 } 10475 } 10476 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) { 10477 $ProblemType .= "_And_Type_Size"; 10478 } 10479 } 10480 if($ProblemType eq "Private_Field_Size") 10481 { # private field size with no effect 10482 $ProblemType = ""; 10483 } 10484 if($ProblemType) 10485 { # register a problem 10486 %{$SubProblems{$ProblemType}{$Member_Name}}=( 10487 "Target"=>$Member_Name, 10488 "Type_Name"=>$Type1_Pure{"Name"}, 10489 "Type_Type"=>$Type1_Pure{"Type"}, 10490 "Old_Size"=>$SizeV1, 10491 "New_Size"=>$SizeV2); 10492 } 10493 } 10494 } 10495 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} 10496 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) 10497 { # do NOT check bitfield type changes 10498 next; 10499 } 10500 if(checkDump(1, "2.13") and checkDump(2, "2.13")) 10501 { 10502 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"} 10503 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"}) 10504 { 10505 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=( 10506 "Target"=>$Member_Name, 10507 "Type_Name"=>$Type1_Pure{"Name"}, 10508 "Type_Type"=>$Type1_Pure{"Type"}); 10509 } 10510 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"} 10511 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"}) 10512 { 10513 %{$SubProblems{"Field_Became_NonMutable"}{$Member_Name}}=( 10514 "Target"=>$Member_Name, 10515 "Type_Name"=>$Type1_Pure{"Name"}, 10516 "Type_Type"=>$Type1_Pure{"Type"}); 10517 } 10518 } 10519 %Sub_SubProblems = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level); 10520 foreach my $ProblemType (keys(%Sub_SubProblems)) 10521 { 10522 my $Old_Value = $Sub_SubProblems{$ProblemType}{"Old_Value"}; 10523 my $New_Value = $Sub_SubProblems{$ProblemType}{"New_Value"}; 10524 if($ProblemType eq "Field_Type" 10525 or $ProblemType eq "Field_Type_And_Size") 10526 { 10527 if(checkDump(1, "2.6") and checkDump(2, "2.6")) 10528 { 10529 if(my $RA = addedQual($Old_Value, $New_Value, "volatile")) 10530 { 10531 %{$Sub_SubProblems{"Field_Became_Volatile"}} = %{$Sub_SubProblems{$ProblemType}}; 10532 if($Level eq "Source" 10533 and cmpBTypes($Old_Value, $New_Value, 1, 2)) { 10534 delete($Sub_SubProblems{$ProblemType}); 10535 } 10536 } 10537 elsif(my $RR = removedQual($Old_Value, $New_Value, "volatile")) 10538 { 10539 %{$Sub_SubProblems{"Field_Became_NonVolatile"}} = %{$Sub_SubProblems{$ProblemType}}; 10540 if($Level eq "Source" 10541 and cmpBTypes($Old_Value, $New_Value, 1, 2)) { 10542 delete($Sub_SubProblems{$ProblemType}); 10543 } 10544 } 10545 } 10546 if(my $RA = addedQual($Old_Value, $New_Value, "const")) 10547 { 10548 if($RA==2) { 10549 %{$Sub_SubProblems{"Field_Added_Const"}} = %{$Sub_SubProblems{$ProblemType}}; 10550 } 10551 else { 10552 %{$Sub_SubProblems{"Field_Became_Const"}} = %{$Sub_SubProblems{$ProblemType}}; 10553 } 10554 if($Level eq "Source" 10555 and cmpBTypes($Old_Value, $New_Value, 1, 2)) { 10556 delete($Sub_SubProblems{$ProblemType}); 10557 } 10558 } 10559 elsif(my $RR = removedQual($Old_Value, $New_Value, "const")) 10560 { 10561 if($RR==2) { 10562 %{$Sub_SubProblems{"Field_Removed_Const"}} = %{$Sub_SubProblems{$ProblemType}}; 10563 } 10564 else { 10565 %{$Sub_SubProblems{"Field_Became_NonConst"}} = %{$Sub_SubProblems{$ProblemType}}; 10566 } 10567 if($Level eq "Source" 10568 and cmpBTypes($Old_Value, $New_Value, 1, 2)) { 10569 delete($Sub_SubProblems{$ProblemType}); 10570 } 10571 } 10572 } 10573 } 10574 foreach my $ProblemType (keys(%Sub_SubProblems)) 10575 { 10576 my $ProblemType_Init = $ProblemType; 10577 if($ProblemType eq "Field_Type_And_Size") 10578 { # Binary 10579 if(not isPublic(\%Type1_Pure, $Member_Pos) 10580 or isUnnamed($Member_Name)) { 10581 $ProblemType = "Private_".$ProblemType; 10582 } 10583 if(not isMemPadded($Member_Pos, $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE, \%Type1_Pure, \%RemovedField, 1)) 10584 { # check an effect 10585 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1)) 10586 { # public fields after the current 10587 if(getOffset($MNum-1, \%Type1_Pure, 1)!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, 2)) 10588 { # changed offset 10589 $ProblemType .= "_And_Layout"; 10590 } 10591 } 10592 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) { 10593 $ProblemType .= "_And_Type_Size"; 10594 } 10595 } 10596 } 10597 else 10598 { 10599 if(not isPublic(\%Type1_Pure, $Member_Pos) 10600 or isUnnamed($Member_Name)) { 10601 next; 10602 } 10603 } 10604 if($ProblemType eq "Private_Field_Type_And_Size") 10605 { # private field change with no effect 10606 next; 10607 } 10608 %{$SubProblems{$ProblemType}{$Member_Name}}=( 10609 "Target"=>$Member_Name, 10610 "Type_Name"=>$Type1_Pure{"Name"}, 10611 "Type_Type"=>$Type1_Pure{"Type"} ); 10612 foreach my $Attr (keys(%{$Sub_SubProblems{$ProblemType_Init}})) 10613 { # other properties 10614 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubProblems{$ProblemType_Init}{$Attr}; 10615 } 10616 } 10617 if(not isPublic(\%Type1_Pure, $Member_Pos)) 10618 { # do NOT check internal type changes 10619 next; 10620 } 10621 if($MemberType1_Id and $MemberType2_Id) 10622 {# checking member type changes (replace) 10623 %Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level); 10624 foreach my $Sub_SubProblemType (keys(%Sub_SubProblems)) 10625 { 10626 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems{$Sub_SubProblemType}})) 10627 { 10628 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name; 10629 $SubProblems{$Sub_SubProblemType}{$NewLocation}{"IsInTypeInternals"}=1; 10630 foreach my $Attr (keys(%{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}})) { 10631 $SubProblems{$Sub_SubProblemType}{$NewLocation}{$Attr} = $Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr}; 10632 } 10633 if($Sub_SubLocation!~/\-\>/) { 10634 $SubProblems{$Sub_SubProblemType}{$NewLocation}{"Start_Type_Name"} = $MemberType1_Name; 10635 } 10636 } 10637 } 10638 } 10639 } 10640 } 10641 } 10642 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}})) 10643 { # checking added members, public and private 10644 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"}; 10645 next if(not $Member_Name); 10646 if($AddedField{$Member_Pos}) 10647 { # added 10648 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/) 10649 { 10650 my $ProblemType = "Added_Field"; 10651 if(not isPublic(\%Type2_Pure, $Member_Pos) 10652 or isUnnamed($Member_Name)) 10653 { 10654 if($Level eq "Source") { 10655 next; 10656 } 10657 $ProblemType = "Added_Private_Field"; 10658 } 10659 if($Level eq "Binary" 10660 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, 2)) 10661 { 10662 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1)) 10663 { # public fields after the current 10664 if(getOffset($MNum-1, \%Type2_Pure, 2)!=getOffset($RelatedField_Rev{$MNum-1}, \%Type1_Pure, 1)) 10665 { # changed offset 10666 $ProblemType .= "_And_Layout"; 10667 } 10668 } 10669 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) { 10670 $ProblemType .= "_And_Size"; 10671 } 10672 } 10673 if($ProblemType eq "Added_Private_Field") 10674 { # skip added private fields 10675 next; 10676 } 10677 %{$SubProblems{$ProblemType}{$Member_Name}}=( 10678 "Target"=>$Member_Name, 10679 "Type_Name"=>$Type1_Pure{"Name"}, 10680 "Type_Type"=>$Type1_Pure{"Type"} ); 10681 } 10682 elsif($Type2_Pure{"Type"} eq "Union") 10683 { 10684 if($Level eq "Binary" 10685 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) 10686 { 10687 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=( 10688 "Target"=>$Member_Name, 10689 "Type_Name"=>$Type1_Pure{"Name"}, 10690 "Type_Type"=>$Type1_Pure{"Type"} ); 10691 } 10692 else 10693 { 10694 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=( 10695 "Target"=>$Member_Name, 10696 "Type_Name"=>$Type1_Pure{"Name"}, 10697 "Type_Type"=>$Type1_Pure{"Type"} ); 10698 } 10699 } 10700 elsif($Type2_Pure{"Type"} eq "Enum") 10701 { 10702 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"}; 10703 next if($Member_Value eq ""); 10704 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=( 10705 "Target"=>$Member_Name, 10706 "Type_Name"=>$Type2_Pure{"Name"}, 10707 "Type_Type"=>$Type2_Pure{"Type"}, 10708 "New_Value"=>$Member_Value ); 10709 } 10710 } 10711 } 10712 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems; 10713 pop(@RecurTypes); 10714 return %SubProblems; 10715} 10716 10717sub isUnnamed($) { 10718 return $_[0]=~/\Aunnamed\d+\Z/; 10719} 10720 10721sub get_ShortType($$) 10722{ 10723 my ($TypeId, $LibVersion) = @_; 10724 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"}; 10725 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) { 10726 $TypeName=~s/\A$NameSpace\:\://g; 10727 } 10728 return $TypeName; 10729} 10730 10731sub goToFirst($$$) 10732{ 10733 my ($TypeId, $LibVersion, $Type_Type) = @_; 10734 return () if(not $TypeId); 10735 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) { 10736 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}}; 10737 } 10738 return () if(not $TypeInfo{$LibVersion}{$TypeId}); 10739 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}}; 10740 return () if(not $Type{"Type"}); 10741 if($Type{"Type"} ne $Type_Type) 10742 { 10743 return () if(not defined $Type{"BaseType"}); 10744 return () if(not $Type{"BaseType"}{"Tid"}); 10745 %Type = goToFirst($Type{"BaseType"}{"Tid"}, $LibVersion, $Type_Type); 10746 } 10747 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type; 10748 return %Type; 10749} 10750 10751my %TypeSpecAttributes = ( 10752 "Const" => 1, 10753 "Volatile" => 1, 10754 "ConstVolatile" => 1, 10755 "Restrict" => 1, 10756 "Typedef" => 1 10757); 10758 10759sub get_PureType($$) 10760{ 10761 my ($TypeId, $LibVersion) = @_; 10762 return () if(not $TypeId); 10763 if(defined $Cache{"get_PureType"}{$TypeId}{$LibVersion}) { 10764 return %{$Cache{"get_PureType"}{$TypeId}{$LibVersion}}; 10765 } 10766 return () if(not $TypeInfo{$LibVersion}{$TypeId}); 10767 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}}; 10768 return %Type if(not defined $Type{"BaseType"}); 10769 return %Type if(not $Type{"BaseType"}{"Tid"}); 10770 if($TypeSpecAttributes{$Type{"Type"}}) { 10771 %Type = get_PureType($Type{"BaseType"}{"Tid"}, $LibVersion); 10772 } 10773 $Cache{"get_PureType"}{$TypeId}{$LibVersion} = \%Type; 10774 return %Type; 10775} 10776 10777sub get_PLevel($$) 10778{ 10779 my ($TypeId, $LibVersion) = @_; 10780 return 0 if(not $TypeId); 10781 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) { 10782 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion}; 10783 } 10784 return 0 if(not $TypeInfo{$LibVersion}{$TypeId}); 10785 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}}; 10786 return 1 if($Type{"Type"}=~/FuncPtr|MethodPtr|FieldPtr/); 10787 return 0 if(not defined $Type{"BaseType"}); 10788 return 0 if(not $Type{"BaseType"}{"Tid"}); 10789 my $PointerLevel = 0; 10790 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|MethodPtr|FieldPtr/) { 10791 $PointerLevel += 1; 10792 } 10793 $PointerLevel += get_PLevel($Type{"BaseType"}{"Tid"}, $LibVersion); 10794 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PointerLevel; 10795 return $PointerLevel; 10796} 10797 10798sub get_BaseType($$) 10799{ 10800 my ($TypeId, $LibVersion) = @_; 10801 return () if(not $TypeId); 10802 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) { 10803 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}}; 10804 } 10805 return () if(not $TypeInfo{$LibVersion}{$TypeId}); 10806 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}}; 10807 return %Type if(not defined $Type{"BaseType"}); 10808 return %Type if(not $Type{"BaseType"}{"Tid"}); 10809 %Type = get_BaseType($Type{"BaseType"}{"Tid"}, $LibVersion); 10810 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type; 10811 return %Type; 10812} 10813 10814sub get_BaseTypeQual($$) 10815{ 10816 my ($TypeId, $LibVersion) = @_; 10817 return "" if(not $TypeId); 10818 return "" if(not $TypeInfo{$LibVersion}{$TypeId}); 10819 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}}; 10820 return "" if(not defined $Type{"BaseType"}); 10821 return "" if(not $Type{"BaseType"}{"Tid"}); 10822 my $Qual = ""; 10823 if($Type{"Type"} eq "Pointer") { 10824 $Qual .= "*"; 10825 } 10826 elsif($Type{"Type"} eq "Ref") { 10827 $Qual .= "&"; 10828 } 10829 elsif($Type{"Type"} eq "ConstVolatile") { 10830 $Qual .= "const volatile"; 10831 } 10832 elsif($Type{"Type"} eq "Const" 10833 or $Type{"Type"} eq "Volatile" 10834 or $Type{"Type"} eq "Restrict") { 10835 $Qual .= lc($Type{"Type"}); 10836 } 10837 my $BQual = get_BaseTypeQual($Type{"BaseType"}{"Tid"}, $LibVersion); 10838 return $BQual.$Qual; 10839} 10840 10841sub get_OneStep_BaseType($$) 10842{ 10843 my ($TypeId, $LibVersion) = @_; 10844 return () if(not $TypeId); 10845 return () if(not $TypeInfo{$LibVersion}{$TypeId}); 10846 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}}; 10847 return %Type if(not defined $Type{"BaseType"}); 10848 return %Type if(not $Type{"BaseType"}{"Tid"}); 10849 return get_Type($Type{"BaseType"}{"Tid"}, $LibVersion); 10850} 10851 10852sub get_Type($$) 10853{ 10854 my ($TypeId, $LibVersion) = @_; 10855 return () if(not $TypeId); 10856 return () if(not $TypeInfo{$LibVersion}{$TypeId}); 10857 return %{$TypeInfo{$LibVersion}{$TypeId}}; 10858} 10859 10860sub isPrivateData($) 10861{ # non-public global data 10862 my $Symbol = $_[0]; 10863 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/); 10864} 10865 10866sub isTemplateInstance($$) 10867{ 10868 my ($Symbol, $LibVersion) = @_; 10869 if($CheckObjectsOnly) 10870 { 10871 if($Symbol!~/\A(_Z|\?)/) { 10872 return 0; 10873 } 10874 if(my $Signature = $tr_name{$Symbol}) 10875 { 10876 if(index($Signature,">")==-1) { 10877 return 0; 10878 } 10879 if(my $ShortName = substr($Signature, 0, find_center($Signature, "("))) 10880 { 10881 if($ShortName=~/<.+>/) { 10882 return 1; 10883 } 10884 } 10885 } 10886 } 10887 else 10888 { 10889 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) 10890 { 10891 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}) 10892 { 10893 if(index($ClassName,"<")!=-1) { 10894 return 1; 10895 } 10896 } 10897 } 10898 if(my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}) 10899 { 10900 if($ShortName=~/<.+>/) { 10901 return 1; 10902 } 10903 } 10904 } 10905 return 0; 10906} 10907 10908sub isTemplateSpec($$) 10909{ 10910 my ($Symbol, $LibVersion) = @_; 10911 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) 10912 { 10913 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"}) 10914 { # class specialization 10915 return 1; 10916 } 10917 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Spec"}) 10918 { # method specialization 10919 return 1; 10920 } 10921 } 10922 return 0; 10923} 10924 10925sub symbolFilter($$$$) 10926{ # some special cases when the symbol cannot be imported 10927 my ($Symbol, $LibVersion, $Type, $Level) = @_; 10928 if(isPrivateData($Symbol)) 10929 { # non-public global data 10930 return 0; 10931 } 10932 if($CheckObjectsOnly) { 10933 return 0 if($Symbol=~/\A(_init|_fini)\Z/); 10934 } 10935 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7")) 10936 { # support for old ABI dumps in --headers-only mode 10937 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}})) 10938 { 10939 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"}) 10940 { 10941 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"}; 10942 if(not $PType or $PType eq "Unknown") { 10943 return 0; 10944 } 10945 } 10946 } 10947 } 10948 if($Type=~/Affected/) 10949 { 10950 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}; 10951 if($SkipSymbols{$LibVersion}{$Symbol}) 10952 { # user defined symbols to ignore 10953 return 0; 10954 } 10955 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}; 10956 if(not $NameSpace and $ClassId) 10957 { # class methods have no "NameSpace" attribute 10958 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"}; 10959 } 10960 if($NameSpace) 10961 { # user defined namespaces to ignore 10962 if($SkipNameSpaces{$LibVersion}{$NameSpace}) { 10963 return 0; 10964 } 10965 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}})) 10966 { # nested namespaces 10967 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) { 10968 return 0; 10969 } 10970 } 10971 } 10972 if(my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"}) 10973 { 10974 if(my $Skip = skipHeader($Header, $LibVersion)) 10975 { # --skip-headers or <skip_headers> (not <skip_including>) 10976 if($Skip==1) { 10977 return 0; 10978 } 10979 } 10980 } 10981 if($SymbolsListPath and not $SymbolsList{$Symbol}) 10982 { # user defined symbols 10983 return 0; 10984 } 10985 if($AppPath and not $SymbolsList_App{$Symbol}) 10986 { # user defined symbols (in application) 10987 return 0; 10988 } 10989 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion)) 10990 { # non-target symbols 10991 return 0; 10992 } 10993 if($Level eq "Binary") 10994 { 10995 if($CheckObjectsOnly) 10996 { 10997 if(isTemplateInstance($Symbol, $LibVersion)) { 10998 return 0; 10999 } 11000 } 11001 else 11002 { 11003 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"} 11004 or (isTemplateInstance($Symbol, $LibVersion) and not isTemplateSpec($Symbol, $LibVersion))) 11005 { 11006 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"}) 11007 { # inline virtual methods 11008 if($Type=~/InlineVirt/) { 11009 return 1; 11010 } 11011 my $Allocable = (not isCopyingClass($ClassId, $LibVersion)); 11012 if(not $Allocable) 11013 { # check bases 11014 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1)) 11015 { 11016 if(not isCopyingClass($DCId, $LibVersion)) 11017 { # exists a derived class without default c-tor 11018 $Allocable=1; 11019 last; 11020 } 11021 } 11022 } 11023 if(not $Allocable) { 11024 return 0; 11025 } 11026 } 11027 else 11028 { # inline non-virtual methods 11029 return 0; 11030 } 11031 } 11032 } 11033 } 11034 } 11035 return 1; 11036} 11037 11038sub mergeImpl() 11039{ 11040 my $DiffCmd = get_CmdPath("diff"); 11041 if(not $DiffCmd) { 11042 exitStatus("Not_Found", "can't find \"diff\""); 11043 } 11044 foreach my $Interface (sort keys(%{$Symbol_Library{1}})) 11045 { # implementation changes 11046 next if($CompleteSignature{1}{$Interface}{"Private"}); 11047 next if(not $CompleteSignature{1}{$Interface}{"Header"} and not $CheckObjectsOnly); 11048 next if(not $Symbol_Library{2}{$Interface} and not $Symbol_Library{2}{$SymVer{2}{$Interface}}); 11049 if(not symbolFilter($Interface, 1, "Affected", "Binary")) { 11050 next; 11051 } 11052 my $Impl1 = canonifyImpl($Interface_Impl{1}{$Interface}); 11053 next if(not $Impl1); 11054 my $Impl2 = canonifyImpl($Interface_Impl{2}{$Interface}); 11055 next if(not $Impl2); 11056 if($Impl1 ne $Impl2) 11057 { 11058 writeFile("$TMP_DIR/impl1", $Impl1); 11059 writeFile("$TMP_DIR/impl2", $Impl2); 11060 my $Diff = `$DiffCmd -rNau \"$TMP_DIR/impl1\" \"$TMP_DIR/impl2\"`; 11061 $Diff=~s/(---|\+\+\+).+\n//g; 11062 $Diff=~s/[ ]{3,}/ /g; 11063 $Diff=~s/\n\@\@/\n \n\@\@/g; 11064 unlink("$TMP_DIR/impl1"); 11065 unlink("$TMP_DIR/impl2"); 11066 %{$ImplProblems{$Interface}}=( 11067 "Diff" => get_CodeView($Diff) ); 11068 } 11069 } 11070 11071 # clean memory 11072 %Interface_Impl = (); 11073} 11074 11075sub canonifyImpl($) 11076{ 11077 my $FuncBody= $_[0]; 11078 return "" if(not $FuncBody); 11079 $FuncBody=~s/0x[a-f\d]+/0x?/g;# addr 11080 $FuncBody=~s/((\A|\n)[a-z]+[\t ]+)[a-f\d]+([^x]|\Z)/$1?$3/g;# call, jump 11081 $FuncBody=~s/# [a-f\d]+ /# ? /g;# call, jump 11082 $FuncBody=~s/%([a-z]+[a-f\d]*)/\%reg/g;# registers 11083 while($FuncBody=~s/\nnop[ \t]*(\n|\Z)/$1/g){};# empty op 11084 $FuncBody=~s/<.+?\.cpp.+?>/<name.cpp>/g; 11085 $FuncBody=~s/(\A|\n)[a-f\d]+ </$1? </g;# 5e74 <_ZN... 11086 $FuncBody=~s/\.L\d+/.L/g; 11087 $FuncBody=~s/#(-?)\d+/#$1?/g;# r3, [r3, #120] 11088 $FuncBody=~s/[\n]{2,}/\n/g; 11089 return $FuncBody; 11090} 11091 11092sub get_CodeView($) 11093{ 11094 my $Code = $_[0]; 11095 my $View = ""; 11096 foreach my $Line (split(/\n/, $Code)) 11097 { 11098 if($Line=~s/\A(\+|-)/$1 /g) 11099 { # bold line 11100 $View .= "<tr><td><b>".htmlSpecChars($Line)."</b></td></tr>\n"; 11101 } 11102 else { 11103 $View .= "<tr><td>".htmlSpecChars($Line)."</td></tr>\n"; 11104 } 11105 } 11106 return "<table class='code_view'>$View</table>\n"; 11107} 11108 11109sub getImplementations($$) 11110{ 11111 my ($LibVersion, $Path) = @_; 11112 return if(not $LibVersion or not -e $Path); 11113 if($OSgroup eq "macos") 11114 { 11115 my $OtoolCmd = get_CmdPath("otool"); 11116 if(not $OtoolCmd) { 11117 exitStatus("Not_Found", "can't find \"otool\""); 11118 } 11119 my $CurInterface = ""; 11120 foreach my $Line (split(/\n/, `$OtoolCmd -tv \"$Path\" 2>\"$TMP_DIR/null\"`)) 11121 { 11122 if($Line=~/\A\s*_(\w+)\s*:/i) { 11123 $CurInterface = $1; 11124 } 11125 elsif($Line=~/\A\s*[\da-z]+\s+(.+?)\Z/i) { 11126 $Interface_Impl{$LibVersion}{$CurInterface} .= $1."\n"; 11127 } 11128 } 11129 } 11130 else 11131 { 11132 my $ObjdumpCmd = get_CmdPath("objdump"); 11133 if(not $ObjdumpCmd) { 11134 exitStatus("Not_Found", "can't find \"objdump\""); 11135 } 11136 my $CurInterface = ""; 11137 foreach my $Line (split(/\n/, `$ObjdumpCmd -d \"$Path\" 2>\"$TMP_DIR/null\"`)) 11138 { 11139 if($Line=~/\A[\da-z]+\s+<(\w+)>/i) { 11140 $CurInterface = $1; 11141 } 11142 else 11143 { # x86: 51fa:(\t)89 e5 (\t)mov %esp,%ebp 11144 # arm: 5020:(\t)e24cb004(\t)sub(\t)fp, ip, #4(\t); 0x4 11145 if($Line=~/\A\s*[a-f\d]+:\s+([a-f\d]+\s+)+([a-z]+\s+.*?)\s*(;.*|)\Z/i) { 11146 $Interface_Impl{$LibVersion}{$CurInterface} .= $2."\n"; 11147 } 11148 } 11149 } 11150 } 11151} 11152 11153sub detectAdded($) 11154{ 11155 my $Level = $_[0]; 11156 foreach my $Symbol (keys(%{$Symbol_Library{2}})) 11157 { 11158 if(link_symbol($Symbol, 1, "+Deps")) 11159 { # linker can find a new symbol 11160 # in the old-version library 11161 # So, it's not a new symbol 11162 next; 11163 } 11164 if(my $VSym = $SymVer{2}{$Symbol} 11165 and index($Symbol,"\@")==-1) { 11166 next; 11167 } 11168 $AddedInt{$Level}{$Symbol} = 1; 11169 } 11170} 11171 11172sub detectRemoved($) 11173{ 11174 my $Level = $_[0]; 11175 foreach my $Symbol (keys(%{$Symbol_Library{1}})) 11176 { 11177 if($CheckObjectsOnly) { 11178 $CheckedSymbols{"Binary"}{$Symbol} = 1; 11179 } 11180 if(link_symbol($Symbol, 2, "+Deps")) 11181 { # linker can find an old symbol 11182 # in the new-version library 11183 next; 11184 } 11185 if(my $VSym = $SymVer{1}{$Symbol} 11186 and index($Symbol,"\@")==-1) { 11187 next; 11188 } 11189 $RemovedInt{$Level}{$Symbol} = 1; 11190 } 11191} 11192 11193sub mergeLibs($) 11194{ 11195 my $Level = $_[0]; 11196 foreach my $Symbol (sort keys(%{$AddedInt{$Level}})) 11197 { # checking added symbols 11198 next if($CompleteSignature{2}{$Symbol}{"Private"}); 11199 next if(not $CompleteSignature{2}{$Symbol}{"Header"} and not $CheckObjectsOnly); 11200 next if(not symbolFilter($Symbol, 2, "Affected", $Level)); 11201 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=(); 11202 } 11203 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}})) 11204 { # checking removed symbols 11205 next if($CompleteSignature{1}{$Symbol}{"Private"}); 11206 next if(not $CompleteSignature{1}{$Symbol}{"Header"} and not $CheckObjectsOnly); 11207 if($Symbol=~/\A_ZTV/) 11208 { # skip v-tables for templates, that should not be imported by applications 11209 next if($tr_name{$Symbol}=~/</); 11210 if(my $CName = $VTableClass{$Symbol}) 11211 { 11212 if(not keys(%{$ClassMethods{$Level}{1}{$CName}})) 11213 { # vtables for "private" classes 11214 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol 11215 next; 11216 } 11217 } 11218 } 11219 else { 11220 next if(not symbolFilter($Symbol, 1, "Affected", $Level)); 11221 } 11222 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) 11223 { # symbols for pure virtual methods cannot be called by clients 11224 next; 11225 } 11226 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=(); 11227 } 11228} 11229 11230sub checkDump($$) 11231{ 11232 my ($LibVersion, $V) = @_; 11233 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) { 11234 return $Cache{"checkDump"}{$LibVersion}{$V}; 11235 } 11236 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0)); 11237} 11238 11239sub detectAdded_H($) 11240{ 11241 my $Level = $_[0]; 11242 foreach my $Symbol (sort keys(%{$CompleteSignature{2}})) 11243 { 11244 if($Level eq "Source") 11245 { # remove symbol version 11246 my ($SN, $SS, $SV) = separate_symbol($Symbol); 11247 $Symbol=$SN; 11248 11249 if($CompleteSignature{2}{$Symbol}{"Artificial"}) 11250 { # skip artificial constructors 11251 next; 11252 } 11253 } 11254 if(not $CompleteSignature{2}{$Symbol}{"Header"} 11255 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) { 11256 next; 11257 } 11258 if($ExtendedSymbols{$Symbol}) { 11259 next; 11260 } 11261 if(not defined $CompleteSignature{1}{$Symbol} 11262 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) 11263 { 11264 if($UsedDump{2}{"SrcBin"}) 11265 { 11266 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11")) 11267 { # support for old and different (!) ABI dumps 11268 if(not $CompleteSignature{2}{$Symbol}{"Virt"} 11269 and not $CompleteSignature{2}{$Symbol}{"PureVirt"}) 11270 { 11271 if($CheckHeadersOnly) 11272 { 11273 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"}) 11274 { 11275 if($Lang eq "C") 11276 { # support for old ABI dumps: missed extern "C" functions 11277 next; 11278 } 11279 } 11280 } 11281 else 11282 { 11283 if(not link_symbol($Symbol, 2, "-Deps")) 11284 { # skip added inline symbols and const global data 11285 next; 11286 } 11287 } 11288 } 11289 } 11290 } 11291 $AddedInt{$Level}{$Symbol} = 1; 11292 } 11293 } 11294} 11295 11296sub detectRemoved_H($) 11297{ 11298 my $Level = $_[0]; 11299 foreach my $Symbol (sort keys(%{$CompleteSignature{1}})) 11300 { 11301 if($Level eq "Source") 11302 { # remove symbol version 11303 my ($SN, $SS, $SV) = separate_symbol($Symbol); 11304 $Symbol=$SN; 11305 } 11306 if(not $CompleteSignature{1}{$Symbol}{"Header"} 11307 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) { 11308 next; 11309 } 11310 if($ExtendedSymbols{$Symbol}) { 11311 next; 11312 } 11313 if(not defined $CompleteSignature{2}{$Symbol} 11314 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) 11315 { 11316 if($UsedDump{1}{"SrcBin"}) 11317 { 11318 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11")) 11319 { # support for old and different (!) ABI dumps 11320 if(not $CompleteSignature{1}{$Symbol}{"Virt"} 11321 and not $CompleteSignature{1}{$Symbol}{"PureVirt"}) 11322 { 11323 if($CheckHeadersOnly) 11324 { # skip all removed symbols 11325 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"}) 11326 { 11327 if($Lang eq "C") 11328 { # support for old ABI dumps: missed extern "C" functions 11329 next; 11330 } 11331 } 11332 } 11333 else 11334 { 11335 if(not link_symbol($Symbol, 1, "-Deps")) 11336 { # skip removed inline symbols 11337 next; 11338 } 11339 } 11340 } 11341 } 11342 } 11343 if(not checkDump(1, "2.15")) 11344 { 11345 if($Symbol=~/_IT_E\Z/) 11346 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E 11347 next; 11348 } 11349 } 11350 $RemovedInt{$Level}{$Symbol} = 1; 11351 if($Level eq "Source") 11352 { # search for a source-compatible equivalent 11353 setAlternative($Symbol, $Level); 11354 } 11355 } 11356 } 11357} 11358 11359sub mergeHeaders($) 11360{ 11361 my $Level = $_[0]; 11362 foreach my $Symbol (sort keys(%{$AddedInt{$Level}})) 11363 { # checking added symbols 11364 next if($CompleteSignature{2}{$Symbol}{"PureVirt"}); 11365 if($Level eq "Binary") 11366 { 11367 if($CompleteSignature{2}{$Symbol}{"InLine"}) 11368 { 11369 if(not $CompleteSignature{2}{$Symbol}{"Virt"}) 11370 { # skip inline non-virtual functions 11371 next; 11372 } 11373 } 11374 } 11375 else 11376 { # Source 11377 if($SourceAlternative_B{$Symbol}) { 11378 next; 11379 } 11380 } 11381 next if($CompleteSignature{2}{$Symbol}{"Private"}); 11382 next if(not symbolFilter($Symbol, 2, "Affected", $Level)); 11383 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=(); 11384 } 11385 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}})) 11386 { # checking removed symbols 11387 next if($CompleteSignature{1}{$Symbol}{"PureVirt"}); 11388 if($Level eq "Binary") 11389 { 11390 if($CompleteSignature{1}{$Symbol}{"InLine"}) 11391 { 11392 if(not $CompleteSignature{1}{$Symbol}{"Virt"}) 11393 { # skip inline non-virtual functions 11394 next; 11395 } 11396 } 11397 } 11398 else 11399 { # Source 11400 if(my $Alt = $SourceAlternative{$Symbol}) 11401 { 11402 if(defined $CompleteSignature{1}{$Alt} 11403 and $CompleteSignature{1}{$Symbol}{"Const"}) 11404 { 11405 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"}; 11406 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{$tr_name{$Symbol}}}=( 11407 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"}, 11408 "Type_Type"=>"Class", 11409 "Target"=>get_Signature($Alt, 1) ); 11410 } 11411 else 11412 { # do NOT show removed symbol 11413 next; 11414 } 11415 } 11416 } 11417 next if($CompleteSignature{1}{$Symbol}{"Private"}); 11418 next if(not symbolFilter($Symbol, 1, "Affected", $Level)); 11419 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=(); 11420 } 11421} 11422 11423sub addParamNames($) 11424{ 11425 my $LibraryVersion = $_[0]; 11426 return if(not keys(%AddIntParams)); 11427 my $SecondVersion = $LibraryVersion==1?2:1; 11428 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}})) 11429 { 11430 next if(not keys(%{$AddIntParams{$Interface}})); 11431 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}})) 11432 { # add absent parameter names 11433 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"}; 11434 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos}) 11435 { # names from the external file 11436 if(defined $CompleteSignature{$SecondVersion}{$Interface} 11437 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}) 11438 { 11439 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) { 11440 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName; 11441 } 11442 } 11443 else { 11444 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName; 11445 } 11446 } 11447 } 11448 } 11449} 11450 11451sub detectChangedTypedefs() 11452{ # detect changed typedefs to show 11453 # correct function signatures 11454 foreach my $Typedef (keys(%{$Typedef_BaseName{1}})) 11455 { 11456 next if(not $Typedef); 11457 my $BName1 = $Typedef_BaseName{1}{$Typedef}; 11458 if(not $BName1 or isAnon($BName1)) { 11459 next; 11460 } 11461 my $BName2 = $Typedef_BaseName{2}{$Typedef}; 11462 if(not $BName2 or isAnon($BName2)) { 11463 next; 11464 } 11465 if($BName1 ne $BName2) { 11466 $ChangedTypedef{$Typedef} = 1; 11467 } 11468 } 11469} 11470 11471sub get_symbol_suffix($$) 11472{ 11473 my ($Symbol, $Full) = @_; 11474 my ($SN, $SO, $SV) = separate_symbol($Symbol); 11475 $Symbol=$SN;# remove version 11476 my $Signature = $tr_name{$Symbol}; 11477 my $Suffix = substr($Signature, find_center($Signature, "(")); 11478 if(not $Full) { 11479 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g; 11480 } 11481 return $Suffix; 11482} 11483 11484sub get_symbol_prefix($$) 11485{ 11486 my ($Symbol, $LibVersion) = @_; 11487 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}; 11488 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) 11489 { # methods 11490 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName; 11491 } 11492 return $ShortName; 11493} 11494 11495sub setAlternative($) 11496{ 11497 my $Symbol = $_[0]; 11498 my $PSymbol = $Symbol; 11499 if(not defined $CompleteSignature{2}{$PSymbol} 11500 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"} 11501 and not $CompleteSignature{2}{$PSymbol}{"ShortName"})) 11502 { # search for a pair 11503 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"}) 11504 { 11505 if($CompleteSignature{1}{$PSymbol}{"Data"}) 11506 { 11507 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/ 11508 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/) 11509 { 11510 if(defined $CompleteSignature{2}{$PSymbol} 11511 and $CompleteSignature{2}{$PSymbol}{"MnglName"}) 11512 { 11513 $SourceAlternative{$Symbol} = $PSymbol; 11514 $SourceAlternative_B{$PSymbol} = $Symbol; 11515 if(not defined $CompleteSignature{1}{$PSymbol} 11516 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) { 11517 $SourceReplacement{$Symbol} = $PSymbol; 11518 } 11519 } 11520 } 11521 } 11522 else 11523 { 11524 foreach my $Sp ("KV", "VK", "K", "V") 11525 { 11526 if($PSymbol=~s/\A_ZN$Sp/_ZN/ 11527 or $PSymbol=~s/\A_ZN/_ZN$Sp/) 11528 { 11529 if(defined $CompleteSignature{2}{$PSymbol} 11530 and $CompleteSignature{2}{$PSymbol}{"MnglName"}) 11531 { 11532 $SourceAlternative{$Symbol} = $PSymbol; 11533 $SourceAlternative_B{$PSymbol} = $Symbol; 11534 if(not defined $CompleteSignature{1}{$PSymbol} 11535 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) { 11536 $SourceReplacement{$Symbol} = $PSymbol; 11537 } 11538 } 11539 } 11540 $PSymbol = $Symbol; 11541 } 11542 } 11543 } 11544 } 11545 return ""; 11546} 11547 11548sub getSymKind($$) 11549{ 11550 my ($Symbol, $LibVersion) = @_; 11551 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}) 11552 { 11553 return "Global_Data"; 11554 } 11555 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"}) 11556 { 11557 return "Method"; 11558 } 11559 return "Function"; 11560} 11561 11562sub mergeSignatures($) 11563{ 11564 my $Level = $_[0]; 11565 my %SubProblems = (); 11566 11567 mergeBases($Level); 11568 11569 my %AddedOverloads = (); 11570 foreach my $Symbol (sort keys(%{$AddedInt{$Level}})) 11571 { # check all added exported symbols 11572 if(not $CompleteSignature{2}{$Symbol}{"Header"}) { 11573 next; 11574 } 11575 if(defined $CompleteSignature{1}{$Symbol} 11576 and $CompleteSignature{1}{$Symbol}{"Header"}) 11577 { # double-check added symbol 11578 next; 11579 } 11580 if(not symbolFilter($Symbol, 2, "Affected", $Level)) { 11581 next; 11582 } 11583 if($Symbol=~/\A(_Z|\?)/) 11584 { # C++ 11585 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol; 11586 } 11587 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"}) 11588 { # register virtual overridings 11589 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"}; 11590 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"}; 11591 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"} 11592 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"}) 11593 { 11594 if($TName_Tid{1}{$AffectedClass_Name}) 11595 { # class should exist in previous version 11596 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1)) 11597 { # old v-table is NOT copied by old applications 11598 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=( 11599 "Type_Name"=>$AffectedClass_Name, 11600 "Type_Type"=>"Class", 11601 "Target"=>get_Signature($Symbol, 2), 11602 "Old_Value"=>get_Signature($OverriddenMethod, 2), 11603 "New_Value"=>get_Signature($Symbol, 2) ); 11604 } 11605 } 11606 } 11607 } 11608 } 11609 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}})) 11610 { # check all removed exported symbols 11611 if(not $CompleteSignature{1}{$Symbol}{"Header"}) { 11612 next; 11613 } 11614 if(defined $CompleteSignature{2}{$Symbol} 11615 and $CompleteSignature{2}{$Symbol}{"Header"}) 11616 { # double-check removed symbol 11617 next; 11618 } 11619 if($CompleteSignature{1}{$Symbol}{"Private"}) 11620 { # skip private methods 11621 next; 11622 } 11623 if(not symbolFilter($Symbol, 1, "Affected", $Level)) { 11624 next; 11625 } 11626 $CheckedSymbols{$Level}{$Symbol} = 1; 11627 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"}) 11628 { # register virtual overridings 11629 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"}; 11630 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"}; 11631 if(defined $CompleteSignature{2}{$OverriddenMethod} 11632 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"}) 11633 { 11634 if($TName_Tid{2}{$AffectedClass_Name}) 11635 { # class should exist in newer version 11636 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1)) 11637 { # old v-table is NOT copied by old applications 11638 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=( 11639 "Type_Name"=>$AffectedClass_Name, 11640 "Type_Type"=>"Class", 11641 "Target"=>get_Signature($OverriddenMethod, 1), 11642 "Old_Value"=>get_Signature($Symbol, 1), 11643 "New_Value"=>get_Signature($OverriddenMethod, 1) ); 11644 } 11645 } 11646 } 11647 } 11648 if($Level eq "Binary" 11649 and $OSgroup eq "windows") 11650 { # register the reason of symbol name change 11651 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}}) 11652 { 11653 if($AddedInt{$Level}{$NewSym}) 11654 { 11655 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"}) 11656 { 11657 if($CompleteSignature{2}{$NewSym}{"Static"}) 11658 { 11659 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=( 11660 "Target"=>$tr_name{$Symbol}, 11661 "Old_Value"=>$Symbol, 11662 "New_Value"=>$NewSym ); 11663 } 11664 else 11665 { 11666 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_NonStatic"}{$tr_name{$Symbol}}}=( 11667 "Target"=>$tr_name{$Symbol}, 11668 "Old_Value"=>$Symbol, 11669 "New_Value"=>$NewSym ); 11670 } 11671 } 11672 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"}) 11673 { 11674 if($CompleteSignature{2}{$NewSym}{"Virt"}) 11675 { 11676 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=( 11677 "Target"=>$tr_name{$Symbol}, 11678 "Old_Value"=>$Symbol, 11679 "New_Value"=>$NewSym ); 11680 } 11681 else 11682 { 11683 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_NonVirtual"}{$tr_name{$Symbol}}}=( 11684 "Target"=>$tr_name{$Symbol}, 11685 "Old_Value"=>$Symbol, 11686 "New_Value"=>$NewSym ); 11687 } 11688 } 11689 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"}; 11690 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"}; 11691 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"}; 11692 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"}; 11693 if($RTName1 ne $RTName2) 11694 { 11695 my $ProblemType = "Symbol_Changed_Return"; 11696 if($CompleteSignature{1}{$Symbol}{"Data"}) { 11697 $ProblemType = "Global_Data_Symbol_Changed_Type"; 11698 } 11699 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=( 11700 "Target"=>$tr_name{$Symbol}, 11701 "Old_Type"=>$RTName1, 11702 "New_Type"=>$RTName2, 11703 "Old_Value"=>$Symbol, 11704 "New_Value"=>$NewSym ); 11705 } 11706 } 11707 } 11708 } 11709 if($Symbol=~/\A(_Z|\?)/) 11710 { # C++ 11711 my $Prefix = get_symbol_prefix($Symbol, 1); 11712 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}}) 11713 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)}) 11714 { # changed signature: params, "const"-qualifier 11715 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]}; 11716 if($CompleteSignature{1}{$Symbol}{"Constructor"}) 11717 { 11718 if($Symbol=~/(C1E|C2E)/) 11719 { 11720 my $CtorType = $1; 11721 $NewSym=~s/(C1E|C2E)/$CtorType/g; 11722 } 11723 } 11724 elsif($CompleteSignature{1}{$Symbol}{"Destructor"}) 11725 { 11726 if($Symbol=~/(D0E|D1E|D2E)/) 11727 { 11728 my $DtorType = $1; 11729 $NewSym=~s/(D0E|D1E|D2E)/$DtorType/g; 11730 } 11731 } 11732 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"}; 11733 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"}; 11734 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2)) 11735 { # from the same class and namespace 11736 if($CompleteSignature{1}{$Symbol}{"Const"} 11737 and not $CompleteSignature{2}{$NewSym}{"Const"}) 11738 { # "const" to non-"const" 11739 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_NonConst"}{$tr_name{$Symbol}}}=( 11740 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"}, 11741 "Target"=>$tr_name{$Symbol}, 11742 "New_Signature"=>get_Signature($NewSym, 2), 11743 "Old_Value"=>$Symbol, 11744 "New_Value"=>$NewSym ); 11745 } 11746 elsif(not $CompleteSignature{1}{$Symbol}{"Const"} 11747 and $CompleteSignature{2}{$NewSym}{"Const"}) 11748 { # non-"const" to "const" 11749 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=( 11750 "Target"=>$tr_name{$Symbol}, 11751 "New_Signature"=>get_Signature($NewSym, 2), 11752 "Old_Value"=>$Symbol, 11753 "New_Value"=>$NewSym ); 11754 } 11755 if($CompleteSignature{1}{$Symbol}{"Volatile"} 11756 and not $CompleteSignature{2}{$NewSym}{"Volatile"}) 11757 { # "volatile" to non-"volatile" 11758 11759 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_NonVolatile"}{$tr_name{$Symbol}}}=( 11760 "Target"=>$tr_name{$Symbol}, 11761 "New_Signature"=>get_Signature($NewSym, 2), 11762 "Old_Value"=>$Symbol, 11763 "New_Value"=>$NewSym ); 11764 } 11765 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"} 11766 and $CompleteSignature{2}{$NewSym}{"Volatile"}) 11767 { # non-"volatile" to "volatile" 11768 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=( 11769 "Target"=>$tr_name{$Symbol}, 11770 "New_Signature"=>get_Signature($NewSym, 2), 11771 "Old_Value"=>$Symbol, 11772 "New_Value"=>$NewSym ); 11773 } 11774 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0)) 11775 { # params list 11776 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=( 11777 "Target"=>$tr_name{$Symbol}, 11778 "New_Signature"=>get_Signature($NewSym, 2), 11779 "Old_Value"=>$Symbol, 11780 "New_Value"=>$NewSym ); 11781 } 11782 } 11783 } 11784 } 11785 } 11786 foreach my $Symbol (sort keys(%{$CompleteSignature{1}})) 11787 { # checking symbols 11788 my ($SN, $SS, $SV) = separate_symbol($Symbol); 11789 if($Level eq "Source") 11790 { # remove symbol version 11791 $Symbol=$SN; 11792 } 11793 else 11794 { # Binary 11795 if(not $SV) 11796 { # symbol without version 11797 if(my $VSym = $SymVer{1}{$Symbol}) 11798 { # the symbol is linked with versioned symbol 11799 if($CompleteSignature{2}{$VSym}{"MnglName"}) 11800 { # show report for symbol@ver only 11801 next; 11802 } 11803 elsif(not link_symbol($VSym, 2, "-Deps")) 11804 { # changed version: sym@v1 to sym@v2 11805 # do NOT show report for symbol 11806 next; 11807 } 11808 } 11809 } 11810 } 11811 my $PSymbol = $Symbol; 11812 if($Level eq "Source" 11813 and my $S = $SourceReplacement{$Symbol}) 11814 { # take a source-compatible replacement function 11815 $PSymbol = $S; 11816 } 11817 if($CompleteSignature{1}{$Symbol}{"Private"}) 11818 { # private symbols 11819 next; 11820 } 11821 if(not defined $CompleteSignature{1}{$Symbol} 11822 or not defined $CompleteSignature{2}{$PSymbol}) 11823 { # no info 11824 next; 11825 } 11826 if(not $CompleteSignature{1}{$Symbol}{"MnglName"} 11827 or not $CompleteSignature{2}{$PSymbol}{"MnglName"}) 11828 { # no mangled name 11829 next; 11830 } 11831 if(not $CompleteSignature{1}{$Symbol}{"Header"} 11832 or not $CompleteSignature{2}{$PSymbol}{"Header"}) 11833 { # without a header 11834 next; 11835 } 11836 if(checkDump(1, "2.13") and checkDump(2, "2.13")) 11837 { 11838 if($CompleteSignature{1}{$Symbol}{"Data"} 11839 and $CompleteSignature{2}{$PSymbol}{"Data"}) 11840 { 11841 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"}; 11842 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"}; 11843 if(defined $Value1) 11844 { 11845 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1); 11846 if(defined $Value2) 11847 { 11848 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2); 11849 if($Value1 ne $Value2) 11850 { 11851 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=( 11852 "Old_Value"=>$Value1, 11853 "New_Value"=>$Value2, 11854 "Target"=>get_Signature($Symbol, 1) ); 11855 } 11856 } 11857 } 11858 } 11859 } 11860 11861 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"} 11862 and $CompleteSignature{2}{$PSymbol}{"PureVirt"}) 11863 { # became pure 11864 next; 11865 } 11866 if($CompleteSignature{1}{$Symbol}{"PureVirt"} 11867 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"}) 11868 { # became non-pure 11869 next; 11870 } 11871 11872 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level)) 11873 { # exported, target, inline virtual and pure virtual 11874 next; 11875 } 11876 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level)) 11877 { # exported, target, inline virtual and pure virtual 11878 next; 11879 } 11880 11881 if($CompleteSignature{2}{$PSymbol}{"Private"}) 11882 { 11883 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=( 11884 "Target"=>get_Signature_M($PSymbol, 2) ); 11885 } 11886 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"} 11887 and $CompleteSignature{2}{$PSymbol}{"Protected"}) 11888 { 11889 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=( 11890 "Target"=>get_Signature_M($PSymbol, 2) ); 11891 } 11892 elsif($CompleteSignature{1}{$Symbol}{"Protected"} 11893 and not $CompleteSignature{2}{$PSymbol}{"Protected"}) 11894 { 11895 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=( 11896 "Target"=>get_Signature_M($PSymbol, 2) ); 11897 } 11898 11899 # checking virtual table 11900 mergeVirtualTables($Symbol, $Level); 11901 11902 if($COMPILE_ERRORS) 11903 { # if some errors occurred at the compiling stage 11904 # then some false positives can be skipped here 11905 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"} 11906 and not $GlobalDataObject{2}{$Symbol}) 11907 { # missed information about parameters in newer version 11908 next; 11909 } 11910 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol} 11911 and not $CompleteSignature{2}{$PSymbol}{"Data"}) 11912 {# missed information about parameters in older version 11913 next; 11914 } 11915 } 11916 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol); 11917 # checking attributes 11918 if($CompleteSignature{2}{$PSymbol}{"Static"} 11919 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/) { 11920 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=( 11921 "Target"=>get_Signature($Symbol, 1) 11922 ); 11923 } 11924 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"} 11925 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/) { 11926 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_NonStatic"}{""}}=( 11927 "Target"=>get_Signature($Symbol, 1) 11928 ); 11929 } 11930 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"}) 11931 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"})) 11932 { # relative position of virtual and pure virtual methods 11933 if($Level eq "Binary") 11934 { 11935 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"} 11936 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"}) 11937 { # top-level virtual methods only 11938 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"}; 11939 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"}; 11940 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name} 11941 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol}) 11942 { # check the absolute position of virtual method (including added and removed methods) 11943 my %Class_Type = get_Type($Class_Id, 1); 11944 my $ProblemType = "Virtual_Method_Position"; 11945 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) { 11946 $ProblemType = "Pure_Virtual_Method_Position"; 11947 } 11948 if(isUsedClass($Class_Id, 1, $Level)) 11949 { 11950 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}})); 11951 foreach my $AffectedInterface (@Affected) 11952 { 11953 %{$CompatProblems{$Level}{$AffectedInterface}{$ProblemType}{$tr_name{$MnglName}}}=( 11954 "Type_Name"=>$Class_Type{"Name"}, 11955 "Type_Type"=>"Class", 11956 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"}, 11957 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"}, 11958 "Target"=>get_Signature($Symbol, 1) ); 11959 } 11960 $VTableChanged_M{$Class_Type{"Name"}} = 1; 11961 } 11962 } 11963 } 11964 } 11965 } 11966 if($CompleteSignature{1}{$Symbol}{"PureVirt"} 11967 or $CompleteSignature{2}{$PSymbol}{"PureVirt"}) 11968 { # do NOT check type changes in pure virtuals 11969 next; 11970 } 11971 $CheckedSymbols{$Level}{$Symbol}=1; 11972 if($Symbol=~/\A(_Z|\?)/ 11973 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})) 11974 { # C/C++: changes in parameters 11975 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})) 11976 { # checking parameters 11977 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level); 11978 } 11979 } 11980 else 11981 { # C: added/removed parameters 11982 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})) 11983 { # checking added parameters 11984 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"}; 11985 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"}; 11986 last if($PType2_Name eq "..."); 11987 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}; 11988 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:""; 11989 my $ParamPos_Prev = "-1"; 11990 if($PName=~/\Ap\d+\Z/i) 11991 { # added unnamed parameter ( pN ) 11992 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1); 11993 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2); 11994 if($#Positions1==-1 or $#Positions2>$#Positions1) { 11995 $ParamPos_Prev = "lost"; 11996 } 11997 } 11998 else { 11999 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1); 12000 } 12001 if($ParamPos_Prev eq "lost") 12002 { 12003 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1) 12004 { 12005 my $ProblemType = "Added_Parameter"; 12006 if($PName=~/\Ap\d+\Z/) { 12007 $ProblemType = "Added_Unnamed_Parameter"; 12008 } 12009 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=( 12010 "Target"=>$PName, 12011 "Param_Pos"=>$ParamPos, 12012 "Param_Type"=>$PType2_Name, 12013 "New_Signature"=>get_Signature($Symbol, 2) ); 12014 } 12015 else 12016 { 12017 my %ParamType_Pure = get_PureType($PType2_Id, 2); 12018 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"}; 12019 my %PairType_Pure = get_PureType($PairType_Id, 1); 12020 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"}) 12021 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost") 12022 { 12023 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/) 12024 { 12025 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=( 12026 "Target"=>$PName_Old, 12027 "Param_Pos"=>$ParamPos, 12028 "Param_Type"=>$PType2_Name, 12029 "Old_Value"=>$PName_Old, 12030 "New_Value"=>$PName, 12031 "New_Signature"=>get_Signature($Symbol, 2) ); 12032 } 12033 } 12034 else 12035 { 12036 my $ProblemType = "Added_Middle_Parameter"; 12037 if($PName=~/\Ap\d+\Z/) { 12038 $ProblemType = "Added_Middle_Unnamed_Parameter"; 12039 } 12040 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=( 12041 "Target"=>$PName, 12042 "Param_Pos"=>$ParamPos, 12043 "Param_Type"=>$PType2_Name, 12044 "New_Signature"=>get_Signature($Symbol, 2) ); 12045 } 12046 } 12047 } 12048 } 12049 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})) 12050 { # check relevant parameters 12051 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"}; 12052 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}; 12053 # FIXME: find relevant parameter by name 12054 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}) 12055 { 12056 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"}; 12057 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}; 12058 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"} 12059 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) { 12060 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level); 12061 } 12062 } 12063 } 12064 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})) 12065 { # checking removed parameters 12066 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"}; 12067 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"}; 12068 last if($PType1_Name eq "..."); 12069 my $Parameter_Name = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}; 12070 my $Parameter_NewName = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:""; 12071 my $ParamPos_New = "-1"; 12072 if($Parameter_Name=~/\Ap\d+\Z/i) 12073 { # removed unnamed parameter ( pN ) 12074 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1); 12075 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2); 12076 if($#Positions2==-1 or $#Positions2<$#Positions1) { 12077 $ParamPos_New = "lost"; 12078 } 12079 } 12080 else { 12081 $ParamPos_New = find_ParamPair_Pos_byName($Parameter_Name, $Symbol, 2); 12082 } 12083 if($ParamPos_New eq "lost") 12084 { 12085 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1) 12086 { 12087 my $ProblemType = "Removed_Parameter"; 12088 if($Parameter_Name=~/\Ap\d+\Z/) { 12089 $ProblemType = "Removed_Unnamed_Parameter"; 12090 } 12091 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=( 12092 "Target"=>$Parameter_Name, 12093 "Param_Pos"=>$ParamPos, 12094 "Param_Type"=>$PType1_Name, 12095 "New_Signature"=>get_Signature($Symbol, 2) ); 12096 } 12097 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1) 12098 { 12099 my %ParamType_Pure = get_PureType($PType1_Id, 1); 12100 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"}; 12101 my %PairType_Pure = get_PureType($PairType_Id, 2); 12102 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"}) 12103 and find_ParamPair_Pos_byName($Parameter_NewName, $Symbol, 1) eq "lost") 12104 { 12105 if($Parameter_NewName!~/\Ap\d+\Z/ and $Parameter_Name!~/\Ap\d+\Z/) 12106 { 12107 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=( 12108 "Target"=>$Parameter_Name, 12109 "Param_Pos"=>$ParamPos, 12110 "Param_Type"=>$PType1_Name, 12111 "Old_Value"=>$Parameter_Name, 12112 "New_Value"=>$Parameter_NewName, 12113 "New_Signature"=>get_Signature($Symbol, 2) ); 12114 } 12115 } 12116 else 12117 { 12118 my $ProblemType = "Removed_Middle_Parameter"; 12119 if($Parameter_Name=~/\Ap\d+\Z/) { 12120 $ProblemType = "Removed_Middle_Unnamed_Parameter"; 12121 } 12122 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=( 12123 "Target"=>$Parameter_Name, 12124 "Param_Pos"=>$ParamPos, 12125 "Param_Type"=>$PType1_Name, 12126 "New_Signature"=>get_Signature($Symbol, 2) ); 12127 } 12128 } 12129 } 12130 } 12131 } 12132 # checking return type 12133 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"}; 12134 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"}; 12135 %SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level); 12136 foreach my $SubProblemType (keys(%SubProblems)) 12137 { 12138 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"}; 12139 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"}; 12140 my $NewProblemType = $SubProblemType; 12141 if($Level eq "Binary" and $SubProblemType eq "Return_Type_Became_Void" 12142 and keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})) 12143 { # parameters stack has been affected 12144 $NewProblemType = "Return_Type_Became_Void_And_Stack_Layout"; 12145 } 12146 elsif($Level eq "Binary" 12147 and $SubProblemType eq "Return_Type_From_Void") 12148 { # parameters stack has been affected 12149 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})) { 12150 $NewProblemType = "Return_Type_From_Void_And_Stack_Layout"; 12151 } 12152 else 12153 { # safe 12154 delete($SubProblems{$SubProblemType}); 12155 next; 12156 } 12157 } 12158 elsif($SubProblemType eq "Return_Type_And_Size" 12159 and $CompleteSignature{1}{$Symbol}{"Data"}) { 12160 $NewProblemType = "Global_Data_Type_And_Size"; 12161 } 12162 elsif($SubProblemType eq "Return_Type") 12163 { 12164 if($CompleteSignature{1}{$Symbol}{"Data"}) 12165 { 12166 if(removedQual($Old_Value, $New_Value, "const")) 12167 { # const -> non-const global data 12168 $NewProblemType = "Global_Data_Became_Non_Const"; 12169 } 12170 elsif(addedQual($Old_Value, $New_Value, "const")) 12171 { # non-const -> const global data 12172 $NewProblemType = "Global_Data_Became_Const"; 12173 } 12174 else { 12175 $NewProblemType = "Global_Data_Type"; 12176 } 12177 } 12178 else 12179 { 12180 if(addedQual($Old_Value, $New_Value, "const")) { 12181 $NewProblemType = "Return_Type_Became_Const"; 12182 } 12183 } 12184 } 12185 elsif($SubProblemType eq "Return_Type_Format") 12186 { 12187 if($CompleteSignature{1}{$Symbol}{"Data"}) { 12188 $NewProblemType = "Global_Data_Type_Format"; 12189 } 12190 } 12191 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{"retval"}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}}; 12192 } 12193 if($ReturnType1_Id and $ReturnType2_Id) 12194 { 12195 @RecurTypes = (); 12196 %SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level); 12197 foreach my $SubProblemType (keys(%SubProblems)) 12198 { # add "Global_Data_Size" problem 12199 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"}; 12200 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"}; 12201 if($SubProblemType eq "DataType_Size" 12202 and $CompleteSignature{1}{$Symbol}{"Data"} 12203 and get_PLevel($ReturnType1_Id, 1)==0) 12204 { # add a new problem 12205 %{$SubProblems{"Global_Data_Size"}} = %{$SubProblems{$SubProblemType}}; 12206 } 12207 } 12208 foreach my $SubProblemType (keys(%SubProblems)) 12209 { 12210 foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}})) 12211 { 12212 my $NewLocation = ($SubLocation)?"retval->".$SubLocation:"retval"; 12213 %{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}=( 12214 "Return_Type_Name"=>$TypeInfo{1}{$ReturnType1_Id}{"Name"} ); 12215 @{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}}; 12216 if($SubLocation!~/\-\>/) { 12217 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$ReturnType1_Id}{"Name"}; 12218 } 12219 } 12220 } 12221 } 12222 12223 # checking object type 12224 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"}; 12225 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"}; 12226 if($ObjTId1 and $ObjTId2 12227 and not $CompleteSignature{1}{$Symbol}{"Static"}) 12228 { 12229 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1); 12230 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2); 12231 if($ThisPtr1_Id and $ThisPtr2_Id) 12232 { 12233 @RecurTypes = (); 12234 %SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level); 12235 foreach my $SubProblemType (keys(%SubProblems)) 12236 { 12237 foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}})) 12238 { 12239 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this"; 12240 %{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}=( 12241 "Object_Type_Name"=>$TypeInfo{1}{$ObjTId1}{"Name"} ); 12242 @{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}}; 12243 if($SubLocation!~/\-\>/) { 12244 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$ObjTId1}{"Name"}; 12245 } 12246 } 12247 } 12248 } 12249 } 12250 } 12251 if($Level eq "Binary") { 12252 mergeVTables($Level); 12253 } 12254 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) { 12255 $CheckedSymbols{$Level}{$Symbol} = 1; 12256 } 12257} 12258 12259sub rmQuals($$) 12260{ 12261 my ($Value, $Qual) = @_; 12262 if(not $Qual) { 12263 return $Value; 12264 } 12265 if($Qual eq "all") 12266 { # all quals 12267 $Qual = "const|volatile|restrict"; 12268 } 12269 while($Value=~s/\b$Qual\b//) { 12270 $Value = formatName($Value); 12271 } 12272 return $Value; 12273} 12274 12275sub cmpBTypes($$$$) 12276{ 12277 my ($T1, $T2, $V1, $V2) = @_; 12278 $T1 = uncover_typedefs($T1, $V1); 12279 $T2 = uncover_typedefs($T2, $V2); 12280 return (rmQuals($T1, "all") eq rmQuals($T2, "all")); 12281} 12282 12283sub addedQual($$$) 12284{ 12285 my ($Old_Value, $New_Value, $Qual) = @_; 12286 return removedQual_($New_Value, $Old_Value, 2, 1, $Qual); 12287} 12288 12289sub removedQual($$$) 12290{ 12291 my ($Old_Value, $New_Value, $Qual) = @_; 12292 return removedQual_($Old_Value, $New_Value, 1, 2, $Qual); 12293} 12294 12295sub removedQual_($$$$$) 12296{ 12297 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_; 12298 $Old_Value = uncover_typedefs($Old_Value, $V1); 12299 $New_Value = uncover_typedefs($New_Value, $V2); 12300 if($Old_Value eq $New_Value) 12301 { # equal types 12302 return 0; 12303 } 12304 if($Old_Value!~/\b$Qual\b/) 12305 { # without a qual 12306 return 0; 12307 } 12308 elsif($New_Value!~/\b$Qual\b/) 12309 { # became non-qual 12310 return 1; 12311 } 12312 else 12313 { 12314 my @BQ1 = getQualModel($Old_Value, $Qual); 12315 my @BQ2 = getQualModel($New_Value, $Qual); 12316 foreach (0 .. $#BQ1) 12317 { # removed qual 12318 if($BQ1[$_]==1 12319 and $BQ2[$_]!=1) 12320 { 12321 return 2; 12322 } 12323 } 12324 } 12325 return 0; 12326} 12327 12328sub getQualModel($$) 12329{ 12330 my ($Value, $Qual) = @_; 12331 if(not $Qual) { 12332 return $Value; 12333 } 12334 12335 # cleaning 12336 while($Value=~/(\w+)/ and $1 ne $Qual) { 12337 $Value=~s/\b$1\b//g; 12338 } 12339 $Value=~s/[^\*\&\w]+//g; 12340 12341 # modeling 12342 # int*const*const == 011 12343 # int**const == 001 12344 my @Model = (); 12345 my @Elems = split(/[\*\&]/, $Value); 12346 if(not @Elems) { 12347 return (0); 12348 } 12349 foreach (@Elems) 12350 { 12351 if($_ eq $Qual) { 12352 push(@Model, 1); 12353 } 12354 else { 12355 push(@Model, 0); 12356 } 12357 } 12358 12359 return @Model; 12360} 12361 12362sub showVal($$$) 12363{ 12364 my ($Value, $TypeId, $LibVersion) = @_; 12365 my %PureType = get_PureType($TypeId, $LibVersion); 12366 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion); 12367 if($TName=~/\A(char(| const)\*|std::(string|basic_string<char>)(|&))\Z/) 12368 { # strings 12369 return "\"$Value\""; 12370 } 12371 elsif($TName=~/\Achar(| const)\Z/) 12372 { # characters 12373 return "\'$Value\'"; 12374 } 12375 return $Value; 12376} 12377 12378sub mergeParameters($$$$$) 12379{ 12380 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level) = @_; 12381 if(not $Symbol) { 12382 return; 12383 } 12384 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"}; 12385 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"}; 12386 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"}; 12387 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"}; 12388 if(not $PType1_Id 12389 or not $PType2_Id) { 12390 return; 12391 } 12392 my %Type1 = get_Type($PType1_Id, 1); 12393 my %Type2 = get_Type($PType2_Id, 2); 12394 my %BaseType1 = get_BaseType($PType1_Id, 1); 12395 my %BaseType2 = get_BaseType($PType2_Id, 2); 12396 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter"; 12397 if($Level eq "Binary") 12398 { 12399 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1")) 12400 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format) 12401 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"} 12402 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"}) 12403 { 12404 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=( 12405 "Target"=>$PName1, 12406 "Param_Pos"=>$ParamPos1 ); 12407 } 12408 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"} 12409 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"}) 12410 { 12411 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=( 12412 "Target"=>$PName1, 12413 "Param_Pos"=>$ParamPos1 ); 12414 } 12415 } 12416 } 12417 if(checkDump(1, "2.0") and checkDump(2, "2.0")) 12418 { # "default" attribute added in ACC 1.22 (dump 2.0 format) 12419 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"}; 12420 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"}; 12421 if(not checkDump(1, "2.13") 12422 and checkDump(2, "2.13")) 12423 { # support for old ABI dumps 12424 if(defined $Value_Old and defined $Value_New) 12425 { 12426 if($Type1{"Name"} eq "bool" 12427 and $Value_Old eq "false" and $Value_New eq "0") 12428 { # int class::method ( bool p = 0 ); 12429 # old ABI dumps: "false" 12430 # new ABI dumps: "0" 12431 $Value_Old = "0"; 12432 } 12433 } 12434 } 12435 if(defined $Value_Old) 12436 { 12437 $Value_Old = showVal($Value_Old, $PType1_Id, 1); 12438 if(defined $Value_New) 12439 { 12440 $Value_New = showVal($Value_New, $PType2_Id, 2); 12441 if($Value_Old ne $Value_New) 12442 { # FIXME: how to distinguish "0" and 0 (NULL) 12443 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=( 12444 "Target"=>$PName1, 12445 "Param_Pos"=>$ParamPos1, 12446 "Old_Value"=>$Value_Old, 12447 "New_Value"=>$Value_New ); 12448 } 12449 } 12450 else 12451 { 12452 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=( 12453 "Target"=>$PName1, 12454 "Param_Pos"=>$ParamPos1, 12455 "Old_Value"=>$Value_Old ); 12456 } 12457 } 12458 elsif(defined $Value_New) 12459 { 12460 $Value_New = showVal($Value_New, $PType2_Id, 2); 12461 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=( 12462 "Target"=>$PName1, 12463 "Param_Pos"=>$ParamPos1, 12464 "New_Value"=>$Value_New ); 12465 } 12466 } 12467 if($PName1 and $PName2 and $PName1 ne $PName2 12468 and $PType1_Id!=-1 and $PType2_Id!=-1 12469 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/) 12470 { # except unnamed "..." value list (Id=-1) 12471 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=( 12472 "Target"=>$PName1, 12473 "Param_Pos"=>$ParamPos1, 12474 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"}, 12475 "Old_Value"=>$PName1, 12476 "New_Value"=>$PName2, 12477 "New_Signature"=>get_Signature($Symbol, 2) ); 12478 } 12479 # checking type change (replace) 12480 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level); 12481 foreach my $SubProblemType (keys(%SubProblems)) 12482 { # add new problems, remove false alarms 12483 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"}; 12484 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"}; 12485 if($SubProblemType eq "Parameter_Type") 12486 { 12487 if(checkDump(1, "2.6") and checkDump(2, "2.6")) 12488 { 12489 if(my $RA = addedQual($Old_Value, $New_Value, "restrict")) 12490 { 12491 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}}; 12492 if($Level eq "Source" 12493 and cmpBTypes($Old_Value, $New_Value, 1, 2)) { 12494 delete($SubProblems{$SubProblemType}); 12495 } 12496 } 12497 elsif(my $RR = removedQual($Old_Value, $New_Value, "restrict")) 12498 { 12499 %{$SubProblems{"Parameter_Became_NonRestrict"}} = %{$SubProblems{$SubProblemType}}; 12500 if($Level eq "Source" 12501 and cmpBTypes($Old_Value, $New_Value, 1, 2)) { 12502 delete($SubProblems{$SubProblemType}); 12503 } 12504 } 12505 } 12506 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"} 12507 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/) 12508 { # int to "int const" 12509 delete($SubProblems{$SubProblemType}); 12510 } 12511 if($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"} 12512 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/) 12513 { # "int const" to int 12514 delete($SubProblems{$SubProblemType}); 12515 } 12516 } 12517 } 12518 foreach my $SubProblemType (keys(%SubProblems)) 12519 { # modify/register problems 12520 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"}; 12521 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"}; 12522 my $NewProblemType = $SubProblemType; 12523 if($Old_Value eq "..." and $New_Value ne "...") 12524 { # change from "..." to "int" 12525 if($ParamPos1==0) 12526 { # ISO C requires a named argument before "..." 12527 next; 12528 } 12529 $NewProblemType = "Parameter_Became_NonVaList"; 12530 } 12531 elsif($New_Value eq "..." and $Old_Value ne "...") 12532 { # change from "int" to "..." 12533 if($ParamPos2==0) 12534 { # ISO C requires a named argument before "..." 12535 next; 12536 } 12537 $NewProblemType = "Parameter_Became_VaList"; 12538 } 12539 elsif($SubProblemType eq "Parameter_Type" 12540 and removedQual($Old_Value, $New_Value, "const")) 12541 { # parameter: "const" to non-"const" 12542 $NewProblemType = "Parameter_Became_Non_Const"; 12543 } 12544 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size" 12545 or $SubProblemType eq "Parameter_Type")) 12546 { 12547 my ($Arch1, $Arch2) = (getArch(1), getArch(2)); 12548 if($Arch1 eq "unknown" or $Arch2 eq "unknown") 12549 { # if one of the architectures is unknown 12550 # then set other arhitecture to unknown too 12551 ($Arch1, $Arch2) = ("unknown", "unknown"); 12552 } 12553 my ($Method1, $Passed1, $SizeOnStack1, $RegName1) = callingConvention($Symbol, $ParamPos1, 1, $Arch1); 12554 my ($Method2, $Passed2, $SizeOnStack2, $RegName2) = callingConvention($Symbol, $ParamPos2, 2, $Arch2); 12555 if($Method1 eq $Method2) 12556 { 12557 if($Method1 eq "stack" and $SizeOnStack1 ne $SizeOnStack2) { 12558 $NewProblemType = "Parameter_Type_And_Stack"; 12559 } 12560 elsif($Method1 eq "register" and $RegName1 ne $RegName2) { 12561 $NewProblemType = "Parameter_Type_And_Register"; 12562 } 12563 } 12564 else 12565 { 12566 if($Method1 eq "stack") { 12567 $NewProblemType = "Parameter_Type_And_Pass_Through_Register"; 12568 } 12569 elsif($Method1 eq "register") { 12570 $NewProblemType = "Parameter_Type_And_Pass_Through_Stack"; 12571 } 12572 } 12573 $SubProblems{$SubProblemType}{"Old_Reg"} = $RegName1; 12574 $SubProblems{$SubProblemType}{"New_Reg"} = $RegName2; 12575 } 12576 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=( 12577 "Target"=>$PName1, 12578 "Param_Pos"=>$ParamPos1, 12579 "New_Signature"=>get_Signature($Symbol, 2) ); 12580 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}}; 12581 } 12582 @RecurTypes = (); 12583 # checking type definition changes 12584 my %SubProblems_Merge = mergeTypes($PType1_Id, $PType2_Id, $Level); 12585 foreach my $SubProblemType (keys(%SubProblems_Merge)) 12586 { 12587 foreach my $SubLocation (keys(%{$SubProblems_Merge{$SubProblemType}})) 12588 { 12589 my $NewProblemType = $SubProblemType; 12590 if($SubProblemType eq "DataType_Size") 12591 { 12592 my $InitialType_Type = $SubProblems_Merge{$SubProblemType}{$SubLocation}{"InitialType_Type"}; 12593 if($InitialType_Type!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/) 12594 { # stack has been affected 12595 $NewProblemType = "DataType_Size_And_Stack"; 12596 } 12597 } 12598 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location; 12599 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}}=( 12600 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"}, 12601 "Param_Pos"=>$ParamPos1, 12602 "Param_Name"=>$PName1 ); 12603 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}}{keys(%{$SubProblems_Merge{$SubProblemType}{$SubLocation}})} = values %{$SubProblems_Merge{$SubProblemType}{$SubLocation}}; 12604 if($SubLocation!~/\-\>/) { 12605 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$PType1_Id}{"Name"}; 12606 } 12607 } 12608 } 12609} 12610 12611sub callingConvention($$$$) 12612{ # calling conventions for different compilers and operating systems 12613 my ($Symbol, $ParamPos, $LibVersion, $Arch) = @_; 12614 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"}; 12615 my %Type = get_PureType($ParamTypeId, $LibVersion); 12616 my ($Method, $Alignment, $Passed, $Register) = ("", 0, "", ""); 12617 if($OSgroup=~/\A(linux|macos|freebsd)\Z/) 12618 { # GCC 12619 if($Arch eq "x86") 12620 { # System V ABI Intel386 ("Function Calling Sequence") 12621 # The stack is word aligned. Although the architecture does not require any 12622 # alignment of the stack, software convention and the operating system 12623 # requires that the stack be aligned on a word boundary. 12624 12625 # Argument words are pushed onto the stack in reverse order (that is, the 12626 # rightmost argument in C call syntax has the highest address), preserving the 12627 # stack’s word alignment. All incoming arguments appear on the stack, residing 12628 # in the stack frame of the caller. 12629 12630 # An argument’s size is increased, if necessary, to make it a multiple of words. 12631 # This may require tail padding, depending on the size of the argument. 12632 12633 # Other areas depend on the compiler and the code being compiled. The stan- 12634 # dard calling sequence does not define a maximum stack frame size, nor does 12635 # it restrict how a language system uses the ‘‘unspecified’’ area of the stan- 12636 # dard stack frame. 12637 ($Method, $Alignment) = ("stack", 4); 12638 } 12639 elsif($Arch eq "x86_64") 12640 { # System V AMD64 ABI ("Function Calling Sequence") 12641 ($Method, $Alignment) = ("stack", 8);# eightbyte aligned 12642 } 12643 elsif($Arch eq "arm") 12644 { # Procedure Call Standard for the ARM Architecture 12645 # The stack must be double-word aligned 12646 ($Method, $Alignment) = ("stack", 8);# double-word 12647 } 12648 } 12649 elsif($OSgroup eq "windows") 12650 { # MS C++ Compiler 12651 if($Arch eq "x86") 12652 { 12653 if($ParamPos==0) { 12654 ($Method, $Register, $Passed) = ("register", "ecx", "value"); 12655 } 12656 elsif($ParamPos==1) { 12657 ($Method, $Register, $Passed) = ("register", "edx", "value"); 12658 } 12659 else { 12660 ($Method, $Alignment) = ("stack", 4); 12661 } 12662 } 12663 elsif($Arch eq "x86_64") 12664 { 12665 if($ParamPos<=3) 12666 { 12667 if($Type{"Name"}=~/\A(float|double|long double)\Z/) { 12668 ($Method, $Passed) = ("xmm".$ParamPos, "value"); 12669 } 12670 elsif(isScalar($Type{"Name"}) 12671 or $Type{"Type"}=~/\A(Struct|Union|Enum|Array)\Z/ 12672 or $Type{"Name"}=~/\A(__m64|__m128)\Z/) 12673 { 12674 if($ParamPos==0) { 12675 ($Method, $Register, $Passed) = ("register", "rcx", "value"); 12676 } 12677 elsif($ParamPos==1) { 12678 ($Method, $Register, $Passed) = ("register", "rdx", "value"); 12679 } 12680 elsif($ParamPos==2) { 12681 ($Method, $Register, $Passed) = ("register", "r8", "value"); 12682 } 12683 elsif($ParamPos==3) { 12684 ($Method, $Register, $Passed) = ("register", "r9", "value"); 12685 } 12686 if($Type{"Size"}>64 12687 or $Type{"Type"} eq "Array") { 12688 $Passed = "pointer"; 12689 } 12690 } 12691 } 12692 else { 12693 ($Method, $Alignment) = ("stack", 8);# word alignment 12694 } 12695 } 12696 } 12697 if($Method eq "register") { 12698 return ("register", $Passed, "", $Register); 12699 } 12700 else 12701 { # on the stack 12702 if(not $Alignment) 12703 { # default convention 12704 $Alignment = $WORD_SIZE{$LibVersion}; 12705 } 12706 if(not $Passed) 12707 { # default convention 12708 $Passed = "value"; 12709 } 12710 my $SizeOnStack = $Type{"Size"}; 12711 # FIXME: improve stack alignment 12712 if($SizeOnStack!=$Alignment) { 12713 $SizeOnStack = int(($Type{"Size"}+$Alignment)/$Alignment)*$Alignment; 12714 } 12715 return ("stack", $Passed, $SizeOnStack, ""); 12716 } 12717} 12718 12719sub find_ParamPair_Pos_byName($$$) 12720{ 12721 my ($Name, $Symbol, $LibVersion) = @_; 12722 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}})) 12723 { 12724 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}); 12725 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name) 12726 { 12727 return $ParamPos; 12728 } 12729 } 12730 return "lost"; 12731} 12732 12733sub find_ParamPair_Pos_byTypeAndPos($$$$$) 12734{ 12735 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_; 12736 my @Positions = (); 12737 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}})) 12738 { 12739 next if($Order eq "backward" and $ParamPos>$MediumPos); 12740 next if($Order eq "forward" and $ParamPos<$MediumPos); 12741 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}); 12742 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"}; 12743 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) { 12744 push(@Positions, $ParamPos); 12745 } 12746 } 12747 return @Positions; 12748} 12749 12750sub getTypeIdByName($$) 12751{ 12752 my ($TypeName, $Version) = @_; 12753 return $TName_Tid{$Version}{formatName($TypeName)}; 12754} 12755 12756sub checkFormatChange($$$) 12757{ 12758 my ($Type1_Id, $Type2_Id, $Level) = @_; 12759 my %Type1_Pure = get_PureType($Type1_Id, 1); 12760 my %Type2_Pure = get_PureType($Type2_Id, 2); 12761 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}) 12762 { # equal types 12763 return 0; 12764 } 12765 if($Type1_Pure{"Name"}=~/\*/ 12766 or $Type2_Pure{"Name"}=~/\*/) 12767 { # compared in detectTypeChange() 12768 return 0; 12769 } 12770 my %FloatType = map {$_=>1} ( 12771 "float", 12772 "double", 12773 "long double" 12774 ); 12775 if($Type1_Pure{"Type"} ne $Type2_Pure{"Type"}) 12776 { # different types 12777 if($Type1_Pure{"Type"} eq "Intrinsic" 12778 and $Type2_Pure{"Type"} eq "Enum") 12779 { # "int" to "enum" 12780 return 0; 12781 } 12782 elsif($Type2_Pure{"Type"} eq "Intrinsic" 12783 and $Type1_Pure{"Type"} eq "Enum") 12784 { # "enum" to "int" 12785 return 0; 12786 } 12787 else 12788 { # "union" to "struct" 12789 # ... 12790 return 1; 12791 } 12792 } 12793 else 12794 { 12795 if($Type1_Pure{"Type"} eq "Intrinsic") 12796 { 12797 if($FloatType{$Type1_Pure{"Name"}} 12798 or $FloatType{$Type2_Pure{"Name"}}) 12799 { # "float" to "double" 12800 # "float" to "int" 12801 if($Level eq "Source") 12802 { # Safe 12803 return 0; 12804 } 12805 else { 12806 return 1; 12807 } 12808 } 12809 } 12810 elsif($Type1_Pure{"Type"}=~/Class|Struct|Union|Enum/) 12811 { 12812 my @Membs1 = keys(%{$Type1_Pure{"Memb"}}); 12813 my @Membs2 = keys(%{$Type2_Pure{"Memb"}}); 12814 if($#Membs1!=$#Membs2) 12815 { # different number of elements 12816 return 1; 12817 } 12818 if($Type1_Pure{"Type"} eq "Enum") 12819 { 12820 foreach my $Pos (@Membs1) 12821 { # compare elements by name and value 12822 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"} 12823 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"}) 12824 { # different names 12825 return 1; 12826 } 12827 } 12828 } 12829 else 12830 { 12831 foreach my $Pos (@Membs1) 12832 { # compare elements by type name 12833 my $MT1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}{"Name"}; 12834 my $MT2 = $TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}{"Name"}; 12835 if($MT1 ne $MT2) 12836 { # different types 12837 return 1; 12838 } 12839 if($Level eq "Source") 12840 { 12841 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}) 12842 { # different names 12843 return 1; 12844 } 12845 } 12846 } 12847 } 12848 } 12849 } 12850 return 0; 12851} 12852 12853sub isScalar($) { 12854 return ($_[0]=~/\A(unsigned |)(short|int|long|long long)\Z/); 12855} 12856 12857sub isFloat($) { 12858 return ($_[0]=~/\A(float|double|long double)\Z/); 12859} 12860 12861sub detectTypeChange($$$$) 12862{ 12863 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_; 12864 if(not $Type1_Id or not $Type2_Id) { 12865 return (); 12866 } 12867 my %LocalProblems = (); 12868 my %Type1 = get_Type($Type1_Id, 1); 12869 my %Type2 = get_Type($Type2_Id, 2); 12870 my %Type1_Pure = get_PureType($Type1_Id, 1); 12871 my %Type2_Pure = get_PureType($Type2_Id, 2); 12872 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, 1):get_BaseType($Type1_Id, 1); 12873 my %Type2_Base = ($Type2_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type2_Pure{"Tid"}, 2):get_BaseType($Type2_Id, 2); 12874 my $Type1_PLevel = get_PLevel($Type1_Id, 1); 12875 my $Type2_PLevel = get_PLevel($Type2_Id, 2); 12876 return () if(not $Type1{"Name"} or not $Type2{"Name"}); 12877 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"}); 12878 return () if($Type1_PLevel eq "" or $Type2_PLevel eq ""); 12879 if($Type1_Base{"Name"} ne $Type2_Base{"Name"} 12880 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel 12881 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void"))) 12882 { # base type change 12883 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef" 12884 and $Type1{"Name"} eq $Type2{"Name"}) 12885 { # will be reported in mergeTypes() as typedef problem 12886 return (); 12887 } 12888 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/) 12889 { 12890 if($Level eq "Binary" 12891 and $Type1_Base{"Size"} ne $Type2_Base{"Size"} 12892 and $Type1_Base{"Size"} and $Type2_Base{"Size"}) 12893 { 12894 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=( 12895 "Old_Value"=>$Type1_Base{"Name"}, 12896 "New_Value"=>$Type2_Base{"Name"}, 12897 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE, 12898 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE, 12899 "InitialType_Type"=>$Type1_Pure{"Type"}); 12900 } 12901 else 12902 { 12903 if(checkFormatChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level)) 12904 { # format change 12905 %{$LocalProblems{$Prefix."_BaseType_Format"}}=( 12906 "Old_Value"=>$Type1_Base{"Name"}, 12907 "New_Value"=>$Type2_Base{"Name"}, 12908 "InitialType_Type"=>$Type1_Pure{"Type"}); 12909 } 12910 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"})) 12911 { 12912 %{$LocalProblems{$Prefix."_BaseType"}}=( 12913 "Old_Value"=>$Type1_Base{"Name"}, 12914 "New_Value"=>$Type2_Base{"Name"}, 12915 "InitialType_Type"=>$Type1_Pure{"Type"}); 12916 } 12917 } 12918 } 12919 } 12920 elsif($Type1{"Name"} ne $Type2{"Name"}) 12921 { # type change 12922 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/) 12923 { 12924 if($Prefix eq "Return" and $Type1{"Name"} eq "void" 12925 and $Type2_Pure{"Type"}=~/Intrinsic|Enum/) { 12926 # safe change 12927 } 12928 elsif($Level eq "Binary" 12929 and $Prefix eq "Return" 12930 and $Type1_Pure{"Name"} eq "void") 12931 { 12932 %{$LocalProblems{"Return_Type_From_Void"}}=( 12933 "New_Value"=>$Type2{"Name"}, 12934 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE, 12935 "InitialType_Type"=>$Type1_Pure{"Type"}); 12936 } 12937 elsif($Level eq "Binary" 12938 and $Prefix eq "Return" and $Type1_Pure{"Type"}=~/Intrinsic|Enum/ 12939 and $Type2_Pure{"Type"}=~/Struct|Class|Union/) 12940 { # returns into hidden first parameter instead of a register 12941 12942 # System V ABI Intel386 ("Function Calling Sequence") 12943 # A function that returns an integral or pointer value places its result in register %eax. 12944 12945 # A floating-point return value appears on the top of the Intel387 register stack. The 12946 # caller then must remove the value from the Intel387 stack, even if it doesn’t use the 12947 # value. 12948 12949 # If a function returns a structure or union, then the caller provides space for the 12950 # return value and places its address on the stack as argument word zero. In effect, 12951 # this address becomes a ‘‘hidden’’ first argument. 12952 12953 %{$LocalProblems{"Return_Type_From_Register_To_Stack"}}=( 12954 "Old_Value"=>$Type1{"Name"}, 12955 "New_Value"=>$Type2{"Name"}, 12956 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE, 12957 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE, 12958 "InitialType_Type"=>$Type1_Pure{"Type"}); 12959 } 12960 elsif($Prefix eq "Return" 12961 and $Type2_Pure{"Name"} eq "void") 12962 { 12963 %{$LocalProblems{"Return_Type_Became_Void"}}=( 12964 "Old_Value"=>$Type1{"Name"}, 12965 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE, 12966 "InitialType_Type"=>$Type1_Pure{"Type"}); 12967 } 12968 elsif($Level eq "Binary" and $Prefix eq "Return" 12969 and ((isScalar($Type1_Pure{"Name"}) and isFloat($Type2_Pure{"Name"})) 12970 or (isScalar($Type2_Pure{"Name"}) and isFloat($Type1_Pure{"Name"})))) 12971 { # The scalar and floating-point values are passed in different registers 12972 %{$LocalProblems{"Return_Type_And_Register"}}=( 12973 "Old_Value"=>$Type1{"Name"}, 12974 "New_Value"=>$Type2{"Name"}, 12975 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE, 12976 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE, 12977 "InitialType_Type"=>$Type1_Pure{"Type"}); 12978 } 12979 elsif($Level eq "Binary" 12980 and $Prefix eq "Return" and $Type2_Pure{"Type"}=~/Intrinsic|Enum/ 12981 and $Type1_Pure{"Type"}=~/Struct|Class|Union/) 12982 { # returns in a register instead of a hidden first parameter 12983 %{$LocalProblems{"Return_Type_From_Stack_To_Register"}}=( 12984 "Old_Value"=>$Type1{"Name"}, 12985 "New_Value"=>$Type2{"Name"}, 12986 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE, 12987 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE, 12988 "InitialType_Type"=>$Type1_Pure{"Type"}); 12989 } 12990 else 12991 { 12992 if($Level eq "Binary" 12993 and $Type1{"Size"} and $Type2{"Size"} 12994 and $Type1{"Size"} ne $Type2{"Size"}) 12995 { 12996 %{$LocalProblems{$Prefix."_Type_And_Size"}}=( 12997 "Old_Value"=>$Type1{"Name"}, 12998 "New_Value"=>$Type2{"Name"}, 12999 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE, 13000 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE, 13001 "InitialType_Type"=>$Type1_Pure{"Type"}); 13002 } 13003 else 13004 { 13005 if(checkFormatChange($Type1_Id, $Type2_Id, $Level)) 13006 { # format change 13007 %{$LocalProblems{$Prefix."_Type_Format"}}=( 13008 "Old_Value"=>$Type1{"Name"}, 13009 "New_Value"=>$Type2{"Name"}, 13010 "InitialType_Type"=>$Type1_Pure{"Type"}); 13011 } 13012 elsif(tNameLock($Type1_Id, $Type2_Id)) 13013 { # FIXME: correct this condition 13014 %{$LocalProblems{$Prefix."_Type"}}=( 13015 "Old_Value"=>$Type1{"Name"}, 13016 "New_Value"=>$Type2{"Name"}, 13017 "InitialType_Type"=>$Type1_Pure{"Type"}); 13018 } 13019 } 13020 } 13021 } 13022 } 13023 if($Type1_PLevel!=$Type2_PLevel) 13024 { 13025 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..." 13026 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...") 13027 { 13028 if($Level eq "Source") 13029 { 13030 %{$LocalProblems{$Prefix."_PointerLevel"}}=( 13031 "Old_Value"=>$Type1_PLevel, 13032 "New_Value"=>$Type2_PLevel); 13033 } 13034 else 13035 { 13036 if($Type2_PLevel>$Type1_PLevel) { 13037 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=( 13038 "Old_Value"=>$Type1_PLevel, 13039 "New_Value"=>$Type2_PLevel); 13040 } 13041 else { 13042 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=( 13043 "Old_Value"=>$Type1_PLevel, 13044 "New_Value"=>$Type2_PLevel); 13045 } 13046 } 13047 } 13048 } 13049 if($Type1_Pure{"Type"} eq "Array") 13050 { # base_type[N] -> base_type[N] 13051 # base_type: older_structure -> typedef to newer_structure 13052 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level); 13053 foreach my $SubProblemType (keys(%SubProblems)) 13054 { 13055 $SubProblemType=~s/_Type/_BaseType/g; 13056 next if(defined $LocalProblems{$SubProblemType}); 13057 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) { 13058 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr}; 13059 } 13060 } 13061 } 13062 return %LocalProblems; 13063} 13064 13065sub tNameLock($$) 13066{ 13067 my ($Tid1, $Tid2) = @_; 13068 my $Changed = 0; 13069 if(differentDumps("G")) 13070 { # different GCC versions 13071 $Changed = 1; 13072 } 13073 elsif(differentDumps("V")) 13074 { # different versions of ABI dumps 13075 if(not checkDump(1, "2.13") 13076 or not checkDump(2, "2.13")) 13077 { # latest names update 13078 # 2.6: added restrict qualifier 13079 # 2.13: added missed typedefs to qualified types 13080 $Changed = 1; 13081 } 13082 } 13083 if($Changed) 13084 { # different formats 13085 if($UseOldDumps) 13086 { # old dumps 13087 return 0; 13088 } 13089 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"}; 13090 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"}; 13091 13092 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"}; 13093 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"}; 13094 13095 my %Base1 = get_Type($Tid1, 1); 13096 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") { 13097 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, 1); 13098 } 13099 my %Base2 = get_Type($Tid2, 2); 13100 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") { 13101 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, 2); 13102 } 13103 my $BName1 = uncover_typedefs($Base1{"Name"}, 1); 13104 my $BName2 = uncover_typedefs($Base2{"Name"}, 2); 13105 if($BName1 eq $BName2) 13106 { # equal base types 13107 return 0; 13108 } 13109 13110 if(not checkDump(1, "2.13") 13111 or not checkDump(2, "2.13")) 13112 { # broken array names in ABI dumps < 2.13 13113 if($TT1 eq "Array" 13114 and $TT2 eq "Array") 13115 { 13116 return 0; 13117 } 13118 } 13119 13120 if(not checkDump(1, "2.6") 13121 or not checkDump(2, "2.6")) 13122 { # added restrict attribute in 2.6 13123 if($TN1!~/\brestrict\b/ 13124 and $TN2=~/\brestrict\b/) 13125 { 13126 return 0; 13127 } 13128 } 13129 } 13130 return 1; 13131} 13132 13133sub differentDumps($) 13134{ 13135 my $Check = $_[0]; 13136 if(defined $Cache{"differentDumps"}{$Check}) { 13137 return $Cache{"differentDumps"}{$Check}; 13138 } 13139 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"}) 13140 { 13141 if($Check eq "G") 13142 { 13143 if(getGccVersion(1) ne getGccVersion(2)) 13144 { # different GCC versions 13145 return ($Cache{"differentDumps"}{$Check}=1); 13146 } 13147 } 13148 if($Check eq "V") 13149 { 13150 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2), 13151 formatVersion($UsedDump{2}{"V"}, 2))!=0) 13152 { # different dump versions (skip micro version) 13153 return ($Cache{"differentDumps"}{$Check}=1); 13154 } 13155 } 13156 } 13157 return ($Cache{"differentDumps"}{$Check}=0); 13158} 13159 13160sub formatVersion($$) 13161{ # cut off version digits 13162 my ($V, $Digits) = @_; 13163 my @Elems = split(/\./, $V); 13164 return join(".", splice(@Elems, 0, $Digits)); 13165} 13166 13167sub htmlSpecChars($) 13168{ 13169 my $Str = $_[0]; 13170 if(not $Str) { 13171 return $Str; 13172 } 13173 $Str=~s/\&([^#]|\Z)/&$1/g; 13174 $Str=~s/</</g; 13175 $Str=~s/\-\>/->/g; # − 13176 $Str=~s/>/>/g; 13177 $Str=~s/([^ ])( )([^ ])/$1\@ALONE_SP\@$3/g; 13178 $Str=~s/ / /g; # 13179 $Str=~s/\@ALONE_SP\@/ /g; 13180 $Str=~s/\n/<br\/>/g; 13181 $Str=~s/\"/"/g; 13182 $Str=~s/\'/'/g; 13183 return $Str; 13184} 13185 13186sub xmlSpecChars($) 13187{ 13188 my $Str = $_[0]; 13189 if(not $Str) { 13190 return $Str; 13191 } 13192 13193 $Str=~s/\&([^#]|\Z)/&$1/g; 13194 $Str=~s/</</g; 13195 $Str=~s/>/>/g; 13196 13197 $Str=~s/\"/"/g; 13198 $Str=~s/\'/'/g; 13199 13200 return $Str; 13201} 13202 13203sub black_name($) 13204{ 13205 my $Name = $_[0]; 13206 return "<span class='iname_b'>".highLight_Signature($Name)."</span>"; 13207} 13208 13209sub highLight_Signature($) 13210{ 13211 my $Signature = $_[0]; 13212 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0); 13213} 13214 13215sub highLight_Signature_Italic_Color($) 13216{ 13217 my $Signature = $_[0]; 13218 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1); 13219} 13220 13221sub separate_symbol($) 13222{ 13223 my $Symbol = $_[0]; 13224 my ($Name, $Spec, $Ver) = ($Symbol, "", ""); 13225 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) { 13226 ($Name, $Spec, $Ver) = ($1, $2, $3); 13227 } 13228 return ($Name, $Spec, $Ver); 13229} 13230 13231sub cut_f_attrs($) 13232{ 13233 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) { 13234 return $2; 13235 } 13236 return ""; 13237} 13238 13239sub highLight_Signature_PPos_Italic($$$$$) 13240{ 13241 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_; 13242 $Param_Pos = "" if(not defined $Param_Pos); 13243 if($CheckObjectsOnly) { 13244 $ItalicParams=$ColorParams=0; 13245 } 13246 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature); 13247 my $Return = ""; 13248 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) { 13249 $Return = $2; 13250 } 13251 my $SCenter = find_center($Signature, "("); 13252 if(not $SCenter) 13253 { # global data 13254 $Signature = htmlSpecChars($Signature); 13255 $Signature=~s!(\[data\])!<span style='color:Black;font-weight:normal;'>$1</span>!g; 13256 $Signature .= (($SymbolVersion)?"<span class='sym_ver'> $VersionSpec $SymbolVersion</span>":""); 13257 if($Return and $ShowReturn) { 13258 $Signature .= "<span class='sym_p nowrap'>  <b>:</b>  ".htmlSpecChars($Return)."</span>"; 13259 } 13260 return $Signature; 13261 } 13262 my ($Begin, $End) = (substr($Signature, 0, $SCenter), ""); 13263 $Begin.=" " if($Begin!~/ \Z/); 13264 $End = cut_f_attrs($Signature); 13265 my @Parts = (); 13266 my @SParts = get_s_params($Signature, 1); 13267 foreach my $Pos (0 .. $#SParts) 13268 { 13269 my $Part = $SParts[$Pos]; 13270 $Part=~s/\A\s+|\s+\Z//g; 13271 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), ""); 13272 if($Part=~/\([\*]+(\w+)\)/i) { 13273 $ParamName = $1;#func-ptr 13274 } 13275 elsif($Part=~/(\w+)[\,\)]*\Z/i) { 13276 $ParamName = $1; 13277 } 13278 if(not $ParamName) { 13279 push(@Parts, $Part_Styled); 13280 next; 13281 } 13282 if($ItalicParams and not $TName_Tid{1}{$Part} 13283 and not $TName_Tid{2}{$Part}) 13284 { 13285 my $Style = "param"; 13286 if($Param_Pos ne "" 13287 and $Pos==$Param_Pos) { 13288 $Style = "focus_p"; 13289 } 13290 elsif($ColorParams) { 13291 $Style = "color_p"; 13292 } 13293 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig; 13294 } 13295 $Part_Styled=~s/,(\w)/, $1/g; 13296 push(@Parts, $Part_Styled); 13297 } 13298 if(@Parts) 13299 { 13300 foreach my $Num (0 .. $#Parts) 13301 { 13302 if($Num==$#Parts) 13303 { # add ")" to the last parameter 13304 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>"; 13305 } 13306 elsif(length($Parts[$Num])<=45) { 13307 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>"; 13308 } 13309 } 13310 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>( ".join(" ", @Parts)."</span>".$End; 13311 } 13312 else { 13313 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>( )</span>".$End; 13314 } 13315 if($Return and $ShowReturn) { 13316 $Signature .= "<span class='sym_p nowrap'>  <b>:</b>  ".htmlSpecChars($Return)."</span>"; 13317 } 13318 $Signature=~s!\[\]![ ]!g; 13319 $Signature=~s!operator=!operator =!g; 13320 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='sym_kind'>$1</span>!g; 13321 return $Signature.(($SymbolVersion)?"<span class='sym_ver'> $VersionSpec $SymbolVersion</span>":""); 13322} 13323 13324sub get_s_params($$) 13325{ 13326 my ($Signature, $Comma) = @_; 13327 my @Parts = (); 13328 my $ShortName = substr($Signature, 0, find_center($Signature, "(")); 13329 $Signature=~s/\A\Q$ShortName\E\(//g; 13330 cut_f_attrs($Signature); 13331 $Signature=~s/\)\Z//; 13332 return separate_params($Signature, $Comma); 13333} 13334 13335sub separate_params($$) 13336{ 13337 my ($Params, $Comma) = @_; 13338 my @Parts = (); 13339 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 ); 13340 my $Part = 0; 13341 foreach my $Pos (0 .. length($Params) - 1) 13342 { 13343 my $S = substr($Params, $Pos, 1); 13344 if(defined $B{$S}) { 13345 $B{$S}+=1; 13346 } 13347 if($S eq "," and 13348 $B{"("}==$B{")"} and $B{"<"}==$B{">"}) 13349 { 13350 if($Comma) 13351 { # include comma 13352 $Parts[$Part] .= $S; 13353 } 13354 $Part += 1; 13355 } 13356 else { 13357 $Parts[$Part] .= $S; 13358 } 13359 } 13360 return @Parts; 13361} 13362 13363sub find_center($$) 13364{ 13365 my ($Sign, $Target) = @_; 13366 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 ); 13367 my $Center = 0; 13368 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g) 13369 { # operators 13370 $Center+=length($1); 13371 } 13372 foreach my $Pos (0 .. length($Sign)-1) 13373 { 13374 my $S = substr($Sign, $Pos, 1); 13375 if($S eq $Target) 13376 { 13377 if($B{"("}==$B{")"} 13378 and $B{"<"}==$B{">"}) { 13379 return $Center; 13380 } 13381 } 13382 if(defined $B{$S}) { 13383 $B{$S}+=1; 13384 } 13385 $Center+=1; 13386 } 13387 return 0; 13388} 13389 13390sub appendFile($$) 13391{ 13392 my ($Path, $Content) = @_; 13393 return if(not $Path); 13394 if(my $Dir = get_dirname($Path)) { 13395 mkpath($Dir); 13396 } 13397 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n"); 13398 print FILE $Content; 13399 close(FILE); 13400} 13401 13402sub writeFile($$) 13403{ 13404 my ($Path, $Content) = @_; 13405 return if(not $Path); 13406 if(my $Dir = get_dirname($Path)) { 13407 mkpath($Dir); 13408 } 13409 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n"); 13410 print FILE $Content; 13411 close(FILE); 13412} 13413 13414sub readFile($) 13415{ 13416 my $Path = $_[0]; 13417 return "" if(not $Path or not -f $Path); 13418 open(FILE, $Path); 13419 local $/ = undef; 13420 my $Content = <FILE>; 13421 close(FILE); 13422 if($Path!~/\.(tu|class|abi)\Z/) { 13423 $Content=~s/\r/\n/g; 13424 } 13425 return $Content; 13426} 13427 13428sub get_filename($) 13429{ # much faster than basename() from File::Basename module 13430 if(defined $Cache{"get_filename"}{$_[0]}) { 13431 return $Cache{"get_filename"}{$_[0]}; 13432 } 13433 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) { 13434 return ($Cache{"get_filename"}{$_[0]}=$1); 13435 } 13436 return ($Cache{"get_filename"}{$_[0]}=""); 13437} 13438 13439sub get_dirname($) 13440{ # much faster than dirname() from File::Basename module 13441 if(defined $Cache{"get_dirname"}{$_[0]}) { 13442 return $Cache{"get_dirname"}{$_[0]}; 13443 } 13444 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) { 13445 return ($Cache{"get_dirname"}{$_[0]}=$1); 13446 } 13447 return ($Cache{"get_dirname"}{$_[0]}=""); 13448} 13449 13450sub separate_path($) { 13451 return (get_dirname($_[0]), get_filename($_[0])); 13452} 13453 13454sub esc($) 13455{ 13456 my $Str = $_[0]; 13457 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g; 13458 return $Str; 13459} 13460 13461sub readLineNum($$) 13462{ 13463 my ($Path, $Num) = @_; 13464 return "" if(not $Path or not -f $Path); 13465 open(FILE, $Path); 13466 foreach (1 ... $Num) { 13467 <FILE>; 13468 } 13469 my $Line = <FILE>; 13470 close(FILE); 13471 return $Line; 13472} 13473 13474sub readAttributes($$) 13475{ 13476 my ($Path, $Num) = @_; 13477 return () if(not $Path or not -f $Path); 13478 my %Attributes = (); 13479 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/) 13480 { 13481 foreach my $AttrVal (split(/;/, $1)) 13482 { 13483 if($AttrVal=~/(.+):(.+)/) 13484 { 13485 my ($Name, $Value) = ($1, $2); 13486 $Attributes{$Name} = $Value; 13487 } 13488 } 13489 } 13490 return \%Attributes; 13491} 13492 13493sub is_abs($) { 13494 return ($_[0]=~/\A(\/|\w+:[\/\\])/); 13495} 13496 13497sub get_abs_path($) 13498{ # abs_path() should NOT be called for absolute inputs 13499 # because it can change them 13500 my $Path = $_[0]; 13501 if(not is_abs($Path)) { 13502 $Path = abs_path($Path); 13503 } 13504 return $Path; 13505} 13506 13507sub get_OSgroup() 13508{ 13509 $_ = $Config{"osname"}; 13510 if(/macos|darwin|rhapsody/i) { 13511 return "macos"; 13512 } 13513 elsif(/freebsd|openbsd|netbsd/i) { 13514 return "bsd"; 13515 } 13516 elsif(/haiku|beos/i) { 13517 return "beos"; 13518 } 13519 elsif(/symbian|epoc/i) { 13520 return "symbian"; 13521 } 13522 elsif(/win/i) { 13523 return "windows"; 13524 } 13525 else { 13526 return $_; 13527 } 13528} 13529 13530sub getGccVersion($) 13531{ 13532 my $LibVersion = $_[0]; 13533 if($GCC_VERSION{$LibVersion}) 13534 { # dump version 13535 return $GCC_VERSION{$LibVersion}; 13536 } 13537 elsif($UsedDump{$LibVersion}{"V"}) 13538 { # old-version dumps 13539 return "unknown"; 13540 } 13541 my $GccVersion = get_dumpversion($GCC_PATH); # host version 13542 if(not $GccVersion) { 13543 return "unknown"; 13544 } 13545 return $GccVersion; 13546} 13547 13548sub showArch($) 13549{ 13550 my $Arch = $_[0]; 13551 if($Arch eq "arm" 13552 or $Arch eq "mips") { 13553 return uc($Arch); 13554 } 13555 return $Arch; 13556} 13557 13558sub getArch($) 13559{ 13560 my $LibVersion = $_[0]; 13561 if($CPU_ARCH{$LibVersion}) 13562 { # dump version 13563 return $CPU_ARCH{$LibVersion}; 13564 } 13565 elsif($UsedDump{$LibVersion}{"V"}) 13566 { # old-version dumps 13567 return "unknown"; 13568 } 13569 if(defined $Cache{"getArch"}{$LibVersion}) { 13570 return $Cache{"getArch"}{$LibVersion}; 13571 } 13572 my $Arch = get_dumpmachine($GCC_PATH); # host version 13573 if(not $Arch) { 13574 return "unknown"; 13575 } 13576 if($Arch=~/\A([\w]{3,})(-|\Z)/) { 13577 $Arch = $1; 13578 } 13579 $Arch = "x86" if($Arch=~/\Ai[3-7]86\Z/); 13580 if($OSgroup eq "windows") { 13581 $Arch = "x86" if($Arch=~/win32|mingw32/i); 13582 $Arch = "x86_64" if($Arch=~/win64|mingw64/i); 13583 } 13584 $Cache{"getArch"}{$LibVersion} = $Arch; 13585 return $Arch; 13586} 13587 13588sub get_Report_Header($) 13589{ 13590 my $Level = $_[0]; 13591 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>"; 13592 if(getArch(1) ne getArch(2) 13593 or getArch(1) eq "unknown" 13594 or $Level eq "Source") 13595 { # don't show architecture in the header 13596 $ArchInfo=""; 13597 } 13598 my $Report_Header = "<h1><span class='nowrap'>"; 13599 if($Level eq "Source") { 13600 $Report_Header .= "Source compatibility"; 13601 } 13602 elsif($Level eq "Binary") { 13603 $Report_Header .= "Binary compatibility"; 13604 } 13605 else { 13606 $Report_Header .= "API compatibility"; 13607 } 13608 $Report_Header .= " report for the <span style='color:Blue;'>$TargetLibraryFName</span> $TargetComponent</span>"; 13609 $Report_Header .= " <span class='nowrap'> between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions$ArchInfo</span>"; 13610 if($AppPath) { 13611 $Report_Header .= " <span class='nowrap'> (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)</span>"; 13612 } 13613 $Report_Header .= "</h1>\n"; 13614 return $Report_Header; 13615} 13616 13617sub get_SourceInfo() 13618{ 13619 my ($CheckedHeaders, $CheckedLibs) = ("", ""); 13620 if(not $CheckObjectsOnly) 13621 { 13622 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".keys(%{$Registered_Headers{1}}).")</h2><hr/>\n"; 13623 $CheckedHeaders .= "<div class='h_list'>\n"; 13624 foreach my $Header_Path (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} keys(%{$Registered_Headers{1}})) 13625 { 13626 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"}; 13627 my $Header_Name = get_filename($Identity); 13628 my $Dest_Comment = ($Identity=~/[\/\\]/)?" ($Identity)":""; 13629 $CheckedHeaders .= $Header_Name.$Dest_Comment."<br/>\n"; 13630 } 13631 $CheckedHeaders .= "</div>\n"; 13632 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n"; 13633 } 13634 if(not $CheckHeadersOnly) 13635 { 13636 $CheckedLibs = "<a name='Libs'></a><h2>".ucfirst($SLIB_TYPE)." Libraries (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n"; 13637 $CheckedLibs .= "<div class='lib_list'>\n"; 13638 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}})) 13639 { 13640 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/); 13641 $CheckedLibs .= $Library."<br/>\n"; 13642 } 13643 $CheckedLibs .= "</div>\n"; 13644 $CheckedLibs .= "<br/>$TOP_REF<br/>\n"; 13645 } 13646 return $CheckedHeaders.$CheckedLibs; 13647} 13648 13649sub get_TypeProblems_Count($$$) 13650{ 13651 my ($TypeChanges, $TargetPriority, $Level) = @_; 13652 my $Type_Problems_Count = 0; 13653 foreach my $Type_Name (sort keys(%{$TypeChanges})) 13654 { 13655 my %Kinds_Target = (); 13656 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}})) 13657 { 13658 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}})) 13659 { 13660 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"}; 13661 my $Priority = getProblemSeverity($Level, $Kind); 13662 next if($Priority ne $TargetPriority); 13663 if($Kinds_Target{$Kind}{$Target}) { 13664 next; 13665 } 13666 if(cmpSeverities($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority)) 13667 { # select a problem with the highest priority 13668 next; 13669 } 13670 $Kinds_Target{$Kind}{$Target} = 1; 13671 $Type_Problems_Count += 1; 13672 } 13673 } 13674 } 13675 return $Type_Problems_Count; 13676} 13677 13678sub get_Summary($) 13679{ 13680 my $Level = $_[0]; 13681 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High, 13682 $C_Problems_Low, $T_Problems_Medium, $T_Problems_Low, $I_Other, $T_Other) = (0,0,0,0,0,0,0,0,0,0,0); 13683 %{$RESULT{$Level}} = ( 13684 "Problems"=>0, 13685 "Warnings"=>0, 13686 "Affected"=>0 ); 13687 # check rules 13688 foreach my $Interface (sort keys(%{$CompatProblems{$Level}})) 13689 { 13690 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}})) 13691 { 13692 if(not defined $CompatRules{$Level}{$Kind}) 13693 { # unknown rule 13694 if(not $UnknownRules{$Level}{$Kind}) 13695 { # only one warning 13696 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")"); 13697 $UnknownRules{$Level}{$Kind}=1; 13698 } 13699 delete($CompatProblems{$Level}{$Interface}{$Kind}); 13700 } 13701 } 13702 } 13703 foreach my $Interface (sort keys(%{$CompatProblems{$Level}})) 13704 { 13705 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}})) 13706 { 13707 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols") 13708 { 13709 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}})) 13710 { 13711 my $Priority = getProblemSeverity($Level, $Kind); 13712 if($Kind eq "Added_Symbol") { 13713 $Added += 1; 13714 } 13715 elsif($Kind eq "Removed_Symbol") 13716 { 13717 $Removed += 1; 13718 $TotalAffected{$Level}{$Interface} = $Priority; 13719 } 13720 else 13721 { 13722 if($Priority eq "Safe") { 13723 $I_Other += 1; 13724 } 13725 elsif($Priority eq "High") { 13726 $I_Problems_High += 1; 13727 } 13728 elsif($Priority eq "Medium") { 13729 $I_Problems_Medium += 1; 13730 } 13731 elsif($Priority eq "Low") { 13732 $I_Problems_Low += 1; 13733 } 13734 if(($Priority ne "Low" or $StrictCompat) 13735 and $Priority ne "Safe") { 13736 $TotalAffected{$Level}{$Interface} = $Priority; 13737 } 13738 } 13739 } 13740 } 13741 } 13742 } 13743 my %TypeChanges = (); 13744 foreach my $Interface (sort keys(%{$CompatProblems{$Level}})) 13745 { 13746 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}})) 13747 { 13748 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types") 13749 { 13750 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}})) 13751 { 13752 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"}; 13753 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"}; 13754 my $Priority = getProblemSeverity($Level, $Kind); 13755 if(cmpSeverities($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority)) 13756 { # select a problem with the highest priority 13757 next; 13758 } 13759 if(($Priority ne "Low" or $StrictCompat) 13760 and $Priority ne "Safe") { 13761 $TotalAffected{$Level}{$Interface} = maxSeverity($TotalAffected{$Level}{$Interface}, $Priority); 13762 } 13763 %{$TypeChanges{$Type_Name}{$Kind}{$Location}} = %{$CompatProblems{$Level}{$Interface}{$Kind}{$Location}}; 13764 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = maxSeverity($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority); 13765 } 13766 } 13767 } 13768 } 13769 13770 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level); 13771 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level); 13772 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level); 13773 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level); 13774 13775 if($CheckObjectsOnly) 13776 { # only removed exported symbols 13777 $RESULT{$Level}{"Affected"} = $Removed*100/keys(%{$Symbol_Library{1}}); 13778 } 13779 else 13780 { # changed and removed public symbols 13781 my $SCount = keys(%{$CheckedSymbols{$Level}}); 13782 if($ExtendedCheck) 13783 { # don't count external_func_0 for constants 13784 $SCount-=1; 13785 } 13786 if($SCount) 13787 { 13788 my %Weight = ( 13789 "High" => 100, 13790 "Medium" => 50, 13791 "Low" => 25 13792 ); 13793 foreach (keys(%{$TotalAffected{$Level}})) { 13794 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}}; 13795 } 13796 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount; 13797 } 13798 else { 13799 $RESULT{$Level}{"Affected"} = 0; 13800 } 13801 } 13802 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"}); 13803 if($RESULT{$Level}{"Affected"}>=100) { 13804 $RESULT{$Level}{"Affected"} = 100; 13805 } 13806 13807 $RESULT{$Level}{"Problems"} += $Removed; 13808 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High; 13809 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium; 13810 if($StrictCompat) { 13811 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low; 13812 } 13813 else { 13814 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low; 13815 } 13816 13817 if($C_Problems_Low = keys(%{$ProblemsWithConstants{$Level}})) 13818 { 13819 if(defined $CompatRules{$Level}{"Changed_Constant"}) 13820 { 13821 if($StrictCompat) { 13822 $RESULT{$Level}{"Problems"} += $C_Problems_Low; 13823 } 13824 else { 13825 $RESULT{$Level}{"Warnings"} += $C_Problems_Low; 13826 } 13827 } 13828 else 13829 { 13830 printMsg("WARNING", "unknown rule \"Changed_Constant\" (\"$Level\")"); 13831 $C_Problems_Low = 0; 13832 } 13833 } 13834 if($CheckImpl and $Level eq "Binary") 13835 { 13836 if($StrictCompat) { 13837 $RESULT{$Level}{"Problems"} += keys(%ImplProblems); 13838 } 13839 else { 13840 $RESULT{$Level}{"Warnings"} += keys(%ImplProblems); 13841 } 13842 } 13843 if($RESULT{$Level}{"Problems"} 13844 and $RESULT{$Level}{"Affected"}) { 13845 $RESULT{$Level}{"Verdict"} = "incompatible"; 13846 } 13847 else { 13848 $RESULT{$Level}{"Verdict"} = "compatible"; 13849 } 13850 13851 my $TotalTypes = keys(%{$CheckedTypes{$Level}}); 13852 if(not $TotalTypes) 13853 { # list all the types 13854 $TotalTypes = keys(%{$TName_Tid{1}}); 13855 } 13856 13857 my ($Arch1, $Arch2) = (getArch(1), getArch(2)); 13858 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2)); 13859 13860 my ($TestInfo, $TestResults, $Problem_Summary) = (); 13861 13862 if($ReportFormat eq "xml") 13863 { # XML 13864 # test info 13865 $TestInfo .= " <library>$TargetLibraryName</library>\n"; 13866 $TestInfo .= " <version1>\n"; 13867 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n"; 13868 $TestInfo .= " <architecture>$Arch1</architecture>\n"; 13869 $TestInfo .= " <gcc>$GccV1</gcc>\n"; 13870 $TestInfo .= " </version1>\n"; 13871 13872 $TestInfo .= " <version2>\n"; 13873 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n"; 13874 $TestInfo .= " <architecture>$Arch2</architecture>\n"; 13875 $TestInfo .= " <gcc>$GccV2</gcc>\n"; 13876 $TestInfo .= " </version2>\n"; 13877 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n"; 13878 13879 # test results 13880 $TestResults .= " <headers>\n"; 13881 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} keys(%{$Registered_Headers{1}})) 13882 { 13883 my $Identity = $Registered_Headers{1}{$Name}{"Identity"}; 13884 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":""; 13885 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n"; 13886 } 13887 $TestResults .= " </headers>\n"; 13888 13889 $TestResults .= " <libs>\n"; 13890 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}})) 13891 { 13892 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/); 13893 $TestResults .= " <name>$Library</name>\n"; 13894 } 13895 $TestResults .= " </libs>\n"; 13896 13897 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n"; 13898 $TestResults .= " <types>".$TotalTypes."</types>\n"; 13899 13900 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n"; 13901 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n"; 13902 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n"; 13903 13904 # problem summary 13905 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n"; 13906 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n"; 13907 13908 $Problem_Summary .= " <problems_with_types>\n"; 13909 $Problem_Summary .= " <high>$T_Problems_High</high>\n"; 13910 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n"; 13911 $Problem_Summary .= " <low>$T_Problems_Low</low>\n"; 13912 $Problem_Summary .= " <safe>$T_Other</safe>\n"; 13913 $Problem_Summary .= " </problems_with_types>\n"; 13914 13915 $Problem_Summary .= " <problems_with_symbols>\n"; 13916 $Problem_Summary .= " <high>$I_Problems_High</high>\n"; 13917 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n"; 13918 $Problem_Summary .= " <low>$I_Problems_Low</low>\n"; 13919 $Problem_Summary .= " <safe>$I_Other</safe>\n"; 13920 $Problem_Summary .= " </problems_with_symbols>\n"; 13921 13922 $Problem_Summary .= " <problems_with_constants>\n"; 13923 $Problem_Summary .= " <low>$C_Problems_Low</low>\n"; 13924 $Problem_Summary .= " </problems_with_constants>\n"; 13925 if($CheckImpl and $Level eq "Binary") 13926 { 13927 $Problem_Summary .= " <impl>\n"; 13928 $Problem_Summary .= " <low>".keys(%ImplProblems)."</low>\n"; 13929 $Problem_Summary .= " </impl>\n"; 13930 } 13931 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n"; 13932 13933 return ($TestInfo.$TestResults.$Problem_Summary, ""); 13934 } 13935 else 13936 { # HTML 13937 # test info 13938 $TestInfo = "<h2>Test Info</h2><hr/>\n"; 13939 $TestInfo .= "<table class='summary'>\n"; 13940 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetLibraryFName</td></tr>\n"; 13941 13942 my (@VInf1, @VInf2, $AddTestInfo) = (); 13943 if($Arch1 ne "unknown" 13944 and $Arch2 ne "unknown") 13945 { # CPU arch 13946 if($Arch1 eq $Arch2) 13947 { # go to the separate section 13948 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n"; 13949 } 13950 else 13951 { # go to the version number 13952 push(@VInf1, showArch($Arch1)); 13953 push(@VInf2, showArch($Arch2)); 13954 } 13955 } 13956 if($GccV1 ne "unknown" 13957 and $GccV2 ne "unknown" 13958 and $OStarget ne "windows") 13959 { # GCC version 13960 if($GccV1 eq $GccV2) 13961 { # go to the separate section 13962 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n"; 13963 } 13964 else 13965 { # go to the version number 13966 push(@VInf1, "gcc ".$GccV1); 13967 push(@VInf2, "gcc ".$GccV2); 13968 } 13969 } 13970 # show long version names with GCC version and CPU architecture name (if different) 13971 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n"; 13972 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n"; 13973 $TestInfo .= $AddTestInfo; 13974 #if($COMMON_LANGUAGE{1}) { 13975 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n"; 13976 #} 13977 if($ExtendedCheck) { 13978 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n"; 13979 } 13980 if($JoinReport) 13981 { 13982 if($Level eq "Binary") { 13983 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time 13984 } 13985 if($Level eq "Source") { 13986 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time 13987 } 13988 } 13989 $TestInfo .= "</table>\n"; 13990 13991 # test results 13992 $TestResults = "<h2>Test Results</h2><hr/>\n"; 13993 $TestResults .= "<table class='summary'>"; 13994 13995 my $Headers_Link = "0"; 13996 $Headers_Link = "<a href='#Headers' style='color:Blue;'>".keys(%{$Registered_Headers{1}})."</a>" if(keys(%{$Registered_Headers{1}})>0); 13997 $TestResults .= "<tr><th>Total Header Files</th><td>".($CheckObjectsOnly?"0 (not analyzed)":$Headers_Link)."</td></tr>\n"; 13998 13999 if(not $ExtendedCheck) 14000 { 14001 my $Libs_Link = "0"; 14002 $Libs_Link = "<a href='#Libs' style='color:Blue;'>".keys(%{$Library_Symbol{1}})."</a>" if(keys(%{$Library_Symbol{1}})>0); 14003 $TestResults .= "<tr><th>Total ".ucfirst($SLIB_TYPE)." Libraries</th><td>".($CheckHeadersOnly?"0 (not analyzed)":$Libs_Link)."</td></tr>\n"; 14004 } 14005 14006 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n"; 14007 14008 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";"; 14009 if($JoinReport) { 14010 $META_DATA = "kind:".lc($Level).";".$META_DATA; 14011 } 14012 $TestResults .= "<tr><th>Verdict</th>"; 14013 if($RESULT{$Level}{"Verdict"} eq "incompatible") { 14014 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>"; 14015 } 14016 else { 14017 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>"; 14018 } 14019 $TestResults .= "</tr>\n"; 14020 $TestResults .= "</table>\n"; 14021 14022 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents 14023 # problem summary 14024 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n"; 14025 $Problem_Summary .= "<table class='summary'>"; 14026 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>"; 14027 14028 my $Added_Link = "0"; 14029 if($Added>0) 14030 { 14031 if($JoinReport) { 14032 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>"; 14033 } 14034 else { 14035 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>"; 14036 } 14037 } 14038 $META_DATA .= "added:$Added;"; 14039 $Problem_Summary .= "<tr><th>Added Symbols</th><td>-</td><td".getStyle("I", "A", $Added).">$Added_Link</td></tr>\n"; 14040 14041 my $Removed_Link = "0"; 14042 if($Removed>0) 14043 { 14044 if($JoinReport) { 14045 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>" 14046 } 14047 else { 14048 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>" 14049 } 14050 } 14051 $META_DATA .= "removed:$Removed;"; 14052 $Problem_Summary .= "<tr><th>Removed Symbols</th>"; 14053 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n"; 14054 14055 my $TH_Link = "0"; 14056 $TH_Link = "<a href='#".get_Anchor("Type", $Level, "High")."' style='color:Blue;'>$T_Problems_High</a>" if($T_Problems_High>0); 14057 $TH_Link = "n/a" if($CheckObjectsOnly); 14058 $META_DATA .= "type_problems_high:$T_Problems_High;"; 14059 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>"; 14060 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n"; 14061 14062 my $TM_Link = "0"; 14063 $TM_Link = "<a href='#".get_Anchor("Type", $Level, "Medium")."' style='color:Blue;'>$T_Problems_Medium</a>" if($T_Problems_Medium>0); 14064 $TM_Link = "n/a" if($CheckObjectsOnly); 14065 $META_DATA .= "type_problems_medium:$T_Problems_Medium;"; 14066 $Problem_Summary .= "<tr><td>Medium</td><td".getStyle("T", "M", $T_Problems_Medium).">$TM_Link</td></tr>\n"; 14067 14068 my $TL_Link = "0"; 14069 $TL_Link = "<a href='#".get_Anchor("Type", $Level, "Low")."' style='color:Blue;'>$T_Problems_Low</a>" if($T_Problems_Low>0); 14070 $TL_Link = "n/a" if($CheckObjectsOnly); 14071 $META_DATA .= "type_problems_low:$T_Problems_Low;"; 14072 $Problem_Summary .= "<tr><td>Low</td><td".getStyle("T", "L", $T_Problems_Low).">$TL_Link</td></tr>\n"; 14073 14074 my $IH_Link = "0"; 14075 $IH_Link = "<a href='#".get_Anchor("Symbol", $Level, "High")."' style='color:Blue;'>$I_Problems_High</a>" if($I_Problems_High>0); 14076 $IH_Link = "n/a" if($CheckObjectsOnly); 14077 $META_DATA .= "interface_problems_high:$I_Problems_High;"; 14078 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>"; 14079 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n"; 14080 14081 my $IM_Link = "0"; 14082 $IM_Link = "<a href='#".get_Anchor("Symbol", $Level, "Medium")."' style='color:Blue;'>$I_Problems_Medium</a>" if($I_Problems_Medium>0); 14083 $IM_Link = "n/a" if($CheckObjectsOnly); 14084 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;"; 14085 $Problem_Summary .= "<tr><td>Medium</td><td".getStyle("I", "M", $I_Problems_Medium).">$IM_Link</td></tr>\n"; 14086 14087 my $IL_Link = "0"; 14088 $IL_Link = "<a href='#".get_Anchor("Symbol", $Level, "Low")."' style='color:Blue;'>$I_Problems_Low</a>" if($I_Problems_Low>0); 14089 $IL_Link = "n/a" if($CheckObjectsOnly); 14090 $META_DATA .= "interface_problems_low:$I_Problems_Low;"; 14091 $Problem_Summary .= "<tr><td>Low</td><td".getStyle("I", "L", $I_Problems_Low).">$IL_Link</td></tr>\n"; 14092 14093 my $ChangedConstants_Link = "0"; 14094 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) 14095 { 14096 if($JoinReport) { 14097 $ChangedConstants_Link = "<a href='#".$Level."_Changed_Constants' style='color:Blue;'>$C_Problems_Low</a>"; 14098 } 14099 else { 14100 $ChangedConstants_Link = "<a href='#Changed_Constants' style='color:Blue;'>$C_Problems_Low</a>"; 14101 } 14102 } 14103 $ChangedConstants_Link = "n/a" if($CheckObjectsOnly); 14104 $META_DATA .= "changed_constants:$C_Problems_Low;"; 14105 $Problem_Summary .= "<tr><th>Problems with<br/>Constants</th><td>Low</td><td".getStyle("C", "L", $C_Problems_Low).">$ChangedConstants_Link</td></tr>\n"; 14106 14107 if($CheckImpl and $Level eq "Binary") 14108 { 14109 my $ChangedImpl_Link = "0"; 14110 $ChangedImpl_Link = "<a href='#Changed_Implementation' style='color:Blue;'>".keys(%ImplProblems)."</a>" if(keys(%ImplProblems)>0); 14111 $ChangedImpl_Link = "n/a" if($CheckHeadersOnly); 14112 $META_DATA .= "changed_implementation:".keys(%ImplProblems).";"; 14113 $Problem_Summary .= "<tr><th>Problems with<br/>Implementation</th><td>Low</td><td".getStyle("Imp", "L", int(keys(%ImplProblems))).">$ChangedImpl_Link</td></tr>\n"; 14114 } 14115 # Safe Changes 14116 if($T_Other and not $CheckObjectsOnly) 14117 { 14118 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>"; 14119 $Problem_Summary .= "<tr><th>Other Changes<br/>in Data Types</th><td>-</td><td".getStyle("T", "S", $T_Other).">$TS_Link</td></tr>\n"; 14120 } 14121 14122 if($I_Other and not $CheckObjectsOnly) 14123 { 14124 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>"; 14125 $Problem_Summary .= "<tr><th>Other Changes<br/>in Symbols</th><td>-</td><td".getStyle("I", "S", $I_Other).">$IS_Link</td></tr>\n"; 14126 } 14127 14128 $META_DATA .= "tool_version:$TOOL_VERSION"; 14129 $Problem_Summary .= "</table>\n"; 14130 # $TestInfo = getLegend().$TestInfo; 14131 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA); 14132 } 14133} 14134 14135sub getStyle($$$) 14136{ 14137 my ($Subj, $Act, $Num) = @_; 14138 my %Style = ( 14139 "A"=>"new", 14140 "R"=>"failed", 14141 "S"=>"passed", 14142 "L"=>"warning", 14143 "M"=>"failed", 14144 "H"=>"failed" 14145 ); 14146 if($Num>0) { 14147 return " class='".$Style{$Act}."'"; 14148 } 14149 return ""; 14150} 14151 14152sub show_number($) 14153{ 14154 if($_[0]) 14155 { 14156 my $Num = cut_off_number($_[0], 2, 0); 14157 if($Num eq "0") 14158 { 14159 foreach my $P (3 .. 7) 14160 { 14161 $Num = cut_off_number($_[0], $P, 1); 14162 if($Num ne "0") { 14163 last; 14164 } 14165 } 14166 } 14167 if($Num eq "0") { 14168 $Num = $_[0]; 14169 } 14170 return $Num; 14171 } 14172 return $_[0]; 14173} 14174 14175sub cut_off_number($$$) 14176{ 14177 my ($num, $digs_to_cut, $z) = @_; 14178 if($num!~/\./) 14179 { 14180 $num .= "."; 14181 foreach (1 .. $digs_to_cut-1) { 14182 $num .= "0"; 14183 } 14184 } 14185 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1) 14186 { 14187 foreach (1 .. $digs_to_cut - 1 - length($1)) { 14188 $num .= "0"; 14189 } 14190 } 14191 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) { 14192 $num=sprintf("%.".($digs_to_cut-1)."f", $num); 14193 } 14194 $num=~s/\.[0]+\Z//g; 14195 if($z) { 14196 $num=~s/(\.[1-9]+)[0]+\Z/$1/g; 14197 } 14198 return $num; 14199} 14200 14201sub get_Report_ChangedConstants($) 14202{ 14203 my $Level = $_[0]; 14204 my $CHANGED_CONSTANTS = ""; 14205 my %ReportMap = (); 14206 foreach my $Constant (keys(%{$ProblemsWithConstants{$Level}})) { 14207 $ReportMap{$Constants{1}{$Constant}{"Header"}}{$Constant} = 1; 14208 } 14209 my $Kind = "Changed_Constant"; 14210 if(not defined $CompatRules{$Level}{$Kind}) { 14211 return ""; 14212 } 14213 if($ReportFormat eq "xml") 14214 { # XML 14215 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap)) 14216 { 14217 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n"; 14218 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}})) 14219 { 14220 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n"; 14221 my $Change = $CompatRules{$Level}{$Kind}{"Change"}; 14222 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"}; 14223 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}; 14224 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n"; 14225 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $ProblemsWithConstants{$Level}{$Constant}).">$Change</change>\n"; 14226 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $ProblemsWithConstants{$Level}{$Constant}).">$Effect</effect>\n"; 14227 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $ProblemsWithConstants{$Level}{$Constant}).">$Overcome</overcome>\n"; 14228 $CHANGED_CONSTANTS .= " </problem>\n"; 14229 $CHANGED_CONSTANTS .= " </constant>\n"; 14230 } 14231 $CHANGED_CONSTANTS .= " </header>\n"; 14232 } 14233 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n"; 14234 } 14235 else 14236 { # HTML 14237 my $Number = 0; 14238 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap)) 14239 { 14240 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n"; 14241 foreach my $Name (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}})) 14242 { 14243 $Number += 1; 14244 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $ProblemsWithConstants{$Level}{$Name}); 14245 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"}; 14246 my $Report = "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n"; 14247 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n"; 14248 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Name.$ContentSpanEnd."<br/>\n".$Report; 14249 $CHANGED_CONSTANTS .= insertIDs($Report); 14250 } 14251 $CHANGED_CONSTANTS .= "<br/>\n"; 14252 } 14253 if($CHANGED_CONSTANTS) 14254 { 14255 my $Anchor = "<a name='Changed_Constants'></a>"; 14256 if($JoinReport) { 14257 $Anchor = "<a name='".$Level."_Changed_Constants'></a>"; 14258 } 14259 $CHANGED_CONSTANTS = $Anchor."<h2>Problems with Constants ($Number)</h2><hr/>\n".$CHANGED_CONSTANTS.$TOP_REF."<br/>\n"; 14260 } 14261 } 14262 return $CHANGED_CONSTANTS; 14263} 14264 14265sub get_Report_Impl() 14266{ 14267 my $CHANGED_IMPLEMENTATION = ""; 14268 my %ReportMap = (); 14269 foreach my $Interface (sort keys(%ImplProblems)) 14270 { 14271 my $HeaderName = $CompleteSignature{1}{$Interface}{"Header"}; 14272 my $DyLib = $Symbol_Library{1}{$Interface}; 14273 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1; 14274 } 14275 my $Changed_Number = 0; 14276 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap)) 14277 { 14278 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}})) 14279 { 14280 my $FDyLib=$DyLib.($DyLib!~/\.\w+\Z/?" (.$LIB_EXT)":""); 14281 if($HeaderName) { 14282 $CHANGED_IMPLEMENTATION .= "<span class='h_name'>$HeaderName</span>, <span class='lib_name'>$FDyLib</span><br/>\n"; 14283 } 14284 else { 14285 $CHANGED_IMPLEMENTATION .= "<span class='lib_name'>$DyLib</span><br/>\n"; 14286 } 14287 my %NameSpaceSymbols = (); 14288 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) { 14289 $NameSpaceSymbols{get_IntNameSpace($Interface, 2)}{$Interface} = 1; 14290 } 14291 foreach my $NameSpace (sort keys(%NameSpaceSymbols)) 14292 { 14293 $CHANGED_IMPLEMENTATION .= ($NameSpace)?"<span class='ns_title'>namespace</span> <span class='ns'>$NameSpace</span><br/>\n":""; 14294 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}}); 14295 foreach my $Interface (@SortedInterfaces) 14296 { 14297 $Changed_Number += 1; 14298 my $Signature = get_Signature($Interface, 1); 14299 if($NameSpace) { 14300 $Signature=~s/\b\Q$NameSpace\E::\b//g; 14301 } 14302 $CHANGED_IMPLEMENTATION .= insertIDs($ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Interface</b>]</span>".$ImplProblems{$Interface}{"Diff"}."<br/><br/>".$ContentDivEnd."\n"); 14303 } 14304 } 14305 $CHANGED_IMPLEMENTATION .= "<br/>\n"; 14306 } 14307 } 14308 if($CHANGED_IMPLEMENTATION) { 14309 $CHANGED_IMPLEMENTATION = "<a name='Changed_Implementation'></a><h2>Problems with Implementation ($Changed_Number)</h2><hr/>\n".$CHANGED_IMPLEMENTATION.$TOP_REF."<br/>\n"; 14310 } 14311 14312 # clean memory 14313 %ImplProblems = (); 14314 14315 return $CHANGED_IMPLEMENTATION; 14316} 14317 14318sub getTitle($$$) 14319{ 14320 my ($Header, $Library, $NameSpace) = @_; 14321 my $Title = ""; 14322 if($Library and $Library!~/\.\w+\Z/) { 14323 $Library .= " (.$LIB_EXT)"; 14324 } 14325 if($Header and $Library) 14326 { 14327 $Title .= "<span class='h_name'>$Header</span>"; 14328 $Title .= ", <span class='lib_name'>$Library</span><br/>\n"; 14329 } 14330 elsif($Library) { 14331 $Title .= "<span class='lib_name'>$Library</span><br/>\n"; 14332 } 14333 elsif($Header) { 14334 $Title .= "<span class='h_name'>$Header</span><br/>\n"; 14335 } 14336 if($NameSpace) { 14337 $Title .= "<span class='ns_title'>namespace</span> <span class='ns'>$NameSpace</span><br/>\n"; 14338 } 14339 return $Title; 14340} 14341 14342sub get_Report_Added($) 14343{ 14344 my $Level = $_[0]; 14345 my $ADDED_INTERFACES = ""; 14346 my %ReportMap = (); 14347 foreach my $Interface (sort keys(%{$CompatProblems{$Level}})) 14348 { 14349 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}})) 14350 { 14351 if($Kind eq "Added_Symbol") 14352 { 14353 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"}; 14354 my $DyLib = $Symbol_Library{2}{$Interface}; 14355 if($Level eq "Source" and $ReportFormat eq "html") 14356 { # do not show library name in HTML report 14357 $DyLib = ""; 14358 } 14359 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1; 14360 } 14361 } 14362 } 14363 if($ReportFormat eq "xml") 14364 { # XML 14365 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap)) 14366 { 14367 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n"; 14368 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}})) 14369 { 14370 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n"; 14371 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) { 14372 $ADDED_INTERFACES .= " <name>$Interface</name>\n"; 14373 } 14374 $ADDED_INTERFACES .= " </library>\n"; 14375 } 14376 $ADDED_INTERFACES .= " </header>\n"; 14377 } 14378 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n"; 14379 } 14380 else 14381 { # HTML 14382 my $Added_Number = 0; 14383 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap)) 14384 { 14385 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}})) 14386 { 14387 my %NameSpaceSymbols = (); 14388 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) { 14389 $NameSpaceSymbols{get_IntNameSpace($Interface, 2)}{$Interface} = 1; 14390 } 14391 foreach my $NameSpace (sort keys(%NameSpaceSymbols)) 14392 { 14393 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace); 14394 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}}); 14395 foreach my $Interface (@SortedInterfaces) 14396 { 14397 $Added_Number += 1; 14398 my $Signature = get_Signature($Interface, 2); 14399 if($NameSpace) { 14400 $Signature=~s/\b\Q$NameSpace\E::\b//g; 14401 } 14402 if($Interface=~/\A(_Z|\?)/) { 14403 if($Signature) { 14404 $ADDED_INTERFACES .= insertIDs($ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Interface</b>]</span><br/><br/>".$ContentDivEnd."\n"); 14405 } 14406 else { 14407 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n"; 14408 } 14409 } 14410 else { 14411 if($Signature) { 14412 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n"; 14413 } 14414 else { 14415 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n"; 14416 } 14417 } 14418 } 14419 $ADDED_INTERFACES .= "<br/>\n"; 14420 } 14421 } 14422 } 14423 if($ADDED_INTERFACES) 14424 { 14425 my $Anchor = "<a name='Added'></a>"; 14426 if($JoinReport) { 14427 $Anchor = "<a name='".$Level."_Added'></a>"; 14428 } 14429 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n"; 14430 } 14431 } 14432 return $ADDED_INTERFACES; 14433} 14434 14435sub get_Report_Removed($) 14436{ 14437 my $Level = $_[0]; 14438 my $REMOVED_INTERFACES = ""; 14439 my %ReportMap = (); 14440 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}})) 14441 { 14442 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}})) 14443 { 14444 if($Kind eq "Removed_Symbol") 14445 { 14446 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"}; 14447 my $DyLib = $Symbol_Library{1}{$Symbol}; 14448 if($Level eq "Source" and $ReportFormat eq "html") 14449 { # do not show library name in HTML report 14450 $DyLib = ""; 14451 } 14452 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1; 14453 } 14454 } 14455 } 14456 if($ReportFormat eq "xml") 14457 { # XML 14458 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap)) 14459 { 14460 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n"; 14461 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}})) 14462 { 14463 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n"; 14464 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) { 14465 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n"; 14466 } 14467 $REMOVED_INTERFACES .= " </library>\n"; 14468 } 14469 $REMOVED_INTERFACES .= " </header>\n"; 14470 } 14471 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n"; 14472 } 14473 else 14474 { # HTML 14475 my $Removed_Number = 0; 14476 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap)) 14477 { 14478 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}})) 14479 { 14480 my %NameSpaceSymbols = (); 14481 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) { 14482 $NameSpaceSymbols{get_IntNameSpace($Interface, 1)}{$Interface} = 1; 14483 } 14484 foreach my $NameSpace (sort keys(%NameSpaceSymbols)) 14485 { 14486 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace); 14487 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}}); 14488 foreach my $Symbol (@SortedInterfaces) 14489 { 14490 $Removed_Number += 1; 14491 my $SubReport = ""; 14492 my $Signature = get_Signature($Symbol, 1); 14493 if($NameSpace) { 14494 $Signature=~s/\b\Q$NameSpace\E::\b//g; 14495 } 14496 if($Symbol=~/\A(_Z|\?)/) 14497 { 14498 if($Signature) { 14499 $REMOVED_INTERFACES .= insertIDs($ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Symbol</b>]</span><br/><br/>".$ContentDivEnd."\n"); 14500 } 14501 else { 14502 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n"; 14503 } 14504 } 14505 else 14506 { 14507 if($Signature) { 14508 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n"; 14509 } 14510 else { 14511 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n"; 14512 } 14513 } 14514 } 14515 } 14516 $REMOVED_INTERFACES .= "<br/>\n"; 14517 } 14518 } 14519 if($REMOVED_INTERFACES) 14520 { 14521 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>"; 14522 if($JoinReport) { 14523 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>"; 14524 } 14525 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n"; 14526 } 14527 } 14528 return $REMOVED_INTERFACES; 14529} 14530 14531sub getXmlParams($$) 14532{ 14533 my ($Content, $Problem) = @_; 14534 return "" if(not $Content or not $Problem); 14535 my %XMLparams = (); 14536 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem})) 14537 { 14538 my $Macro = "\@".lc($Attr); 14539 if($Content=~/\Q$Macro\E/) { 14540 $XMLparams{lc($Attr)} = $Problem->{$Attr}; 14541 } 14542 } 14543 my @PString = (); 14544 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) { 14545 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\""); 14546 } 14547 if(@PString) { 14548 return " ".join(" ", @PString); 14549 } 14550 else { 14551 return ""; 14552 } 14553} 14554 14555sub addMarkup($) 14556{ 14557 my $Content = $_[0]; 14558 # auto-markup 14559 $Content=~s/\n[ ]*//; # spaces 14560 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size) 14561 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list) 14562 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g; 14563 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ... 14564 if($Content=~/\ANOTE:/) 14565 { # notes 14566 $Content=~s!(NOTE):!<b>$1</b>:!g; 14567 } 14568 else { 14569 $Content=~s!(NOTE):!<br/><b>$1</b>:!g; 14570 } 14571 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters 14572 my @Keywords = ( 14573 "void", 14574 "const", 14575 "static", 14576 "restrict", 14577 "volatile", 14578 "register", 14579 "virtual" 14580 ); 14581 my $MKeys = join("|", @Keywords); 14582 foreach (@Keywords) { 14583 $MKeys .= "|non-".$_; 14584 } 14585 $Content=~s!(added\s*|to\s*|from\s*|became\s*)($MKeys)([^\w-]|\Z)!$1<b>$2</b>$3!ig; # intrinsic types, modifiers 14586 14587 # Markdown 14588 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig; 14589 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig; 14590 return $Content; 14591} 14592 14593sub applyMacroses($$$$) 14594{ 14595 my ($Level, $Kind, $Content, $Problem) = @_; 14596 return "" if(not $Content or not $Problem); 14597 $Problem->{"Word_Size"} = $WORD_SIZE{2}; 14598 $Content = addMarkup($Content); 14599 # macros 14600 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem})) 14601 { 14602 my $Macro = "\@".lc($Attr); 14603 my $Value = $Problem->{$Attr}; 14604 if(not defined $Value 14605 or $Value eq "") { 14606 next; 14607 } 14608 if($Value=~/\s\(/ and $Value!~/['"]/) 14609 { # functions 14610 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals 14611 $Value=~s/\s\w+(\)|,)/$1/g; # remove parameter names 14612 $Value = black_name($Value); 14613 } 14614 elsif($Value=~/\s/) { 14615 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>"; 14616 } 14617 elsif($Value=~/\A\d+\Z/ 14618 and ($Attr eq "Old_Size" or $Attr eq "New_Size")) 14619 { # bits to bytes 14620 if($Value % $BYTE_SIZE) 14621 { # bits 14622 if($Value==1) { 14623 $Value = "<b>".$Value."</b> bit"; 14624 } 14625 else { 14626 $Value = "<b>".$Value."</b> bits"; 14627 } 14628 } 14629 else 14630 { # bytes 14631 $Value /= $BYTE_SIZE; 14632 if($Value==1) { 14633 $Value = "<b>".$Value."</b> byte"; 14634 } 14635 else { 14636 $Value = "<b>".$Value."</b> bytes"; 14637 } 14638 } 14639 } 14640 else 14641 { 14642 $Value = "<b>".htmlSpecChars($Value)."</b>"; 14643 } 14644 $Content=~s/\Q$Macro\E/$Value/g; 14645 } 14646 14647 if($Content=~/(\A|[^\@\w])\@\w/) 14648 { 14649 if(not $IncompleteRules{$Level}{$Kind}) 14650 { # only one warning 14651 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")"); 14652 $IncompleteRules{$Level}{$Kind} = 1; 14653 } 14654 } 14655 return $Content; 14656} 14657 14658sub get_Report_SymbolProblems($$) 14659{ 14660 my ($TargetSeverity, $Level) = @_; 14661 my $INTERFACE_PROBLEMS = ""; 14662 my (%ReportMap, %SymbolChanges) = (); 14663 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}})) 14664 { 14665 my ($SN, $SS, $SV) = separate_symbol($Symbol); 14666 if($SV and defined $CompatProblems{$Level}{$SN}) { 14667 next; 14668 } 14669 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}})) 14670 { 14671 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols" 14672 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol") 14673 { 14674 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"}; 14675 my $DyLib = $Symbol_Library{1}{$Symbol}; 14676 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol}) 14677 { # Symbol with Version 14678 $DyLib = $Symbol_Library{1}{$VSym}; 14679 } 14680 if(not $DyLib) 14681 { # const global data 14682 $DyLib = ""; 14683 } 14684 if($Level eq "Source" and $ReportFormat eq "html") 14685 { # do not show library name in HTML report 14686 $DyLib = ""; 14687 } 14688 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}}; 14689 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}})) 14690 { 14691 my $Priority = getProblemSeverity($Level, $Kind); 14692 if($Priority ne $TargetSeverity) { 14693 delete($SymbolChanges{$Symbol}{$Kind}{$Location}); 14694 } 14695 } 14696 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}})) 14697 { 14698 delete($SymbolChanges{$Symbol}{$Kind}); 14699 next; 14700 } 14701 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1; 14702 } 14703 } 14704 if(not keys(%{$SymbolChanges{$Symbol}})) { 14705 delete($SymbolChanges{$Symbol}); 14706 } 14707 } 14708 if($ReportFormat eq "xml") 14709 { # XML 14710 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap)) 14711 { 14712 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n"; 14713 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}})) 14714 { 14715 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n"; 14716 foreach my $Symbol (sort {lc($tr_name{$a}) cmp lc($tr_name{$b})} keys(%SymbolChanges)) 14717 { 14718 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n"; 14719 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}})) 14720 { 14721 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}})) 14722 { 14723 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}}; 14724 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"}); 14725 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n"; 14726 my $Change = $CompatRules{$Level}{$Kind}{"Change"}; 14727 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n"; 14728 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"}; 14729 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n"; 14730 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}; 14731 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n"; 14732 $INTERFACE_PROBLEMS .= " </problem>\n"; 14733 } 14734 } 14735 $INTERFACE_PROBLEMS .= " </symbol>\n"; 14736 } 14737 $INTERFACE_PROBLEMS .= " </library>\n"; 14738 } 14739 $INTERFACE_PROBLEMS .= " </header>\n"; 14740 } 14741 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n"; 14742 } 14743 else 14744 { # HTML 14745 my $ProblemsNum = 0; 14746 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap)) 14747 { 14748 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}})) 14749 { 14750 my (%NameSpaceSymbols, %NewSignature) = (); 14751 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) { 14752 $NameSpaceSymbols{get_IntNameSpace($Symbol, 1)}{$Symbol} = 1; 14753 } 14754 foreach my $NameSpace (sort keys(%NameSpaceSymbols)) 14755 { 14756 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace); 14757 my @SortedInterfaces = sort {lc($tr_name{$a}) cmp lc($tr_name{$b})} keys(%{$NameSpaceSymbols{$NameSpace}}); 14758 foreach my $Symbol (@SortedInterfaces) 14759 { 14760 my $Signature = get_Signature($Symbol, 1); 14761 my $SYMBOL_REPORT = ""; 14762 my $ProblemNum = 1; 14763 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}})) 14764 { 14765 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}})) 14766 { 14767 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}}; 14768 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"}); 14769 if($Problem{"New_Signature"}) { 14770 $NewSignature{$Symbol} = $Problem{"New_Signature"}; 14771 } 14772 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem)) 14773 { 14774 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem); 14775 $SYMBOL_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>".$Effect."</td></tr>\n"; 14776 $ProblemNum += 1; 14777 $ProblemsNum += 1; 14778 } 14779 } 14780 } 14781 $ProblemNum -= 1; 14782 if($SYMBOL_REPORT) 14783 { 14784 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> "; 14785 if($Signature) { 14786 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature); 14787 } 14788 else { 14789 $INTERFACE_PROBLEMS .= $Symbol; 14790 } 14791 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n"; 14792 $INTERFACE_PROBLEMS .= $ContentDivStart."\n"; 14793 if($NewSignature{$Symbol}) 14794 { # argument list changed to 14795 $INTERFACE_PROBLEMS .= "\n<span class='new_sign_lbl'>changed to:</span><br/><span class='new_sign'>".highLight_Signature_Italic_Color($NewSignature{$Symbol})."</span><br/>\n"; 14796 } 14797 if($Symbol=~/\A(_Z|\?)/) { 14798 $INTERFACE_PROBLEMS .= "<span class='mangled'>    [symbol: <b>$Symbol</b>]</span><br/>\n"; 14799 } 14800 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n"; 14801 $INTERFACE_PROBLEMS .= $ContentDivEnd; 14802 if($NameSpace) { 14803 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g; 14804 } 14805 } 14806 } 14807 $INTERFACE_PROBLEMS .= "<br/>"; 14808 } 14809 } 14810 } 14811 if($INTERFACE_PROBLEMS) 14812 { 14813 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS); 14814 my $Title = "Problems with Symbols, $TargetSeverity Severity"; 14815 if($TargetSeverity eq "Safe") 14816 { # Safe Changes 14817 $Title = "Other Changes in Symbols"; 14818 } 14819 $INTERFACE_PROBLEMS = "<a name=\'".get_Anchor("Symbol", $Level, $TargetSeverity)."\'></a><a name=\'".get_Anchor("Interface", $Level, $TargetSeverity)."\'></a>\n<h2>$Title ($ProblemsNum)</h2><hr/>\n".$INTERFACE_PROBLEMS.$TOP_REF."<br/>\n"; 14820 } 14821 } 14822 return $INTERFACE_PROBLEMS; 14823} 14824 14825sub get_Report_TypeProblems($$) 14826{ 14827 my ($TargetSeverity, $Level) = @_; 14828 my $TYPE_PROBLEMS = ""; 14829 my (%ReportMap, %TypeChanges, %TypeType) = (); 14830 foreach my $Interface (sort keys(%{$CompatProblems{$Level}})) 14831 { 14832 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}})) 14833 { 14834 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types") 14835 { 14836 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}})) 14837 { 14838 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"}; 14839 my $TypeType = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Type"}; 14840 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"}; 14841 $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Type"} = lc($TypeType); 14842 my $Severity = getProblemSeverity($Level, $Kind); 14843 if($Severity eq "Safe" 14844 and $TargetSeverity ne "Safe") { 14845 next; 14846 } 14847 if(not $TypeType{$TypeName} 14848 or $TypeType{$TypeName} eq "struct") 14849 { # register type of the type, select "class" if type has "class"- and "struct"-type changes 14850 $TypeType{$TypeName} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Type"}; 14851 } 14852 14853 if(cmpSeverities($Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target}, $Severity)) 14854 { # select a problem with the highest priority 14855 next; 14856 } 14857 %{$TypeChanges{$TypeName}{$Kind}{$Location}} = %{$CompatProblems{$Level}{$Interface}{$Kind}{$Location}}; 14858 } 14859 } 14860 } 14861 } 14862 my %Kinds_Locations = (); 14863 foreach my $TypeName (keys(%TypeChanges)) 14864 { 14865 my %Kinds_Target = (); 14866 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}})) 14867 { 14868 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}})) 14869 { 14870 my $Severity = getProblemSeverity($Level, $Kind); 14871 if($Severity ne $TargetSeverity) 14872 { # other priority 14873 delete($TypeChanges{$TypeName}{$Kind}{$Location}); 14874 next; 14875 } 14876 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1; 14877 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"}; 14878 if($Kinds_Target{$Kind}{$Target}) 14879 { # duplicate target 14880 delete($TypeChanges{$TypeName}{$Kind}{$Location}); 14881 next; 14882 } 14883 $Kinds_Target{$Kind}{$Target} = 1; 14884 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"}; 14885 $ReportMap{$HeaderName}{$TypeName} = 1; 14886 } 14887 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) { 14888 delete($TypeChanges{$TypeName}{$Kind}); 14889 } 14890 } 14891 if(not keys(%{$TypeChanges{$TypeName}})) { 14892 delete($TypeChanges{$TypeName}); 14893 } 14894 } 14895 my @Symbols = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$CompatProblems{$Level}}); 14896 if($ReportFormat eq "xml") 14897 { # XML 14898 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap)) 14899 { 14900 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n"; 14901 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) 14902 { 14903 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n"; 14904 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}})) 14905 { 14906 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}})) 14907 { 14908 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}}; 14909 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n"; 14910 my $Change = $CompatRules{$Level}{$Kind}{"Change"}; 14911 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n"; 14912 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"}; 14913 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n"; 14914 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}; 14915 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n"; 14916 $TYPE_PROBLEMS .= " </problem>\n"; 14917 } 14918 } 14919 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols); 14920 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) { 14921 $TYPE_PROBLEMS .= showVTables($TypeName); 14922 } 14923 $TYPE_PROBLEMS .= " </type>\n"; 14924 } 14925 $TYPE_PROBLEMS .= " </header>\n"; 14926 } 14927 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n"; 14928 } 14929 else 14930 { # HTML 14931 my $ProblemsNum = 0; 14932 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap)) 14933 { 14934 my (%NameSpace_Type) = (); 14935 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) { 14936 $NameSpace_Type{parse_TypeNameSpace($TypeName, 1)}{$TypeName} = 1; 14937 } 14938 foreach my $NameSpace (sort keys(%NameSpace_Type)) 14939 { 14940 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace); 14941 my @SortedTypes = sort {$TypeType{$a}." ".lc($a) cmp $TypeType{$b}." ".lc($b)} keys(%{$NameSpace_Type{$NameSpace}}); 14942 foreach my $TypeName (@SortedTypes) 14943 { 14944 my $ProblemNum = 1; 14945 my $TYPE_REPORT = ""; 14946 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}})) 14947 { 14948 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}})) 14949 { 14950 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}}; 14951 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem)) 14952 { 14953 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem); 14954 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n"; 14955 $ProblemNum += 1; 14956 $ProblemsNum += 1; 14957 } 14958 } 14959 } 14960 $ProblemNum -= 1; 14961 if($TYPE_REPORT) 14962 { 14963 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols); 14964 my $ShowVTables = ""; 14965 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) { 14966 $ShowVTables = showVTables($TypeName); 14967 } 14968 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> <span class='ttype'>".$TypeType{$TypeName}."</span> ".htmlSpecChars($TypeName)." ($ProblemNum)".$ContentSpanEnd; 14969 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n"; 14970 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n"; 14971 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n"; 14972 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n"; 14973 if($NameSpace) { 14974 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g; 14975 } 14976 } 14977 } 14978 $TYPE_PROBLEMS .= "<br/>"; 14979 } 14980 } 14981 if($TYPE_PROBLEMS) 14982 { 14983 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS); 14984 my $Title = "Problems with Data Types, $TargetSeverity Severity"; 14985 if($TargetSeverity eq "Safe") 14986 { # Safe Changes 14987 $Title = "Other Changes in Data Types"; 14988 } 14989 $TYPE_PROBLEMS = "<a name=\'".get_Anchor("Type", $Level, $TargetSeverity)."\'></a>\n<h2>$Title ($ProblemsNum)</h2><hr/>\n".$TYPE_PROBLEMS.$TOP_REF."<br/>\n"; 14990 } 14991 } 14992 return $TYPE_PROBLEMS; 14993} 14994 14995sub get_Anchor($$$) 14996{ 14997 my ($Kind, $Level, $Severity) = @_; 14998 if($JoinReport) 14999 { 15000 if($Severity eq "Safe") { 15001 return "Other_".$Level."_Changes_In_".$Kind."s"; 15002 } 15003 else { 15004 return $Kind."_".$Level."_Problems_".$Severity; 15005 } 15006 } 15007 else 15008 { 15009 if($Severity eq "Safe") { 15010 return "Other_Changes_In_".$Kind."s"; 15011 } 15012 else { 15013 return $Kind."_Problems_".$Severity; 15014 } 15015 } 15016} 15017 15018sub showVTables($) 15019{ 15020 my $TypeName = $_[0]; 15021 my $TypeId1 = $TName_Tid{1}{$TypeName}; 15022 my %Type1 = get_Type($TypeId1, 1); 15023 if(defined $Type1{"VTable"} 15024 and keys(%{$Type1{"VTable"}})) 15025 { 15026 my $TypeId2 = $TName_Tid{2}{$TypeName}; 15027 my %Type2 = get_Type($TypeId2, 2); 15028 if(defined $Type2{"VTable"} 15029 and keys(%{$Type2{"VTable"}})) 15030 { 15031 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}})); 15032 my %Entries = (); 15033 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes))) 15034 { 15035 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index}); 15036 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index}); 15037 } 15038 my $VTABLES = ""; 15039 if($ReportFormat eq "xml") 15040 { # XML 15041 $VTABLES .= " <vtable>\n"; 15042 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries))) 15043 { 15044 $VTABLES .= " <entry offset=\"".$Index."\">\n"; 15045 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n"; 15046 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n"; 15047 $VTABLES .= " </entry>\n"; 15048 } 15049 $VTABLES .= " </vtable>\n\n"; 15050 } 15051 else 15052 { # HTML 15053 $VTABLES .= "<table class='vtable'>"; 15054 $VTABLES .= "<tr><th width='2%'>Offset</th>"; 15055 $VTABLES .= "<th width='45%'>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>"; 15056 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>"; 15057 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries))) 15058 { 15059 my ($Color1, $Color2) = ("", ""); 15060 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"}) 15061 { 15062 if($Entries{$Index}{"E1"}) 15063 { 15064 $Color1 = " class='failed'"; 15065 $Color2 = " class='failed'"; 15066 } 15067 else { 15068 $Color2 = " class='warning'"; 15069 } 15070 } 15071 $VTABLES .= "<tr><th>".$Index."</th>\n"; 15072 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n"; 15073 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n"; 15074 } 15075 $VTABLES .= "</table><br/>\n"; 15076 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd; 15077 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES; 15078 } 15079 return $VTABLES; 15080 } 15081 } 15082 return ""; 15083} 15084 15085sub simpleVEntry($) 15086{ 15087 my $VEntry = $_[0]; 15088 if(not defined $VEntry 15089 or $VEntry eq "") { 15090 return ""; 15091 } 15092 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks 15093 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo 15094 if($VEntry=~/\A_ZThn.+\Z/) { 15095 $VEntry = "non-virtual thunk"; 15096 } 15097 $VEntry=~s/\A\(int \(\*\)\(...\)\)([^\(\d])/$1/i; 15098 # support for old GCC versions 15099 $VEntry=~s/\A0u\Z/(int (*)(...))0/; 15100 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/; 15101 $VEntry=~s/\A&_Z\Z/& _Z/; 15102 # templates 15103 if($VEntry=~s/ \[with (\w+) = (.+?)(, [^=]+ = .+|])\Z//g) 15104 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>] 15105 # become std::basic_streambuf<char, ...>::imbue 15106 my ($Pname, $Pval) = ($1, $2); 15107 if($Pname eq "_CharT" and $VEntry=~/\Astd::/) 15108 { # stdc++ typedefs 15109 $VEntry=~s/<$Pname(, [^<>]+|)>/<$Pval>/g; 15110 # FIXME: simplify names using stdcxx typedefs (StdCxxTypedef) 15111 # The typedef info should be added to ABI dumps 15112 } 15113 else 15114 { 15115 $VEntry=~s/<$Pname>/<$Pval>/g; 15116 $VEntry=~s/<$Pname, [^<>]+>/<$Pval, ...>/g; 15117 } 15118 } 15119 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors 15120 return $VEntry; 15121} 15122 15123sub getAffectedSymbols($$$$) 15124{ 15125 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_; 15126 my $LIMIT = 1000; 15127 if($#{$Syms}>=10000) 15128 { # reduce size of the report 15129 $LIMIT = 10; 15130 } 15131 my %SProblems = (); 15132 foreach my $Symbol (@{$Syms}) 15133 { 15134 if(keys(%SProblems)>$LIMIT) { 15135 last; 15136 } 15137 if(($Symbol=~/C2E|D2E|D0E/)) 15138 { # duplicated problems for C2 constructors, D2 and D0 destructors 15139 next; 15140 } 15141 my ($SN, $SS, $SV) = separate_symbol($Symbol); 15142 if($Level eq "Source") 15143 { # remove symbol version 15144 $Symbol=$SN; 15145 } 15146 my ($MinPath_Length, $ProblemLocation_Last) = (-1, ""); 15147 my $Severity_Max = 0; 15148 my $Signature = get_Signature($Symbol, 1); 15149 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Symbol}})) 15150 { 15151 foreach my $Location (keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}})) 15152 { 15153 if(not defined $Kinds_Locations->{$Kind} 15154 or not $Kinds_Locations->{$Kind}{$Location}) { 15155 next; 15156 } 15157 if($SV and defined $CompatProblems{$Level}{$SN} 15158 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Location}) 15159 { # duplicated problems for versioned symbols 15160 next; 15161 } 15162 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Type_Name"}; 15163 next if($Type_Name ne $Target_TypeName); 15164 15165 my $Position = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Param_Pos"}; 15166 my $Param_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Param_Name"}; 15167 my $Severity = getProblemSeverity($Level, $Kind); 15168 my $Path_Length = 0; 15169 my $ProblemLocation = $Location; 15170 if($Type_Name) { 15171 $ProblemLocation=~s/->\Q$Type_Name\E\Z//g; 15172 } 15173 while($ProblemLocation=~/\-\>/g) { 15174 $Path_Length += 1; 15175 } 15176 if($MinPath_Length==-1 or ($Path_Length<=$MinPath_Length and $Severity_Val{$Severity}>$Severity_Max) 15177 or (cmp_locations($ProblemLocation, $ProblemLocation_Last) and $Severity_Val{$Severity}==$Severity_Max)) 15178 { 15179 $MinPath_Length = $Path_Length; 15180 $Severity_Max = $Severity_Val{$Severity}; 15181 $ProblemLocation_Last = $ProblemLocation; 15182 %{$SProblems{$Symbol}} = ( 15183 "Descr"=>getAffectDescription($Level, $Symbol, $Kind, $Location), 15184 "Severity_Max"=>$Severity_Max, 15185 "Signature"=>$Signature, 15186 "Position"=>$Position, 15187 "Param_Name"=>$Param_Name, 15188 "Location"=>$Location 15189 ); 15190 } 15191 } 15192 } 15193 } 15194 my @Symbols = keys(%SProblems); 15195 @Symbols = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} @Symbols; 15196 @Symbols = sort {$SProblems{$b}{"Severity_Max"}<=>$SProblems{$a}{"Severity_Max"}} @Symbols; 15197 if($#Symbols+1>$LIMIT) 15198 { # remove last element 15199 pop(@Symbols); 15200 } 15201 my $Affected = ""; 15202 if($ReportFormat eq "xml") 15203 { # XML 15204 $Affected .= " <affected>\n"; 15205 foreach my $Symbol (@Symbols) 15206 { 15207 my $Param_Name = $SProblems{$Symbol}{"Param_Name"}; 15208 my $Description = $SProblems{$Symbol}{"Descr"}; 15209 my $Location = $SProblems{$Symbol}{"Location"}; 15210 my $Target = ""; 15211 if($Param_Name) { 15212 $Target = " affected=\"param\" param_name=\"$Param_Name\""; 15213 } 15214 elsif($Location=~/\Aretval(\-|\Z)/i) { 15215 $Target = " affected=\"retval\""; 15216 } 15217 elsif($Location=~/\Athis(\-|\Z)/i) { 15218 $Target = " affected=\"this\""; 15219 } 15220 $Affected .= " <symbol$Target name=\"$Symbol\">\n"; 15221 $Affected .= " <comment>".xmlSpecChars($Description)."</comment>\n"; 15222 $Affected .= " </symbol>\n"; 15223 } 15224 $Affected .= " </affected>\n"; 15225 } 15226 else 15227 { # HTML 15228 foreach my $Symbol (@Symbols) 15229 { 15230 my $Description = $SProblems{$Symbol}{"Descr"}; 15231 my $Signature = $SProblems{$Symbol}{"Signature"}; 15232 my $Pos = $SProblems{$Symbol}{"Position"}; 15233 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($Signature, $Pos, 1, 0, 0)."</span><br/><div class='affect'>".htmlSpecChars($Description)."</div>\n"; 15234 } 15235 if(keys(%SProblems)>$LIMIT) { 15236 $Affected .= "and others ...<br/>"; 15237 } 15238 $Affected = "<div class='affected'>".$Affected."</div>"; 15239 if($Affected) 15240 { 15241 $Affected = $ContentDivStart.$Affected.$ContentDivEnd; 15242 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".(keys(%SProblems)>$LIMIT?">".$LIMIT:keys(%SProblems)).")".$ContentSpanEnd.$Affected; 15243 } 15244 } 15245 return $Affected; 15246} 15247 15248sub cmp_locations($$) 15249{ 15250 my ($L1, $L2) = @_; 15251 if($L2=~/\b(retval|this)\b/ 15252 and $L1!~/\b(retval|this)\b/ and $L1!~/\-\>/) { 15253 return 1; 15254 } 15255 if($L2=~/\b(retval|this)\b/ and $L2=~/\-\>/ 15256 and $L1!~/\b(retval|this)\b/ and $L1=~/\-\>/) { 15257 return 1; 15258 } 15259 return 0; 15260} 15261 15262sub getAffectDescription($$$$) 15263{ 15264 my ($Level, $Symbol, $Kind, $Location) = @_; 15265 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}}; 15266 my $PPos = showPos($Problem{"Param_Pos"}); 15267 my @Sentence = (); 15268 $Location=~s/\A(.*)\-\>.+?\Z/$1/; 15269 if($Kind eq "Overridden_Virtual_Method" 15270 or $Kind eq "Overridden_Virtual_Method_B") { 15271 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method."); 15272 } 15273 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types") 15274 { 15275 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/) 15276 { 15277 my $METHOD_TYPE = $CompleteSignature{1}{$Symbol}{"Constructor"}?"constructor":"method"; 15278 my $ClassName = $TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"}; 15279 if($ClassName eq $Problem{"Type_Name"}) { 15280 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class."); 15281 } 15282 else { 15283 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'."); 15284 } 15285 } 15286 else 15287 { 15288 if($Location=~/retval/) 15289 { # return value 15290 if($Location=~/\-\>/) { 15291 push(@Sentence, "Field \'".$Location."\' in return value"); 15292 } 15293 else { 15294 push(@Sentence, "Return value"); 15295 } 15296 if(my $Init = $Problem{"InitialType_Type"}) 15297 { 15298 if($Init eq "Pointer") { 15299 push(@Sentence, "(pointer)"); 15300 } 15301 elsif($Init eq "Ref") { 15302 push(@Sentence, "(reference)"); 15303 } 15304 } 15305 } 15306 elsif($Location=~/this/) 15307 { # "this" pointer 15308 if($Location=~/\-\>/) { 15309 push(@Sentence, "Field \'".$Location."\' in the object of this method"); 15310 } 15311 else { 15312 push(@Sentence, "\'this\' pointer"); 15313 } 15314 } 15315 else 15316 { # parameters 15317 if($Location=~/\-\>/) { 15318 push(@Sentence, "Field \'".$Location."\' in $PPos parameter"); 15319 } 15320 else { 15321 push(@Sentence, "$PPos parameter"); 15322 } 15323 if($Problem{"Param_Name"}) { 15324 push(@Sentence, "\'".$Problem{"Param_Name"}."\'"); 15325 } 15326 if(my $Init = $Problem{"InitialType_Type"}) 15327 { 15328 if($Init eq "Pointer") { 15329 push(@Sentence, "(pointer)"); 15330 } 15331 elsif($Init eq "Ref") { 15332 push(@Sentence, "(reference)"); 15333 } 15334 } 15335 } 15336 if($Location eq "this") { 15337 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'."); 15338 } 15339 elsif(defined $Problem{"Start_Type_Name"} 15340 and $Problem{"Start_Type_Name"} eq $Problem{"Type_Name"}) { 15341 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'."); 15342 } 15343 else { 15344 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'."); 15345 } 15346 } 15347 } 15348 if($ExtendedSymbols{$Symbol}) { 15349 push(@Sentence, " This is a symbol from an artificial external library that may use the \'$TargetLibraryName\' library and change its ABI after recompiling."); 15350 } 15351 return join(" ", @Sentence); 15352} 15353 15354sub get_XmlSign($$) 15355{ 15356 my ($Symbol, $LibVersion) = @_; 15357 my $Info = $CompleteSignature{$LibVersion}{$Symbol}; 15358 my $Report = ""; 15359 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}})) 15360 { 15361 my $Name = $Info->{"Param"}{$Pos}{"name"}; 15362 my $Type = $Info->{"Param"}{$Pos}{"type"}; 15363 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"}; 15364 foreach my $Typedef (keys(%ChangedTypedef)) 15365 { 15366 my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}; 15367 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g; 15368 } 15369 $Report .= " <param pos=\"$Pos\">\n"; 15370 $Report .= " <name>".$Name."</name>\n"; 15371 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n"; 15372 $Report .= " </param>\n"; 15373 } 15374 if(my $Return = $Info->{"Return"}) 15375 { 15376 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"}; 15377 $Report .= " <retval>\n"; 15378 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n"; 15379 $Report .= " </retval>\n"; 15380 } 15381 return $Report; 15382} 15383 15384sub get_Report_SymbolsInfo($) 15385{ 15386 my $Level = $_[0]; 15387 my $Report = "<symbols_info>\n"; 15388 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}})) 15389 { 15390 my ($SN, $SS, $SV) = separate_symbol($Symbol); 15391 if($SV and defined $CompatProblems{$Level}{$SN}) { 15392 next; 15393 } 15394 $Report .= " <symbol name=\"$Symbol\">\n"; 15395 my ($S1, $P1, $S2, $P2) = (); 15396 if(not $AddedInt{$Level}{$Symbol}) 15397 { 15398 if(defined $CompleteSignature{1}{$Symbol} 15399 and defined $CompleteSignature{1}{$Symbol}{"Header"}) 15400 { 15401 $P1 = get_XmlSign($Symbol, 1); 15402 $S1 = get_Signature($Symbol, 1); 15403 } 15404 elsif($Symbol=~/\A(_Z|\?)/) { 15405 $S1 = $tr_name{$Symbol}; 15406 } 15407 } 15408 if(not $RemovedInt{$Level}{$Symbol}) 15409 { 15410 if(defined $CompleteSignature{2}{$Symbol} 15411 and defined $CompleteSignature{2}{$Symbol}{"Header"}) 15412 { 15413 $P2 = get_XmlSign($Symbol, 2); 15414 $S2 = get_Signature($Symbol, 2); 15415 } 15416 elsif($Symbol=~/\A(_Z|\?)/) { 15417 $S2 = $tr_name{$Symbol}; 15418 } 15419 } 15420 if($S1) 15421 { 15422 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n"; 15423 $Report .= $P1; 15424 $Report .= " </old>\n"; 15425 } 15426 if($S2 and $S2 ne $S1) 15427 { 15428 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n"; 15429 $Report .= $P2; 15430 $Report .= " </new>\n"; 15431 } 15432 $Report .= " </symbol>\n"; 15433 } 15434 $Report .= "</symbols_info>\n"; 15435 return $Report; 15436} 15437 15438sub writeReport($$) 15439{ 15440 my ($Level, $Report) = @_; 15441 if($ReportFormat eq "xml") { 15442 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report; 15443 } 15444 if($StdOut) 15445 { # --stdout option 15446 print STDOUT $Report; 15447 } 15448 else 15449 { 15450 my $RPath = getReportPath($Level); 15451 mkpath(get_dirname($RPath)); 15452 15453 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n"); 15454 print REPORT $Report; 15455 close(REPORT); 15456 15457 if($Browse or $OpenReport) 15458 { # open in browser 15459 openReport($RPath); 15460 if($JoinReport or $DoubleReport) 15461 { 15462 if($Level eq "Binary") 15463 { # wait to open a browser 15464 sleep(1); 15465 } 15466 } 15467 } 15468 } 15469} 15470 15471sub openReport($) 15472{ 15473 my $Path = $_[0]; 15474 my $Cmd = ""; 15475 if($Browse) 15476 { # user-defined browser 15477 $Cmd = $Browse." \"$Path\""; 15478 } 15479 if(not $Cmd) 15480 { # default browser 15481 if($OSgroup eq "macos") { 15482 system("open \"$Path\""); 15483 } 15484 elsif($OSgroup eq "windows") { 15485 system("start \"$Path\""); 15486 } 15487 else 15488 { # linux, freebsd, solaris 15489 my @Browsers = ( 15490 "x-www-browser", 15491 "sensible-browser", 15492 "firefox", 15493 "opera", 15494 "xdg-open", 15495 "lynx", 15496 "links" 15497 ); 15498 foreach my $Br (@Browsers) 15499 { 15500 if($Br = get_CmdPath($Br)) 15501 { 15502 $Cmd = $Br." \"$Path\""; 15503 last; 15504 } 15505 } 15506 } 15507 } 15508 if($Cmd) 15509 { 15510 if($Debug) { 15511 printMsg("INFO", "running $Cmd"); 15512 } 15513 if($Cmd!~/lynx|links/) { 15514 $Cmd .= " >\"$TMP_DIR/null\" 2>&1 &"; 15515 } 15516 system($Cmd); 15517 } 15518 else { 15519 printMsg("ERROR", "cannot open report in browser"); 15520 } 15521} 15522 15523sub getReport($) 15524{ 15525 my $Level = $_[0]; 15526 if($ReportFormat eq "xml") 15527 { # XML 15528 15529 if($Level eq "Join") 15530 { 15531 my $Report = "<reports>\n"; 15532 $Report .= getReport("Binary"); 15533 $Report .= getReport("Source"); 15534 $Report .= "</reports>\n"; 15535 return $Report; 15536 } 15537 else 15538 { 15539 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n"; 15540 my ($Summary, $MetaData) = get_Summary($Level); 15541 $Report .= $Summary."\n"; 15542 $Report .= get_Report_Added($Level).get_Report_Removed($Level); 15543 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level); 15544 $Report .= get_Report_SymbolsInfo($Level); 15545 $Report .= "</report>\n"; 15546 return $Report; 15547 } 15548 } 15549 else 15550 { # HTML 15551 my $CssStyles = readModule("Styles", "Report.css"); 15552 my $JScripts = readModule("Scripts", "Sections.js"); 15553 if($Level eq "Join") 15554 { 15555 $CssStyles .= "\n".readModule("Styles", "Tabs.css"); 15556 $JScripts .= "\n".readModule("Scripts", "Tabs.js"); 15557 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report"; 15558 my $Keywords = $TargetLibraryFName.", compatibility, API, report"; 15559 my $Description = "Compatibility report for the $TargetLibraryFName $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions"; 15560 my ($BSummary, $BMetaData) = get_Summary("Binary"); 15561 my ($SSummary, $SMetaData) = get_Summary("Source"); 15562 my $Report = "<!-\- $BMetaData -\->\n<!-\- $SMetaData -\->\n".composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."<body><a name='Source'></a><a name='Binary'></a><a name='Top'></a>"; 15563 $Report .= get_Report_Header("Join")." 15564 <br/><div class='tabset'> 15565 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a> 15566 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a> 15567 </div>"; 15568 $Report .= "<div id='BinaryTab' class='tab'>\n$BSummary\n".get_Report_Added("Binary").get_Report_Removed("Binary").get_Report_Problems("High", "Binary").get_Report_Problems("Medium", "Binary").get_Report_Problems("Low", "Binary").get_Report_Problems("Safe", "Binary").get_SourceInfo()."<br/><br/><br/></div>"; 15569 $Report .= "<div id='SourceTab' class='tab'>\n$SSummary\n".get_Report_Added("Source").get_Report_Removed("Source").get_Report_Problems("High", "Source").get_Report_Problems("Medium", "Source").get_Report_Problems("Low", "Source").get_Report_Problems("Safe", "Source").get_SourceInfo()."<br/><br/><br/></div>"; 15570 $Report .= getReportFooter($TargetLibraryFName); 15571 $Report .= "\n<div style='height:999px;'></div>\n</body></html>"; 15572 return $Report; 15573 } 15574 else 15575 { 15576 my ($Summary, $MetaData) = get_Summary($Level); 15577 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report"; 15578 my $Keywords = $TargetLibraryFName.", ".lc($Level)." compatibility, API, report"; 15579 my $Description = "$Level compatibility report for the ".$TargetLibraryFName." ".$TargetComponent." between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions"; 15580 if($Level eq "Binary") 15581 { 15582 if(getArch(1) eq getArch(2) 15583 and getArch(1) ne "unknown") { 15584 $Description .= " on ".showArch(getArch(1)); 15585 } 15586 } 15587 my $Report = "<!-\- $MetaData -\->\n".composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."\n<body>\n<div><a name='Top'></a>\n"; 15588 $Report .= get_Report_Header($Level)."\n".$Summary."\n"; 15589 $Report .= get_Report_Added($Level).get_Report_Removed($Level); 15590 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level); 15591 $Report .= get_SourceInfo(); 15592 $Report .= "</div>\n<br/><br/><br/><hr/>\n"; 15593 $Report .= getReportFooter($TargetLibraryFName); 15594 $Report .= "\n<div style='height:999px;'></div>\n</body></html>"; 15595 return $Report; 15596 } 15597 } 15598} 15599 15600sub getLegend() 15601{ 15602 return "<br/> 15603<table class='summary'> 15604<tr> 15605 <td class='new'>added</td> 15606 <td class='passed'>compatible</td> 15607</tr> 15608<tr> 15609 <td class='warning'>warning</td> 15610 <td class='failed'>incompatible</td> 15611</tr></table>\n"; 15612} 15613 15614sub createReport() 15615{ 15616 if($JoinReport) 15617 { # --stdout 15618 writeReport("Join", getReport("Join")); 15619 } 15620 elsif($DoubleReport) 15621 { # default 15622 writeReport("Binary", getReport("Binary")); 15623 writeReport("Source", getReport("Source")); 15624 } 15625 elsif($BinaryOnly) 15626 { # --binary 15627 writeReport("Binary", getReport("Binary")); 15628 } 15629 elsif($SourceOnly) 15630 { # --source 15631 writeReport("Source", getReport("Source")); 15632 } 15633} 15634 15635sub getReportFooter($) 15636{ 15637 my $LibName = $_[0]; 15638 my $FooterStyle = (not $JoinReport)?"width:99%":"width:97%;padding-top:3px"; 15639 my $Footer = "<div style='$FooterStyle;font-size:11px;' align='right'><i>Generated on ".(localtime time); # report date 15640 $Footer .= " for <span style='font-weight:bold'>$LibName</span>"; # tested library/system name 15641 $Footer .= " by <a href='".$HomePage{"Wiki"}."'>ABI Compliance Checker</a>"; # tool name 15642 my $ToolSummary = "<br/>A tool for checking backward compatibility of a C/C++ library API  "; 15643 $Footer .= " $TOOL_VERSION  $ToolSummary</i></div>"; # tool version 15644 return $Footer; 15645} 15646 15647sub get_Report_Problems($$) 15648{ 15649 my ($Priority, $Level) = @_; 15650 my $Report = get_Report_TypeProblems($Priority, $Level); 15651 if(my $SProblems = get_Report_SymbolProblems($Priority, $Level)) { 15652 $Report .= $SProblems; 15653 } 15654 if($Priority eq "Low") 15655 { 15656 $Report .= get_Report_ChangedConstants($Level); 15657 if($ReportFormat eq "html") { 15658 if($CheckImpl and $Level eq "Binary") { 15659 $Report .= get_Report_Impl(); 15660 } 15661 } 15662 } 15663 if($ReportFormat eq "html") 15664 { 15665 if($Report) 15666 { # add anchor 15667 if($JoinReport) 15668 { 15669 if($Priority eq "Safe") { 15670 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report; 15671 } 15672 else { 15673 $Report = "<a name=\'".$Priority."_Risk_".$Level."_Problems\'></a>".$Report; 15674 } 15675 } 15676 else 15677 { 15678 if($Priority eq "Safe") { 15679 $Report = "<a name=\'Other_Changes\'></a>".$Report; 15680 } 15681 else { 15682 $Report = "<a name=\'".$Priority."_Risk_Problems\'></a>".$Report; 15683 } 15684 } 15685 } 15686 } 15687 return $Report; 15688} 15689 15690sub composeHTML_Head($$$$$) 15691{ 15692 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_; 15693 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"> 15694 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\"> 15695 <head> 15696 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /> 15697 <meta name=\"keywords\" content=\"$Keywords\" /> 15698 <meta name=\"description\" content=\"$Description\" /> 15699 <title> 15700 $Title 15701 </title> 15702 <style type=\"text/css\"> 15703 $Styles 15704 </style> 15705 <script type=\"text/javascript\" language=\"JavaScript\"> 15706 <!-- 15707 $Scripts 15708 --> 15709 </script> 15710 </head>"; 15711} 15712 15713sub insertIDs($) 15714{ 15715 my $Text = $_[0]; 15716 while($Text=~/CONTENT_ID/) 15717 { 15718 if(int($Content_Counter)%2) { 15719 $ContentID -= 1; 15720 } 15721 $Text=~s/CONTENT_ID/c_$ContentID/; 15722 $ContentID += 1; 15723 $Content_Counter += 1; 15724 } 15725 return $Text; 15726} 15727 15728sub checkPreprocessedUnit($) 15729{ 15730 my $Path = $_[0]; 15731 my ($CurHeader, $CurHeaderName) = ("", ""); 15732 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n"); 15733 while(my $Line = <PREPROC>) 15734 { # detecting public and private constants 15735 15736 if(substr($Line, 0, 1) eq "#") 15737 { 15738 chomp($Line); 15739 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/) 15740 { 15741 $CurHeader = path_format($1, $OSgroup); 15742 $CurHeaderName = get_filename($CurHeader); 15743 } 15744 if(not $Include_Neighbors{$Version}{$CurHeaderName} 15745 and not $Registered_Headers{$Version}{$CurHeader}) 15746 { # not a target 15747 next; 15748 } 15749 if(not is_target_header($CurHeaderName, 1) 15750 and not is_target_header($CurHeaderName, 2)) 15751 { # user-defined header 15752 next; 15753 } 15754 if($Line=~/\A\#\s*define\s+([_A-Z0-9]+)\s+(.+)\s*\Z/) 15755 { 15756 my ($Name, $Value) = ($1, $2); 15757 if(not $Constants{$Version}{$Name}{"Access"}) 15758 { 15759 $Constants{$Version}{$Name}{"Access"} = "public"; 15760 $Constants{$Version}{$Name}{"Value"} = $Value; 15761 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName; 15762 } 15763 } 15764 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) { 15765 $Constants{$Version}{$1}{"Access"} = "private"; 15766 } 15767 } 15768 } 15769 close(PREPROC); 15770 foreach my $Constant (keys(%{$Constants{$Version}})) 15771 { 15772 if($Constants{$Version}{$Constant}{"Access"} eq "private" 15773 or $Constant=~/_h\Z/i 15774 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})) 15775 { # skip private constants 15776 delete($Constants{$Version}{$Constant}); 15777 } 15778 else { 15779 delete($Constants{$Version}{$Constant}{"Access"}); 15780 } 15781 } 15782 if($Debug) 15783 { 15784 mkpath($DEBUG_PATH{$Version}); 15785 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt"); 15786 } 15787} 15788 15789sub uncoverConstant($$) 15790{ 15791 my ($LibVersion, $Constant) = @_; 15792 return "" if(not $LibVersion or not $Constant); 15793 return $Constant if(isCyclical(\@RecurConstant, $Constant)); 15794 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) { 15795 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant}; 15796 } 15797 my $Value = $Constants{$LibVersion}{$Constant}{"Value"}; 15798 if(defined $Value) 15799 { 15800 if($Value=~/\A[A-Z0-9_]+\Z/ and $Value=~/[A-Z]/) 15801 { 15802 push(@RecurConstant, $Constant); 15803 my $Uncovered = uncoverConstant($LibVersion, $Value); 15804 if($Uncovered ne "") { 15805 $Value = $Uncovered; 15806 } 15807 pop(@RecurConstant); 15808 } 15809 # FIXME: uncover $Value using all the enum constants 15810 # USECASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define) 15811 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value); 15812 } 15813 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = ""); 15814} 15815 15816my %IgnoreConstant=( 15817 "VERSION"=>1, 15818 "VERSIONCODE"=>1, 15819 "VERNUM"=>1, 15820 "VERS_INFO"=>1, 15821 "PATCHLEVEL"=>1, 15822 "INSTALLPREFIX"=>1, 15823 "VBUILD"=>1, 15824 "VPATCH"=>1, 15825 "VMINOR"=>1, 15826 "BUILD_STRING"=>1, 15827 "BUILD_TIME"=>1, 15828 "PACKAGE_STRING"=>1, 15829 "PRODUCTION"=>1, 15830 "CONFIGURE_COMMAND"=>1, 15831 "INSTALLDIR"=>1, 15832 "BINDIR"=>1, 15833 "CONFIG_FILE_PATH"=>1, 15834 "DATADIR"=>1, 15835 "EXTENSION_DIR"=>1, 15836 "INCLUDE_PATH"=>1, 15837 "LIBDIR"=>1, 15838 "LOCALSTATEDIR"=>1, 15839 "SBINDIR"=>1, 15840 "SYSCONFDIR"=>1, 15841 "RELEASE"=>1, 15842 "SOURCE_ID"=>1, 15843 "SUBMINOR"=>1, 15844 "MINOR"=>1, 15845 "MINNOR"=>1, 15846 "MINORVERSION"=>1, 15847 "MAJOR"=>1, 15848 "MAJORVERSION"=>1, 15849 "MICRO"=>1, 15850 "MICROVERSION"=>1, 15851 "BINARY_AGE"=>1, 15852 "INTERFACE_AGE"=>1, 15853 "CORE_ABI"=>1, 15854 "PATCH"=>1, 15855 "COPYRIGHT"=>1, 15856 "TIMESTAMP"=>1, 15857 "REVISION"=>1, 15858 "PACKAGE_TAG"=>1, 15859 "PACKAGEDATE"=>1, 15860 "NUMVERSION"=>1 15861); 15862 15863sub mergeConstants($) 15864{ 15865 my $Level = $_[0]; 15866 foreach my $Constant (keys(%{$Constants{1}})) 15867 { 15868 if($SkipConstants{1}{$Constant}) 15869 { # skipped by the user 15870 next; 15871 } 15872 if(not defined $Constants{2}{$Constant}{"Value"} 15873 or $Constants{2}{$Constant}{"Value"} eq "") 15874 { # empty value 15875 next; 15876 } 15877 my $Header = $Constants{1}{$Constant}{"Header"}; 15878 if(not is_target_header($Header, 1) 15879 and not is_target_header($Header, 2)) 15880 { # user-defined header 15881 next; 15882 } 15883 my ($Old_Value, $New_Value, $Old_Value_Pure, $New_Value_Pure); 15884 $Old_Value = $Old_Value_Pure = uncoverConstant(1, $Constant); 15885 $New_Value = $New_Value_Pure = uncoverConstant(2, $Constant); 15886 $Old_Value_Pure=~s/(\W)\s+/$1/g; 15887 $Old_Value_Pure=~s/\s+(\W)/$1/g; 15888 $New_Value_Pure=~s/(\W)\s+/$1/g; 15889 $New_Value_Pure=~s/\s+(\W)/$1/g; 15890 next if($New_Value_Pure eq "" or $Old_Value_Pure eq ""); 15891 if($New_Value_Pure ne $Old_Value_Pure) 15892 { # different values 15893 if($Level eq "Binary") 15894 { 15895 if(grep {$Constant=~/(\A|_)$_(_|\Z)/} keys(%IgnoreConstant)) 15896 { # ignore library version 15897 next; 15898 } 15899 if($Constant=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i) 15900 { # ignore library version 15901 next; 15902 } 15903 if($Old_Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Old_Value=~/[\/\\]\w+[\/\\]\w+/) 15904 { # ignoring path defines: 15905 # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ... 15906 next; 15907 } 15908 if($Old_Value=~/\A\(*[a-z_]+(\s+|\|)/i) 15909 { # ignore source defines: 15910 # static int gcry_pth_init ( void) { return ... 15911 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE... 15912 next; 15913 } 15914 if($Old_Value=~/\(/i and $Old_Value!~/[\"\']/i) 15915 { # ignore source defines: 15916 # foo(p) 15917 next; 15918 } 15919 } 15920 if(convert_integer($Old_Value) eq convert_integer($New_Value)) 15921 { # 0x0001 and 0x1, 0x1 and 1 equal constants 15922 next; 15923 } 15924 if($Old_Value eq "0" and $New_Value eq "NULL") 15925 { # 0 => NULL 15926 next; 15927 } 15928 if($Old_Value eq "NULL" and $New_Value eq "0") 15929 { # NULL => 0 15930 next; 15931 } 15932 %{$ProblemsWithConstants{$Level}{$Constant}} = ( 15933 "Target"=>$Constant, 15934 "Old_Value"=>$Old_Value, 15935 "New_Value"=>$New_Value ); 15936 } 15937 } 15938} 15939 15940sub convert_integer($) 15941{ 15942 my $Value = $_[0]; 15943 if($Value=~/\A0x[a-f0-9]+\Z/) 15944 { # hexadecimal 15945 return hex($Value); 15946 } 15947 elsif($Value=~/\A0[0-7]+\Z/) 15948 { # octal 15949 return oct($Value); 15950 } 15951 elsif($Value=~/\A0b[0-1]+\Z/) 15952 { # binary 15953 return oct($Value); 15954 } 15955 else { 15956 return $Value; 15957 } 15958} 15959 15960sub readSymbols($) 15961{ 15962 my $LibVersion = $_[0]; 15963 my @LibPaths = getSOPaths($LibVersion); 15964 if($#LibPaths==-1 and not $CheckHeadersOnly) 15965 { 15966 if($LibVersion==1) 15967 { 15968 printMsg("WARNING", "checking headers only"); 15969 $CheckHeadersOnly = 1; 15970 } 15971 else { 15972 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"}); 15973 } 15974 } 15975 my %GroupNames = map {parse_libname(get_filename($_), "name+ext", $OStarget)=>1} @LibPaths; 15976 foreach my $LibPath (sort {length($a)<=>length($b)} @LibPaths) { 15977 readSymbols_Lib($LibVersion, $LibPath, 0, \%GroupNames, "+Weak"); 15978 } 15979 if(not $CheckHeadersOnly) 15980 { 15981 if($#LibPaths!=-1) 15982 { 15983 if(not keys(%{$Symbol_Library{$LibVersion}})) 15984 { 15985 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)"); 15986 printMsg("WARNING", "checking headers only"); 15987 $CheckHeadersOnly = 1; 15988 } 15989 } 15990 } 15991 15992 # clean memory 15993 %SystemObjects = (); 15994} 15995 15996sub getSymbolSize($$) 15997{ # size from the shared library 15998 my ($Symbol, $LibVersion) = @_; 15999 return 0 if(not $Symbol); 16000 if(defined $Symbol_Library{$LibVersion}{$Symbol} 16001 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol}) 16002 { 16003 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol} 16004 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol}) 16005 { 16006 if($Size<0) { 16007 return -$Size; 16008 } 16009 } 16010 } 16011 return 0; 16012} 16013 16014sub canonifyName($) 16015{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*) 16016 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*) 16017 my $Name = $_[0]; 16018 my $Rem = "std::(allocator|less|char_traits|regex_traits)"; 16019 while($Name=~/([^<>,]+),\s*$Rem<([^<>,]+)>\s*/ and $1 eq $3) 16020 { 16021 my $P = $1; 16022 $Name=~s/\Q$P\E,\s*$Rem<\Q$P\E>\s*/$P/g; 16023 } 16024 return $Name; 16025} 16026 16027sub translateSymbols(@) 16028{ 16029 my $LibVersion = pop(@_); 16030 my (@MnglNames1, @MnglNames2, @UnmangledNames) = (); 16031 foreach my $Interface (sort @_) 16032 { 16033 if($Interface=~/\A_Z/) 16034 { 16035 next if($tr_name{$Interface}); 16036 $Interface=~s/[\@\$]+(.*)\Z//; 16037 push(@MnglNames1, $Interface); 16038 } 16039 elsif($Interface=~/\A\?/) { 16040 push(@MnglNames2, $Interface); 16041 } 16042 else 16043 { # not mangled 16044 $tr_name{$Interface} = $Interface; 16045 $mangled_name_gcc{$Interface} = $Interface; 16046 $mangled_name{$LibVersion}{$Interface} = $Interface; 16047 } 16048 } 16049 if($#MnglNames1 > -1) 16050 { # GCC names 16051 @UnmangledNames = reverse(unmangleArray(@MnglNames1)); 16052 foreach my $MnglName (@MnglNames1) 16053 { 16054 if(my $Unmangled = pop(@UnmangledNames)) 16055 { 16056 $tr_name{$MnglName} = formatName(canonifyName($Unmangled)); 16057 if(not $mangled_name_gcc{$tr_name{$MnglName}}) { 16058 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName; 16059 } 16060 if($MnglName=~/\A_ZTV/ 16061 and $tr_name{$MnglName}=~/vtable for (.+)/) 16062 { # bind class name and v-table symbol 16063 my $ClassName = $1; 16064 $ClassVTable{$ClassName} = $MnglName; 16065 $VTableClass{$MnglName} = $ClassName; 16066 } 16067 } 16068 } 16069 } 16070 if($#MnglNames2 > -1) 16071 { # MSVC names 16072 @UnmangledNames = reverse(unmangleArray(@MnglNames2)); 16073 foreach my $MnglName (@MnglNames2) 16074 { 16075 if(my $Unmangled = pop(@UnmangledNames)) 16076 { 16077 $tr_name{$MnglName} = formatName($Unmangled); 16078 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName; 16079 } 16080 } 16081 } 16082 return \%tr_name; 16083} 16084 16085sub link_symbol($$$) 16086{ 16087 my ($Symbol, $RunWith, $Deps) = @_; 16088 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) { 16089 return 1; 16090 } 16091 if($Deps eq "+Deps") 16092 { # check the dependencies 16093 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) { 16094 return 1; 16095 } 16096 } 16097 return 0; 16098} 16099 16100sub link_symbol_internal($$$) 16101{ 16102 my ($Symbol, $RunWith, $Where) = @_; 16103 return 0 if(not $Where or not $Symbol); 16104 if($Where->{$RunWith}{$Symbol}) 16105 { # the exact match by symbol name 16106 return 1; 16107 } 16108 if(my $VSym = $SymVer{$RunWith}{$Symbol}) 16109 { # indirect symbol version, i.e. 16110 # foo_old and its symlink foo@v (or foo@@v) 16111 # foo_old may be in .symtab table 16112 if($Where->{$RunWith}{$VSym}) { 16113 return 1; 16114 } 16115 } 16116 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol); 16117 if($Sym and $Ver) 16118 { # search for the symbol with the same version 16119 # or without version 16120 if($Where->{$RunWith}{$Sym}) 16121 { # old: foo@v|foo@@v 16122 # new: foo 16123 return 1; 16124 } 16125 if($Where->{$RunWith}{$Sym."\@".$Ver}) 16126 { # old: foo|foo@@v 16127 # new: foo@v 16128 return 1; 16129 } 16130 if($Where->{$RunWith}{$Sym."\@\@".$Ver}) 16131 { # old: foo|foo@v 16132 # new: foo@@v 16133 return 1; 16134 } 16135 } 16136 return 0; 16137} 16138 16139sub readSymbols_App($) 16140{ 16141 my $Path = $_[0]; 16142 return () if(not $Path or not -f $Path); 16143 my @Imported = (); 16144 if($OSgroup eq "macos") 16145 { 16146 my $OtoolCmd = get_CmdPath("otool"); 16147 if(not $OtoolCmd) { 16148 exitStatus("Not_Found", "can't find \"otool\""); 16149 } 16150 open(APP, "$OtoolCmd -IV \"$Path\" 2>\"$TMP_DIR/null\" |"); 16151 while(<APP>) { 16152 if(/[^_]+\s+_?([\w\$]+)\s*\Z/) { 16153 push(@Imported, $1); 16154 } 16155 } 16156 close(APP); 16157 } 16158 elsif($OSgroup eq "windows") 16159 { 16160 my $DumpBinCmd = get_CmdPath("dumpbin"); 16161 if(not $DumpBinCmd) { 16162 exitStatus("Not_Found", "can't find \"dumpbin.exe\""); 16163 } 16164 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |"); 16165 while(<APP>) { 16166 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) { 16167 push(@Imported, $1); 16168 } 16169 } 16170 close(APP); 16171 } 16172 else 16173 { 16174 my $ReadelfCmd = get_CmdPath("readelf"); 16175 if(not $ReadelfCmd) { 16176 exitStatus("Not_Found", "can't find \"readelf\""); 16177 } 16178 open(APP, "$ReadelfCmd -WhlSsdA \"$Path\" 2>\"$TMP_DIR/null\" |"); 16179 my $symtab=0; # indicates that we are processing 'symtab' section of 'readelf' output 16180 while(<APP>) 16181 { 16182 if( /'.dynsym'/ ) { 16183 $symtab=0; 16184 } 16185 elsif($symtab == 1) { 16186 # do nothing with symtab (but there are some plans for the future) 16187 next; 16188 } 16189 elsif( /'.symtab'/ ) { 16190 $symtab=1; 16191 } 16192 elsif(my ($fullname, $idx, $Ndx, $type, $size, $bind) = readline_ELF($_)) 16193 { 16194 if( $Ndx eq "UND" ) { 16195 #only imported symbols 16196 push(@Imported, $fullname); 16197 } 16198 } 16199 } 16200 close(APP); 16201 } 16202 return @Imported; 16203} 16204 16205sub readline_ELF($) 16206{ 16207 if($_[0]=~/\s*\d+:\s+(\w*)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s([^\s]+)/) 16208 { # the line of 'readelf' output corresponding to the interface 16209 # symbian-style: _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll 16210 my ($value, $size, $type, $bind, 16211 $vis, $Ndx, $fullname)=($1, $2, $3, $4, $5, $6, $7); 16212 if($bind!~/\A(WEAK|GLOBAL)\Z/) { 16213 return (); 16214 } 16215 if($type!~/\A(FUNC|IFUNC|OBJECT|COMMON)\Z/) { 16216 return (); 16217 } 16218 if($vis!~/\A(DEFAULT|PROTECTED)\Z/) { 16219 return (); 16220 } 16221 if($Ndx eq "ABS" and $value!~/\D|1|2|3|4|5|6|7|8|9/) { 16222 return (); 16223 } 16224 if($OStarget eq "symbian") 16225 { 16226 if($fullname=~/_\._\.absent_export_\d+/) 16227 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll 16228 return (); 16229 } 16230 my @Elems = separate_symbol($fullname); 16231 $fullname = $Elems[0]; # remove internal version, {00020001}[10011235].dll 16232 } 16233 if(index($size, "0x")!=-1) 16234 { # 0x3d158 16235 $size = hex($size); 16236 } 16237 return ($fullname, $value, $Ndx, $type, $size, $bind); 16238 } 16239 return (); 16240} 16241 16242sub read_symlink($) 16243{ 16244 my $Path = $_[0]; 16245 return "" if(not $Path); 16246 return "" if(not -f $Path and not -l $Path); 16247 if(defined $Cache{"read_symlink"}{$Path}) { 16248 return $Cache{"read_symlink"}{$Path}; 16249 } 16250 if(my $Res = readlink($Path)) { 16251 return ($Cache{"read_symlink"}{$Path} = $Res); 16252 } 16253 elsif(my $ReadlinkCmd = get_CmdPath("readlink")) { 16254 return ($Cache{"read_symlink"}{$Path} = `$ReadlinkCmd -n \"$Path\"`); 16255 } 16256 elsif(my $FileCmd = get_CmdPath("file")) 16257 { 16258 my $Info = `$FileCmd \"$Path\"`; 16259 if($Info=~/symbolic\s+link\s+to\s+['`"]*([\w\d\.\-\/\\]+)['`"]*/i) { 16260 return ($Cache{"read_symlink"}{$Path} = $1); 16261 } 16262 } 16263 return ($Cache{"read_symlink"}{$Path} = ""); 16264} 16265 16266sub resolve_symlink($) 16267{ 16268 my $Path = $_[0]; 16269 return "" if(not $Path); 16270 return "" if(not -f $Path and not -l $Path); 16271 if(defined $Cache{"resolve_symlink"}{$Path}) { 16272 return $Cache{"resolve_symlink"}{$Path}; 16273 } 16274 return $Path if(isCyclical(\@RecurSymlink, $Path)); 16275 push(@RecurSymlink, $Path); 16276 if(-l $Path and my $Redirect=read_symlink($Path)) 16277 { 16278 if(is_abs($Redirect)) 16279 { # absolute path 16280 if($SystemRoot and $SystemRoot ne "/" 16281 and $Path=~/\A\Q$SystemRoot\E\// 16282 and (-f $SystemRoot.$Redirect or -l $SystemRoot.$Redirect)) 16283 { # symbolic links from the sysroot 16284 # should be corrected to point to 16285 # the files inside sysroot 16286 $Redirect = $SystemRoot.$Redirect; 16287 } 16288 my $Res = resolve_symlink($Redirect); 16289 pop(@RecurSymlink); 16290 return ($Cache{"resolve_symlink"}{$Path} = $Res); 16291 } 16292 elsif($Redirect=~/\.\.[\/\\]/) 16293 { # relative path 16294 $Redirect = joinPath(get_dirname($Path), $Redirect); 16295 while($Redirect=~s&(/|\\)[^\/\\]+(\/|\\)\.\.(\/|\\)&$1&){}; 16296 my $Res = resolve_symlink($Redirect); 16297 pop(@RecurSymlink); 16298 return ($Cache{"resolve_symlink"}{$Path} = $Res); 16299 } 16300 elsif(-f get_dirname($Path)."/".$Redirect) 16301 { # file name in the same directory 16302 my $Res = resolve_symlink(joinPath(get_dirname($Path), $Redirect)); 16303 pop(@RecurSymlink); 16304 return ($Cache{"resolve_symlink"}{$Path} = $Res); 16305 } 16306 else 16307 { # broken link 16308 pop(@RecurSymlink); 16309 return ($Cache{"resolve_symlink"}{$Path} = ""); 16310 } 16311 } 16312 pop(@RecurSymlink); 16313 return ($Cache{"resolve_symlink"}{$Path} = $Path); 16314} 16315 16316sub find_lib_path($$) 16317{ 16318 my ($LibVersion, $DyLib) = @_; 16319 return "" if(not $DyLib or not $LibVersion); 16320 return $DyLib if(is_abs($DyLib)); 16321 if(defined $Cache{"find_lib_path"}{$LibVersion}{$DyLib}) { 16322 return $Cache{"find_lib_path"}{$LibVersion}{$DyLib}; 16323 } 16324 if(my @Paths = sort keys(%{$InputObject_Paths{$LibVersion}{$DyLib}})) { 16325 return ($Cache{"find_lib_path"}{$LibVersion}{$DyLib} = $Paths[0]); 16326 } 16327 elsif(my $DefaultPath = $DyLib_DefaultPath{$DyLib}) { 16328 return ($Cache{"find_lib_path"}{$LibVersion}{$DyLib} = $DefaultPath); 16329 } 16330 else 16331 { 16332 foreach my $Dir (sort keys(%DefaultLibPaths), sort keys(%{$SystemPaths{"lib"}})) 16333 { # search in default linker paths and then in all system paths 16334 if(-f $Dir."/".$DyLib) { 16335 return ($Cache{"find_lib_path"}{$LibVersion}{$DyLib} = joinPath($Dir,$DyLib)); 16336 } 16337 } 16338 detectSystemObjects() if(not keys(%SystemObjects)); 16339 if(my @AllObjects = keys(%{$SystemObjects{$DyLib}})) { 16340 return ($Cache{"find_lib_path"}{$LibVersion}{$DyLib} = $AllObjects[0]); 16341 } 16342 my $ShortName = parse_libname($DyLib, "name+ext", $OStarget); 16343 if($ShortName ne $DyLib 16344 and my $Path = find_lib_path($ShortName)) 16345 { # FIXME: check this case 16346 return ($Cache{"find_lib_path"}{$LibVersion}{$DyLib} = $Path); 16347 } 16348 return ($Cache{"find_lib_path"}{$LibVersion}{$DyLib} = ""); 16349 } 16350} 16351 16352sub readSymbols_Lib($$$$$) 16353{ 16354 my ($LibVersion, $Lib_Path, $IsNeededLib, $GroupNames, $Weak) = @_; 16355 return if(not $Lib_Path or not -f $Lib_Path); 16356 my ($Lib_Dir, $Lib_Name) = separate_path(resolve_symlink($Lib_Path)); 16357 return if($CheckedDyLib{$LibVersion}{$Lib_Name} and $IsNeededLib); 16358 return if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1); 16359 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1; 16360 my $Lib_SName = parse_libname($Lib_Name, "name+ext", $OStarget); 16361 16362 if($CheckImpl and not $IsNeededLib) { 16363 getImplementations($LibVersion, $Lib_Path); 16364 } 16365 16366 push(@RecurLib, $Lib_Name); 16367 my (%Value_Interface, %Interface_Value, %NeededLib) = (); 16368 if(not $IsNeededLib) 16369 { # libstdc++ and libc are always used by other libs 16370 # if you test one of these libs then you not need 16371 # to find them in the system for reusing 16372 if(parse_libname($Lib_Name, "short", $OStarget) eq "libstdc++") 16373 { # libstdc++.so.6 16374 $STDCXX_TESTING = 1; 16375 } 16376 if(parse_libname($Lib_Name, "short", $OStarget) eq "libc") 16377 { # libc-2.11.3.so 16378 $GLIBC_TESTING = 1; 16379 } 16380 } 16381 my $DebugPath = ""; 16382 if($Debug and not $DumpSystem) 16383 { # debug mode 16384 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt"; 16385 mkpath(get_dirname($DebugPath)); 16386 } 16387 if($OStarget eq "macos") 16388 { # Mac OS X: *.dylib, *.a 16389 my $OtoolCmd = get_CmdPath("otool"); 16390 if(not $OtoolCmd) { 16391 exitStatus("Not_Found", "can't find \"otool\""); 16392 } 16393 $OtoolCmd .= " -TV \"$Lib_Path\" 2>\"$TMP_DIR/null\""; 16394 if($DebugPath) 16395 { # debug mode 16396 # write to file 16397 system($OtoolCmd." >\"$DebugPath\""); 16398 open(LIB, $DebugPath); 16399 } 16400 else 16401 { # write to pipe 16402 open(LIB, $OtoolCmd." |"); 16403 } 16404 while(<LIB>) 16405 { 16406 if(/[^_]+\s+_([\w\$]+)\s*\Z/) 16407 { 16408 my $realname = $1; 16409 if($IsNeededLib) 16410 { 16411 if(not $GroupNames->{$Lib_SName}) 16412 { 16413 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name; 16414 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1; 16415 } 16416 } 16417 else 16418 { 16419 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name; 16420 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1; 16421 if($COMMON_LANGUAGE{$LibVersion} ne "C++" 16422 and $realname=~/\A(_Z|\?)/) { 16423 setLanguage($LibVersion, "C++"); 16424 } 16425 if($CheckObjectsOnly 16426 and $LibVersion==1) { 16427 $CheckedSymbols{"Binary"}{$realname} = 1; 16428 } 16429 } 16430 } 16431 } 16432 close(LIB); 16433 if($LIB_TYPE eq "dynamic") 16434 { # dependencies 16435 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |"); 16436 while(<LIB>) 16437 { 16438 if(/\s*([\/\\].+\.$LIB_EXT)\s*/ 16439 and $1 ne $Lib_Path) { 16440 $NeededLib{$1} = 1; 16441 } 16442 } 16443 close(LIB); 16444 } 16445 } 16446 elsif($OStarget eq "windows") 16447 { # Windows *.dll, *.lib 16448 my $DumpBinCmd = get_CmdPath("dumpbin"); 16449 if(not $DumpBinCmd) { 16450 exitStatus("Not_Found", "can't find \"dumpbin\""); 16451 } 16452 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null"; 16453 if($DebugPath) 16454 { # debug mode 16455 # write to file 16456 system($DumpBinCmd." >\"$DebugPath\""); 16457 open(LIB, $DebugPath); 16458 } 16459 else 16460 { # write to pipe 16461 open(LIB, $DumpBinCmd." |"); 16462 } 16463 while(<LIB>) 16464 { # 1197 4AC 0000A620 SetThreadStackGuarantee 16465 # 1198 4AD SetThreadToken (forwarded to ...) 16466 # 3368 _o2i_ECPublicKey 16467 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*\Z/i 16468 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/ 16469 or /\A\s*\d+\s+_([\w\?\@]+)\s*\Z/) 16470 { # dynamic, static and forwarded symbols 16471 my $realname = $1; 16472 if($IsNeededLib) 16473 { 16474 if(not $GroupNames->{$Lib_SName}) 16475 { 16476 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name; 16477 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1; 16478 } 16479 } 16480 else 16481 { 16482 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name; 16483 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1; 16484 if($COMMON_LANGUAGE{$LibVersion} ne "C++" 16485 and $realname=~/\A(_Z|\?)/) { 16486 setLanguage($LibVersion, "C++"); 16487 } 16488 if($CheckObjectsOnly 16489 and $LibVersion==1) { 16490 $CheckedSymbols{"Binary"}{$realname} = 1; 16491 } 16492 } 16493 } 16494 } 16495 close(LIB); 16496 if($LIB_TYPE eq "dynamic") 16497 { # dependencies 16498 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |"); 16499 while(<LIB>) 16500 { 16501 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i 16502 and $1 ne $Lib_Path) { 16503 $NeededLib{path_format($1, $OSgroup)} = 1; 16504 } 16505 } 16506 close(LIB); 16507 } 16508 } 16509 else 16510 { # Unix; *.so, *.a 16511 # Symbian: *.dso, *.lib 16512 my $ReadelfCmd = get_CmdPath("readelf"); 16513 if(not $ReadelfCmd) { 16514 exitStatus("Not_Found", "can't find \"readelf\""); 16515 } 16516 $ReadelfCmd .= " -WhlSsdA \"$Lib_Path\" 2>\"$TMP_DIR/null\""; 16517 if($DebugPath) 16518 { # debug mode 16519 # write to file 16520 system($ReadelfCmd." >\"$DebugPath\""); 16521 open(LIB, $DebugPath); 16522 } 16523 else 16524 { # write to pipe 16525 open(LIB, $ReadelfCmd." |"); 16526 } 16527 my $symtab=0; # indicates that we are processing 'symtab' section of 'readelf' output 16528 while(<LIB>) 16529 { 16530 if($LIB_TYPE eq "dynamic") 16531 { # dynamic library specifics 16532 if($symtab==1) 16533 { 16534 if(/'\.dynsym'/) 16535 { # dynamic table 16536 $symtab=0; 16537 next; 16538 } 16539 else 16540 { # do nothing with symtab 16541 next; 16542 } 16543 } 16544 elsif(/'\.symtab'/) 16545 { # symbol table 16546 $symtab=1; 16547 next; 16548 } 16549 } 16550 if(my ($fullname, $idx, $Ndx, $type, $size, $bind) = readline_ELF($_)) 16551 { # read ELF entry 16552 if( $Ndx eq "UND" ) 16553 { # ignore interfaces that are imported from somewhere else 16554 next; 16555 } 16556 if($bind eq "WEAK" 16557 and $Weak eq "-Weak") 16558 { # skip WEAK symbols 16559 next; 16560 } 16561 my ($realname, $version_spec, $version) = separate_symbol($fullname); 16562 if($type eq "OBJECT") 16563 { # global data 16564 $GlobalDataObject{$LibVersion}{$fullname} = 1; 16565 $GlobalDataObject{$LibVersion}{$realname} = 1; 16566 } 16567 if($IsNeededLib) 16568 { 16569 if(not $GroupNames->{$Lib_SName}) 16570 { 16571 $DepSymbol_Library{$LibVersion}{$fullname} = $Lib_Name; 16572 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$fullname} = ($type eq "OBJECT")?-$size:1; 16573 } 16574 } 16575 else 16576 { 16577 $Symbol_Library{$LibVersion}{$fullname} = $Lib_Name; 16578 $Library_Symbol{$LibVersion}{$Lib_Name}{$fullname} = ($type eq "OBJECT")?-$size:1; 16579 if($LIB_EXT eq "so") 16580 { # value 16581 $Interface_Value{$LibVersion}{$fullname} = $idx; 16582 $Value_Interface{$LibVersion}{$idx}{$fullname} = 1; 16583 } 16584 if($COMMON_LANGUAGE{$LibVersion} ne "C++" 16585 and $realname=~/\A(_Z|\?)/) { 16586 setLanguage($LibVersion, "C++"); 16587 } 16588 if($CheckObjectsOnly 16589 and $LibVersion==1) { 16590 $CheckedSymbols{"Binary"}{$fullname} = 1; 16591 } 16592 } 16593 } 16594 elsif($LIB_TYPE eq "dynamic") 16595 { # dynamic library specifics 16596 if(/NEEDED.+\[([^\[\]]+)\]/) 16597 { # dependencies: 16598 # 0x00000001 (NEEDED) Shared library: [libc.so.6] 16599 $NeededLib{$1} = 1; 16600 } 16601 } 16602 } 16603 close(LIB); 16604 } 16605 if(not $IsNeededLib and $LIB_EXT eq "so") 16606 { # get symbol versions 16607 foreach my $Symbol (keys(%{$Symbol_Library{$LibVersion}})) 16608 { 16609 next if(index($Symbol,"\@")==-1); 16610 if(my $Value = $Interface_Value{$LibVersion}{$Symbol}) 16611 { 16612 my $Interface_SymName = ""; 16613 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}})) 16614 { 16615 if($Symbol_SameValue ne $Symbol 16616 and index($Symbol_SameValue,"\@")==-1) 16617 { 16618 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol; 16619 $Interface_SymName = $Symbol_SameValue; 16620 last; 16621 } 16622 } 16623 if(not $Interface_SymName) 16624 { 16625 if($Symbol=~/\A([^\@\$\?]*)[\@\$]+([^\@\$]*)\Z/ 16626 and not $SymVer{$LibVersion}{$1}) { 16627 $SymVer{$LibVersion}{$1} = $Symbol; 16628 } 16629 } 16630 } 16631 } 16632 } 16633 foreach my $DyLib (sort keys(%NeededLib)) 16634 { 16635 my $DepPath = find_lib_path($LibVersion, $DyLib); 16636 if($DepPath and -f $DepPath) { 16637 readSymbols_Lib($LibVersion, $DepPath, 1, $GroupNames, "+Weak"); 16638 } 16639 } 16640 pop(@RecurLib); 16641 return $Library_Symbol{$LibVersion}; 16642} 16643 16644sub get_path_prefixes($) 16645{ 16646 my $Path = $_[0]; 16647 my ($Dir, $Name) = separate_path($Path); 16648 my %Prefixes = (); 16649 foreach my $Prefix (reverse(split(/[\/\\]+/, $Dir))) 16650 { 16651 $Prefixes{$Name} = 1; 16652 $Name = joinPath($Prefix, $Name); 16653 last if(keys(%Prefixes)>5 or $Prefix eq "include"); 16654 } 16655 return keys(%Prefixes); 16656} 16657 16658sub detectSystemHeaders() 16659{ 16660 my @SysHeaders = (); 16661 foreach my $DevelPath (keys(%{$SystemPaths{"include"}})) 16662 { 16663 next if(not -d $DevelPath); 16664 # search for all header files in the /usr/include 16665 # with or without extension (ncurses.h, QtCore, ...) 16666 @SysHeaders = (@SysHeaders, cmd_find($DevelPath,"f","","")); 16667 foreach my $Link (cmd_find($DevelPath,"l","","")) 16668 { # add symbolic links 16669 if(-f $Link) { 16670 push(@SysHeaders, $Link); 16671 } 16672 } 16673 } 16674 foreach my $DevelPath (keys(%{$SystemPaths{"lib"}})) 16675 { 16676 next if(not -d $DevelPath); 16677 # search for config headers in the /usr/lib 16678 @SysHeaders = (@SysHeaders, cmd_find($DevelPath,"f","*.h","")); 16679 foreach my $Dir (cmd_find($DevelPath,"d","include","")) 16680 { # search for all include directories 16681 # this is for headers that are installed to /usr/lib 16682 # Example: Qt4 headers in Mandriva (/usr/lib/qt4/include/) 16683 if($Dir=~/\/(gcc|jvm|syslinux|kdb)\//) { 16684 next; 16685 } 16686 @SysHeaders = (@SysHeaders, cmd_find($Dir,"f","","")); 16687 } 16688 } 16689 foreach my $Path (@SysHeaders) 16690 { 16691 foreach my $Part (get_path_prefixes($Path)) { 16692 $SystemHeaders{$Part}{$Path}=1; 16693 } 16694 } 16695} 16696 16697sub detectSystemObjects() 16698{ 16699 foreach my $DevelPath (keys(%{$SystemPaths{"lib"}})) 16700 { 16701 next if(not -d $DevelPath); 16702 foreach my $Path (find_libs($DevelPath,"","")) 16703 { # search for shared libraries in the /usr/lib (including symbolic links) 16704 $SystemObjects{parse_libname(get_filename($Path), "name+ext", $OStarget)}{$Path}=1; 16705 } 16706 } 16707} 16708 16709sub getSOPaths($) 16710{ 16711 my $LibVersion = $_[0]; 16712 my @SoPaths = (); 16713 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"})) 16714 { 16715 if(not -e $Dest) { 16716 exitStatus("Access_Error", "can't access \'$Dest\'"); 16717 } 16718 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion); 16719 foreach (@SoPaths_Dest) { 16720 push(@SoPaths, $_); 16721 } 16722 } 16723 return sort @SoPaths; 16724} 16725 16726sub skip_lib($$) 16727{ 16728 my ($Path, $LibVersion) = @_; 16729 return 1 if(not $Path or not $LibVersion); 16730 my $Name = get_filename($Path); 16731 if($SkipLibs{$LibVersion}{"Name"}{$Name}) { 16732 return 1; 16733 } 16734 my $ShortName = parse_libname($Name, "name+ext", $OStarget); 16735 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) { 16736 return 1; 16737 } 16738 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}})) 16739 { 16740 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) { 16741 return 1; 16742 } 16743 } 16744 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}})) 16745 { 16746 if($Name=~/$P/) { 16747 return 1; 16748 } 16749 if($P=~/[\/\\]/ and $Path=~/$P/) { 16750 return 1; 16751 } 16752 } 16753 return 0; 16754} 16755 16756sub skipHeader($$) 16757{ 16758 my ($Path, $LibVersion) = @_; 16759 return 1 if(not $Path or not $LibVersion); 16760 if(not keys(%{$SkipHeaders{$LibVersion}})) { 16761 return 0; 16762 } 16763 if(defined $Cache{"skipHeader"}{$Path}) { 16764 return $Cache{"skipHeader"}{$Path}; 16765 } 16766 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_)); 16767} 16768 16769sub skipHeader_I($$) 16770{ # returns: 16771 # 1 - if header should NOT be included and checked 16772 # 2 - if header should NOT be included, but should be checked 16773 my ($Path, $LibVersion) = @_; 16774 my $Name = get_filename($Path); 16775 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) { 16776 return $Kind; 16777 } 16778 foreach my $D (keys(%{$SkipHeaders{$LibVersion}{"Path"}})) 16779 { 16780 if($Path=~/\Q$D\E([\/\\]|\Z)/) { 16781 return $SkipHeaders{$LibVersion}{"Path"}{$D}; 16782 } 16783 } 16784 foreach my $P (keys(%{$SkipHeaders{$LibVersion}{"Pattern"}})) 16785 { 16786 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P}) 16787 { 16788 if($Name=~/$P/) { 16789 return $Kind; 16790 } 16791 if($P=~/[\/\\]/ and $Path=~/$P/) { 16792 return $Kind; 16793 } 16794 } 16795 } 16796 return 0; 16797} 16798 16799sub register_objects($$) 16800{ 16801 my ($Dir, $LibVersion) = @_; 16802 if($SystemPaths{"lib"}{$Dir}) 16803 { # system directory 16804 return; 16805 } 16806 if($RegisteredObjDirs{$LibVersion}{$Dir}) 16807 { # already registered 16808 return; 16809 } 16810 foreach my $Path (find_libs($Dir,"",1)) 16811 { 16812 next if(ignore_path($Path)); 16813 next if(skip_lib($Path, $LibVersion)); 16814 $InputObject_Paths{$LibVersion}{get_filename($Path)}{$Path} = 1; 16815 } 16816 $RegisteredObjDirs{$LibVersion}{$Dir} = 1; 16817} 16818 16819sub getSOPaths_Dest($$) 16820{ 16821 my ($Dest, $LibVersion) = @_; 16822 if(skip_lib($Dest, $LibVersion)) { 16823 return (); 16824 } 16825 if(-f $Dest) 16826 { 16827 if(not parse_libname($Dest, "name", $OStarget)) { 16828 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'"); 16829 } 16830 $InputObject_Paths{$LibVersion}{get_filename($Dest)}{$Dest} = 1; 16831 register_objects(get_dirname($Dest), $LibVersion); 16832 return ($Dest); 16833 } 16834 elsif(-d $Dest) 16835 { 16836 $Dest=~s/[\/\\]+\Z//g; 16837 my %Libs = (); 16838 if($SystemPaths{"lib"}{$Dest}) 16839 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor 16840 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...) 16841 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*\.$LIB_EXT*",2)) 16842 { # all files and symlinks that match the name of a library 16843 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i) 16844 { 16845 $InputObject_Paths{$LibVersion}{get_filename($Path)}{$Path} = 1; 16846 $Libs{resolve_symlink($Path)}=1; 16847 } 16848 } 16849 } 16850 else 16851 { # search for all files and symlinks 16852 foreach my $Path (find_libs($Dest,"","")) 16853 { 16854 next if(ignore_path($Path)); 16855 next if(skip_lib($Path, $LibVersion)); 16856 $InputObject_Paths{$LibVersion}{get_filename($Path)}{$Path} = 1; 16857 $Libs{resolve_symlink($Path)}=1; 16858 } 16859 if($OSgroup eq "macos") 16860 { # shared libraries on MacOS X may have no extension 16861 foreach my $Path (cmd_find($Dest,"f","","")) 16862 { 16863 next if(ignore_path($Path)); 16864 next if(skip_lib($Path, $LibVersion)); 16865 if(get_filename($Path)!~/\./ 16866 and cmd_file($Path)=~/(shared|dynamic)\s+library/i) 16867 { 16868 $InputObject_Paths{$LibVersion}{get_filename($Path)}{$Path} = 1; 16869 $Libs{resolve_symlink($Path)}=1; 16870 } 16871 } 16872 } 16873 } 16874 return keys(%Libs); 16875 } 16876 else { 16877 return (); 16878 } 16879} 16880 16881sub isCyclical($$) 16882{ 16883 my ($Stack, $Value) = @_; 16884 return (grep {$_ eq $Value} @{$Stack}); 16885} 16886 16887sub generateTemplate() 16888{ 16889 writeFile("VERSION.xml", $DescriptorTemplate."\n"); 16890 printMsg("INFO", "XML-descriptor template ./VERSION.xml has been generated"); 16891} 16892 16893sub detectWordSize() 16894{ 16895 return "" if(not $GCC_PATH); 16896 if($Cache{"detectWordSize"}) { 16897 return $Cache{"detectWordSize"}; 16898 } 16899 writeFile("$TMP_DIR/empty.h", ""); 16900 my $Defines = `$GCC_PATH -E -dD \"$TMP_DIR/empty.h\"`; 16901 unlink("$TMP_DIR/empty.h"); 16902 my $WSize = 0; 16903 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/) 16904 { # GCC 4 16905 $WSize = $1; 16906 } 16907 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/) 16908 { # GCC 3 16909 my $PTRDIFF = $1; 16910 if($PTRDIFF=~/long/) { 16911 $WSize = "8"; 16912 } 16913 else { 16914 $WSize = "4"; 16915 } 16916 } 16917 if(not int($WSize)) { 16918 exitStatus("Error", "can't check WORD size"); 16919 } 16920 return ($Cache{"detectWordSize"} = $WSize); 16921} 16922 16923sub majorVersion($) 16924{ 16925 my $V = $_[0]; 16926 return 0 if(not $V); 16927 my @VParts = split(/\./, $V); 16928 return $VParts[0]; 16929} 16930 16931sub cmpVersions($$) 16932{ # compare two versions in dotted-numeric format 16933 my ($V1, $V2) = @_; 16934 return 0 if($V1 eq $V2); 16935 my @V1Parts = split(/\./, $V1); 16936 my @V2Parts = split(/\./, $V2); 16937 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++) { 16938 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i])); 16939 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i])); 16940 } 16941 return -1 if($#V1Parts < $#V2Parts); 16942 return 1 if($#V1Parts > $#V2Parts); 16943 return 0; 16944} 16945 16946sub read_ABI_Dump($$) 16947{ 16948 my ($LibVersion, $Path) = @_; 16949 return if(not $LibVersion or not -e $Path); 16950 my $FilePath = ""; 16951 if($Path=~/\.abi\Z/) 16952 { # input *.abi 16953 $FilePath = $Path; 16954 } 16955 else 16956 { # input *.abi.tar.gz 16957 $FilePath = unpackDump($Path); 16958 } 16959 if($FilePath!~/\.abi\Z/) { 16960 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it"); 16961 } 16962 16963 my $Line = readLineNum($FilePath, 1); 16964 if($Line=~/xml/) { 16965 exitStatus("Invalid_Dump", "reading of XML-format ABI dumps is not implemented yet"); 16966 } 16967 16968 open(DUMP, $FilePath); 16969 local $/ = undef; 16970 my $Content = <DUMP>; 16971 close(DUMP); 16972 16973 if(get_dirname($FilePath) eq $TMP_DIR."/unpack") 16974 { # remove temp file 16975 unlink($FilePath); 16976 } 16977 if($Content!~/};\s*\Z/) { 16978 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it"); 16979 } 16980 my $LibraryABI = eval($Content); 16981 if(not $LibraryABI) { 16982 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again"); 16983 } 16984 # new dumps (>=1.22) have a personal versioning 16985 my $DumpVersion = $LibraryABI->{"ABI_DUMP_VERSION"}; 16986 my $ToolVersion = $LibraryABI->{"ABI_COMPLIANCE_CHECKER_VERSION"}; 16987 if(not $DumpVersion) 16988 { # old dumps (<=1.21.6) have been marked by the tool version 16989 $DumpVersion = $ToolVersion; 16990 } 16991 $UsedDump{$LibVersion}{"V"} = $DumpVersion; 16992 if(majorVersion($DumpVersion) ne majorVersion($ABI_DUMP_VERSION)) 16993 { # should be compatible with dumps of the same major version 16994 if(cmpVersions($DumpVersion, $ABI_DUMP_VERSION)>0) 16995 { # Don't know how to parse future dump formats 16996 exitStatus("Dump_Version", "incompatible version $DumpVersion of specified ABI dump (newer than $ABI_DUMP_VERSION)"); 16997 } 16998 elsif(cmpVersions($DumpVersion, $TOOL_VERSION)>0 and not $LibraryABI->{"ABI_DUMP_VERSION"}) 16999 { # Don't know how to parse future dump formats 17000 exitStatus("Dump_Version", "incompatible version $DumpVersion of specified ABI dump (newer than $TOOL_VERSION)"); 17001 } 17002 if($UseOldDumps) 17003 { 17004 if(cmpVersions($DumpVersion, $OLDEST_SUPPORTED_VERSION)<0) { 17005 exitStatus("Dump_Version", "incompatible version $DumpVersion of specified ABI dump (older than $OLDEST_SUPPORTED_VERSION)"); 17006 } 17007 } 17008 else 17009 { 17010 my $Msg = "incompatible version $DumpVersion of specified ABI dump (allowed only ".majorVersion($ABI_DUMP_VERSION).".0<=V<=$ABI_DUMP_VERSION)"; 17011 if(cmpVersions($DumpVersion, $OLDEST_SUPPORTED_VERSION)>=0) { 17012 $Msg .= "\nUse -old-dumps option to use old-version dumps ($OLDEST_SUPPORTED_VERSION<=V<".majorVersion($ABI_DUMP_VERSION).".0)"; 17013 } 17014 exitStatus("Dump_Version", $Msg); 17015 } 17016 } 17017 if(not checkDump($LibVersion, "2.11")) 17018 { # old ABI dumps 17019 $UsedDump{$LibVersion}{"BinOnly"} = 1; 17020 } 17021 elsif($LibraryABI->{"BinOnly"}) 17022 { # ABI dump created with --binary option 17023 $UsedDump{$LibVersion}{"BinOnly"} = 1; 17024 } 17025 else 17026 { # default 17027 $UsedDump{$LibVersion}{"SrcBin"} = 1; 17028 } 17029 if(defined $LibraryABI->{"Mode"} 17030 and $LibraryABI->{"Mode"} eq "Extended") 17031 { # --ext option 17032 $ExtendedCheck = 1; 17033 } 17034 if(my $Lang = $LibraryABI->{"Language"}) 17035 { 17036 $UsedDump{$LibVersion}{"L"} = $Lang; 17037 setLanguage($LibVersion, $Lang); 17038 } 17039 if(checkDump($LibVersion, "2.15")) { 17040 $TypeInfo{$LibVersion} = $LibraryABI->{"TypeInfo"}; 17041 } 17042 else 17043 { # support for old ABI dumps 17044 my $TInfo = $LibraryABI->{"TypeInfo"}; 17045 if(not $TInfo) 17046 { # support for older ABI dumps 17047 $TInfo = $LibraryABI->{"TypeDescr"}; 17048 } 17049 my %Tid_TDid = (); 17050 foreach my $TDid (keys(%{$TInfo})) 17051 { 17052 foreach my $Tid (keys(%{$TInfo->{$TDid}})) 17053 { 17054 $MAX_ID = $Tid if($Tid>$MAX_ID); 17055 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID); 17056 $Tid_TDid{$Tid}{$TDid}=1; 17057 } 17058 } 17059 my %NewID = (); 17060 foreach my $Tid (keys(%Tid_TDid)) 17061 { 17062 my @TDids = keys(%{$Tid_TDid{$Tid}}); 17063 if($#TDids>=1) 17064 { 17065 foreach my $TDid (@TDids) 17066 { 17067 if($TDid) { 17068 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}}; 17069 } 17070 else 17071 { 17072 if(my $ID = ++$MAX_ID) 17073 { 17074 $NewID{$TDid}{$Tid} = $ID; 17075 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}}; 17076 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID; 17077 } 17078 } 17079 } 17080 } 17081 else 17082 { 17083 my $TDid = $TDids[0]; 17084 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}}; 17085 } 17086 } 17087 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}})) 17088 { 17089 my %Info = %{$TypeInfo{$LibVersion}{$Tid}}; 17090 if(defined $Info{"BaseType"}) 17091 { 17092 my $Bid = $Info{"BaseType"}{"Tid"}; 17093 my $BDid = $Info{"BaseType"}{"TDid"}; 17094 $BDid="" if(not defined $BDid); 17095 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) { 17096 $TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"Tid"} = $ID; 17097 } 17098 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"}); 17099 } 17100 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"}); 17101 } 17102 } 17103 read_Machine_DumpInfo($LibraryABI, $LibVersion); 17104 $SymbolInfo{$LibVersion} = $LibraryABI->{"SymbolInfo"}; 17105 if(not $SymbolInfo{$LibVersion}) 17106 { # support for old dumps 17107 $SymbolInfo{$LibVersion} = $LibraryABI->{"FuncDescr"}; 17108 } 17109 if(not keys(%{$SymbolInfo{$LibVersion}})) 17110 { # validation of old-version dumps 17111 if(not $ExtendedCheck) { 17112 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid"); 17113 } 17114 } 17115 $Library_Symbol{$LibVersion} = $LibraryABI->{"Symbols"}; 17116 if(not $Library_Symbol{$LibVersion}) 17117 { # support for old dumps 17118 $Library_Symbol{$LibVersion} = $LibraryABI->{"Interfaces"}; 17119 } 17120 if(checkDump($LibVersion, "2.15")) { 17121 $DepLibrary_Symbol{$LibVersion} = $LibraryABI->{"DepSymbols"}; 17122 } 17123 else 17124 { # support for old ABI dumps 17125 my $DepSymbols = $LibraryABI->{"DepSymbols"}; 17126 if(not $DepSymbols) { 17127 $DepSymbols = $LibraryABI->{"DepInterfaces"}; 17128 } 17129 if(not $DepSymbols) 17130 { # Cannot reconstruct DepSymbols. This may result in false 17131 # positives if the old dump is for library 2. Not a problem if 17132 # old dumps are only from old libraries. 17133 $DepSymbols = {}; 17134 } 17135 foreach my $Symbol (keys(%{$DepSymbols})) { 17136 $DepSymbol_Library{$LibVersion}{$Symbol} = 1; 17137 } 17138 } 17139 $SymVer{$LibVersion} = $LibraryABI->{"SymbolVersion"}; 17140 $Descriptor{$LibVersion}{"Version"} = $LibraryABI->{"LibraryVersion"}; 17141 $SkipTypes{$LibVersion} = $LibraryABI->{"SkipTypes"}; 17142 if(not $SkipTypes{$LibVersion}) 17143 { # support for old dumps 17144 $SkipTypes{$LibVersion} = $LibraryABI->{"OpaqueTypes"}; 17145 } 17146 $SkipSymbols{$LibVersion} = $LibraryABI->{"SkipSymbols"}; 17147 if(not $SkipSymbols{$LibVersion}) 17148 { # support for old dumps 17149 $SkipSymbols{$LibVersion} = $LibraryABI->{"SkipInterfaces"}; 17150 } 17151 if(not $SkipSymbols{$LibVersion}) 17152 { # support for old dumps 17153 $SkipSymbols{$LibVersion} = $LibraryABI->{"InternalInterfaces"}; 17154 } 17155 $SkipNameSpaces{$LibVersion} = $LibraryABI->{"SkipNameSpaces"}; 17156 $TargetHeaders{$LibVersion} = $LibraryABI->{"TargetHeaders"}; 17157 foreach my $Path (keys(%{$LibraryABI->{"SkipHeaders"}})) 17158 { 17159 $SkipHeadersList{$LibVersion}{$Path} = $LibraryABI->{"SkipHeaders"}{$Path}; 17160 my ($CPath, $Type) = classifyPath($Path); 17161 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $LibraryABI->{"SkipHeaders"}{$Path}; 17162 } 17163 read_Headers_DumpInfo($LibraryABI, $LibVersion); 17164 read_Libs_DumpInfo($LibraryABI, $LibVersion); 17165 if(not checkDump($LibVersion, "2.10.1") 17166 or not $TargetHeaders{$LibVersion}) 17167 { # support for old ABI dumps: added target headers 17168 foreach (keys(%{$Registered_Headers{$LibVersion}})) { 17169 $TargetHeaders{$LibVersion}{get_filename($_)}=1; 17170 } 17171 } 17172 $Constants{$LibVersion} = $LibraryABI->{"Constants"}; 17173 $NestedNameSpaces{$LibVersion} = $LibraryABI->{"NameSpaces"}; 17174 if(not $NestedNameSpaces{$LibVersion}) 17175 { # support for old dumps 17176 # Cannot reconstruct NameSpaces. This may affect design 17177 # of the compatibility report. 17178 $NestedNameSpaces{$LibVersion} = {}; 17179 } 17180 # target system type 17181 # needed to adopt HTML report 17182 if(not $DumpSystem) 17183 { # to use in createSymbolsList(...) 17184 $OStarget = $LibraryABI->{"Target"}; 17185 } 17186 # recreate environment 17187 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}})) 17188 { 17189 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}})) 17190 { 17191 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name; 17192 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1) 17193 { # data marked as -size in the dump 17194 $GlobalDataObject{$LibVersion}{$Symbol}=1; 17195 } 17196 if($COMMON_LANGUAGE{$LibVersion} ne "C++" 17197 and $Symbol=~/\A(_Z|\?)/) { 17198 setLanguage($LibVersion, "C++"); 17199 } 17200 } 17201 } 17202 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}})) 17203 { 17204 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) { 17205 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name; 17206 } 17207 } 17208 17209 my @VFunc = (); 17210 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}})) 17211 { 17212 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"}; 17213 if($MnglName) 17214 { 17215 if(not $Symbol_Library{$LibVersion}{$MnglName} 17216 and not $DepSymbol_Library{$LibVersion}{$MnglName}) { 17217 push(@VFunc, $MnglName); 17218 } 17219 } 17220 } 17221 translateSymbols(@VFunc, $LibVersion); 17222 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion); 17223 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion); 17224 17225 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}})) 17226 { 17227 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}) 17228 { # support for old ABI dumps < 2.0 (ACC 1.22) 17229 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}})) 17230 { 17231 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId}) 17232 { 17233 if($Access ne "public") { 17234 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access; 17235 } 17236 } 17237 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {}; 17238 } 17239 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}); 17240 } 17241 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}}; 17242 if(defined $TInfo{"Base"}) 17243 { 17244 foreach (keys(%{$TInfo{"Base"}})) { 17245 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1; 17246 } 17247 } 17248 if($TInfo{"Type"} eq "Typedef" and defined $TInfo{"BaseType"}) 17249 { 17250 if(my $BTid = $TInfo{"BaseType"}{"Tid"}) 17251 { 17252 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"}; 17253 if(not $BName) 17254 { # broken type 17255 next; 17256 } 17257 if($TInfo{"Name"} eq $BName) 17258 { # typedef to "class Class" 17259 # should not be registered in TName_Tid 17260 next; 17261 } 17262 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) { 17263 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName; 17264 } 17265 } 17266 } 17267 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}}) 17268 { # classes: class (id1), typedef (artificial, id2 > id1) 17269 $TName_Tid{$LibVersion}{$TInfo{"Name"}} = $TypeId; 17270 } 17271 } 17272 17273 if(not checkDump($LibVersion, "2.15")) 17274 { # support for old ABI dumps 17275 my %Dups = (); 17276 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}})) 17277 { 17278 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}) 17279 { 17280 if(not defined $TypeInfo{$LibVersion}{$ClassId}) 17281 { # remove template decls 17282 delete($SymbolInfo{$LibVersion}{$InfoId}); 17283 next; 17284 } 17285 } 17286 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"}; 17287 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"}) 17288 { # templates 17289 delete($SymbolInfo{$LibVersion}{$InfoId}); 17290 } 17291 } 17292 } 17293 17294 $Descriptor{$LibVersion}{"Dump"} = 1; 17295} 17296 17297sub read_Machine_DumpInfo($$) 17298{ 17299 my ($LibraryABI, $LibVersion) = @_; 17300 if($LibraryABI->{"Arch"}) { 17301 $CPU_ARCH{$LibVersion} = $LibraryABI->{"Arch"}; 17302 } 17303 if($LibraryABI->{"WordSize"}) { 17304 $WORD_SIZE{$LibVersion} = $LibraryABI->{"WordSize"}; 17305 } 17306 else 17307 { # support for old dumps 17308 $WORD_SIZE{$LibVersion} = $LibraryABI->{"SizeOfPointer"}; 17309 } 17310 if(not $WORD_SIZE{$LibVersion}) 17311 { # support for old dumps (<1.23) 17312 if(my $Tid = getTypeIdByName("char*", $LibVersion)) 17313 { # size of char* 17314 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"}; 17315 } 17316 else 17317 { 17318 my $PSize = 0; 17319 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}})) 17320 { 17321 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer") 17322 { # any "pointer"-type 17323 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"}; 17324 last; 17325 } 17326 } 17327 if($PSize) 17328 { # a pointer type size 17329 $WORD_SIZE{$LibVersion} = $PSize; 17330 } 17331 else { 17332 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)"); 17333 } 17334 } 17335 } 17336 if($LibraryABI->{"GccVersion"}) { 17337 $GCC_VERSION{$LibVersion} = $LibraryABI->{"GccVersion"}; 17338 } 17339} 17340 17341sub read_Libs_DumpInfo($$) 17342{ 17343 my ($LibraryABI, $LibVersion) = @_; 17344 if(keys(%{$Library_Symbol{$LibVersion}}) 17345 and not $DumpAPI) { 17346 $Descriptor{$LibVersion}{"Libs"} = "OK"; 17347 } 17348} 17349 17350sub read_Headers_DumpInfo($$) 17351{ 17352 my ($LibraryABI, $LibVersion) = @_; 17353 if(keys(%{$LibraryABI->{"Headers"}}) 17354 and not $DumpAPI) { 17355 $Descriptor{$LibVersion}{"Headers"} = "OK"; 17356 } 17357 foreach my $Identity (keys(%{$LibraryABI->{"Headers"}})) 17358 { # headers info is stored in the old dumps in the different way 17359 if($UseOldDumps 17360 and my $Name = $LibraryABI->{"Headers"}{$Identity}{"Name"}) 17361 { # support for old dumps: headers info corrected in 1.22 17362 $Identity = $Name; 17363 } 17364 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity; 17365 } 17366} 17367 17368sub find_libs($$$) 17369{ 17370 my ($Path, $Type, $MaxDepth) = @_; 17371 # FIXME: correct the search pattern 17372 return cmd_find($Path, $Type, ".*\\.$LIB_EXT\[0-9.]*", $MaxDepth); 17373} 17374 17375sub createDescriptor($$) 17376{ 17377 my ($LibVersion, $Path) = @_; 17378 if(not $LibVersion or not $Path 17379 or not -e $Path) { 17380 return ""; 17381 } 17382 if(-d $Path) 17383 { # directory with headers files and shared objects 17384 return " 17385 <version> 17386 ".$TargetVersion{$LibVersion}." 17387 </version> 17388 17389 <headers> 17390 $Path 17391 </headers> 17392 17393 <libs> 17394 $Path 17395 </libs>"; 17396 } 17397 else 17398 { # files 17399 if($Path=~/\.xml\Z/i) 17400 { # standard XML-descriptor 17401 return readFile($Path); 17402 } 17403 elsif(is_header($Path, 2, $LibVersion)) 17404 { # header file 17405 return " 17406 <version> 17407 ".$TargetVersion{$LibVersion}." 17408 </version> 17409 17410 <headers> 17411 $Path 17412 </headers> 17413 17414 <libs> 17415 none 17416 </libs>"; 17417 } 17418 elsif(parse_libname($Path, "name", $OStarget)) 17419 { # shared object 17420 return " 17421 <version> 17422 ".$TargetVersion{$LibVersion}." 17423 </version> 17424 17425 <headers> 17426 none 17427 </headers> 17428 17429 <libs> 17430 $Path 17431 </libs>"; 17432 } 17433 else 17434 { # standard XML-descriptor 17435 return readFile($Path); 17436 } 17437 } 17438} 17439 17440sub detect_lib_default_paths() 17441{ 17442 my %LPaths = (); 17443 if($OSgroup eq "bsd") 17444 { 17445 if(my $LdConfig = get_CmdPath("ldconfig")) 17446 { 17447 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`)) 17448 { 17449 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/) { 17450 $LPaths{"lib".$1} = $2; 17451 } 17452 } 17453 } 17454 else { 17455 printMsg("WARNING", "can't find ldconfig"); 17456 } 17457 } 17458 else 17459 { 17460 if(my $LdConfig = get_CmdPath("ldconfig")) 17461 { 17462 if($SystemRoot and $OSgroup eq "linux") 17463 { # use host (x86) ldconfig with the target (arm) ld.so.conf 17464 if(-e $SystemRoot."/etc/ld.so.conf") { 17465 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf"; 17466 } 17467 } 17468 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`)) 17469 { 17470 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/) 17471 { 17472 my ($Name, $Path) = ($1, $2); 17473 $Path=~s/[\/]{2,}/\//; 17474 $LPaths{$Name} = $Path; 17475 } 17476 } 17477 } 17478 elsif($OSgroup=~/linux/i) { 17479 printMsg("WARNING", "can't find ldconfig"); 17480 } 17481 } 17482 return \%LPaths; 17483} 17484 17485sub detect_bin_default_paths() 17486{ 17487 my $EnvPaths = $ENV{"PATH"}; 17488 if($OSgroup eq "beos") { 17489 $EnvPaths.=":".$ENV{"BETOOLS"}; 17490 } 17491 my $Sep = ($OSgroup eq "windows")?";":":|;"; 17492 foreach my $Path (sort {length($a)<=>length($b)} split(/$Sep/, $EnvPaths)) 17493 { 17494 $Path = path_format($Path, $OSgroup); 17495 $Path=~s/[\/\\]+\Z//g; 17496 next if(not $Path); 17497 if($SystemRoot 17498 and $Path=~/\A\Q$SystemRoot\E\//) 17499 { # do NOT use binaries from target system 17500 next; 17501 } 17502 $DefaultBinPaths{$Path} = 1; 17503 } 17504} 17505 17506sub detect_inc_default_paths() 17507{ 17508 return () if(not $GCC_PATH); 17509 my %DPaths = ("Cpp"=>{},"Gcc"=>{},"Inc"=>{}); 17510 writeFile("$TMP_DIR/empty.h", ""); 17511 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`)) 17512 { # detecting GCC default include paths 17513 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/) 17514 { 17515 my $Path = simplify_path($1); 17516 $Path=~s/[\/\\]+\Z//g; 17517 $Path = path_format($Path, $OSgroup); 17518 if($Path=~/c\+\+|\/g\+\+\//) 17519 { 17520 $DPaths{"Cpp"}{$Path}=1; 17521 if(not defined $MAIN_CPP_DIR 17522 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) { 17523 $MAIN_CPP_DIR = $Path; 17524 } 17525 } 17526 elsif($Path=~/gcc/) { 17527 $DPaths{"Gcc"}{$Path}=1; 17528 } 17529 else 17530 { 17531 next if($Path=~/local[\/\\]+include/); 17532 if($SystemRoot 17533 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/) 17534 { # The GCC include path for user headers is not a part of the system root 17535 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler 17536 # or it is the internal cross-GCC path like arm-linux-gnueabi/include 17537 next; 17538 } 17539 $DPaths{"Inc"}{$Path}=1; 17540 } 17541 } 17542 } 17543 unlink("$TMP_DIR/empty.h"); 17544 return %DPaths; 17545} 17546 17547sub detect_default_paths($) 17548{ 17549 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1); 17550 my $Search = $_[0]; 17551 if($Search!~/inc/) { 17552 $HSearch = 0; 17553 } 17554 if($Search!~/lib/) { 17555 $LSearch = 0; 17556 } 17557 if($Search!~/bin/) { 17558 $BSearch = 0; 17559 } 17560 if($Search!~/gcc/) { 17561 $GSearch = 0; 17562 } 17563 if(keys(%{$SystemPaths{"include"}})) 17564 { # <search_headers> section of the XML descriptor 17565 # do NOT search for systems headers 17566 $HSearch = 0; 17567 } 17568 if(keys(%{$SystemPaths{"lib"}})) 17569 { # <search_headers> section of the XML descriptor 17570 # do NOT search for systems headers 17571 $LSearch = 0; 17572 } 17573 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}})) 17574 { # additional search paths 17575 next if($Type eq "include" and not $HSearch); 17576 next if($Type eq "lib" and not $LSearch); 17577 next if($Type eq "bin" and not $BSearch); 17578 foreach my $Path (keys(%{$OS_AddPath{$OSgroup}{$Type}})) 17579 { 17580 next if(not -d $Path); 17581 $SystemPaths{$Type}{$Path} = $OS_AddPath{$OSgroup}{$Type}{$Path}; 17582 } 17583 } 17584 if($OSgroup ne "windows") 17585 { # unix-like 17586 foreach my $Type ("include", "lib", "bin") 17587 { # automatic detection of system "devel" directories 17588 next if($Type eq "include" and not $HSearch); 17589 next if($Type eq "lib" and not $LSearch); 17590 next if($Type eq "bin" and not $BSearch); 17591 my ($UsrDir, $RootDir) = ("/usr", "/"); 17592 if($SystemRoot and $Type ne "bin") 17593 { # 1. search for target headers and libraries 17594 # 2. use host commands: ldconfig, readelf, etc. 17595 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot); 17596 } 17597 foreach my $Path (cmd_find($RootDir,"d","*$Type*",1)) { 17598 $SystemPaths{$Type}{$Path} = 1; 17599 } 17600 if(-d $RootDir."/".$Type) 17601 { # if "/lib" is symbolic link 17602 if($RootDir eq "/") { 17603 $SystemPaths{$Type}{"/".$Type} = 1; 17604 } 17605 else { 17606 $SystemPaths{$Type}{$RootDir."/".$Type} = 1; 17607 } 17608 } 17609 if(-d $UsrDir) { 17610 foreach my $Path (cmd_find($UsrDir,"d","*$Type*",1)) { 17611 $SystemPaths{$Type}{$Path} = 1; 17612 } 17613 if(-d $UsrDir."/".$Type) 17614 { # if "/usr/lib" is symbolic link 17615 $SystemPaths{$Type}{$UsrDir."/".$Type} = 1; 17616 } 17617 } 17618 } 17619 } 17620 if($BSearch) 17621 { 17622 detect_bin_default_paths(); 17623 foreach my $Path (keys(%DefaultBinPaths)) { 17624 $SystemPaths{"bin"}{$Path} = $DefaultBinPaths{$Path}; 17625 } 17626 } 17627 # check environment variables 17628 if($OSgroup eq "beos") 17629 { 17630 foreach (keys(%{$SystemPaths{"bin"}})) 17631 { 17632 if($_ eq ".") { 17633 next; 17634 } 17635 foreach my $Path (cmd_find($_, "d", "bin", "")) 17636 { # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/ 17637 $SystemPaths{"bin"}{$Path} = 1; 17638 } 17639 } 17640 if($HSearch) 17641 { 17642 foreach my $Path (split(/:|;/, $ENV{"BEINCLUDES"})) 17643 { 17644 if(is_abs($Path)) { 17645 $DefaultIncPaths{$Path} = 1; 17646 } 17647 } 17648 } 17649 if($LSearch) 17650 { 17651 foreach my $Path (split(/:|;/, $ENV{"BELIBRARIES"}), split(/:|;/, $ENV{"LIBRARY_PATH"})) 17652 { 17653 if(is_abs($Path)) { 17654 $DefaultLibPaths{$Path} = 1; 17655 } 17656 } 17657 } 17658 } 17659 if($LSearch) 17660 { # using linker to get system paths 17661 if(my $LPaths = detect_lib_default_paths()) 17662 { # unix-like 17663 foreach my $Name (keys(%{$LPaths})) 17664 { 17665 if($SystemRoot 17666 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//) 17667 { # wrong ldconfig configuration 17668 # check your <sysroot>/etc/ld.so.conf 17669 next; 17670 } 17671 $DyLib_DefaultPath{$Name} = $LPaths->{$Name}; 17672 $DefaultLibPaths{get_dirname($LPaths->{$Name})} = 1; 17673 } 17674 } 17675 foreach my $Path (keys(%DefaultLibPaths)) { 17676 $SystemPaths{"lib"}{$Path} = $DefaultLibPaths{$Path}; 17677 } 17678 } 17679 if($BSearch) 17680 { 17681 if($CrossGcc) 17682 { # --cross-gcc=arm-linux-gcc 17683 if(-e $CrossGcc) 17684 { # absolute or relative path 17685 $GCC_PATH = get_abs_path($CrossGcc); 17686 } 17687 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc)) 17688 { # command name 17689 $GCC_PATH = $CrossGcc; 17690 } 17691 else { 17692 exitStatus("Access_Error", "can't access \'$CrossGcc\'"); 17693 } 17694 if($GCC_PATH=~/\s/) { 17695 $GCC_PATH = "\"".$GCC_PATH."\""; 17696 } 17697 } 17698 } 17699 if($GSearch) 17700 { # GCC path and default include dirs 17701 if(not $CrossGcc) { 17702 $GCC_PATH = get_CmdPath("gcc"); 17703 } 17704 if(not $GCC_PATH) { 17705 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH"); 17706 } 17707 if(not $CheckObjectsOnly_Opt) 17708 { 17709 if(my $GCC_Ver = get_dumpversion($GCC_PATH)) 17710 { 17711 my $GccTarget = get_dumpmachine($GCC_PATH); 17712 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget)"); 17713 if($GccTarget=~/symbian/) 17714 { 17715 $OStarget = "symbian"; 17716 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget}; 17717 } 17718 } 17719 else { 17720 exitStatus("Error", "something is going wrong with the GCC compiler"); 17721 } 17722 } 17723 if(not $NoStdInc) 17724 { # do NOT search in GCC standard paths 17725 my %DPaths = detect_inc_default_paths(); 17726 %DefaultCppPaths = %{$DPaths{"Cpp"}}; 17727 %DefaultGccPaths = %{$DPaths{"Gcc"}}; 17728 %DefaultIncPaths = %{$DPaths{"Inc"}}; 17729 foreach my $Path (keys(%DefaultIncPaths)) { 17730 $SystemPaths{"include"}{$Path} = $DefaultIncPaths{$Path}; 17731 } 17732 } 17733 } 17734 if($HSearch) 17735 { # user include paths 17736 my $IncPath = "/usr/include"; 17737 if($SystemRoot) { 17738 $IncPath = $SystemRoot.$IncPath; 17739 } 17740 if(-d $IncPath) { 17741 $UserIncPath{$IncPath}=1; 17742 } 17743 } 17744} 17745 17746sub getLIB_EXT($) 17747{ 17748 my $Target = $_[0]; 17749 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) { 17750 return $Ext; 17751 } 17752 return $OS_LibExt{$LIB_TYPE}{"default"}; 17753} 17754 17755sub getAR_EXT($) 17756{ 17757 my $Target = $_[0]; 17758 if(my $Ext = $OS_Archive{$Target}) { 17759 return $Ext; 17760 } 17761 return $OS_Archive{"default"}; 17762} 17763 17764sub get_dumpversion($) 17765{ 17766 my $Cmd = $_[0]; 17767 return "" if(not $Cmd); 17768 if($Cache{"get_dumpversion"}{$Cmd}) { 17769 return $Cache{"get_dumpversion"}{$Cmd}; 17770 } 17771 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`; 17772 chomp($V); 17773 return ($Cache{"get_dumpversion"}{$Cmd} = $V); 17774} 17775 17776sub get_dumpmachine($) 17777{ 17778 my $Cmd = $_[0]; 17779 return "" if(not $Cmd); 17780 if($Cache{"get_dumpmachine"}{$Cmd}) { 17781 return $Cache{"get_dumpmachine"}{$Cmd}; 17782 } 17783 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`; 17784 chomp($Machine); 17785 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine); 17786} 17787 17788sub check_command($) 17789{ 17790 my $Cmd = $_[0]; 17791 return "" if(not $Cmd); 17792 my @Options = ( 17793 "--version", 17794 "-help" 17795 ); 17796 foreach my $Opt (@Options) 17797 { 17798 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`; 17799 if($Info) { 17800 return 1; 17801 } 17802 } 17803 return 0; 17804} 17805 17806sub check_gcc($$) 17807{ 17808 my ($Cmd, $ReqVer) = @_; 17809 return 0 if(not $Cmd or not $ReqVer); 17810 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) { 17811 return $Cache{"check_gcc"}{$Cmd}{$ReqVer}; 17812 } 17813 if(my $GccVer = get_dumpversion($Cmd)) 17814 { 17815 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818") 17816 if(cmpVersions($GccVer, $ReqVer)>=0) { 17817 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd); 17818 } 17819 } 17820 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = ""); 17821} 17822 17823sub get_depth($) 17824{ 17825 if(defined $Cache{"get_depth"}{$_[0]}) { 17826 return $Cache{"get_depth"}{$_[0]} 17827 } 17828 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!)); 17829} 17830 17831sub find_gcc_cxx_headers($) 17832{ 17833 my $LibVersion = $_[0]; 17834 return if($Cache{"find_gcc_cxx_headers"});# this function should be called once 17835 # detecting system header paths 17836 foreach my $Path (sort {get_depth($b) <=> get_depth($a)} keys(%DefaultGccPaths)) 17837 { 17838 foreach my $HeaderPath (sort {get_depth($a) <=> get_depth($b)} cmd_find($Path,"f","","")) 17839 { 17840 my $FileName = get_filename($HeaderPath); 17841 next if($DefaultGccHeader{$FileName}); 17842 $DefaultGccHeader{$FileName} = $HeaderPath; 17843 } 17844 } 17845 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING) 17846 { 17847 foreach my $CppDir (sort {get_depth($b)<=>get_depth($a)} keys(%DefaultCppPaths)) 17848 { 17849 my @AllCppHeaders = cmd_find($CppDir,"f","",""); 17850 foreach my $Path (sort {get_depth($a)<=>get_depth($b)} @AllCppHeaders) 17851 { 17852 my $FileName = get_filename($Path); 17853 next if($DefaultCppHeader{$FileName}); 17854 $DefaultCppHeader{$FileName} = $Path; 17855 } 17856 } 17857 } 17858 $Cache{"find_gcc_cxx_headers"} = 1; 17859} 17860 17861sub parse_libname($$$) 17862{ 17863 my ($Name, $Type, $Target) = @_; 17864 if(not $Name) { 17865 return ""; 17866 } 17867 if($Target eq "symbian") { 17868 return parse_libname_symbian($Name, $Type); 17869 } 17870 elsif($Target eq "windows") { 17871 return parse_libname_windows($Name, $Type); 17872 } 17873 my $Ext = getLIB_EXT($Target); 17874 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/) 17875 { # libSDL-1.2.so.0.7.1 17876 # libwbxml2.so.0.0.18 17877 # libopcodes-2.21.53-system.20110810.so 17878 if($Type eq "name") 17879 { # libSDL-1.2 17880 # libwbxml2 17881 return $2; 17882 } 17883 elsif($Type eq "name+ext") 17884 { # libSDL-1.2.so 17885 # libwbxml2.so 17886 return $1; 17887 } 17888 elsif($Type eq "version") 17889 { 17890 if(defined $7 17891 and $7 ne "") 17892 { # 0.7.1 17893 return $7; 17894 } 17895 else 17896 { # libc-2.5.so (=>2.5 version) 17897 my $MV = $5; 17898 $MV=~s/\A[\-\_]+//g; 17899 return $MV; 17900 } 17901 } 17902 elsif($Type eq "short") 17903 { # libSDL 17904 # libwbxml2 17905 return $3; 17906 } 17907 elsif($Type eq "shortest") 17908 { # SDL 17909 # wbxml 17910 return shortest_name($3); 17911 } 17912 } 17913 return "";# error 17914} 17915 17916sub parse_libname_symbian($$) 17917{ 17918 my ($Name, $Type) = @_; 17919 my $Ext = getLIB_EXT("symbian"); 17920 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/) 17921 { # libpthread{00010001}.dso 17922 if($Type eq "name") 17923 { # libpthread{00010001} 17924 return $2; 17925 } 17926 elsif($Type eq "name+ext") 17927 { # libpthread{00010001}.dso 17928 return $1; 17929 } 17930 elsif($Type eq "version") 17931 { # 00010001 17932 my $V = $4; 17933 $V=~s/\{(.+)\}/$1/; 17934 return $V; 17935 } 17936 elsif($Type eq "short") 17937 { # libpthread 17938 return $3; 17939 } 17940 elsif($Type eq "shortest") 17941 { # pthread 17942 return shortest_name($3); 17943 } 17944 } 17945 return "";# error 17946} 17947 17948sub parse_libname_windows($$) 17949{ 17950 my ($Name, $Type) = @_; 17951 my $Ext = getLIB_EXT("windows"); 17952 if($Name=~/((.+?)\.$Ext)\Z/) 17953 { # netapi32.dll 17954 if($Type eq "name") 17955 { # netapi32 17956 return $2; 17957 } 17958 elsif($Type eq "name+ext") 17959 { # netapi32.dll 17960 return $1; 17961 } 17962 elsif($Type eq "version") 17963 { # DLL version embedded 17964 # at binary-level 17965 return ""; 17966 } 17967 elsif($Type eq "short") 17968 { # netapi32 17969 return $2; 17970 } 17971 elsif($Type eq "shortest") 17972 { # netapi 17973 return shortest_name($2); 17974 } 17975 } 17976 return "";# error 17977} 17978 17979sub shortest_name($) 17980{ 17981 my $Name = $_[0]; 17982 # remove prefix 17983 $Name=~s/\A(lib|open)//; 17984 # remove suffix 17985 $Name=~s/[\W\d_]+\Z//i; 17986 $Name=~s/([a-z]{2,})(lib)\Z/$1/i; 17987 return $Name; 17988} 17989 17990sub getPrefix($) 17991{ 17992 my $Str = $_[0]; 17993 if($Str=~/\A(Get|get|Set|set)([A-Z]|_)/) 17994 { # GetError 17995 return ""; 17996 } 17997 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/) 17998 { # XmuValidArea: Xmu 17999 return $1; 18000 } 18001 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/) 18002 { # snfReadFont: snf 18003 return $1; 18004 } 18005 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/) 18006 { # XRRTimes: XRR 18007 return $1; 18008 } 18009 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i) 18010 { # alarm_event_add: alarm_ 18011 return $1; 18012 } 18013 elsif($Str=~/\A(([a-z])\2{1,})/i) 18014 { # ffopen 18015 return $1; 18016 } 18017 else { 18018 return ""; 18019 } 18020} 18021 18022sub problem_title($) 18023{ 18024 if($_[0]==1) { 18025 return "1 problem"; 18026 } 18027 else { 18028 return $_[0]." problems"; 18029 } 18030} 18031 18032sub warning_title($) 18033{ 18034 if($_[0]==1) { 18035 return "1 warning"; 18036 } 18037 else { 18038 return $_[0]." warnings"; 18039 } 18040} 18041 18042sub createSymbolsList($$$$$) 18043{ 18044 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_; 18045 read_ABI_Dump(1, $DPath); 18046 if(not $CheckObjectsOnly) { 18047 prepareSymbols(1); 18048 } 18049 my %SymbolHeaderLib = (); 18050 my $Total = 0; 18051 # Get List 18052 foreach my $Symbol (sort keys(%{$CompleteSignature{1}})) 18053 { 18054 if(not link_symbol($Symbol, 1, "-Deps")) 18055 { # skip src only and all external functions 18056 next; 18057 } 18058 if(not symbolFilter($Symbol, 1, "Public", "Binary")) 18059 { # skip other symbols 18060 next; 18061 } 18062 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"}; 18063 if(not $HeaderName) 18064 { # skip src only and all external functions 18065 next; 18066 } 18067 my $DyLib = $Symbol_Library{1}{$Symbol}; 18068 if(not $DyLib) 18069 { # skip src only and all external functions 18070 next; 18071 } 18072 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1; 18073 $Total+=1; 18074 } 18075 # Draw List 18076 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)"; 18077 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>"; 18078 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib)) 18079 { 18080 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}})) 18081 { 18082 my %NS_Symbol = (); 18083 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) { 18084 $NS_Symbol{get_IntNameSpace($Symbol, 1)}{$Symbol} = 1; 18085 } 18086 foreach my $NameSpace (sort keys(%NS_Symbol)) 18087 { 18088 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace); 18089 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}}); 18090 foreach my $Symbol (@SortedInterfaces) 18091 { 18092 my $SubReport = ""; 18093 my $Signature = get_Signature($Symbol, 1); 18094 if($NameSpace) { 18095 $Signature=~s/\b\Q$NameSpace\E::\b//g; 18096 } 18097 if($Symbol=~/\A(_Z|\?)/) 18098 { 18099 if($Signature) { 18100 $SubReport = insertIDs($ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Symbol</b>]</span><br/><br/>".$ContentDivEnd."\n"); 18101 }# report_added 18102 else { 18103 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n"; 18104 } 18105 } 18106 else 18107 { 18108 if($Signature) { 18109 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n"; 18110 } 18111 else { 18112 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n"; 18113 } 18114 } 18115 $SYMBOLS_LIST .= $SubReport; 18116 } 18117 } 18118 $SYMBOLS_LIST .= "<br/>\n"; 18119 } 18120 } 18121 # clear info 18122 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library, 18123 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols, 18124 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames, 18125 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = (); 18126 ($Content_Counter, $ContentID) = (0, 0); 18127 # print report 18128 my $CssStyles = readModule("Styles", "SymbolsList.css"); 18129 my $JScripts = readModule("Scripts", "Sections.js"); 18130 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n"; 18131 my $Title = "$LName: public symbols"; 18132 my $Keywords = "$LName, API, symbols"; 18133 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName); 18134 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)." 18135 <body><div>\n$SYMBOLS_LIST</div> 18136 <br/><br/><hr/>\n".getReportFooter($LName)." 18137 <div style='height:999px;'></div></body></html>"; 18138 writeFile($SaveTo, $SYMBOLS_LIST); 18139} 18140 18141sub readModule($$) 18142{ 18143 my ($Module, $Name) = @_; 18144 my $Path = $MODULES_DIR."/Internals/$Module/".$Name; 18145 if(not -f $Path) { 18146 exitStatus("Module_Error", "can't access \'$Path\'"); 18147 } 18148 return readFile($Path); 18149} 18150 18151sub is_target_lib($) 18152{ 18153 my $LName = $_[0]; 18154 if(not $LName) { 18155 return 0; 18156 } 18157 if($TargetLibraryName 18158 and $LName!~/\Q$TargetLibraryName\E/) { 18159 return 0; 18160 } 18161 if(keys(%TargetLibs) 18162 and not $TargetLibs{$LName} 18163 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) { 18164 return 0; 18165 } 18166 return 1; 18167} 18168 18169sub is_target_header($$) 18170{ # --header, --headers-list 18171 my ($H, $V) = @_; 18172 if(keys(%{$TargetHeaders{$V}})) 18173 { 18174 if($TargetHeaders{$V}{$H}) { 18175 return 1; 18176 } 18177 } 18178 return 0; 18179} 18180 18181sub checkVersionNum($$) 18182{ 18183 my ($LibVersion, $Path) = @_; 18184 if(my $VerNum = $TargetVersion{$LibVersion}) { 18185 return $VerNum; 18186 } 18187 my $UsedAltDescr = 0; 18188 foreach my $Part (split(/\s*,\s*/, $Path)) 18189 { # try to get version string from file path 18190 next if($Part=~/\.xml\Z/i); 18191 next if(isDump($Part)); 18192 my $VerNum = ""; 18193 if(parse_libname($Part, "name", $OStarget)) 18194 { 18195 $UsedAltDescr = 1; 18196 $VerNum = parse_libname($Part, "version", $OStarget); 18197 if(not $VerNum) { 18198 $VerNum = readStringVersion($Part); 18199 } 18200 } 18201 elsif(is_header($Part, 2, $LibVersion) or -d $Part) 18202 { 18203 $UsedAltDescr = 1; 18204 $VerNum = readStringVersion($Part); 18205 } 18206 if($VerNum ne "") 18207 { 18208 $TargetVersion{$LibVersion} = $VerNum; 18209 if($DumpAPI) { 18210 printMsg("WARNING", "setting version number to $VerNum (use -vnum <num> option to change it)"); 18211 } 18212 else { 18213 printMsg("WARNING", "setting ".($LibVersion==1?"1st":"2nd")." version number to \"$VerNum\" (use -v$LibVersion <num> option to change it)"); 18214 } 18215 return $TargetVersion{$LibVersion}; 18216 } 18217 } 18218 if($UsedAltDescr) 18219 { 18220 if($DumpAPI) { 18221 exitStatus("Error", "version number is not set (use -vnum <num> option)"); 18222 } 18223 else { 18224 exitStatus("Error", ($LibVersion==1?"1st":"2nd")." version number is not set (use -v$LibVersion <num> option)"); 18225 } 18226 } 18227} 18228 18229sub readStringVersion($) 18230{ 18231 my $Str = $_[0]; 18232 return "" if(not $Str); 18233 $Str=~s/\Q$TargetLibraryName\E//g; 18234 if($Str=~/(\/|\\|\w|\A)[\-\_]*(\d+[\d\.\-]+\d+|\d+)/) 18235 { # .../libssh-0.4.0/... 18236 return $2; 18237 } 18238 elsif(my $V = parse_libname($Str, "version", $OStarget)) { 18239 return $V; 18240 } 18241 return ""; 18242} 18243 18244sub readLibs($) 18245{ 18246 my $LibVersion = $_[0]; 18247 if($OStarget eq "windows") 18248 { # dumpbin.exe will crash 18249 # without VS Environment 18250 check_win32_env(); 18251 } 18252 readSymbols($LibVersion); 18253 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion); 18254 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion); 18255} 18256 18257sub dump_sorting($) 18258{ 18259 my $Hash = $_[0]; 18260 return [] if(not $Hash); 18261 my @Keys = keys(%{$Hash}); 18262 return [] if($#Keys<0); 18263 if($Keys[0]=~/\A\d+\Z/) 18264 { # numbers 18265 return [sort {int($a)<=>int($b)} @Keys]; 18266 } 18267 else 18268 { # strings 18269 return [sort {$a cmp $b} @Keys]; 18270 } 18271} 18272 18273sub printMsg($$) 18274{ 18275 my ($Type, $Msg) = @_; 18276 if($Type!~/\AINFO/) { 18277 $Msg = $Type.": ".$Msg; 18278 } 18279 if($Type!~/_C\Z/) { 18280 $Msg .= "\n"; 18281 } 18282 if($Quiet) 18283 { # --quiet option 18284 appendFile($COMMON_LOG_PATH, $Msg); 18285 } 18286 else 18287 { 18288 if($Type eq "ERROR") { 18289 print STDERR $Msg; 18290 } 18291 else { 18292 print $Msg; 18293 } 18294 } 18295} 18296 18297sub exitStatus($$) 18298{ 18299 my ($Code, $Msg) = @_; 18300 printMsg("ERROR", $Msg); 18301 exit($ERROR_CODE{$Code}); 18302} 18303 18304sub exitReport() 18305{ # the tool has run without any errors 18306 printReport(); 18307 if($COMPILE_ERRORS) 18308 { # errors in headers may add false positives/negatives 18309 exit($ERROR_CODE{"Compile_Error"}); 18310 } 18311 if($BinaryOnly and $RESULT{"Binary"}{"Problems"}) 18312 { # --binary 18313 exit($ERROR_CODE{"Incompatible"}); 18314 } 18315 elsif($SourceOnly and $RESULT{"Source"}{"Problems"}) 18316 { # --source 18317 exit($ERROR_CODE{"Incompatible"}); 18318 } 18319 elsif($RESULT{"Source"}{"Problems"} 18320 or $RESULT{"Binary"}{"Problems"}) 18321 { # default 18322 exit($ERROR_CODE{"Incompatible"}); 18323 } 18324 else { 18325 exit($ERROR_CODE{"Compatible"}); 18326 } 18327} 18328 18329sub readRules($) 18330{ 18331 my $Kind = $_[0]; 18332 if(not -f $RULES_PATH{$Kind}) { 18333 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'"); 18334 } 18335 my $Content = readFile($RULES_PATH{$Kind}); 18336 while(my $Rule = parseTag(\$Content, "rule")) 18337 { 18338 my $RId = parseTag(\$Rule, "id"); 18339 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind"); 18340 foreach my $Prop (@Properties) { 18341 if(my $Value = parseTag(\$Rule, lc($Prop))) 18342 { 18343 $Value=~s/\n[ ]*//; 18344 $CompatRules{$Kind}{$RId}{$Prop} = $Value; 18345 } 18346 } 18347 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) { 18348 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols"; 18349 } 18350 else { 18351 $CompatRules{$Kind}{$RId}{"Kind"} = "Types"; 18352 } 18353 } 18354} 18355 18356sub getReportPath($) 18357{ 18358 my $Level = $_[0]; 18359 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"}; 18360 if($Level eq "Binary") 18361 { 18362 if($BinaryReportPath) 18363 { # --bin-report-path 18364 return $BinaryReportPath; 18365 } 18366 elsif($OutputReportPath) 18367 { # --report-path 18368 return $OutputReportPath; 18369 } 18370 else 18371 { # default 18372 return $Dir."/abi_compat_report.$ReportFormat"; 18373 } 18374 } 18375 elsif($Level eq "Source") 18376 { 18377 if($SourceReportPath) 18378 { # --src-report-path 18379 return $SourceReportPath; 18380 } 18381 elsif($OutputReportPath) 18382 { # --report-path 18383 return $OutputReportPath; 18384 } 18385 else 18386 { # default 18387 return $Dir."/src_compat_report.$ReportFormat"; 18388 } 18389 } 18390 else 18391 { 18392 if($OutputReportPath) 18393 { # --report-path 18394 return $OutputReportPath; 18395 } 18396 else 18397 { # default 18398 return $Dir."/compat_report.$ReportFormat"; 18399 } 18400 } 18401} 18402 18403sub printStatMsg($) 18404{ 18405 my $Level = $_[0]; 18406 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"}); 18407} 18408 18409sub listAffected($) 18410{ 18411 my $Level = $_[0]; 18412 my $List = ""; 18413 foreach (keys(%{$TotalAffected{$Level}})) 18414 { 18415 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low") 18416 { # skip "Low"-severity problems 18417 next; 18418 } 18419 $List .= "$_\n"; 18420 } 18421 my $Dir = get_dirname(getReportPath($Level)); 18422 if($Level eq "Binary") { 18423 writeFile($Dir."/abi_affected.txt", $List); 18424 } 18425 elsif($Level eq "Source") { 18426 writeFile($Dir."/src_affected.txt", $List); 18427 } 18428} 18429 18430sub printReport() 18431{ 18432 printMsg("INFO", "creating compatibility report ..."); 18433 createReport(); 18434 if($JoinReport or $DoubleReport) 18435 { 18436 if($RESULT{"Binary"}{"Problems"} 18437 or $RESULT{"Source"}{"Problems"}) { 18438 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)"); 18439 } 18440 else { 18441 printMsg("INFO", "result: COMPATIBLE"); 18442 } 18443 printStatMsg("Binary"); 18444 printStatMsg("Source"); 18445 if($ListAffected) 18446 { # --list-affected 18447 listAffected("Binary"); 18448 listAffected("Source"); 18449 } 18450 } 18451 elsif($BinaryOnly) 18452 { 18453 if($RESULT{"Binary"}{"Problems"}) { 18454 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)"); 18455 } 18456 else { 18457 printMsg("INFO", "result: COMPATIBLE"); 18458 } 18459 printStatMsg("Binary"); 18460 if($ListAffected) 18461 { # --list-affected 18462 listAffected("Binary"); 18463 } 18464 } 18465 elsif($SourceOnly) 18466 { 18467 if($RESULT{"Source"}{"Problems"}) { 18468 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)"); 18469 } 18470 else { 18471 printMsg("INFO", "result: COMPATIBLE"); 18472 } 18473 printStatMsg("Source"); 18474 if($ListAffected) 18475 { # --list-affected 18476 listAffected("Source"); 18477 } 18478 } 18479 if($StdOut) 18480 { 18481 if($JoinReport or not $DoubleReport) 18482 { # --binary or --source 18483 printMsg("INFO", "compatibility report has been generated to stdout"); 18484 } 18485 else 18486 { # default 18487 printMsg("INFO", "compatibility reports have been generated to stdout"); 18488 } 18489 } 18490 else 18491 { 18492 if($JoinReport) 18493 { 18494 printMsg("INFO", "see detailed report:\n ".getReportPath("Join")); 18495 } 18496 elsif($DoubleReport) 18497 { # default 18498 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source")); 18499 } 18500 elsif($BinaryOnly) 18501 { # --binary 18502 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary")); 18503 } 18504 elsif($SourceOnly) 18505 { # --source 18506 printMsg("INFO", "see detailed report:\n ".getReportPath("Source")); 18507 } 18508 } 18509} 18510 18511sub check_win32_env() 18512{ 18513 if(not $ENV{"DevEnvDir"} 18514 or not $ENV{"LIB"}) { 18515 exitStatus("Error", "can't start without VS environment (vsvars32.bat)"); 18516 } 18517} 18518 18519sub diffSets($$) 18520{ 18521 my ($S1, $S2) = @_; 18522 my @SK1 = keys(%{$S1}); 18523 my @SK2 = keys(%{$S2}); 18524 if($#SK1!=$#SK2) { 18525 return 1; 18526 } 18527 foreach my $K1 (@SK1) 18528 { 18529 if(not defined $S2->{$K1}) { 18530 return 1; 18531 } 18532 } 18533 return 0; 18534} 18535 18536sub create_ABI_Dump() 18537{ 18538 if(not -e $DumpAPI) { 18539 exitStatus("Access_Error", "can't access \'$DumpAPI\'"); 18540 } 18541 # check the archive utilities 18542 if($OSgroup eq "windows") 18543 { # using zip 18544 my $ZipCmd = get_CmdPath("zip"); 18545 if(not $ZipCmd) { 18546 exitStatus("Not_Found", "can't find \"zip\""); 18547 } 18548 } 18549 else 18550 { # using tar and gzip 18551 my $TarCmd = get_CmdPath("tar"); 18552 if(not $TarCmd) { 18553 exitStatus("Not_Found", "can't find \"tar\""); 18554 } 18555 my $GzipCmd = get_CmdPath("gzip"); 18556 if(not $GzipCmd) { 18557 exitStatus("Not_Found", "can't find \"gzip\""); 18558 } 18559 } 18560 my @DParts = split(/\s*,\s*/, $DumpAPI); 18561 foreach my $Part (@DParts) 18562 { 18563 if(not -e $Part) { 18564 exitStatus("Access_Error", "can't access \'$Part\'"); 18565 } 18566 } 18567 checkVersionNum(1, $DumpAPI); 18568 foreach my $Part (@DParts) 18569 { 18570 if(isDump($Part)) { 18571 read_ABI_Dump(1, $Part); 18572 } 18573 else { 18574 readDescriptor(1, createDescriptor(1, $Part)); 18575 } 18576 } 18577 initLogging(1); 18578 detect_default_paths("inc|lib|bin|gcc"); # complete analysis 18579 if(not $CheckHeadersOnly) { 18580 readLibs(1); 18581 } 18582 if($CheckHeadersOnly) { 18583 setLanguage(1, "C++"); 18584 } 18585 if(not $CheckObjectsOnly) { 18586 searchForHeaders(1); 18587 } 18588 $WORD_SIZE{1} = detectWordSize(); 18589 if($Descriptor{1}{"Headers"} 18590 and not $Descriptor{1}{"Dump"}) { 18591 readHeaders(1); 18592 } 18593 cleanDump(1); 18594 if(not keys(%{$SymbolInfo{1}})) 18595 { # check if created dump is valid 18596 if(not $ExtendedCheck and not $CheckObjectsOnly) 18597 { 18598 if($CheckHeadersOnly) { 18599 exitStatus("Empty_Set", "the set of public symbols is empty"); 18600 } 18601 else { 18602 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection"); 18603 } 18604 } 18605 } 18606 my %HeadersInfo = (); 18607 foreach my $HPath (keys(%{$Registered_Headers{1}})) 18608 { # headers info stored without paths in the dump 18609 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"}; 18610 } 18611 printMsg("INFO", "creating library ABI dump ..."); 18612 my %LibraryABI = ( 18613 "TypeInfo" => $TypeInfo{1}, 18614 "SymbolInfo" => $SymbolInfo{1}, 18615 "Symbols" => $Library_Symbol{1}, 18616 "DepSymbols" => $DepLibrary_Symbol{1}, 18617 "SymbolVersion" => $SymVer{1}, 18618 "LibraryVersion" => $Descriptor{1}{"Version"}, 18619 "LibraryName" => $TargetLibraryName, 18620 "Language" => $COMMON_LANGUAGE{1}, 18621 "SkipTypes" => $SkipTypes{1}, 18622 "SkipSymbols" => $SkipSymbols{1}, 18623 "SkipNameSpaces" => $SkipNameSpaces{1}, 18624 "SkipHeaders" => $SkipHeadersList{1}, 18625 "Headers" => \%HeadersInfo, 18626 "Constants" => $Constants{1}, 18627 "NameSpaces" => $NestedNameSpaces{1}, 18628 "Target" => $OStarget, 18629 "Arch" => getArch(1), 18630 "WordSize" => $WORD_SIZE{1}, 18631 "GccVersion" => get_dumpversion($GCC_PATH), 18632 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION, 18633 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION 18634 ); 18635 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) { 18636 $LibraryABI{"TargetHeaders"} = $TargetHeaders{1}; 18637 } 18638 if($UseXML) { 18639 $LibraryABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION; 18640 } 18641 if($ExtendedCheck) 18642 { # --ext option 18643 $LibraryABI{"Mode"} = "Extended"; 18644 } 18645 if($BinaryOnly) 18646 { # --binary 18647 $LibraryABI{"BinOnly"} = 1; 18648 } 18649 18650 my $ABI_DUMP = ""; 18651 if($UseXML) 18652 { 18653 loadModule("XmlDump"); 18654 $ABI_DUMP = createXmlDump(\%LibraryABI); 18655 } 18656 else 18657 { # default 18658 $ABI_DUMP = Dumper(\%LibraryABI); 18659 } 18660 if($StdOut) 18661 { # --stdout option 18662 print STDOUT $ABI_DUMP; 18663 printMsg("INFO", "ABI dump has been generated to stdout"); 18664 return; 18665 } 18666 else 18667 { # write to gzipped file 18668 my $DumpPath = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi"; 18669 $DumpPath .= ".".$AR_EXT; # gzipped by default 18670 if($OutputDumpPath) 18671 { # user defined path 18672 $DumpPath = $OutputDumpPath; 18673 } 18674 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g); 18675 my ($DDir, $DName) = separate_path($DumpPath); 18676 my $DPath = $TMP_DIR."/".$DName; 18677 if(not $Archive) { 18678 $DPath = $DumpPath; 18679 } 18680 18681 mkpath($DDir); 18682 18683 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n"); 18684 print DUMP $ABI_DUMP; 18685 close(DUMP); 18686 18687 if(not -s $DPath) { 18688 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module"); 18689 } 18690 if($Archive) 18691 { 18692 my $PkgPath = createArchive($DPath, $DDir); 18693 printMsg("INFO", "library ABI has been dumped to:\n $PkgPath"); 18694 } 18695 else { 18696 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath"); 18697 } 18698 18699 printMsg("INFO", "you can transfer this dump everywhere and use instead of the ".$Descriptor{1}{"Version"}." version descriptor"); 18700 } 18701} 18702 18703sub quickEmptyReports() 18704{ # Quick "empty" reports 18705 # 4 times faster than merging equal dumps 18706 # NOTE: the dump contains the "LibraryVersion" attribute 18707 # if you change the version, then your dump will be different 18708 # OVERCOME: use -v1 and v2 options for comparing dumps 18709 # and don't change version in the XML descriptor (and dumps) 18710 # OVERCOME 2: separate meta info from the dumps in ACC 2.0 18711 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"}) 18712 { 18713 my $FilePath1 = unpackDump($Descriptor{1}{"Path"}); 18714 my $FilePath2 = unpackDump($Descriptor{2}{"Path"}); 18715 if($FilePath1 and $FilePath2) 18716 { 18717 local $/ = undef; 18718 18719 open(DUMP1, $FilePath1); 18720 my $Content1 = <DUMP1>; 18721 close(DUMP1); 18722 18723 open(DUMP2, $FilePath2); 18724 my $Content2 = <DUMP2>; 18725 close(DUMP2); 18726 18727 if($Content1 eq $Content2) 18728 { 18729 # clean memory 18730 undef $Content2; 18731 18732 # read a number of headers, libs, symbols and types 18733 my $ABIdump = eval($Content1); 18734 18735 # clean memory 18736 undef $Content1; 18737 18738 if(not $ABIdump) { 18739 exitStatus("Error", "internal error"); 18740 } 18741 if(not $ABIdump->{"TypeInfo"}) 18742 { # support for old dumps 18743 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"}; 18744 } 18745 if(not $ABIdump->{"SymbolInfo"}) 18746 { # support for old dumps 18747 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"}; 18748 } 18749 read_Headers_DumpInfo($ABIdump, 1); 18750 read_Libs_DumpInfo($ABIdump, 1); 18751 read_Machine_DumpInfo($ABIdump, 1); 18752 read_Machine_DumpInfo($ABIdump, 2); 18753 18754 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}}; 18755 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}}; 18756 18757 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}}; 18758 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}}; 18759 18760 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"}; 18761 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"}; 18762 exitReport(); 18763 } 18764 } 18765 } 18766} 18767 18768sub initLogging($) 18769{ 18770 my $LibVersion = $_[0]; 18771 # create log directory 18772 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt"); 18773 if($OutputLogPath{$LibVersion}) 18774 { # user-defined by -log-path option 18775 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion}); 18776 } 18777 if($LogMode ne "n") { 18778 mkpath($LOG_DIR); 18779 } 18780 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE; 18781 if($Debug) 18782 { # debug directory 18783 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}; 18784 } 18785 resetLogging($LibVersion); 18786} 18787 18788sub writeLog($$) 18789{ 18790 my ($LibVersion, $Msg) = @_; 18791 if($LogMode ne "n") { 18792 appendFile($LOG_PATH{$LibVersion}, $Msg); 18793 } 18794} 18795 18796sub resetLogging($) 18797{ 18798 my $LibVersion = $_[0]; 18799 if($LogMode!~/a|n/) 18800 { # remove old log 18801 unlink($LOG_PATH{$LibVersion}); 18802 if($Debug) { 18803 rmtree($DEBUG_PATH{$LibVersion}); 18804 } 18805 } 18806} 18807 18808sub printErrorLog($) 18809{ 18810 my $LibVersion = $_[0]; 18811 if($LogMode ne "n") { 18812 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n"); 18813 } 18814} 18815 18816sub isDump($) 18817{ 18818 if(get_filename($_[0])=~/\A(.+)\.abi(\Q.tar.gz\E|\Q.zip\E|)\Z/) 18819 { # returns a name of package 18820 return $1; 18821 } 18822 return 0; 18823} 18824 18825sub compareInit() 18826{ 18827 # read input XML descriptors or ABI dumps 18828 if(not $Descriptor{1}{"Path"}) { 18829 exitStatus("Error", "-old option is not specified"); 18830 } 18831 my @DParts1 = split(/\s*,\s*/, $Descriptor{1}{"Path"}); 18832 foreach my $Part (@DParts1) 18833 { 18834 if(not -e $Part) { 18835 exitStatus("Access_Error", "can't access \'$Part\'"); 18836 } 18837 } 18838 if(not $Descriptor{2}{"Path"}) { 18839 exitStatus("Error", "-new option is not specified"); 18840 } 18841 my @DParts2 = split(/\s*,\s*/, $Descriptor{2}{"Path"}); 18842 foreach my $Part (@DParts2) 18843 { 18844 if(not -e $Part) { 18845 exitStatus("Access_Error", "can't access \'$Part\'"); 18846 } 18847 } 18848 detect_default_paths("bin"); # to extract dumps 18849 if($#DParts1==0 and $#DParts2==0 18850 and isDump($Descriptor{1}{"Path"}) 18851 and isDump($Descriptor{2}{"Path"})) 18852 { # optimization: equal ABI dumps 18853 quickEmptyReports(); 18854 } 18855 checkVersionNum(1, $Descriptor{1}{"Path"}); 18856 checkVersionNum(2, $Descriptor{2}{"Path"}); 18857 printMsg("INFO", "preparation, please wait ..."); 18858 foreach my $Part (@DParts1) 18859 { 18860 if(isDump($Part)) { 18861 read_ABI_Dump(1, $Part); 18862 } 18863 else { 18864 readDescriptor(1, createDescriptor(1, $Part)); 18865 } 18866 } 18867 foreach my $Part (@DParts2) 18868 { 18869 if(isDump($Part)) { 18870 read_ABI_Dump(2, $Part); 18871 } 18872 else { 18873 readDescriptor(2, createDescriptor(2, $Part)); 18874 } 18875 } 18876 initLogging(1); 18877 initLogging(2); 18878 # check consistency 18879 if(not $Descriptor{1}{"Headers"} 18880 and not $Descriptor{1}{"Libs"}) { 18881 exitStatus("Error", "descriptor d1 does not contain both header files and libraries info"); 18882 } 18883 if(not $Descriptor{2}{"Headers"} 18884 and not $Descriptor{2}{"Libs"}) { 18885 exitStatus("Error", "descriptor d2 does not contain both header files and libraries info"); 18886 } 18887 if($Descriptor{1}{"Headers"} and not $Descriptor{1}{"Libs"} 18888 and not $Descriptor{2}{"Headers"} and $Descriptor{2}{"Libs"}) { 18889 exitStatus("Error", "can't compare headers with $SLIB_TYPE libraries"); 18890 } 18891 elsif(not $Descriptor{1}{"Headers"} and $Descriptor{1}{"Libs"} 18892 and $Descriptor{2}{"Headers"} and not $Descriptor{2}{"Libs"}) { 18893 exitStatus("Error", "can't compare $SLIB_TYPE libraries with headers"); 18894 } 18895 if(not $Descriptor{1}{"Headers"}) { 18896 if($CheckHeadersOnly_Opt) { 18897 exitStatus("Error", "can't find header files info in descriptor d1"); 18898 } 18899 } 18900 if(not $Descriptor{2}{"Headers"}) { 18901 if($CheckHeadersOnly_Opt) { 18902 exitStatus("Error", "can't find header files info in descriptor d2"); 18903 } 18904 } 18905 if(not $Descriptor{1}{"Headers"} 18906 or not $Descriptor{2}{"Headers"}) { 18907 if(not $CheckObjectsOnly_Opt) { 18908 printMsg("WARNING", "comparing $SLIB_TYPE libraries only"); 18909 $CheckObjectsOnly = 1; 18910 } 18911 } 18912 if(not $Descriptor{1}{"Libs"}) { 18913 if($CheckObjectsOnly_Opt) { 18914 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d1"); 18915 } 18916 } 18917 if(not $Descriptor{2}{"Libs"}) { 18918 if($CheckObjectsOnly_Opt) { 18919 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d2"); 18920 } 18921 } 18922 if(not $Descriptor{1}{"Libs"} 18923 or not $Descriptor{2}{"Libs"}) 18924 { # comparing standalone header files 18925 # comparing ABI dumps created with --headers-only 18926 if(not $CheckHeadersOnly_Opt) 18927 { 18928 printMsg("WARNING", "checking headers only"); 18929 $CheckHeadersOnly = 1; 18930 } 18931 } 18932 if($UseDumps) 18933 { # --use-dumps 18934 # parallel processing 18935 my $pid = fork(); 18936 if($pid) 18937 { # dump on two CPU cores 18938 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName); 18939 if($RelativeDirectory{1}) { 18940 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1}); 18941 } 18942 if($OutputLogPath{1}) { 18943 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1}); 18944 } 18945 if($CrossGcc) { 18946 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc); 18947 } 18948 if($Quiet) 18949 { 18950 @PARAMS = (@PARAMS, "-quiet"); 18951 @PARAMS = (@PARAMS, "-logging-mode", "a"); 18952 } 18953 elsif($LogMode and $LogMode ne "w") 18954 { # "w" is default 18955 @PARAMS = (@PARAMS, "-logging-mode", $LogMode); 18956 } 18957 if($ExtendedCheck) { 18958 @PARAMS = (@PARAMS, "-extended"); 18959 } 18960 if($UserLang) { 18961 @PARAMS = (@PARAMS, "-lang", $UserLang); 18962 } 18963 if($TargetVersion{1}) { 18964 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1}); 18965 } 18966 if($BinaryOnly) { 18967 @PARAMS = (@PARAMS, "-binary"); 18968 } 18969 if($SourceOnly) { 18970 @PARAMS = (@PARAMS, "-source"); 18971 } 18972 if($SortDump) { 18973 @PARAMS = (@PARAMS, "-sort"); 18974 } 18975 if($Debug) 18976 { 18977 @PARAMS = (@PARAMS, "-debug"); 18978 printMsg("INFO", "running perl $0 @PARAMS"); 18979 } 18980 system("perl", $0, @PARAMS); 18981 if($?) { 18982 exit(1); 18983 } 18984 } 18985 else 18986 { # child 18987 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName); 18988 if($RelativeDirectory{2}) { 18989 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2}); 18990 } 18991 if($OutputLogPath{2}) { 18992 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2}); 18993 } 18994 if($CrossGcc) { 18995 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc); 18996 } 18997 if($Quiet) 18998 { 18999 @PARAMS = (@PARAMS, "-quiet"); 19000 @PARAMS = (@PARAMS, "-logging-mode", "a"); 19001 } 19002 elsif($LogMode and $LogMode ne "w") 19003 { # "w" is default 19004 @PARAMS = (@PARAMS, "-logging-mode", $LogMode); 19005 } 19006 if($ExtendedCheck) { 19007 @PARAMS = (@PARAMS, "-extended"); 19008 } 19009 if($UserLang) { 19010 @PARAMS = (@PARAMS, "-lang", $UserLang); 19011 } 19012 if($TargetVersion{2}) { 19013 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2}); 19014 } 19015 if($BinaryOnly) { 19016 @PARAMS = (@PARAMS, "-binary"); 19017 } 19018 if($SourceOnly) { 19019 @PARAMS = (@PARAMS, "-source"); 19020 } 19021 if($SortDump) { 19022 @PARAMS = (@PARAMS, "-sort"); 19023 } 19024 if($Debug) 19025 { 19026 @PARAMS = (@PARAMS, "-debug"); 19027 printMsg("INFO", "running perl $0 @PARAMS"); 19028 } 19029 system("perl", $0, @PARAMS); 19030 if($?) { 19031 exit(1); 19032 } 19033 else { 19034 exit(0); 19035 } 19036 } 19037 waitpid($pid, 0); 19038 my @CMP_PARAMS = ("-l", $TargetLibraryName); 19039 @CMP_PARAMS = (@CMP_PARAMS, "-d1", "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi.$AR_EXT"); 19040 @CMP_PARAMS = (@CMP_PARAMS, "-d2", "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{2}{"Version"}.".abi.$AR_EXT"); 19041 if($TargetLibraryFName ne $TargetLibraryName) { 19042 @CMP_PARAMS = (@CMP_PARAMS, "-l-full", $TargetLibraryFName); 19043 } 19044 if($ShowRetVal) { 19045 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval"); 19046 } 19047 if($CrossGcc) { 19048 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc); 19049 } 19050 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a"); 19051 if($Quiet) { 19052 @CMP_PARAMS = (@CMP_PARAMS, "-quiet"); 19053 } 19054 if($ReportFormat and $ReportFormat ne "html") 19055 { # HTML is default format 19056 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat); 19057 } 19058 if($OutputReportPath) { 19059 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath); 19060 } 19061 if($BinaryReportPath) { 19062 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath); 19063 } 19064 if($SourceReportPath) { 19065 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath); 19066 } 19067 if($LoggingPath) { 19068 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath); 19069 } 19070 if($Browse) { 19071 @CMP_PARAMS = (@CMP_PARAMS, "-browse", $Browse); 19072 } 19073 if($OpenReport) { 19074 @CMP_PARAMS = (@CMP_PARAMS, "-open"); 19075 } 19076 if($Debug) 19077 { 19078 @CMP_PARAMS = (@CMP_PARAMS, "-debug"); 19079 printMsg("INFO", "running perl $0 @CMP_PARAMS"); 19080 } 19081 system("perl", $0, @CMP_PARAMS); 19082 exit($?>>8); 19083 } 19084 if(not $Descriptor{1}{"Dump"} 19085 or not $Descriptor{2}{"Dump"}) 19086 { # need GCC toolchain to analyze 19087 # header files and libraries 19088 detect_default_paths("inc|lib|gcc"); 19089 } 19090 if(not $Descriptor{1}{"Dump"}) 19091 { 19092 if(not $CheckHeadersOnly) { 19093 readLibs(1); 19094 } 19095 if($CheckHeadersOnly) { 19096 setLanguage(1, "C++"); 19097 } 19098 if(not $CheckObjectsOnly) { 19099 searchForHeaders(1); 19100 } 19101 $WORD_SIZE{1} = detectWordSize(); 19102 } 19103 if(not $Descriptor{2}{"Dump"}) 19104 { 19105 if(not $CheckHeadersOnly) { 19106 readLibs(2); 19107 } 19108 if($CheckHeadersOnly) { 19109 setLanguage(2, "C++"); 19110 } 19111 if(not $CheckObjectsOnly) { 19112 searchForHeaders(2); 19113 } 19114 $WORD_SIZE{2} = detectWordSize(); 19115 } 19116 if($WORD_SIZE{1} ne $WORD_SIZE{2}) 19117 { # support for old ABI dumps 19118 # try to synch different WORD sizes 19119 if(not checkDump(1, "2.1")) 19120 { 19121 $WORD_SIZE{1} = $WORD_SIZE{2}; 19122 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes"); 19123 } 19124 elsif(not checkDump(2, "2.1")) 19125 { 19126 $WORD_SIZE{2} = $WORD_SIZE{1}; 19127 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes"); 19128 } 19129 } 19130 elsif(not $WORD_SIZE{1} 19131 and not $WORD_SIZE{2}) 19132 { # support for old ABI dumps 19133 $WORD_SIZE{1} = "4"; 19134 $WORD_SIZE{2} = "4"; 19135 } 19136 if($Descriptor{1}{"Dump"}) 19137 { # support for old ABI dumps 19138 prepareTypes(1); 19139 } 19140 if($Descriptor{2}{"Dump"}) 19141 { # support for old ABI dumps 19142 prepareTypes(2); 19143 } 19144 if($AppPath and not keys(%{$Symbol_Library{1}})) { 19145 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries"); 19146 } 19147 # started to process input data 19148 if(not $CheckObjectsOnly) 19149 { 19150 if($Descriptor{1}{"Headers"} 19151 and not $Descriptor{1}{"Dump"}) { 19152 readHeaders(1); 19153 } 19154 if($Descriptor{2}{"Headers"} 19155 and not $Descriptor{2}{"Dump"}) { 19156 readHeaders(2); 19157 } 19158 } 19159 19160 # clean memory 19161 %SystemHeaders = (); 19162 %mangled_name_gcc = (); 19163 19164 prepareSymbols(1); 19165 prepareSymbols(2); 19166 19167 # clean memory 19168 %SymbolInfo = (); 19169 19170 # Virtual Tables 19171 registerVTable(1); 19172 registerVTable(2); 19173 19174 if(not checkDump(1, "1.22") 19175 and checkDump(2, "1.22")) 19176 { # support for old ABI dumps 19177 foreach my $ClassName (keys(%{$VirtualTable{2}})) 19178 { 19179 if($ClassName=~/</) 19180 { # templates 19181 if(not defined $VirtualTable{1}{$ClassName}) 19182 { # synchronize 19183 delete($VirtualTable{2}{$ClassName}); 19184 } 19185 } 19186 } 19187 } 19188 19189 registerOverriding(1); 19190 registerOverriding(2); 19191 19192 setVirtFuncPositions(1); 19193 setVirtFuncPositions(2); 19194 19195 # Other 19196 addParamNames(1); 19197 addParamNames(2); 19198 19199 detectChangedTypedefs(); 19200} 19201 19202sub compareAPIs($) 19203{ 19204 my $Level = $_[0]; 19205 readRules($Level); 19206 if($Level eq "Binary") { 19207 printMsg("INFO", "comparing ABIs ..."); 19208 } 19209 else { 19210 printMsg("INFO", "comparing APIs ..."); 19211 } 19212 if($CheckHeadersOnly 19213 or $Level eq "Source") 19214 { # added/removed in headers 19215 detectAdded_H($Level); 19216 detectRemoved_H($Level); 19217 } 19218 else 19219 { # added/removed in libs 19220 detectAdded($Level); 19221 detectRemoved($Level); 19222 } 19223 if(not $CheckObjectsOnly) 19224 { 19225 mergeSignatures($Level); 19226 if(keys(%{$CheckedSymbols{$Level}})) { 19227 mergeConstants($Level); 19228 } 19229 } 19230 if($CheckHeadersOnly 19231 or $Level eq "Source") 19232 { # added/removed in headers 19233 mergeHeaders($Level); 19234 } 19235 else 19236 { # added/removed in libs 19237 mergeLibs($Level); 19238 if($CheckImpl 19239 and $Level eq "Binary") { 19240 mergeImpl(); 19241 } 19242 } 19243} 19244 19245sub writeOpts() 19246{ 19247 my %Opts = ( 19248 "OStarget"=>$OStarget, 19249 "Debug"=>$Debug, 19250 "Quiet"=>$Quiet, 19251 "LogMode"=>$LogMode, 19252 "CheckHeadersOnly"=>$CheckHeadersOnly, 19253 19254 "SystemRoot"=>$SystemRoot, 19255 "MODULES_DIR"=>$MODULES_DIR, 19256 "GCC_PATH"=>$GCC_PATH, 19257 "TargetSysInfo"=>$TargetSysInfo, 19258 "CrossPrefix"=>$CrossPrefix, 19259 "TargetLibraryName"=>$TargetLibraryName, 19260 "CrossGcc"=>$CrossGcc, 19261 "UseStaticLibs"=>$UseStaticLibs, 19262 "NoStdInc"=>$NoStdInc 19263 ); 19264 return \%Opts; 19265} 19266 19267sub get_CoreError($) 19268{ 19269 my %CODE_ERROR = reverse(%ERROR_CODE); 19270 return $CODE_ERROR{$_[0]}; 19271} 19272 19273sub scenario() 19274{ 19275 if($StdOut) 19276 { # enable quiet mode 19277 $Quiet = 1; 19278 $JoinReport = 1; 19279 } 19280 if(not $LogMode) 19281 { # default 19282 $LogMode = "w"; 19283 } 19284 if($UserLang) 19285 { # --lang=C++ 19286 $UserLang = uc($UserLang); 19287 $COMMON_LANGUAGE{1}=$UserLang; 19288 $COMMON_LANGUAGE{2}=$UserLang; 19289 } 19290 if($LoggingPath) 19291 { 19292 $OutputLogPath{1} = $LoggingPath; 19293 $OutputLogPath{2} = $LoggingPath; 19294 if($Quiet) { 19295 $COMMON_LOG_PATH = $LoggingPath; 19296 } 19297 } 19298 if($OutputDumpPath) 19299 { # validate 19300 if($OutputDumpPath!~/\.abi(\.\Q$AR_EXT\E|)\Z/) { 19301 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file"); 19302 } 19303 } 19304 if($BinaryOnly and $SourceOnly) 19305 { # both --binary and --source 19306 # is the default mode 19307 $DoubleReport = 1; 19308 $JoinReport = 0; 19309 $BinaryOnly = 0; 19310 $SourceOnly = 0; 19311 if($OutputReportPath) 19312 { # --report-path 19313 $DoubleReport = 0; 19314 $JoinReport = 1; 19315 } 19316 } 19317 elsif($BinaryOnly or $SourceOnly) 19318 { # --binary or --source 19319 $DoubleReport = 0; 19320 $JoinReport = 0; 19321 } 19322 if($UseXML) 19323 { # --xml option 19324 $ReportFormat = "xml"; 19325 $DumpFormat = "xml"; 19326 } 19327 if($ReportFormat) 19328 { # validate 19329 $ReportFormat = lc($ReportFormat); 19330 if($ReportFormat!~/\A(xml|html|htm)\Z/) { 19331 exitStatus("Error", "unknown report format \'$ReportFormat\'"); 19332 } 19333 if($ReportFormat eq "htm") 19334 { # HTM == HTML 19335 $ReportFormat = "html"; 19336 } 19337 elsif($ReportFormat eq "xml") 19338 { # --report-format=XML equal to --xml 19339 $UseXML = 1; 19340 } 19341 } 19342 else 19343 { # default: HTML 19344 $ReportFormat = "html"; 19345 } 19346 if($DumpFormat) 19347 { # validate 19348 $DumpFormat = lc($DumpFormat); 19349 if($DumpFormat!~/\A(xml|perl)\Z/) { 19350 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'"); 19351 } 19352 if($DumpFormat eq "xml") 19353 { # --dump-format=XML equal to --xml 19354 $UseXML = 1; 19355 } 19356 } 19357 else 19358 { # default: HTML 19359 $DumpFormat = "perl"; 19360 } 19361 if($Quiet and $LogMode!~/a|n/) 19362 { # --quiet log 19363 if(-f $COMMON_LOG_PATH) { 19364 unlink($COMMON_LOG_PATH); 19365 } 19366 } 19367 if($TestTool and $UseDumps) 19368 { # --test && --use-dumps == --test-dump 19369 $TestDump = 1; 19370 } 19371 if($Help) { 19372 HELP_MESSAGE(); 19373 exit(0); 19374 } 19375 if($InfoMsg) { 19376 INFO_MESSAGE(); 19377 exit(0); 19378 } 19379 if($ShowVersion) { 19380 printMsg("INFO", "ABI Compliance Checker (ACC) $TOOL_VERSION\nCopyright (C) 2012 ROSA Laboratory\nLicense: LGPL or GPL <http://www.gnu.org/licenses/>\nThis program is free software: you can redistribute it and/or modify it.\n\nWritten by Andrey Ponomarenko."); 19381 exit(0); 19382 } 19383 if($DumpVersion) { 19384 printMsg("INFO", $TOOL_VERSION); 19385 exit(0); 19386 } 19387 if($ExtendedCheck) { 19388 $CheckHeadersOnly = 1; 19389 } 19390 if($SystemRoot_Opt) 19391 { # user defined root 19392 if(not -e $SystemRoot_Opt) { 19393 exitStatus("Access_Error", "can't access \'$SystemRoot\'"); 19394 } 19395 $SystemRoot = $SystemRoot_Opt; 19396 $SystemRoot=~s/[\/]+\Z//g; 19397 if($SystemRoot) { 19398 $SystemRoot = get_abs_path($SystemRoot); 19399 } 19400 } 19401 $Data::Dumper::Sortkeys = 1; 19402 19403 if($SortDump) 19404 { 19405 $Data::Dumper::Useperl = 1; 19406 $Data::Dumper::Sortkeys = \&dump_sorting; 19407 } 19408 19409 if($TargetLibsPath) 19410 { 19411 if(not -f $TargetLibsPath) { 19412 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'"); 19413 } 19414 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) { 19415 $TargetLibs{$Lib} = 1; 19416 } 19417 } 19418 if($TargetHeadersPath) 19419 { # --headers-list 19420 if(not -f $TargetHeadersPath) { 19421 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'"); 19422 } 19423 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath))) 19424 { 19425 $TargetHeaders{1}{$Header} = 1; 19426 $TargetHeaders{2}{$Header} = 1; 19427 } 19428 } 19429 if($TargetHeader) 19430 { # --header 19431 $TargetHeaders{1}{$TargetHeader} = 1; 19432 $TargetHeaders{2}{$TargetHeader} = 1; 19433 } 19434 if($TestTool 19435 or $TestDump) 19436 { # --test, --test-dump 19437 detect_default_paths("bin|gcc"); # to compile libs 19438 loadModule("RegTests"); 19439 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, 19440 $ReportFormat, $LIB_EXT, $GCC_PATH, $Browse, $OpenReport, $SortDump); 19441 exit(0); 19442 } 19443 if($DumpSystem) 19444 { # --dump-system 19445 loadModule("SysCheck"); 19446 if($DumpSystem=~/\.xml\Z/) 19447 { # system XML descriptor 19448 if(not -f $DumpSystem) { 19449 exitStatus("Access_Error", "can't access file \'$DumpSystem\'"); 19450 } 19451 my $Ret = readSystemDescriptor(readFile($DumpSystem)); 19452 foreach (@{$Ret->{"Tools"}}) { 19453 $SystemPaths{"bin"}{$_} = 1; 19454 $TargetTools{$_}=1; 19455 } 19456 if($Ret->{"CrossPrefix"}) { 19457 $CrossPrefix = $Ret->{"CrossPrefix"}; 19458 } 19459 } 19460 elsif($SystemRoot_Opt) 19461 { # -sysroot "/" option 19462 # default target: /usr/lib, /usr/include 19463 # search libs: /usr/lib and /lib 19464 if(not -e $SystemRoot."/usr/lib") { 19465 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'"); 19466 } 19467 if(not -e $SystemRoot."/lib") { 19468 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'"); 19469 } 19470 if(not -e $SystemRoot."/usr/include") { 19471 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'"); 19472 } 19473 readSystemDescriptor(" 19474 <name> 19475 $DumpSystem 19476 </name> 19477 <headers> 19478 $SystemRoot/usr/include 19479 </headers> 19480 <libs> 19481 $SystemRoot/usr/lib 19482 </libs> 19483 <search_libs> 19484 $SystemRoot/lib 19485 </search_libs>"); 19486 } 19487 else { 19488 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\""); 19489 } 19490 detect_default_paths("bin|gcc"); # to check symbols 19491 if($OStarget eq "windows") 19492 { # to run dumpbin.exe 19493 # and undname.exe 19494 check_win32_env(); 19495 } 19496 dumpSystem(writeOpts()); 19497 exit(0); 19498 } 19499 if($CmpSystems) 19500 { # --cmp-systems 19501 detect_default_paths("bin"); # to extract dumps 19502 loadModule("SysCheck"); 19503 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, writeOpts()); 19504 exit(0); 19505 } 19506 if($GenerateTemplate) { 19507 generateTemplate(); 19508 exit(0); 19509 } 19510 if(not $TargetLibraryName) { 19511 exitStatus("Error", "library name is not selected (option -l <name>)"); 19512 } 19513 else 19514 { # validate library name 19515 if($TargetLibraryName=~/[\*\/\\]/) { 19516 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name"); 19517 } 19518 } 19519 if(not $TargetLibraryFName) { 19520 $TargetLibraryFName = $TargetLibraryName; 19521 } 19522 if($CheckHeadersOnly_Opt and $CheckObjectsOnly_Opt) { 19523 exitStatus("Error", "you can't specify both -headers-only and -objects-only options at the same time"); 19524 } 19525 if($SymbolsListPath) 19526 { 19527 if(not -f $SymbolsListPath) { 19528 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'"); 19529 } 19530 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) { 19531 $SymbolsList{$Interface} = 1; 19532 } 19533 } 19534 if($SkipHeadersPath) 19535 { 19536 if(not -f $SkipHeadersPath) { 19537 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'"); 19538 } 19539 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath))) 19540 { # register for both versions 19541 $SkipHeadersList{1}{$Path} = 1; 19542 $SkipHeadersList{2}{$Path} = 1; 19543 my ($CPath, $Type) = classifyPath($Path); 19544 $SkipHeaders{1}{$Type}{$CPath} = 1; 19545 $SkipHeaders{2}{$Type}{$CPath} = 1; 19546 } 19547 } 19548 if($ParamNamesPath) 19549 { 19550 if(not -f $ParamNamesPath) { 19551 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'"); 19552 } 19553 foreach my $Line (split(/\n/, readFile($ParamNamesPath))) 19554 { 19555 if($Line=~s/\A(\w+)\;//) 19556 { 19557 my $Interface = $1; 19558 if($Line=~/;(\d+);/) 19559 { 19560 while($Line=~s/(\d+);(\w+)//) { 19561 $AddIntParams{$Interface}{$1}=$2; 19562 } 19563 } 19564 else 19565 { 19566 my $Num = 0; 19567 foreach my $Name (split(/;/, $Line)) { 19568 $AddIntParams{$Interface}{$Num++}=$Name; 19569 } 19570 } 19571 } 19572 } 19573 } 19574 if($AppPath) 19575 { 19576 if(not -f $AppPath) { 19577 exitStatus("Access_Error", "can't access file \'$AppPath\'"); 19578 } 19579 foreach my $Interface (readSymbols_App($AppPath)) { 19580 $SymbolsList_App{$Interface} = 1; 19581 } 19582 } 19583 if($DumpAPI) 19584 { # --dump-abi 19585 # make an API dump 19586 create_ABI_Dump(); 19587 exit($COMPILE_ERRORS); 19588 } 19589 # default: compare APIs 19590 # -d1 <path> 19591 # -d2 <path> 19592 compareInit(); 19593 if($JoinReport or $DoubleReport) 19594 { 19595 compareAPIs("Binary"); 19596 compareAPIs("Source"); 19597 } 19598 elsif($BinaryOnly) { 19599 compareAPIs("Binary"); 19600 } 19601 elsif($SourceOnly) { 19602 compareAPIs("Source"); 19603 } 19604 exitReport(); 19605} 19606 19607scenario(); 19608