blob: 9c8b1085031d225886a4656c253103b160a41ccf [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko959dd192016-10-06 19:51:11 +03003# ABI Compliance Checker (ABICC) 1.99.25
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004# A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005#
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006# Copyright (C) 2009-2011 Institute for System Programming, RAS
7# Copyright (C) 2011-2012 Nokia Corporation and/or its subsidiary(-ies)
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +03008# Copyright (C) 2011-2012 ROSA Laboratory
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +03009# Copyright (C) 2012-2016 Andrey Ponomarenko's ABI Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010#
11# Written by Andrey Ponomarenko
12#
13# PLATFORMS
14# =========
15# Linux, FreeBSD, Mac OS X, Haiku, MS Windows, Symbian
16#
17# REQUIREMENTS
18# ============
19# Linux
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +040020# - G++ (3.0-4.7, 4.8.3, 4.9 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021# - GNU Binutils (readelf, c++filt, objdump)
Andrey Ponomarenkodd172162016-10-04 19:41:25 +030022# - Perl 5
23# - Ctags
24# - ABI Dumper >= 0.99.15
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040025#
26# Mac OS X
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040027# - Xcode (g++, c++filt, otool, nm)
Andrey Ponomarenkodd172162016-10-04 19:41:25 +030028# - Ctags
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040029#
30# MS Windows
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +040031# - MinGW (3.0-4.7, 4.8.3, 4.9 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040032# - MS Visual C++ (dumpbin, undname, cl)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040033# - Active Perl 5 (5.8 or newer)
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030034# - Sigcheck v2.52 or newer
35# - GnuWin Zip and UnZip
Andrey Ponomarenkodd172162016-10-04 19:41:25 +030036# - Ctags (Exuberant or Universal)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040037# - Add tool locations to the PATH environment variable
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030038# - Run vcvars64.bat (C:\Microsoft Visual Studio 9.0\VC\bin\)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040039#
40# This program is free software: you can redistribute it and/or modify
41# it under the terms of the GNU General Public License or the GNU Lesser
42# General Public License as published by the Free Software Foundation.
43#
44# This program is distributed in the hope that it will be useful,
45# but WITHOUT ANY WARRANTY; without even the implied warranty of
46# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47# GNU General Public License for more details.
48#
49# You should have received a copy of the GNU General Public License
50# and the GNU Lesser General Public License along with this program.
51# If not, see <http://www.gnu.org/licenses/>.
52###########################################################################
53use Getopt::Long;
54Getopt::Long::Configure ("posix_default", "no_ignore_case");
55use File::Path qw(mkpath rmtree);
56use File::Temp qw(tempdir);
57use File::Copy qw(copy move);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040058use Cwd qw(abs_path cwd realpath);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040059use Storable qw(dclone);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040060use Data::Dumper;
Andrey Ponomarenko2fba6302012-03-29 17:44:47 +040061use Config;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040062
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030063my $TOOL_VERSION = "1.99.25";
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030064my $ABI_DUMP_VERSION = "3.3";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040065my $XML_REPORT_VERSION = "1.2";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040066my $XML_ABI_DUMP_VERSION = "1.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040067my $OSgroup = get_OSgroup();
68my $ORIG_DIR = cwd();
69my $TMP_DIR = tempdir(CLEANUP=>1);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030070my $LOCALE = "C.UTF-8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040071
72# Internal modules
73my $MODULES_DIR = get_Modules();
74push(@INC, get_dirname($MODULES_DIR));
75# Rules DB
76my %RULES_PATH = (
77 "Binary" => $MODULES_DIR."/RulesBin.xml",
78 "Source" => $MODULES_DIR."/RulesSrc.xml");
79
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030080my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040081$TestTool, $DumpAPI, $SymbolsListPath, $CheckHeadersOnly_Opt, $UseDumps,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030082$AppPath, $StrictCompat, $DumpVersion, $ParamNamesPath,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030083%RelativeDirectory, $TargetTitle, $TestDump, $LoggingPath,
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030084%TargetVersion, $InfoMsg, $CrossGcc, %OutputLogPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040085$OutputReportPath, $OutputDumpPath, $ShowRetVal, $SystemRoot_Opt, $DumpSystem,
86$CmpSystems, $TargetLibsPath, $Debug, $CrossPrefix, $UseStaticLibs, $NoStdInc,
87$TargetComponent_Opt, $TargetSysInfo, $TargetHeader, $ExtendedCheck, $Quiet,
Andrey Ponomarenko991da682016-09-07 19:09:50 +030088$SkipHeadersPath, $CxxCompat, $LogMode, $StdOut, $ListAffected, $ReportFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040089$UserLang, $TargetHeadersPath, $BinaryOnly, $SourceOnly, $BinaryReportPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030090$SourceReportPath, $UseXML, $SortDump, $DumpFormat,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040091$ExtraInfo, $ExtraDump, $Force, $Tolerance, $Tolerant, $SkipSymbolsListPath,
Andrey Ponomarenko991da682016-09-07 19:09:50 +030092$CheckInfo, $Quick, $AffectLimit, $AllAffected, $CxxIncompat,
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030093$SkipInternalSymbols, $SkipInternalTypes, $TargetArch, $GccOptions,
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030094$TypesListPath, $SkipTypesListPath, $CheckPrivateABI, $CountSymbols, $OldStyle,
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030095$DisableQuickEmptyReport, $SkipTypedefUncover, $MinGWCompat, $SkipUnidentified,
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030096$DisableConstantsCheck, $SkipAddedConstants, $SkipRemovedConstants, $TestABIDumper);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040097
98my $CmdName = get_filename($0);
99my %OS_LibExt = (
100 "dynamic" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400101 "linux"=>"so",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400102 "macos"=>"dylib",
103 "windows"=>"dll",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400104 "symbian"=>"dso",
105 "default"=>"so"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400106 },
107 "static" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400108 "linux"=>"a",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400109 "windows"=>"lib",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400110 "symbian"=>"lib",
111 "default"=>"a"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400112 }
113);
114
115my %OS_Archive = (
116 "windows"=>"zip",
117 "default"=>"tar.gz"
118);
119
120my %ERROR_CODE = (
121 # Compatible verdict
122 "Compatible"=>0,
123 "Success"=>0,
124 # Incompatible verdict
125 "Incompatible"=>1,
126 # Undifferentiated error code
127 "Error"=>2,
128 # System command is not found
129 "Not_Found"=>3,
130 # Cannot access input files
131 "Access_Error"=>4,
132 # Cannot compile header files
133 "Cannot_Compile"=>5,
134 # Header compiled with errors
135 "Compile_Error"=>6,
136 # Invalid input ABI dump
137 "Invalid_Dump"=>7,
138 # Incompatible version of ABI dump
139 "Dump_Version"=>8,
140 # Cannot find a module
141 "Module_Error"=>9,
142 # Empty intersection between
143 # headers and shared objects
144 "Empty_Intersection"=>10,
145 # Empty set of symbols in headers
146 "Empty_Set"=>11
147);
148
Andrey Ponomarenko26742a82016-09-27 18:27:08 +0300149my %HomePage = (
150 "Dev"=>"https://github.com/lvc/abi-compliance-checker",
151 "Wiki"=>"https://lvc.github.io/abi-compliance-checker/"
152);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400153
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400154my $ShortUsage = "ABI Compliance Checker (ABICC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400155A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300156Copyright (C) 2016 Andrey Ponomarenko's ABI Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400157License: GNU LGPL or GNU GPL
158
159Usage: $CmdName [options]
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400160Example: $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400161
162OLD.xml and NEW.xml are XML-descriptors:
163
164 <version>
165 1.0
166 </version>
167
168 <headers>
169 /path/to/headers/
170 </headers>
171
172 <libs>
173 /path/to/libraries/
174 </libs>
175
176More info: $CmdName --help\n";
177
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400178if($#ARGV==-1)
179{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400180 printMsg("INFO", $ShortUsage);
181 exit(0);
182}
183
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400184GetOptions("h|help!" => \$Help,
185 "i|info!" => \$InfoMsg,
186 "v|version!" => \$ShowVersion,
187 "dumpversion!" => \$DumpVersion,
188# general options
189 "l|lib|library=s" => \$TargetLibraryName,
190 "d1|old|o=s" => \$Descriptor{1}{"Path"},
191 "d2|new|n=s" => \$Descriptor{2}{"Path"},
192 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400193# extra options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400194 "app|application=s" => \$AppPath,
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300195 "static|static-libs!" => \$UseStaticLibs,
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +0400196 "gcc-path|cross-gcc=s" => \$CrossGcc,
197 "gcc-prefix|cross-prefix=s" => \$CrossPrefix,
198 "gcc-options=s" => \$GccOptions,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400199 "sysroot=s" => \$SystemRoot_Opt,
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +0300200 "v1|vnum1|version1|vnum=s" => \$TargetVersion{1},
201 "v2|vnum2|version2=s" => \$TargetVersion{2},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400202 "s|strict!" => \$StrictCompat,
203 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300204 "types-list=s" => \$TypesListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400205 "skip-symbols=s" => \$SkipSymbolsListPath,
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300206 "skip-types=s" => \$SkipTypesListPath,
Andrey Ponomarenko26742a82016-09-27 18:27:08 +0300207 "disable-constants-check!" => \$DisableConstantsCheck,
208 "skip-added-constants!" => \$SkipAddedConstants,
209 "skip-removed-constants!" => \$SkipRemovedConstants,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400210 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400211 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400212 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400213 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400214 "show-retval!" => \$ShowRetVal,
215 "use-dumps!" => \$UseDumps,
216 "nostdinc!" => \$NoStdInc,
217 "dump-system=s" => \$DumpSystem,
218 "sysinfo=s" => \$TargetSysInfo,
219 "cmp-systems!" => \$CmpSystems,
220 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400221 "ext|extended!" => \$ExtendedCheck,
222 "q|quiet!" => \$Quiet,
223 "stdout!" => \$StdOut,
224 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400225 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400226 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400227 "lang=s" => \$UserLang,
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400228 "arch=s" => \$TargetArch,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400229 "binary|bin|abi!" => \$BinaryOnly,
230 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400231 "limit-affected|affected-limit=s" => \$AffectLimit,
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +0300232 "count-symbols=s" => \$CountSymbols,
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +0300233 "old-style!" => \$OldStyle,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400234# other options
235 "test!" => \$TestTool,
236 "test-dump!" => \$TestDump,
Andrey Ponomarenko959dd192016-10-06 19:51:11 +0300237 "test-abi-dumper!" => \$TestABIDumper,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400238 "debug!" => \$Debug,
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300239 "cpp-compatible!" => \$CxxCompat,
240 "cxx-incompatible|cpp-incompatible!" => \$CxxIncompat,
241 "mingw-compatible!" => \$MinGWCompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400242 "p|params=s" => \$ParamNamesPath,
243 "relpath1|relpath=s" => \$RelativeDirectory{1},
244 "relpath2=s" => \$RelativeDirectory{2},
245 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400246 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400247 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400248 "bin-report-path=s" => \$BinaryReportPath,
249 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400250 "log-path=s" => \$LoggingPath,
251 "log1-path=s" => \$OutputLogPath{1},
252 "log2-path=s" => \$OutputLogPath{2},
253 "logging-mode=s" => \$LogMode,
254 "list-affected!" => \$ListAffected,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300255 "title|l-full|lib-full=s" => \$TargetTitle,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400256 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400257 "extra-info=s" => \$ExtraInfo,
258 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400259 "force!" => \$Force,
260 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400261 "tolerant!" => \$Tolerant,
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300262 "skip-unidentified!" => \$SkipUnidentified,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400263 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400264 "quick!" => \$Quick,
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300265 "disable-quick-empty-report!" => \$DisableQuickEmptyReport,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400266 "all-affected!" => \$AllAffected,
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300267 "skip-internal-symbols|skip-internal=s" => \$SkipInternalSymbols,
268 "skip-internal-types=s" => \$SkipInternalTypes,
Andrey Ponomarenko8580e852016-08-19 19:11:48 +0300269 "skip-typedef-uncover!" => \$SkipTypedefUncover,
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300270 "check-private-abi!" => \$CheckPrivateABI
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400271) or ERR_MESSAGE();
272
273sub ERR_MESSAGE()
274{
275 printMsg("INFO", "\n".$ShortUsage);
276 exit($ERROR_CODE{"Error"});
277}
278
279my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
280my $SLIB_TYPE = $LIB_TYPE;
281if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
282{ # show as "shared" library
283 $SLIB_TYPE = "shared";
284}
285my $LIB_EXT = getLIB_EXT($OSgroup);
286my $AR_EXT = getAR_EXT($OSgroup);
287my $BYTE_SIZE = 8;
288my $COMMON_LOG_PATH = "logs/run.log";
289
290my $HelpMessage="
291NAME:
292 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400293 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400294
295DESCRIPTION:
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400296 ABI Compliance Checker (ABICC) is a tool for checking backward binary and
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400297 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
298 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
299 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
300 and/or source-level compatibility: changes in calling stack, v-table changes,
301 removed symbols, renamed fields, etc. Binary incompatibility may result in
302 crashing or incorrect behavior of applications built with an old version of
303 a library if they run on a new one. Source incompatibility may result in
304 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400305
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400306 The tool is intended for developers of software libraries and maintainers
307 of operating systems who are interested in ensuring backward compatibility,
308 i.e. allow old applications to run or to be recompiled with newer library
309 versions.
310
311 Also the tool can be used by ISVs for checking applications portability to
312 new library versions. Found issues can be taken into account when adapting
313 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400314
315 This tool is free software: you can redistribute it and/or modify it
316 under the terms of the GNU LGPL or GNU GPL.
317
318USAGE:
319 $CmdName [options]
320
321EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400322 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400323
324 OLD.xml and NEW.xml are XML-descriptors:
325
326 <version>
327 1.0
328 </version>
329
330 <headers>
331 /path1/to/header(s)/
332 /path2/to/header(s)/
333 ...
334 </headers>
335
336 <libs>
337 /path1/to/library(ies)/
338 /path2/to/library(ies)/
339 ...
340 </libs>
341
342INFORMATION OPTIONS:
343 -h|-help
344 Print this help.
345
346 -i|-info
347 Print complete info.
348
349 -v|-version
350 Print version information.
351
352 -dumpversion
353 Print the tool version ($TOOL_VERSION) and don't do anything else.
354
355GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400356 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400357 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400358
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400359 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400360 Descriptor of 1st (old) library version.
361 It may be one of the following:
362
363 1. XML-descriptor (VERSION.xml file):
364
365 <version>
366 1.0
367 </version>
368
369 <headers>
370 /path1/to/header(s)/
371 /path2/to/header(s)/
372 ...
373 </headers>
374
375 <libs>
376 /path1/to/library(ies)/
377 /path2/to/library(ies)/
378 ...
379 </libs>
380
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300381 ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400382
383 2. ABI dump generated by -dump option
384 3. Directory with headers and/or $SLIB_TYPE libraries
385 4. Single header file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400386
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300387 If you are using an 2-4 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400388 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400389
390 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400391 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400392
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400393 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400394 Descriptor of 2nd (new) library version.
395
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400396 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400397 Create library ABI dump for the input XML descriptor. You can
398 transfer it anywhere and pass instead of the descriptor. Also
399 it can be used for debugging the tool.
400
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +0300401 Supported versions of ABI dump: 2.0<=V<=$ABI_DUMP_VERSION\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400402
403sub HELP_MESSAGE() {
404 printMsg("INFO", $HelpMessage."
405MORE INFO:
406 $CmdName --info\n");
407}
408
409sub INFO_MESSAGE()
410{
411 printMsg("INFO", "$HelpMessage
412EXTRA OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400413 -app|-application PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300414 This option allows to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400415 for portability to the new library version.
416
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300417 -static
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400418 Check static libraries instead of the shared ones. The <libs> section
419 of the XML-descriptor should point to static libraries location.
420
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300421 -gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400422 Path to the cross GCC compiler to use instead of the usual (host) GCC.
423
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300424 -gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400425 GCC toolchain prefix.
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300426
427 -gcc-options OPTS
428 Additional compiler options.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400429
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400430 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400431 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400432 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400433
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400434 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400435 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200436 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400437
438 In general case you should specify it in the XML-descriptor:
439 <version>
440 VERSION
441 </version>
442
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400443 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400444 Specify 2nd library version outside the descriptor.
445
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +0400446 -vnum NUM
447 Specify the library version in the generated ABI dump. The <version> section
448 of the input XML descriptor will be overwritten in this case.
449
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400450 -s|-strict
451 Treat all compatibility warnings as problems. Add a number of \"Low\"
452 severity problems to the return value of the tool.
453
454 -headers-only
455 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
456 provide a low quality compatibility report with false positives and
457 without detecting of added/removed symbols.
458
459 Alternatively you can write \"none\" word to the <libs> section
460 in the XML-descriptor:
461 <libs>
462 none
463 </libs>
464
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400465 -show-retval
466 Show the symbol's return type in the report.
467
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400468 -symbols-list PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300469 This option allows to specify a file with a list of symbols (mangled
470 names in C++) that should be checked. Other symbols will not be checked.
471
472 -types-list PATH
473 This option allows to specify a file with a list of types that should
474 be checked. Other types will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400475
476 -skip-symbols PATH
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300477 The list of symbols that should not be checked.
478
479 -skip-types PATH
480 The list of types that should not be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400481
Andrey Ponomarenko26742a82016-09-27 18:27:08 +0300482 -disable-constants-check
483 Do not check for changes in constants.
Andrey Ponomarenkodd172162016-10-04 19:41:25 +0300484
485 -skip-added-constants
486 Do not detect added constants.
487
488 -skip-removed-constants
489 Do not detect removed constants.
490
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400491 -headers-list PATH
492 The file with a list of headers, that should be checked/dumped.
493
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400494 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400495 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400496
497 -header NAME
498 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400499
500 -use-dumps
501 Make dumps for two versions of a library and compare dumps. This should
502 increase the performance of the tool and decrease the system memory usage.
503
504 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400505 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400506
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400507 -dump-system NAME -sysroot DIR
508 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400509 create XML descriptors and make ABI dumps for each library. The result
510 set of ABI dumps can be compared (--cmp-systems) with the other one
511 created for other version of operating system in order to check them for
512 compatibility. Do not forget to specify -cross-gcc option if your target
513 system requires some specific version of GCC compiler (different from
514 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400515 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400516
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400517 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400518 The same as the previous option but takes an XML descriptor of the target
519 system as input, where you should describe it:
520
521 /* Primary sections */
522
523 <name>
524 /* Name of the system */
525 </name>
526
527 <headers>
528 /* The list of paths to header files and/or
529 directories with header files, one per line */
530 </headers>
531
532 <libs>
533 /* The list of paths to shared libraries and/or
534 directories with shared libraries, one per line */
535 </libs>
536
537 /* Optional sections */
538
539 <search_headers>
540 /* List of directories to be searched
541 for header files to automatically
542 generate include paths, one per line */
543 </search_headers>
544
545 <search_libs>
546 /* List of directories to be searched
547 for shared libraries to resolve
548 dependencies, one per line */
549 </search_libs>
550
551 <tools>
552 /* List of directories with tools used
553 for analysis (GCC toolchain), one per line */
554 </tools>
555
556 <cross_prefix>
557 /* GCC toolchain prefix.
558 Examples:
559 arm-linux-gnueabi
560 arm-none-symbianelf */
561 </cross_prefix>
562
563 <gcc_options>
564 /* Additional GCC options, one per line */
565 </gcc_options>
566
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400567 -sysinfo DIR
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300568 This option should be used with -dump-system option to dump
569 ABI of operating systems and configure the dumping process.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400570
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400571 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300572 Compare two ABI dumps of a system. Create compatibility reports for
573 each system library and the common HTML report including the summary
574 of test results for all checked libraries.
575
576 Summary report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400577 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400578
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400579 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400580 The file with a list of libraries, that should be dumped by
581 the -dump-system option or should be checked by the -cmp-systems option.
582
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400583 -ext|-extended
584 If your library A is supposed to be used by other library B and you
585 want to control the ABI of B, then you should enable this option. The
586 tool will check for changes in all data types, even if they are not
587 used by any function in the library A. Such data types are not part
588 of the A library ABI, but may be a part of the ABI of the B library.
589
590 The short scheme is:
591 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
592
593 -q|-quiet
594 Print all messages to the file instead of stdout and stderr.
595 Default path (can be changed by -log-path option):
596 $COMMON_LOG_PATH
597
598 -stdout
599 Print analysis results (compatibility reports and ABI dumps) to stdout
600 instead of creating a file. This would allow piping data to other programs.
601
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400602 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400603 Change format of compatibility report.
604 Formats:
605 htm - HTML format (default)
606 xml - XML format
607
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400608 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400609 Change format of ABI dump.
610 Formats:
611 perl - Data::Dumper format (default)
612 xml - XML format
613
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400614 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400615 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400616
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400617 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400618 Set library language (C or C++). You can use this option if the tool
619 cannot auto-detect a language. This option may be useful for checking
620 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400621
622 -arch ARCH
623 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
624 ect.). The option is useful if the tool cannot detect correct architecture
625 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400626
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400627 -binary|-bin|-abi
628 Show \"Binary\" compatibility problems only.
629 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400630 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400631
632 -source|-src|-api
633 Show \"Source\" compatibility problems only.
634 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400635 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400636
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400637 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400638 The maximum number of affected symbols listed under the description
639 of the changed type in the report.
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +0300640
641 -count-symbols PATH
642 Count total public symbols in the ABI dump.
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +0300643
644 -old-style
645 Generate old-style report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400646
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400647OTHER OPTIONS:
648 -test
649 Run internal tests. Create two binary incompatible versions of a sample
650 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300651 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400652
653 -test-dump
654 Test ability to create, read and compare ABI dumps.
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300655
Andrey Ponomarenko959dd192016-10-06 19:51:11 +0300656 -test-abi-dumper
657 Compare ABI dumps created by the ABI Dumper tool.
658
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400659 -debug
660 Debugging mode. Print debug info on the screen. Save intermediate
661 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400662 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400663
Andrey Ponomarenko959dd192016-10-06 19:51:11 +0300664 Also consider using -dump option for debugging the tool.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400665
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400666 -cpp-compatible
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300667 Do nothing.
668
669 -cxx-incompatible
670 Set this option if input C header files use C++ keywords. The tool
671 will try to replace such keywords at preprocessor stage and replace
672 them back in the final TU dump.
673
674 -mingw-compatible
675 If input header files are compatible with the MinGW GCC compiler,
Andrey Ponomarenkodd172162016-10-04 19:41:25 +0300676 then you can tell the tool about this and speedup the analysis.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400677
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400678 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400679 Path to file with the function parameter names. It can be used
680 for improving report view if the library header files have no
681 parameter names. File format:
682
683 func1;param1;param2;param3 ...
684 func2;param1;param2;param3 ...
685 ...
686
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400687 -relpath PATH
688 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400689 for dumping the library ABI (see -dump option).
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300690
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400691 -relpath1 PATH
692 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400693
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400694 -relpath2 PATH
695 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400696
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400697 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400698 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400699 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400700 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400701
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400702 -sort
703 Enable sorting of data in ABI dumps.
704
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400705 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400706 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400707 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400708 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400709
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400710 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400711 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400712 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400713 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400714
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400715 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400716 Path to \"Source\" compatibility report.
717 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400718 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400719
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400720 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400721 Log path for all messages.
722 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400723 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400724
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400725 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400726 Log path for 1st version of a library.
727 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400728 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400729
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400730 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400731 Log path for 2nd version of a library.
732 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400733 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400734
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400735 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400736 Change logging mode.
737 Modes:
738 w - overwrite old logs (default)
739 a - append old logs
740 n - do not write any logs
741
742 -list-affected
743 Generate file with the list of incompatible
744 symbols beside the HTML compatibility report.
745 Use 'c++filt \@file' command from GNU binutils
746 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400747 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400748 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400749 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400750
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400751 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400752 The component name in the title and summary of the HTML report.
753 Default:
754 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300755
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300756 -title NAME
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400757 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400758 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400759
760 -extra-info DIR
761 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400762
763 -extra-dump
764 Create extended ABI dump containing all symbols
765 from the translation unit.
766
767 -force
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300768 Try to enable this option if the tool checked zero
769 types and symbols in header files.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400770
771 -tolerance LEVEL
772 Apply a set of heuristics to successfully compile input
773 header files. You can enable several tolerance levels by
774 joining them into one string (e.g. 13, 124, etc.).
775 Levels:
776 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
777 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
Sangwoo Lee159324e2016-06-26 01:55:55 +0900778 3 - skip headers that include non-Linux headers
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400779 4 - skip headers included by others
780
781 -tolerant
782 Enable highest tolerance level [1234].
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300783
784 -skip-unidentified
785 Skip header files in 'headers' and 'include_preamble' sections
786 of the XML descriptor that cannot be found. This is useful if
787 you are trying to use the same descriptor for different targets.
788
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400789 -check
790 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400791
792 -quick
793 Quick analysis. Disable check of some template instances.
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300794
795 -disable-quick-empty-report
796 Do not generate quick empty report if input ABI dumps are equal.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400797
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300798 -skip-internal-symbols PATTERN
799 Do not check symbols matched by the pattern.
800
801 -skip-internal-types PATTERN
802 Do not check types matched by the pattern.
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300803
Andrey Ponomarenko8580e852016-08-19 19:11:48 +0300804 -skip-typedef-uncover
805 Do not report a problem if type is covered or
806 uncovered by typedef (useful for broken debug info).
807
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300808 -check-private-abi
809 Check data types from the private part of the ABI when
810 comparing ABI dumps created by the ABI Dumper tool with
811 use of the -public-headers option.
812
813 Requires ABI Dumper >= 0.99.14
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400814
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400815REPORT:
816 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400817 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400818
819 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400820 logs/LIB_NAME/V1/log.txt
821 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400822
823EXIT CODES:
824 0 - Compatible. The tool has run without any errors.
825 non-zero - Incompatible or the tool has run with errors.
826
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400827MORE INFORMATION:
Andrey Ponomarenko26742a82016-09-27 18:27:08 +0300828 ".$HomePage{"Wiki"}."
Andrey Ponomarenko868b1352016-09-29 14:13:30 +0300829 ".$HomePage{"Dev"}."\n\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400830}
831
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400832my %Operator_Indication = (
833 "not" => "~",
834 "assign" => "=",
835 "andassign" => "&=",
836 "orassign" => "|=",
837 "xorassign" => "^=",
838 "or" => "|",
839 "xor" => "^",
840 "addr" => "&",
841 "and" => "&",
842 "lnot" => "!",
843 "eq" => "==",
844 "ne" => "!=",
845 "lt" => "<",
846 "lshift" => "<<",
847 "lshiftassign" => "<<=",
848 "rshiftassign" => ">>=",
849 "call" => "()",
850 "mod" => "%",
851 "modassign" => "%=",
852 "subs" => "[]",
853 "land" => "&&",
854 "lor" => "||",
855 "rshift" => ">>",
856 "ref" => "->",
857 "le" => "<=",
858 "deref" => "*",
859 "mult" => "*",
860 "preinc" => "++",
861 "delete" => " delete",
862 "vecnew" => " new[]",
863 "vecdelete" => " delete[]",
864 "predec" => "--",
865 "postinc" => "++",
866 "postdec" => "--",
867 "plusassign" => "+=",
868 "plus" => "+",
869 "minus" => "-",
870 "minusassign" => "-=",
871 "gt" => ">",
872 "ge" => ">=",
873 "new" => " new",
874 "multassign" => "*=",
875 "divassign" => "/=",
876 "div" => "/",
877 "neg" => "-",
878 "pos" => "+",
879 "memref" => "->*",
880 "compound" => "," );
881
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400882my %UnknownOperator;
883
884my %NodeType= (
885 "array_type" => "Array",
886 "binfo" => "Other",
887 "boolean_type" => "Intrinsic",
888 "complex_type" => "Intrinsic",
889 "const_decl" => "Other",
890 "enumeral_type" => "Enum",
891 "field_decl" => "Other",
892 "function_decl" => "Other",
893 "function_type" => "FunctionType",
894 "identifier_node" => "Other",
895 "integer_cst" => "Other",
896 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400897 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400898 "method_type" => "MethodType",
899 "namespace_decl" => "Other",
900 "parm_decl" => "Other",
901 "pointer_type" => "Pointer",
902 "real_cst" => "Other",
903 "real_type" => "Intrinsic",
904 "record_type" => "Struct",
905 "reference_type" => "Ref",
906 "string_cst" => "Other",
907 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400908 "template_type_parm" => "TemplateParam",
909 "typename_type" => "TypeName",
910 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400911 "tree_list" => "Other",
912 "tree_vec" => "Other",
913 "type_decl" => "Other",
914 "union_type" => "Union",
915 "var_decl" => "Other",
916 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400917 "nop_expr" => "Other", #
918 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400919 "offset_type" => "Other" );
920
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400921my %CppKeywords_C = map {$_=>1} (
922 # C++ 2003 keywords
923 "public",
924 "protected",
925 "private",
926 "default",
927 "template",
928 "new",
929 #"asm",
930 "dynamic_cast",
931 "auto",
932 "try",
933 "namespace",
934 "typename",
935 "using",
936 "reinterpret_cast",
937 "friend",
938 "class",
939 "virtual",
940 "const_cast",
941 "mutable",
942 "static_cast",
943 "export",
944 # C++0x keywords
945 "noexcept",
946 "nullptr",
947 "constexpr",
948 "static_assert",
949 "explicit",
950 # cannot be used as a macro name
951 # as it is an operator in C++
952 "and",
953 #"and_eq",
954 "not",
955 #"not_eq",
956 "or"
957 #"or_eq",
958 #"bitand",
959 #"bitor",
960 #"xor",
961 #"xor_eq",
962 #"compl"
963);
964
965my %CppKeywords_F = map {$_=>1} (
966 "delete",
967 "catch",
968 "alignof",
969 "thread_local",
970 "decltype",
971 "typeid"
972);
973
974my %CppKeywords_O = map {$_=>1} (
975 "bool",
976 "register",
977 "inline",
978 "operator"
979);
980
981my %CppKeywords_A = map {$_=>1} (
982 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400983 "throw",
984 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400985);
986
987foreach (keys(%CppKeywords_C),
988keys(%CppKeywords_F),
989keys(%CppKeywords_O)) {
990 $CppKeywords_A{$_}=1;
991}
992
993# Header file extensions as described by gcc
994my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
995
996my %IntrinsicMangling = (
997 "void" => "v",
998 "bool" => "b",
999 "wchar_t" => "w",
1000 "char" => "c",
1001 "signed char" => "a",
1002 "unsigned char" => "h",
1003 "short" => "s",
1004 "unsigned short" => "t",
1005 "int" => "i",
1006 "unsigned int" => "j",
1007 "long" => "l",
1008 "unsigned long" => "m",
1009 "long long" => "x",
1010 "__int64" => "x",
1011 "unsigned long long" => "y",
1012 "__int128" => "n",
1013 "unsigned __int128" => "o",
1014 "float" => "f",
1015 "double" => "d",
1016 "long double" => "e",
1017 "__float80" => "e",
1018 "__float128" => "g",
1019 "..." => "z"
1020);
1021
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001022my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
1023
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001024my %StdcxxMangling = (
1025 "3std"=>"St",
1026 "3std9allocator"=>"Sa",
1027 "3std12basic_string"=>"Sb",
1028 "3std12basic_stringIcE"=>"Ss",
1029 "3std13basic_istreamIcE"=>"Si",
1030 "3std13basic_ostreamIcE"=>"So",
1031 "3std14basic_iostreamIcE"=>"Sd"
1032);
1033
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04001034my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001035my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
1036
1037my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001038my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001039
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001040my %ConstantSuffix = (
1041 "unsigned int"=>"u",
1042 "long"=>"l",
1043 "unsigned long"=>"ul",
1044 "long long"=>"ll",
1045 "unsigned long long"=>"ull"
1046);
1047
1048my %ConstantSuffixR =
1049reverse(%ConstantSuffix);
1050
1051my %OperatorMangling = (
1052 "~" => "co",
1053 "=" => "aS",
1054 "|" => "or",
1055 "^" => "eo",
1056 "&" => "an",#ad (addr)
1057 "==" => "eq",
1058 "!" => "nt",
1059 "!=" => "ne",
1060 "<" => "lt",
1061 "<=" => "le",
1062 "<<" => "ls",
1063 "<<=" => "lS",
1064 ">" => "gt",
1065 ">=" => "ge",
1066 ">>" => "rs",
1067 ">>=" => "rS",
1068 "()" => "cl",
1069 "%" => "rm",
1070 "[]" => "ix",
1071 "&&" => "aa",
1072 "||" => "oo",
1073 "*" => "ml",#de (deref)
1074 "++" => "pp",#
1075 "--" => "mm",#
1076 "new" => "nw",
1077 "delete" => "dl",
1078 "new[]" => "na",
1079 "delete[]" => "da",
1080 "+=" => "pL",
1081 "+" => "pl",#ps (pos)
1082 "-" => "mi",#ng (neg)
1083 "-=" => "mI",
1084 "*=" => "mL",
1085 "/=" => "dV",
1086 "&=" => "aN",
1087 "|=" => "oR",
1088 "%=" => "rM",
1089 "^=" => "eO",
1090 "/" => "dv",
1091 "->*" => "pm",
1092 "->" => "pt",#rf (ref)
1093 "," => "cm",
1094 "?" => "qu",
1095 "." => "dt",
1096 "sizeof"=> "sz"#st
1097);
1098
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001099my %Intrinsic_Keywords = map {$_=>1} (
1100 "true",
1101 "false",
1102 "_Bool",
1103 "_Complex",
1104 "const",
1105 "int",
1106 "long",
1107 "void",
1108 "short",
1109 "float",
1110 "volatile",
1111 "restrict",
1112 "unsigned",
1113 "signed",
1114 "char",
1115 "double",
1116 "class",
1117 "struct",
1118 "union",
1119 "enum"
1120);
1121
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001122my %GlibcHeader = map {$_=>1} (
1123 "aliases.h",
1124 "argp.h",
1125 "argz.h",
1126 "assert.h",
1127 "cpio.h",
1128 "ctype.h",
1129 "dirent.h",
1130 "envz.h",
1131 "errno.h",
1132 "error.h",
1133 "execinfo.h",
1134 "fcntl.h",
1135 "fstab.h",
1136 "ftw.h",
1137 "glob.h",
1138 "grp.h",
1139 "iconv.h",
1140 "ifaddrs.h",
1141 "inttypes.h",
1142 "langinfo.h",
1143 "limits.h",
1144 "link.h",
1145 "locale.h",
1146 "malloc.h",
1147 "math.h",
1148 "mntent.h",
1149 "monetary.h",
1150 "nl_types.h",
1151 "obstack.h",
1152 "printf.h",
1153 "pwd.h",
1154 "regex.h",
1155 "sched.h",
1156 "search.h",
1157 "setjmp.h",
1158 "shadow.h",
1159 "signal.h",
1160 "spawn.h",
1161 "stdarg.h",
1162 "stdint.h",
1163 "stdio.h",
1164 "stdlib.h",
1165 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001166 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001167 "tar.h",
1168 "termios.h",
1169 "time.h",
1170 "ulimit.h",
1171 "unistd.h",
1172 "utime.h",
1173 "wchar.h",
1174 "wctype.h",
1175 "wordexp.h" );
1176
1177my %GlibcDir = map {$_=>1} (
1178 "arpa",
1179 "bits",
1180 "gnu",
1181 "netinet",
1182 "net",
1183 "nfs",
1184 "rpc",
1185 "sys",
1186 "linux" );
1187
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001188my %WinHeaders = map {$_=>1} (
1189 "dos.h",
1190 "process.h",
1191 "winsock.h",
1192 "config-win.h",
1193 "mem.h",
1194 "windows.h",
1195 "winsock2.h",
1196 "crtdbg.h",
1197 "ws2tcpip.h"
1198);
1199
1200my %ObsoleteHeaders = map {$_=>1} (
1201 "iostream.h",
1202 "fstream.h"
1203);
1204
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001205my %AlienHeaders = map {$_=>1} (
1206 # Solaris
1207 "thread.h",
1208 "sys/atomic.h",
1209 # HPUX
1210 "sys/stream.h",
1211 # Symbian
1212 "AknDoc.h",
1213 # Atari ST
1214 "ext.h",
1215 "tos.h",
1216 # MS-DOS
1217 "alloc.h",
1218 # Sparc
1219 "sys/atomic.h"
1220);
1221
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001222my %ConfHeaders = map {$_=>1} (
1223 "atomic",
1224 "conf.h",
1225 "config.h",
1226 "configure.h",
1227 "build.h",
1228 "setup.h"
1229);
1230
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001231my %LocalIncludes = map {$_=>1} (
1232 "/usr/local/include",
1233 "/usr/local" );
1234
1235my %OS_AddPath=(
1236# These paths are needed if the tool cannot detect them automatically
1237 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001238 "include"=>[
1239 "/Library",
1240 "/Developer/usr/include"
1241 ],
1242 "lib"=>[
1243 "/Library",
1244 "/Developer/usr/lib"
1245 ],
1246 "bin"=>[
1247 "/Developer/usr/bin"
1248 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001249 },
1250 "beos"=>{
1251 # Haiku has GCC 2.95.3 by default
1252 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001253 "include"=>[
1254 "/boot/common",
1255 "/boot/develop"
1256 ],
1257 "lib"=>[
1258 "/boot/common/lib",
1259 "/boot/system/lib",
1260 "/boot/apps"
1261 ],
1262 "bin"=>[
1263 "/boot/common/bin",
1264 "/boot/system/bin",
1265 "/boot/develop/abi"
1266 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001268);
1269
1270my %Slash_Type=(
1271 "default"=>"/",
1272 "windows"=>"\\"
1273);
1274
1275my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1276
1277# Global Variables
1278my %COMMON_LANGUAGE=(
1279 1 => "C",
1280 2 => "C" );
1281
1282my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001283my $MAX_CPPFILT_FILE_SIZE = 50000;
1284my $CPPFILT_SUPPORT_FILE;
1285
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +03001286my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION, %CLANG_VERSION);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001287
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001288my $STDCXX_TESTING = 0;
1289my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001290my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001291
1292my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001293my $CheckUndefined = 0;
1294
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +03001295my $TargetComponent = undef;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001296if($TargetComponent_Opt) {
1297 $TargetComponent = lc($TargetComponent_Opt);
1298}
1299else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001300{ # default: library
1301 # other components: header, system, ...
1302 $TargetComponent = "library";
1303}
1304
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001305my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001306
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001307my $SystemRoot;
1308
1309my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001310my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001311my %LOG_PATH;
1312my %DEBUG_PATH;
1313my %Cache;
1314my %LibInfo;
1315my $COMPILE_ERRORS = 0;
1316my %CompilerOptions;
1317my %CheckedDyLib;
1318my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1319
1320# Constants (#defines)
1321my %Constants;
1322my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001323my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001324
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001325# Extra Info
1326my %SymbolHeader;
1327my %KnownLibs;
1328
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001329# Templates
1330my %TemplateInstance;
1331my %BasicTemplate;
1332my %TemplateArg;
1333my %TemplateDecl;
1334my %TemplateMap;
1335
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001336# Types
1337my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001338my %SkipTypes = (
1339 "1"=>{},
1340 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001341my %CheckedTypes;
1342my %TName_Tid;
1343my %EnumMembName_Id;
1344my %NestedNameSpaces = (
1345 "1"=>{},
1346 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001347my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001348my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001349my %ClassVTable;
1350my %ClassVTable_Content;
1351my %VTableClass;
1352my %AllocableClass;
1353my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001354my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001355my %Class_SubClasses;
1356my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001357my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001358my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001359
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001360my %CheckedTypeInfo;
1361
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001362# Typedefs
1363my %Typedef_BaseName;
1364my %Typedef_Tr;
1365my %Typedef_Eq;
1366my %StdCxxTypedef;
1367my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001368my %MissedBase;
1369my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001370my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001371
1372# Symbols
1373my %SymbolInfo;
1374my %tr_name;
1375my %mangled_name_gcc;
1376my %mangled_name;
1377my %SkipSymbols = (
1378 "1"=>{},
1379 "2"=>{} );
1380my %SkipNameSpaces = (
1381 "1"=>{},
1382 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001383my %AddNameSpaces = (
1384 "1"=>{},
1385 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001386my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001387my %TypesList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001388my %SymbolsList_App;
1389my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001390my %Symbol_Library = (
1391 "1"=>{},
1392 "2"=>{} );
1393my %Library_Symbol = (
1394 "1"=>{},
1395 "2"=>{} );
1396my %DepSymbol_Library = (
1397 "1"=>{},
1398 "2"=>{} );
1399my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001400 "1"=>{},
1401 "2"=>{} );
1402my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001403my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001404my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001405my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001406my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001407my %Library_Needed= (
1408 "1"=>{},
1409 "2"=>{} );
Andrey Ponomarenko991da682016-09-07 19:09:50 +03001410my $DisabledMSVCUnmangling = undef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001411
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001412# Extra Info
1413my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001414my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001415
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001416# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001417my %Include_Preamble = (
1418 "1"=>[],
1419 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001420my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001421my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001422my %HeaderName_Paths;
1423my %Header_Dependency;
1424my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001425my %Include_Paths = (
1426 "1"=>[],
1427 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001428my %INC_PATH_AUTODETECT = (
1429 "1"=>1,
1430 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001431my %Add_Include_Paths = (
1432 "1"=>[],
1433 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001434my %Skip_Include_Paths;
1435my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001436my %Header_ErrorRedirect;
1437my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001438my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001439my %Header_ShouldNotBeUsed;
1440my %RecursiveIncludes;
1441my %Header_Include_Prefix;
1442my %SkipHeaders;
1443my %SkipHeadersList=(
1444 "1"=>{},
1445 "2"=>{} );
1446my %SkipLibs;
1447my %Include_Order;
1448my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001449my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001450my %TUnit_Funcs;
1451my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001452
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001453my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001454 "1"=>0,
1455 "2"=>0 );
1456my %AutoPreambleMode = (
1457 "1"=>0,
1458 "2"=>0 );
1459my %MinGWMode = (
1460 "1"=>0,
1461 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001462my %Cpp0xMode = (
1463 "1"=>0,
1464 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001465
1466# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001467my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001468my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001469my %RegisteredSONAMEs;
1470my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001471
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001472my %CheckedArch;
1473
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001474# System Objects
1475my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001476my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001477my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001478
1479# System Headers
1480my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001481my @DefaultCppPaths;
1482my @DefaultGccPaths;
1483my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001484my %DefaultCppHeader;
1485my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001486my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001487
1488# Merging
1489my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001490my $Version;
1491my %AddedInt;
1492my %RemovedInt;
1493my %AddedInt_Virt;
1494my %RemovedInt_Virt;
1495my %VirtualReplacement;
1496my %ChangedTypedef;
1497my %CompatRules;
1498my %IncompleteRules;
1499my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001500my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001501my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001502my %ReturnedClass;
1503my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001504my %SourceAlternative;
1505my %SourceAlternative_B;
1506my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001507my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001508
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03001509#Report
1510my %TypeChanges;
1511
1512#Speedup
1513my %TypeProblemsIndex;
1514
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001515# Calling Conventions
1516my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001517 1=>{ "R"=>0, "P"=>0 },
1518 2=>{ "R"=>0, "P"=>0 }
1519);
1520
1521# ABI Dump
1522my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001523
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001524# Filters
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001525my %TargetLibs;
1526my %TargetHeaders;
1527
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001528# Format of objects
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001529my $OStarget = $OSgroup;
1530my %TargetTools;
1531
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001532# Recursion locks
1533my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001534my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001535my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001536my @RecurInclude;
1537my @RecurConstant;
1538
1539# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001540my %SystemPaths = (
1541 "include"=>[],
1542 "lib"=>[],
1543 "bin"=>[]
1544);
1545my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001546my $GCC_PATH;
1547
1548# Symbols versioning
1549my %SymVer = (
1550 "1"=>{},
1551 "2"=>{} );
1552
1553# Problem descriptions
1554my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001555my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001556my %TotalAffected;
1557
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001558# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001559my $ContentID = 1;
1560my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +03001561my $ContentSpanStart_Affected = "<span class=\"sect_aff\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1562my $ContentSpanStart_Info = "<span class=\"sect_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001563my $ContentSpanEnd = "</span>\n";
1564my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1565my $ContentDivEnd = "</div>\n";
1566my $Content_Counter = 0;
1567
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001568# Modes
1569my $JoinReport = 1;
1570my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001571
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001572my %Severity_Val=(
1573 "High"=>3,
1574 "Medium"=>2,
1575 "Low"=>1,
1576 "Safe"=>-1
1577);
1578
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001579sub get_Modules()
1580{
1581 my $TOOL_DIR = get_dirname($0);
1582 if(not $TOOL_DIR)
1583 { # patch for MS Windows
1584 $TOOL_DIR = ".";
1585 }
1586 my @SEARCH_DIRS = (
1587 # tool's directory
1588 abs_path($TOOL_DIR),
1589 # relative path to modules
1590 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001591 # install path
1592 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001593 );
1594 foreach my $DIR (@SEARCH_DIRS)
1595 {
1596 if(not is_abs($DIR))
1597 { # relative path
1598 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1599 }
1600 if(-d $DIR."/modules") {
1601 return $DIR."/modules";
1602 }
1603 }
1604 exitStatus("Module_Error", "can't find modules");
1605}
1606
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001607my %LoadedModules = ();
1608
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001609sub loadModule($)
1610{
1611 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001612 if(defined $LoadedModules{$Name}) {
1613 return;
1614 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001615 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1616 if(not -f $Path) {
1617 exitStatus("Module_Error", "can't access \'$Path\'");
1618 }
1619 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001620 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001621}
1622
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001623sub readModule($$)
1624{
1625 my ($Module, $Name) = @_;
1626 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1627 if(not -f $Path) {
1628 exitStatus("Module_Error", "can't access \'$Path\'");
1629 }
1630 return readFile($Path);
1631}
1632
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001633sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001634{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001635 my $Number = $_[0];
1636 if(not $Number) {
1637 $Number = 1;
1638 }
1639 else {
1640 $Number = int($Number)+1;
1641 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001642 if($Number>3) {
1643 return $Number."th";
1644 }
1645 elsif($Number==1) {
1646 return "1st";
1647 }
1648 elsif($Number==2) {
1649 return "2nd";
1650 }
1651 elsif($Number==3) {
1652 return "3rd";
1653 }
1654 else {
1655 return $Number;
1656 }
1657}
1658
1659sub search_Tools($)
1660{
1661 my $Name = $_[0];
1662 return "" if(not $Name);
1663 if(my @Paths = keys(%TargetTools))
1664 {
1665 foreach my $Path (@Paths)
1666 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001667 if(-f join_P($Path, $Name)) {
1668 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001669 }
1670 if($CrossPrefix)
1671 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001672 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001673 if(-f $Candidate) {
1674 return $Candidate;
1675 }
1676 }
1677 }
1678 }
1679 else {
1680 return "";
1681 }
1682}
1683
1684sub synch_Cmd($)
1685{
1686 my $Name = $_[0];
1687 if(not $GCC_PATH)
1688 { # GCC was not found yet
1689 return "";
1690 }
1691 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001692 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001693 return $Candidate;
1694 }
1695 return "";
1696}
1697
1698sub get_CmdPath($)
1699{
1700 my $Name = $_[0];
1701 return "" if(not $Name);
1702 if(defined $Cache{"get_CmdPath"}{$Name}) {
1703 return $Cache{"get_CmdPath"}{$Name};
1704 }
1705 my %BinUtils = map {$_=>1} (
1706 "c++filt",
1707 "objdump",
1708 "readelf"
1709 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001710 if($BinUtils{$Name} and $GCC_PATH)
1711 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001712 if(my $Dir = get_dirname($GCC_PATH)) {
1713 $TargetTools{$Dir}=1;
1714 }
1715 }
1716 my $Path = search_Tools($Name);
1717 if(not $Path and $OSgroup eq "windows") {
1718 $Path = search_Tools($Name.".exe");
1719 }
1720 if(not $Path and $BinUtils{$Name})
1721 {
1722 if($CrossPrefix)
1723 { # user-defined prefix
1724 $Path = search_Cmd($CrossPrefix."-".$Name);
1725 }
1726 }
1727 if(not $Path and $BinUtils{$Name})
1728 {
1729 if(my $Candidate = synch_Cmd($Name))
1730 { # synch with GCC
1731 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001732 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001733 if(-f $Candidate) {
1734 $Path = $Candidate;
1735 }
1736 }
1737 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001738 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001739 $Path = $Candidate;
1740 }
1741 }
1742 }
1743 if(not $Path) {
1744 $Path = search_Cmd($Name);
1745 }
1746 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001747 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001748 $Path=search_Cmd($Name.".exe");
1749 }
1750 if($Path=~/\s/) {
1751 $Path = "\"".$Path."\"";
1752 }
1753 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1754}
1755
1756sub search_Cmd($)
1757{
1758 my $Name = $_[0];
1759 return "" if(not $Name);
1760 if(defined $Cache{"search_Cmd"}{$Name}) {
1761 return $Cache{"search_Cmd"}{$Name};
1762 }
1763 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1764 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1765 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001766 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001767 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001768 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001769 if(-f $CmdPath)
1770 {
1771 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001772 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001773 }
1774 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1775 }
1776 }
1777 return ($Cache{"search_Cmd"}{$Name} = "");
1778}
1779
1780sub get_CmdPath_Default($)
1781{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001782 return "" if(not $_[0]);
1783 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1784 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001785 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001786 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1787}
1788
1789sub get_CmdPath_Default_I($)
1790{ # search in PATH
1791 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001792 if($Name=~/find/)
1793 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001794 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001795 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001796 }
1797 }
1798 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001799 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001800 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001801 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001802 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001803 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001804 if($OSgroup eq "windows")
1805 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001806 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001807 return $Name;
1808 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001809 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001810 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001811 {
1812 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001813 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001814 }
1815 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001816 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001817}
1818
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001819sub classifyPath($)
1820{
1821 my $Path = $_[0];
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001822 if($Path=~/[\*\+\(\[\|]/)
1823 { # pattern
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001824 return ($Path, "Pattern");
1825 }
1826 elsif($Path=~/[\/\\]/)
1827 { # directory or relative path
1828 return (path_format($Path, $OSgroup), "Path");
1829 }
1830 else {
1831 return ($Path, "Name");
1832 }
1833}
1834
1835sub readDescriptor($$)
1836{
1837 my ($LibVersion, $Content) = @_;
1838 return if(not $LibVersion);
1839 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1840 if(not $Content) {
1841 exitStatus("Error", "$DName is empty");
1842 }
1843 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001844 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001845 }
1846 $Content=~s/\/\*(.|\n)+?\*\///g;
1847 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001848
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001849 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1850 if($TargetVersion{$LibVersion}) {
1851 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1852 }
1853 if(not $Descriptor{$LibVersion}{"Version"}) {
1854 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1855 }
1856 if($Content=~/{RELPATH}/)
1857 {
1858 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1859 $Content =~ s/{RELPATH}/$RelDir/g;
1860 }
1861 else
1862 {
1863 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1864 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1865 }
1866 }
1867
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001868 my $DHeaders = parseTag(\$Content, "headers");
1869 if(not $DHeaders) {
1870 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1871 }
1872 elsif(lc($DHeaders) ne "none")
1873 { # append the descriptor headers list
1874 if($Descriptor{$LibVersion}{"Headers"})
1875 { # multiple descriptors
1876 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001877 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001878 else {
1879 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1880 }
1881 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1882 {
1883 if(not -e $Path) {
1884 exitStatus("Access_Error", "can't access \'$Path\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001885 }
1886 }
1887 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001888
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001889 if(not $CheckHeadersOnly_Opt)
1890 {
1891 my $DObjects = parseTag(\$Content, "libs");
1892 if(not $DObjects) {
1893 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1894 }
1895 elsif(lc($DObjects) ne "none")
1896 { # append the descriptor libraries list
1897 if($Descriptor{$LibVersion}{"Libs"})
1898 { # multiple descriptors
1899 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1900 }
1901 else {
1902 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1903 }
1904 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1905 {
1906 if(not -e $Path) {
1907 exitStatus("Access_Error", "can't access \'$Path\'");
1908 }
1909 }
1910 }
1911 }
1912 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1913 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001914 if(not -d $Path) {
1915 exitStatus("Access_Error", "can't access directory \'$Path\'");
1916 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001917 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001918 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001919 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001920 }
1921 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1922 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001923 if(not -d $Path) {
1924 exitStatus("Access_Error", "can't access directory \'$Path\'");
1925 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001926 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001927 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001928 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001929 }
1930 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1931 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001932 if(not -d $Path) {
1933 exitStatus("Access_Error", "can't access directory \'$Path\'");
1934 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001935 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001936 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001937 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001938 $TargetTools{$Path}=1;
1939 }
1940 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1941 $CrossPrefix = $Prefix;
1942 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001943 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001944 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1945 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001946 if(not -d $Path) {
1947 exitStatus("Access_Error", "can't access directory \'$Path\'");
1948 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001949 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001950 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001951 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001952 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001953 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001954 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1955 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001956 if(not -d $Path) {
1957 exitStatus("Access_Error", "can't access directory \'$Path\'");
1958 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001959 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001960 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001961 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001962 }
1963 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001964 { # skip some auto-generated include paths
1965 if(not is_abs($Path))
1966 {
1967 if(my $P = abs_path($Path)) {
1968 $Path = $P;
1969 }
1970 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001971 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001972 }
1973 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001974 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001975 my ($CPath, $Type) = classifyPath($Path);
1976 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001977 }
1978 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001979 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1980 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001981 if($Option!~/\A\-(Wl|l|L)/)
1982 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001983 $CompilerOptions{$LibVersion} .= " ".$Option;
1984 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001985 }
1986 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1987 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1988 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001989 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001990
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001991 my ($CPath, $Type) = classifyPath($Path);
1992 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001993 }
1994 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1995 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1996 {
1997 my ($CPath, $Type) = classifyPath($Path);
1998 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1999 }
2000 if(my $DDefines = parseTag(\$Content, "defines"))
2001 {
2002 if($Descriptor{$LibVersion}{"Defines"})
2003 { # multiple descriptors
2004 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
2005 }
2006 else {
2007 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
2008 }
2009 }
2010 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
2011 {
2012 if($Order=~/\A(.+):(.+)\Z/) {
2013 $Include_Order{$LibVersion}{$1} = $2;
2014 }
2015 }
2016 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
2017 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002018 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002019 $SkipTypes{$LibVersion}{$Type_Name} = 1;
2020 }
2021 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
2022 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002023 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002024 $SkipSymbols{$LibVersion}{$Symbol} = 1;
2025 }
2026 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
2027 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
2028 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04002029 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
2030 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
2031 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002032 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
2033 $SkipConstants{$LibVersion}{$Constant} = 1;
2034 }
2035 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
2036 {
2037 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002038 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002039 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
2040 }
2041 else {
2042 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2043 }
2044 }
2045}
2046
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002047sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002048{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002049 my $CodeRef = shift(@_);
2050 my $Tag = shift(@_);
2051 if(not $Tag or not $CodeRef) {
2052 return undef;
2053 }
2054 my $Sp = 0;
2055 if(@_) {
2056 $Sp = shift(@_);
2057 }
2058 my $Start = index(${$CodeRef}, "<$Tag>");
2059 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002060 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002061 my $End = index(${$CodeRef}, "</$Tag>");
2062 if($End!=-1)
2063 {
2064 my $TS = length($Tag)+3;
2065 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2066 substr($Content, 0, $TS-1, ""); # cut start tag
2067 substr($Content, -$TS, $TS, ""); # cut end tag
2068 if(not $Sp)
2069 {
2070 $Content=~s/\A\s+//g;
2071 $Content=~s/\s+\Z//g;
2072 }
2073 if(substr($Content, 0, 1) ne "<") {
2074 $Content = xmlSpecChars_R($Content);
2075 }
2076 return $Content;
2077 }
2078 }
2079 return undef;
2080}
2081
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002082sub getInfo($)
2083{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002084 my $DumpPath = $_[0];
2085 return if(not $DumpPath or not -f $DumpPath);
2086
2087 readTUDump($DumpPath);
2088
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002089 # processing info
2090 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002091
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002092 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002093 setAnonTypedef_All();
2094 }
2095
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002096 getTypeInfo_All();
2097 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002098 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002099 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002100 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002101
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002102 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002103 %LibInfo = ();
2104 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002105 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002106 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002107 %TemplateDecl = ();
2108 %StdCxxTypedef = ();
2109 %MissedTypedef = ();
2110 %Typedef_Tr = ();
2111 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002112 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002113
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002114 # clean cache
2115 delete($Cache{"getTypeAttr"});
2116 delete($Cache{"getTypeDeclId"});
2117
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002118 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002119 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002120 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002121 }
2122 else
2123 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002124 if($BinaryOnly and not $ExtendedCheck)
2125 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002126 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002127 }
2128 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002129 remove_Unused($Version, "Extended");
2130 }
2131 }
2132
2133 if($CheckInfo)
2134 {
2135 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2136 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2137 }
2138
2139 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2140 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002141 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002142 }
2143
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002144 if($Debug) {
2145 # debugMangling($Version);
2146 }
2147}
2148
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002149sub readTUDump($)
2150{
2151 my $DumpPath = $_[0];
2152
2153 open(TU_DUMP, $DumpPath);
2154 local $/ = undef;
2155 my $Content = <TU_DUMP>;
2156 close(TU_DUMP);
2157
2158 unlink($DumpPath);
2159
2160 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002161 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002162
2163 # clean memory
2164 undef $Content;
2165
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002166 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002167
2168 foreach (0 .. $#Lines)
2169 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002170 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002171 { # get a number and attributes of a node
2172 next if(not $NodeType{$2});
2173 $LibInfo{$Version}{"info_type"}{$1}=$2;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03002174 $LibInfo{$Version}{"info"}{$1}=$3." ";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002175 }
2176
2177 # clean memory
2178 delete($Lines[$_]);
2179 }
2180
2181 # clean memory
2182 undef @Lines;
2183}
2184
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002185sub simplifyConstants()
2186{
2187 foreach my $Constant (keys(%{$Constants{$Version}}))
2188 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002189 if(defined $Constants{$Version}{$Constant}{"Header"})
2190 {
2191 my $Value = $Constants{$Version}{$Constant}{"Value"};
2192 if(defined $EnumConstants{$Version}{$Value}) {
2193 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2194 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002195 }
2196 }
2197}
2198
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002199sub simplifyNames()
2200{
2201 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2202 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002203 if($Typedef_Eq{$Version}{$Base}) {
2204 next;
2205 }
2206 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2207 if($#Translations==0)
2208 {
2209 if(length($Translations[0])<=length($Base)) {
2210 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2211 }
2212 }
2213 else
2214 { # select most appropriate
2215 foreach my $Tr (@Translations)
2216 {
2217 if($Base=~/\A\Q$Tr\E/)
2218 {
2219 $Typedef_Eq{$Version}{$Base} = $Tr;
2220 last;
2221 }
2222 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002223 }
2224 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002225 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002226 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002227 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002228 if(not $TypeName) {
2229 next;
2230 }
2231 next if(index($TypeName,"<")==-1);# template instances only
2232 if($TypeName=~/>(::\w+)+\Z/)
2233 { # skip unused types
2234 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002235 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002236 foreach my $Base (sort {length($b)<=>length($a)}
2237 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002238 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002239 next if(not $Base);
2240 next if(index($TypeName,$Base)==-1);
2241 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002242 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002243 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002244 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2245 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2246 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002247 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002248 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2249 {
2250 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2251 {
2252 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2253 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002254 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002255 }
2256 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002257 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002258 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002259 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002260 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002261 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2262 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002263 }
2264}
2265
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002266sub setAnonTypedef_All()
2267{
2268 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2269 {
2270 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2271 {
2272 if(isAnon(getNameByInfo($InfoId))) {
2273 $TypedefToAnon{getTypeId($InfoId)} = 1;
2274 }
2275 }
2276 }
2277}
2278
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002279sub setTemplateParams_All()
2280{
2281 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2282 {
2283 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2284 setTemplateParams($_);
2285 }
2286 }
2287}
2288
2289sub setTemplateParams($)
2290{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002291 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002292 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002293 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002294 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002295 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002296 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002297 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002298 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002299 setTemplateInstParams($_[0], $TmplInst_Id);
2300 }
2301 }
2302
2303 $BasicTemplate{$Version}{$Tid} = $_[0];
2304
2305 if(my $Prms = getTreeAttr_Prms($_[0]))
2306 {
2307 if(my $Valu = getTreeAttr_Valu($Prms))
2308 {
2309 my $Vector = getTreeVec($Valu);
2310 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2311 {
2312 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2313 {
2314 if(my $Name = getNameByInfo($Val))
2315 {
2316 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2317 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2318 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2319 }
2320 else {
2321 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2322 }
2323 }
2324 }
2325 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002326 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002327 }
2328 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002329 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002330 {
2331 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2332 {
2333 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002334 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002335 }
2336 }
2337 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002338}
2339
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002340sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002341{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002342 my ($Tmpl, $Inst) = @_;
2343
2344 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002345 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002346 my ($Params_InfoId, $ElemId) = ();
2347 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2348 $Params_InfoId = $1;
2349 }
2350 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2351 $ElemId = $1;
2352 }
2353 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002354 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002355 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2356 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2357 {
2358 my ($PPos, $PTypeId) = ($1, $2);
2359 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2360 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002361 if($PType eq "template_type_parm") {
2362 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002363 }
2364 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002365 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2366 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002367 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002368 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002369 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002370 else
2371 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002372 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002373 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002374 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002375 }
2376 }
2377 }
2378}
2379
2380sub getTypeDeclId($)
2381{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002382 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002383 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002384 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2385 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2386 }
2387 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2388 {
2389 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2390 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2391 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002392 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002393 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002394 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002395}
2396
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002397sub getTypeInfo_All()
2398{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002399 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002400 { # support for GCC < 4.5
2401 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2402 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2403 # FIXME: check GCC versions
2404 addMissedTypes_Pre();
2405 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002406
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002407 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002408 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002409 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2410 if($IType=~/_type\Z/ and $IType ne "function_type"
2411 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002412 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002413 }
2414 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002415
2416 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002417 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002418 "Name" => "...",
2419 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002420 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002421 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002422 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002423
2424 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002425 { # support for GCC < 4.5
2426 addMissedTypes_Post();
2427 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002428
2429 if($ADD_TMPL_INSTANCES)
2430 {
2431 # templates
2432 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2433 {
2434 if(defined $TemplateMap{$Version}{$Tid}
2435 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2436 {
2437 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2438 {
2439 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2440 {
2441 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2442 {
2443 if(my %MAttr = getTypeAttr($MembTypeId))
2444 {
2445 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2446 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2447 }
2448 }
2449 }
2450 }
2451 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2452 {
2453 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2454 {
2455 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2456
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002457 if($NBid ne $Bid
2458 and $NBid ne $Tid)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002459 {
2460 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2461 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2462 }
2463 }
2464 }
2465 }
2466 }
2467 }
2468}
2469
2470sub createType($$)
2471{
2472 my ($Attr, $LibVersion) = @_;
2473 my $NewId = ++$MAX_ID;
2474
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002475 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002476 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002477 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002478
2479 return "$NewId";
2480}
2481
2482sub instType($$$)
2483{ # create template instances
2484 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002485
2486 if(not $TypeInfo{$LibVersion}{$Tid}) {
2487 return undef;
2488 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002489 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2490
2491 foreach my $Key (sort keys(%{$Map}))
2492 {
2493 if(my $Val = $Map->{$Key})
2494 {
2495 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2496
2497 if(defined $Attr->{"NameSpace"}) {
2498 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2499 }
2500 foreach (keys(%{$Attr->{"TParam"}})) {
2501 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2502 }
2503 }
2504 else
2505 { # remove absent
2506 # _Traits, etc.
2507 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002508 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002509 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2510 }
2511 foreach (keys(%{$Attr->{"TParam"}}))
2512 {
2513 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2514 delete($Attr->{"TParam"}{$_});
2515 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002516 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002517 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2518 }
2519 }
2520 }
2521 }
2522
2523 my $Tmpl = 0;
2524
2525 if(defined $Attr->{"TParam"})
2526 {
2527 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2528 {
2529 my $PName = $Attr->{"TParam"}{$_}{"name"};
2530
2531 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2532 {
2533 my %Base = get_BaseType($PTid, $LibVersion);
2534
2535 if($Base{"Type"} eq "TemplateParam"
2536 or defined $Base{"Template"})
2537 {
2538 $Tmpl = 1;
2539 last
2540 }
2541 }
2542 }
2543 }
2544
2545 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2546 return "$Id";
2547 }
2548 else
2549 {
2550 if(not $Tmpl) {
2551 delete($Attr->{"Template"});
2552 }
2553
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002554 my $New = createType($Attr, $LibVersion);
2555
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002556 my %EMap = ();
2557 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2558 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2559 }
2560 foreach (keys(%{$Map})) {
2561 $EMap{$_} = $Map->{$_};
2562 }
2563
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002564 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2565 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002566 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002567 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002568 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002569 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002570 {
2571 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2572
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002573 if($NBid ne $Bid
2574 and $NBid ne $New)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002575 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002576 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2577 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002578 }
2579 }
2580 }
2581
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002582 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002583 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002584 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2585 {
2586 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2587 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2588 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002589 }
2590 }
2591
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002592 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002593 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002594 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2595 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002596 }
2597 }
2598
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002599 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2600 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002601 }
2602
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002603 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002604 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002605}
2606
2607sub addMissedTypes_Pre()
2608{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002609 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002610 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2611 { # detecting missed typedefs
2612 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2613 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002614 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002615 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002616 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002617 if($TypeType eq "Unknown")
2618 { # template_type_parm
2619 next;
2620 }
2621 my $TypeDeclId = getTypeDeclId($TypeId);
2622 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2623 my $TypedefName = getNameByInfo($MissedTDid);
2624 next if(not $TypedefName);
2625 next if($TypedefName eq "__float80");
2626 next if(isAnon($TypedefName));
2627 if(not $TypeDeclId
2628 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002629 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002630 }
2631 }
2632 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002633 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002634 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002635 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002636 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002637 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002638 next;
2639 }
2640 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002641 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002642 if(not $TypedefName) {
2643 next;
2644 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002645 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002646 my %MissedInfo = ( # typedef info
2647 "Name" => $TypedefName,
2648 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002649 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002650 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002651 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002652 my ($H, $L) = getLocation($MissedTDid);
2653 $MissedInfo{"Header"} = $H;
2654 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002655 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002656 { # other types
2657 next;
2658 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002659 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002660 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002661 next;
2662 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002663 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002664 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002665 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002666 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002667 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002668 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002669 next;
2670 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002671 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002672 next;
2673 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002674 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002675 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002676 next;
2677 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002678 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002679 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002680 next;
2681 }
2682 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002683
2684 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2685
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002686 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002687 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002688 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002689 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002690 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002691
2692 # add missed & remove other
2693 $TypeInfo{$Version} = \%AddTypes;
2694 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002695}
2696
2697sub addMissedTypes_Post()
2698{
2699 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2700 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002701 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2702 {
2703 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2704 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2705 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2706 }
2707 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002708 }
2709}
2710
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002711sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002712{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002713 my $TypeId = $_[0];
2714 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2715 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002716 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002717 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002718 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002719}
2720
2721sub getArraySize($$)
2722{
2723 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002724 if(my $Size = getSize($TypeId))
2725 {
2726 my $Elems = $Size/$BYTE_SIZE;
2727 while($BaseName=~s/\s*\[(\d+)\]//) {
2728 $Elems/=$1;
2729 }
2730 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2731 {
2732 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2733 $Elems/=$BasicSize;
2734 }
2735 }
2736 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002737 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002738 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002739}
2740
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002741sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002742{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002743 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002744 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002745 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2746 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002747 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002748 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2749 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2750 if(not $NodeType)
2751 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002752 return ();
2753 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002754 if($NodeType eq "tree_vec")
2755 {
2756 if($Pos!=$#Positions)
2757 { # select last vector of parameters ( ns<P1>::type<P2> )
2758 next;
2759 }
2760 }
2761 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2762 foreach my $P (@Params)
2763 {
2764 if($P eq "") {
2765 return ();
2766 }
2767 elsif($P ne "\@skip\@") {
2768 @TmplParams = (@TmplParams, $P);
2769 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002770 }
2771 }
2772 return @TmplParams;
2773}
2774
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002775sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002776{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002777 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002778 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002779 if(defined $TypeInfo{$Version}{$TypeId}
2780 and $TypeInfo{$Version}{$TypeId}{"Name"})
2781 { # already created
2782 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002783 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002784 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2785 { # incomplete type
2786 return ();
2787 }
2788 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2789
2790 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002791 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002792
2793 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2794 {
2795 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2796 {
2797 if($Info=~/qual[ ]*:/)
2798 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002799 my $NewId = ++$MAX_ID;
2800
2801 $MissedBase{$Version}{$TypeId} = "$NewId";
2802 $MissedBase_R{$Version}{$NewId} = $TypeId;
2803 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2804 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002805 }
2806 }
2807 $TypeAttr{"Type"} = "Typedef";
2808 }
2809 else {
2810 $TypeAttr{"Type"} = getTypeType($TypeId);
2811 }
2812
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002813 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2814 {
2815 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2816 { # local code
2817 return ();
2818 }
2819 }
2820
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002821 if($TypeAttr{"Type"} eq "Unknown") {
2822 return ();
2823 }
2824 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2825 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002826 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002827 if(my $TName = $TypeAttr{"Name"})
2828 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002829 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002830 $TName_Tid{$Version}{$TName} = $TypeId;
2831 return %TypeAttr;
2832 }
2833 else {
2834 return ();
2835 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002836 }
2837 elsif($TypeAttr{"Type"} eq "Array")
2838 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002839 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2840 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002841 return ();
2842 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002843 if(my $Algn = getAlgn($TypeId)) {
2844 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2845 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002846 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002847 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002848 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002849 if(not $BTAttr{"Name"}) {
2850 return ();
2851 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002852 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002853 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002854 if(my $Size = getSize($TypeId)) {
2855 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2856 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002857 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002858 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2859 }
2860 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002861 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002862 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002863 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002864 else
2865 {
2866 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002867 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002868 $TypeAttr{"Name"} = $1."[]".$2;
2869 }
2870 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002871 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002872 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002873 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002874 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002875 if($BTAttr{"Header"}) {
2876 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002877 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002878 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002879 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2880 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002881 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002882 return ();
2883 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002884 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002885 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002886 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002887 if($TypeAttr{"Name"})
2888 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002889 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002890
2891 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2892 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002893 { # NOTE: register only one int: with built-in decl
2894 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2895 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2896 }
2897 }
2898 return %TypeAttr;
2899 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002900 else {
2901 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002902 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002903 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002904 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2905 {
2906 %TypeAttr = getTrivialTypeAttr($TypeId);
2907 if($TypeAttr{"Name"})
2908 {
2909 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2910 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2911 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2912 }
2913 return %TypeAttr;
2914 }
2915 else {
2916 return ();
2917 }
2918 }
2919 elsif($TypeAttr{"Type"} eq "SizeOf")
2920 {
2921 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2922 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2923 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2924 if($TypeAttr{"Name"})
2925 {
2926 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2927 return %TypeAttr;
2928 }
2929 else {
2930 return ();
2931 }
2932 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002933 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002934 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002935 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2936 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002937 return ();
2938 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002939 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002940 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002941 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002942 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002943 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002944 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002945 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002946 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002947 }
2948 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002949 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002950 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002951 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002952 return ();
2953 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002954 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002955 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002956 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002957 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002958 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002959 }
2960 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002961 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002962 {
2963 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002964 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002965 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002966 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002967 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2968 }
2969 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002970 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002971 }
2972 }
2973 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002974 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002975 }
2976 if($TypeAttr{"Type"} eq "Typedef")
2977 {
2978 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002979
2980 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2981 return ();
2982 }
2983
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002984 if(isAnon($TypeAttr{"Name"}))
2985 { # anon typedef to anon type: ._N
2986 return ();
2987 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002988
2989 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2990 { # artificial typedef of "struct X" to "X"
2991 $TypeAttr{"Artificial"} = 1;
2992 }
2993
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002994 if(my $NS = getNameSpace($TypeDeclId))
2995 {
2996 my $TypeName = $TypeAttr{"Name"};
2997 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2998 { # "some_type" is the typedef to "struct some_type" in C++
2999 if($3) {
3000 $TypeAttr{"Name"} = $3."::".$TypeName;
3001 }
3002 }
3003 else
3004 {
3005 $TypeAttr{"NameSpace"} = $NS;
3006 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003007
3008 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
3009 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
3010 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003011 if($BTAttr{"NameSpace"}
3012 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003013 { # types like "std::fpos<__mbstate_t>" are
3014 # not covered by typedefs in the TU dump
3015 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003016 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3017 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003018 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003019 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003020 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003021 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003022 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003023 }
3024 }
3025 }
3026 }
3027 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003028 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003029 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003030 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003031 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
3032 { # typedef int*const TYPEDEF; // first
3033 # int foo(TYPEDEF p); // const is optimized out
3034 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
3035 if($BTAttr{"Name"}=~/</)
3036 {
3037 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
3038 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3039 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003040 }
3041 }
3042 }
3043 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
3044 }
3045 if(not $TypeAttr{"Size"})
3046 {
3047 if($TypeAttr{"Type"} eq "Pointer") {
3048 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3049 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003050 elsif($BTAttr{"Size"}) {
3051 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003052 }
3053 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003054 if(my $Algn = getAlgn($TypeId)) {
3055 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3056 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003057 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003058 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3059 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003060 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003061 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003062 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003063 { # typedef to "class Class"
3064 # should not be registered in TName_Tid
3065 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3066 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3067 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003068 }
3069 return %TypeAttr;
3070 }
3071}
3072
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003073sub getTreeVec($)
3074{
3075 my %Vector = ();
3076 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3077 {
3078 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3079 { # string length is N-1 because of the null terminator
3080 $Vector{$1} = $2;
3081 }
3082 }
3083 return \%Vector;
3084}
3085
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003086sub get_TemplateParam($$)
3087{
3088 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003089 return () if(not $Type_Id);
3090 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3091 return () if(not $NodeType);
3092 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003093 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003094 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003095 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003096 my $Num = getNodeIntCst($Type_Id);
3097 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003098 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003099 }
3100 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003101 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003102 }
3103 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003104 elsif($NodeType eq "string_cst") {
3105 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003106 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003107 elsif($NodeType eq "tree_vec")
3108 {
3109 my $Vector = getTreeVec($Type_Id);
3110 my @Params = ();
3111 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3112 {
3113 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3114 push(@Params, $P2);
3115 }
3116 }
3117 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003118 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003119 elsif($NodeType eq "parm_decl")
3120 {
3121 (getNameByInfo($Type_Id));
3122 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003123 else
3124 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003125 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003126 my $PName = $ParamAttr{"Name"};
3127 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003128 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003129 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003130 if($PName=~/\>/)
3131 {
3132 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003133 $PName = $Cover;
3134 }
3135 }
3136 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003137 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003138 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3139 # template<typename _Key, typename _Compare = std::less<_Key>
3140 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3141 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3142 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3143 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003144 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003145 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003146 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003147 }
3148}
3149
3150sub cover_stdcxx_typedef($)
3151{
3152 my $TypeName = $_[0];
3153 if(my @Covers = sort {length($a)<=>length($b)}
3154 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3155 { # take the shortest typedef
3156 # FIXME: there may be more than
3157 # one typedefs to the same type
3158 return $Covers[0];
3159 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003160 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003161 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3162 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3163 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003164 if(my $Cover = $Covers[0])
3165 {
3166 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3167 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3168 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003169 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003170 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003171}
3172
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003173sub getNodeIntCst($)
3174{
3175 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003176 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003177 if($EnumMembName_Id{$Version}{$CstId}) {
3178 return $EnumMembName_Id{$Version}{$CstId};
3179 }
3180 elsif((my $Value = getTreeValue($CstId)) ne "")
3181 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003182 if($Value eq "0")
3183 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003184 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003185 return "false";
3186 }
3187 else {
3188 return "0";
3189 }
3190 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003191 elsif($Value eq "1")
3192 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003193 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003194 return "true";
3195 }
3196 else {
3197 return "1";
3198 }
3199 }
3200 else {
3201 return $Value;
3202 }
3203 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003204 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003205}
3206
3207sub getNodeStrCst($)
3208{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003209 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3210 {
3211 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003212 {
3213 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3214 { # string length is N-1 because of the null terminator
3215 return substr($1, 0, $2-1);
3216 }
3217 else
3218 { # identifier_node
3219 return substr($1, 0, $2);
3220 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003221 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003222 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003223 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003224}
3225
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003226sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003227{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003228 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003229 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3230 if($Type eq "FieldPtr") {
3231 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3232 }
3233 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3234 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003235 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003236 if($Type eq "MethodPtr")
3237 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003238 if(my $Size = getSize($TypeId))
3239 {
3240 $Size/=$BYTE_SIZE;
3241 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003242 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003243 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003244 if(my $Algn = getAlgn($TypeId)) {
3245 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3246 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003247 # Return
3248 if($Type eq "FieldPtr")
3249 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003250 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003251 if($ReturnAttr{"Name"}) {
3252 $MemPtrName .= $ReturnAttr{"Name"};
3253 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003254 $TypeAttr{"Return"} = $PtrId;
3255 }
3256 else
3257 {
3258 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3259 {
3260 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003261 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3262 if(not $ReturnAttr{"Name"})
3263 { # templates
3264 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003265 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003266 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003267 $TypeAttr{"Return"} = $ReturnTypeId;
3268 }
3269 }
3270 # Class
3271 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3272 {
3273 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003274 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003275 if($Class{"Name"}) {
3276 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3277 }
3278 else {
3279 $MemPtrName .= " (*)";
3280 }
3281 }
3282 else {
3283 $MemPtrName .= " (*)";
3284 }
3285 # Parameters
3286 if($Type eq "FuncPtr"
3287 or $Type eq "MethodPtr")
3288 {
3289 my @ParamTypeName = ();
3290 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3291 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003292 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003293 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003294 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003295 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003296 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3297 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003298 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003299 my $PTypeId = $1;
3300 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003301 if(not $ParamAttr{"Name"})
3302 { # templates (template_type_parm), etc.
3303 return ();
3304 }
3305 if($ParamAttr{"Name"} eq "void") {
3306 last;
3307 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003308 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003309 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003310 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003311 push(@ParamTypeName, $ParamAttr{"Name"});
3312 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003313 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3314 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003315 }
3316 else {
3317 last;
3318 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003319 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003320 else {
3321 last;
3322 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003323 }
3324 }
3325 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3326 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003327 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003328 return %TypeAttr;
3329}
3330
3331sub getTreeTypeName($)
3332{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003333 my $TypeId = $_[0];
3334 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003335 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003336 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003337 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003338 if(my $Name = getNameByInfo($TypeId))
3339 { # bit_size_type
3340 return $Name;
3341 }
3342 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003343 return "unsigned int";
3344 }
3345 else {
3346 return "int";
3347 }
3348 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003349 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003350 return getNameByInfo($1);
3351 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003352 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003353 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003354}
3355
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003356sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003357{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003358 my $Ptd = pointTo($_[0]);
3359 return 0 if(not $Ptd);
3360 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003361 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003362 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3363 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003364 }
3365 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003366 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3367 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003368 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003369 if($InfoT1 eq "pointer_type"
3370 and $InfoT2 eq "function_type") {
3371 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003372 }
3373 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003374 return 0;
3375}
3376
3377sub isMethodPtr($)
3378{
3379 my $Ptd = pointTo($_[0]);
3380 return 0 if(not $Ptd);
3381 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3382 {
3383 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3384 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3385 and $Info=~/ ptrmem /) {
3386 return 1;
3387 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003388 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003389 return 0;
3390}
3391
3392sub isFieldPtr($)
3393{
3394 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3395 {
3396 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3397 and $Info=~/ ptrmem /) {
3398 return 1;
3399 }
3400 }
3401 return 0;
3402}
3403
3404sub pointTo($)
3405{
3406 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3407 {
3408 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3409 return $1;
3410 }
3411 }
3412 return "";
3413}
3414
3415sub getTypeTypeByTypeId($)
3416{
3417 my $TypeId = $_[0];
3418 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3419 {
3420 my $NType = $NodeType{$TType};
3421 if($NType eq "Intrinsic") {
3422 return $NType;
3423 }
3424 elsif(isFuncPtr($TypeId)) {
3425 return "FuncPtr";
3426 }
3427 elsif(isMethodPtr($TypeId)) {
3428 return "MethodPtr";
3429 }
3430 elsif(isFieldPtr($TypeId)) {
3431 return "FieldPtr";
3432 }
3433 elsif($NType ne "Other") {
3434 return $NType;
3435 }
3436 }
3437 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003438}
3439
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003440my %UnQual = (
3441 "r"=>"restrict",
3442 "v"=>"volatile",
3443 "c"=>"const",
3444 "cv"=>"const volatile"
3445);
3446
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003447sub getQual($)
3448{
3449 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003450 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3451 {
3452 my ($Qual, $To) = ();
3453 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3454 $Qual = $UnQual{$1};
3455 }
3456 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3457 $To = $1;
3458 }
3459 if($Qual and $To) {
3460 return ($Qual, $To);
3461 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003462 }
3463 return ();
3464}
3465
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003466sub getQualType($)
3467{
3468 if($_[0] eq "const volatile") {
3469 return "ConstVolatile";
3470 }
3471 return ucfirst($_[0]);
3472}
3473
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003474sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003475{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003476 my $TypeId = $_[0];
3477 my $TypeDeclId = getTypeDeclId($TypeId);
3478 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003479 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003480 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3481 return "Typedef";
3482 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003483 }
3484 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3485 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003486 if(($Qual or $To) and $TypeDeclId
3487 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003488 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003489 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003490 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003491 elsif(not $MissedBase_R{$Version}{$TypeId}
3492 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003493 return "Typedef";
3494 }
3495 elsif($Qual)
3496 { # qualified types
3497 return getQualType($Qual);
3498 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003499
3500 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3501 { # typedef struct { ... } name
3502 $TypeTypedef{$Version}{$TypeId} = $1;
3503 }
3504
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003505 my $TypeType = getTypeTypeByTypeId($TypeId);
3506 if($TypeType eq "Struct")
3507 {
3508 if($TypeDeclId
3509 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3510 return "Template";
3511 }
3512 }
3513 return $TypeType;
3514}
3515
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003516sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003517{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003518 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003519 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003520 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3521 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3522 return 0;
3523 }
3524 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3525 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003526 if(my $TDid = getTypeDeclId($_[0]))
3527 {
3528 if(getTypeId($TDid) eq $_[0]
3529 and getNameByInfo($TDid))
3530 {
3531 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3532 return $1;
3533 }
3534 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003535 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003536 }
3537 }
3538 return 0;
3539}
3540
3541sub selectBaseType($)
3542{
3543 my $TypeId = $_[0];
3544 if(defined $MissedTypedef{$Version}{$TypeId})
3545 { # add missed typedefs
3546 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3547 return ($TypeId, "");
3548 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003549 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003550 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3551 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003552
3553 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3554 my $MB = $MissedBase{$Version}{$TypeId};
3555
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003556 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003557 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003558 and (getTypeId($1) ne $TypeId)
3559 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003560 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003561 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003562 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003563 elsif($MB)
3564 { # add base
3565 return ($MB, "");
3566 }
3567 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003568 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003569 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003570 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003571 elsif($Qual or $To)
3572 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003573 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003574 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003575 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003576 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003577 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003578 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003579 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003580 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003581 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003582 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003583 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003584 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003585 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003586 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003587 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003588 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003589 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003590 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003591 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003592 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003593
3594 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003595}
3596
3597sub getSymbolInfo_All()
3598{
3599 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3600 { # reverse order
3601 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003602 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003603 }
3604 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003605
3606 if($ADD_TMPL_INSTANCES)
3607 {
3608 # templates
3609 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3610 {
3611 my %Map = ();
3612
3613 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3614 {
3615 if(defined $TemplateMap{$Version}{$ClassId})
3616 {
3617 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3618 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3619 }
3620 }
3621 }
3622
3623 if(defined $TemplateMap{$Version}{$Sid})
3624 {
3625 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3626 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3627 }
3628 }
3629
3630 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3631 {
3632 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3633 {
3634 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3635 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3636 }
3637 }
3638 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3639 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3640 }
3641 }
3642 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003643}
3644
3645sub getVarInfo_All()
3646{
3647 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3648 { # reverse order
3649 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003650 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003651 }
3652 }
3653}
3654
3655sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003656 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003657}
3658
3659sub getVarInfo($)
3660{
3661 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003662 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003663 {
3664 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3665 if($NSInfoType and $NSInfoType eq "function_decl") {
3666 return;
3667 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003668 }
3669 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3670 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3671 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3672 delete($SymbolInfo{$Version}{$InfoId});
3673 return;
3674 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003675 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003676 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003677 delete($SymbolInfo{$Version}{$InfoId});
3678 return;
3679 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003680 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3681 delete($SymbolInfo{$Version}{$InfoId});
3682 return;
3683 }
3684 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003685 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3686 {
3687 if($OSgroup eq "windows")
3688 { # cut the offset
3689 $MnglName=~s/\@\d+\Z//g;
3690 }
3691 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003693 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003694 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003695 { # validate mangled name
3696 delete($SymbolInfo{$Version}{$InfoId});
3697 return;
3698 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003699 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003700 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003701 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003702 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003703 }
3704 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3705 { # non-public global data
3706 delete($SymbolInfo{$Version}{$InfoId});
3707 return;
3708 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003709 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003710 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003711 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003712 if(not defined $TypeInfo{$Version}{$Rid}
3713 or not $TypeInfo{$Version}{$Rid}{"Name"})
3714 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003715 delete($SymbolInfo{$Version}{$InfoId});
3716 return;
3717 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003718 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3719 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003720 if(defined $Val) {
3721 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3722 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003723 }
3724 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003725 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3726 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003727 if(not defined $TypeInfo{$Version}{$ClassId}
3728 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3729 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003730 delete($SymbolInfo{$Version}{$InfoId});
3731 return;
3732 }
3733 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003734 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3735 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003736 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003737 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003738 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003739 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003740 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003741 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003742 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003743 if(not $CheckHeadersOnly)
3744 {
3745 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3746 {
3747 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3748 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3749 {
3750 if(link_symbol($ShortName, $Version, "-Deps"))
3751 { # "const" global data is mangled as _ZL... in the TU dump
3752 # but not mangled when compiling a C shared library
3753 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3754 }
3755 }
3756 }
3757 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003758 if($COMMON_LANGUAGE{$Version} eq "C++")
3759 {
3760 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3761 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003762 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003763 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3764 }
3765 }
3766 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3767 { # try to mangle symbol (link with libraries)
3768 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3769 }
3770 if($OStarget eq "windows")
3771 {
3772 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3773 { # link MS C++ symbols from library with GCC symbols from headers
3774 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3775 }
3776 }
3777 }
3778 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3779 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3780 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003781 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3782 {
3783 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3784 { # non-target symbols
3785 delete($SymbolInfo{$Version}{$InfoId});
3786 return;
3787 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003788 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003789 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3790 {
3791 if(defined $MissedTypedef{$Version}{$Rid})
3792 {
3793 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3794 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3795 }
3796 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003797 }
3798 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003799 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003800 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3801 }
3802 if($ShortName=~/\A(_Z|\?)/) {
3803 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3804 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003805
3806 if($ExtraDump) {
3807 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3808 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003809}
3810
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003811sub isConstType($$)
3812{
3813 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003814 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003815 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003816 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003817 }
3818 return ($Base{"Type"} eq "Const");
3819}
3820
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003821sub getTrivialName($$)
3822{
3823 my ($TypeInfoId, $TypeId) = @_;
3824 my %TypeAttr = ();
3825 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3826 if(not $TypeAttr{"Name"}) {
3827 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3828 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003829 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003830 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003831 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003832 if(isAnon($TypeAttr{"Name"}))
3833 {
3834 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003835 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003836 { # searching for a first not anon scope
3837 if($NSId eq $NameSpaceId) {
3838 last;
3839 }
3840 else
3841 {
3842 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3843 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003844 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003845 last;
3846 }
3847 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003848 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003849 }
3850 }
3851 else
3852 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003853 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003854 {
3855 if($NameSpaceId ne $TypeId) {
3856 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3857 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003858 }
3859 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003860 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003861 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3862 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003863 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003864 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003865 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003866 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003867 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003868 if($TypeAttr{"NameSpace"}) {
3869 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3870 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003871 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003872 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3873 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003874 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003875 if(my @TParams = getTParams($TypeId, "Type")) {
3876 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3877 }
3878 else {
3879 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3880 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003881 }
3882 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3883}
3884
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003885sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003886{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003887 my $TypeId = $_[0];
3888 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003889
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003890 my %TypeAttr = ();
3891
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003892 if($TemplateDecl{$Version}{$TypeId})
3893 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003894 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003895 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003896
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003897 setTypeAccess($TypeId, \%TypeAttr);
3898 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3899 if(isBuiltIn($TypeAttr{"Header"}))
3900 {
3901 delete($TypeAttr{"Header"});
3902 delete($TypeAttr{"Line"});
3903 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003904
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003905 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003906 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3907 if(not $TypeAttr{"Name"}) {
3908 return ();
3909 }
3910 if(not $TypeAttr{"NameSpace"}) {
3911 delete($TypeAttr{"NameSpace"});
3912 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003913
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003914 if($TypeAttr{"Type"} eq "Intrinsic")
3915 {
3916 if(defined $TypeAttr{"Header"})
3917 {
3918 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3919 { # support for SUSE 11.2
3920 # integer_type has srcp dump{1-2}.i
3921 delete($TypeAttr{"Header"});
3922 }
3923 }
3924 }
3925
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003926 my $Tmpl = undef;
3927
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003928 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003929 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003930 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3931
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003932 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003933 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003934 foreach my $Pos (0 .. $#TParams)
3935 {
3936 my $Val = $TParams[$Pos];
3937 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3938
3939 if(not defined $TypeAttr{"Template"})
3940 {
3941 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3942
3943 if($Base{"Type"} eq "TemplateParam"
3944 or defined $Base{"Template"}) {
3945 $TypeAttr{"Template"} = 1;
3946 }
3947 }
3948
3949 if($Tmpl)
3950 {
3951 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3952 {
3953 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3954
3955 if($Val eq $Arg) {
3956 $TypeAttr{"Template"} = 1;
3957 }
3958 }
3959 }
3960 }
3961
3962 if($Tmpl)
3963 {
3964 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3965 {
3966 if($Pos>$#TParams)
3967 {
3968 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3969 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3970 }
3971 }
3972 }
3973 }
3974
3975 if($ADD_TMPL_INSTANCES)
3976 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003977 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003978 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003979 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003980 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003981 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003982 {
3983 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3984 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3985 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003986 }
3987 if(not getTreeAttr_Binf($TypeId))
3988 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003989 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3990 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3991 }
3992 }
3993 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003994 }
3995 }
3996 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003997
3998 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3999
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004000 if(my $Size = getSize($TypeId))
4001 {
4002 $Size = $Size/$BYTE_SIZE;
4003 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004004 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004005 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004006 {
4007 if($ExtraDump)
4008 {
4009 if(not defined $TypeAttr{"Memb"}
4010 and not $Tmpl)
4011 { # declaration only
4012 $TypeAttr{"Forward"} = 1;
4013 }
4014 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004015 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004016
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004017 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004018 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004019 {
4020 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004021 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004022 }
4023 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004024 or $TypeAttr{"Type"} eq "Class")
4025 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004026 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004027 if($Skip) {
4028 return ();
4029 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004030 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004031 if(my $Algn = getAlgn($TypeId)) {
4032 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
4033 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004034 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004035
4036 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
4037 {
4038 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004039 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004040 {
4041 if(not isAnon($TypeAttr{"Name"})) {
4042 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
4043 }
4044 }
4045 }
4046
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004047 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004048 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4049 {
4050 my @Entries = split(/\n/, $VTable);
4051 foreach (1 .. $#Entries)
4052 {
4053 my $Entry = $Entries[$_];
4054 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004055 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004056 }
4057 }
4058 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004059
4060 if($TypeAttr{"Type"} eq "Enum")
4061 {
4062 if(not $TypeAttr{"NameSpace"})
4063 {
4064 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4065 {
4066 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004067 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004068 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004069 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004070 "Header"=>$TypeAttr{"Header"}
4071 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004072 if(isAnon($TypeAttr{"Name"}))
4073 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004074 if($ExtraDump
4075 or is_target_header($TypeAttr{"Header"}, $Version))
4076 {
4077 %{$Constants{$Version}{$MName}} = (
4078 "Value" => $MVal,
4079 "Header" => $TypeAttr{"Header"}
4080 );
4081 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004082 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004083 }
4084 }
4085 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004086 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004087 {
4088 if(defined $TypedefToAnon{$TypeId}) {
4089 $TypeAttr{"AnonTypedef"} = 1;
4090 }
4091 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004092
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004093 return %TypeAttr;
4094}
4095
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004096sub simplifyVTable($)
4097{
4098 my $Content = $_[0];
4099 if($Content=~s/ \[with (.+)]//)
4100 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4101 if(my @Elems = separate_Params($1, 0, 0))
4102 {
4103 foreach my $Elem (@Elems)
4104 {
4105 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4106 {
4107 my ($Arg, $Val) = ($1, $2);
4108
4109 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4110 $Content=~s/,\s*$Arg\b//g;
4111 }
4112 else {
4113 $Content=~s/\b$Arg\b/$Val/g;
4114 }
4115 }
4116 }
4117 }
4118 }
4119
4120 return $Content;
4121}
4122
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004123sub detect_lang($)
4124{
4125 my $TypeId = $_[0];
4126 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004127 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004128 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004129 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4130 }
4131 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004132 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004133 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004134 while($Fncs)
4135 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004136 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004137 return 1;
4138 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004139 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004140 }
4141 }
4142 return 0;
4143}
4144
4145sub setSpec($$)
4146{
4147 my ($TypeId, $TypeAttr) = @_;
4148 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4149 if($Info=~/\s+spec\s+/) {
4150 $TypeAttr->{"Spec"} = 1;
4151 }
4152}
4153
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004154sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004155{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004156 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004157 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004158 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004159 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004160 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004161 my $Pos = 0;
4162 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4163 {
4164 my ($Access, $BInfoId) = ($1, $2);
4165 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004166
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03004167 if($ClassId eq $TypeId)
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004168 { # class A<N>:public A<N-1>
4169 next;
4170 }
4171
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004172 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4173 if(not $CType or $CType eq "template_type_parm"
4174 or $CType eq "typename_type")
4175 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004176 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004177 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004178 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004179 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004180 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4181 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004182 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004183 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4184 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004185 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004186 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004187 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004188 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4189 }
4190 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004191 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004192 }
4193 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004194 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004195}
4196
4197sub getBinfClassId($)
4198{
4199 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03004200 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
4201 return $1;
4202 }
4203
4204 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004205}
4206
4207sub unmangledFormat($$)
4208{
4209 my ($Name, $LibVersion) = @_;
4210 $Name = uncover_typedefs($Name, $LibVersion);
4211 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4212 $Name=~s/\(\w+\)(\d)/$1/;
4213 return $Name;
4214}
4215
4216sub modelUnmangled($$)
4217{
4218 my ($InfoId, $Compiler) = @_;
4219 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4220 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4221 }
4222 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4223 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4224 $PureSignature = "~".$PureSignature;
4225 }
4226 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4227 {
4228 my (@Params, @ParamTypes) = ();
4229 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4230 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4231 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4232 }
4233 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4234 { # checking parameters
4235 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004236 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004237 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004238 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004239
4240 if($PName eq "this"
4241 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4242 {
4243 next;
4244 }
4245
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004246 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004247 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004248 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004249 }
4250 @ParamTypes = (@ParamTypes, $PTName);
4251 }
4252 if(@ParamTypes) {
4253 $PureSignature .= "(".join(", ", @ParamTypes).")";
4254 }
4255 else
4256 {
4257 if($Compiler eq "MSVC")
4258 {
4259 $PureSignature .= "(void)";
4260 }
4261 else
4262 { # GCC
4263 $PureSignature .= "()";
4264 }
4265 }
4266 $PureSignature = delete_keywords($PureSignature);
4267 }
4268 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4269 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004270 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004271 $PureSignature = $ClassName."::".$PureSignature;
4272 }
4273 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4274 $PureSignature = $NS."::".$PureSignature;
4275 }
4276 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4277 $PureSignature .= " const";
4278 }
4279 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4280 $PureSignature .= " volatile";
4281 }
4282 my $ShowReturn = 0;
4283 if($Compiler eq "MSVC"
4284 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4285 {
4286 $ShowReturn=1;
4287 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004288 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4289 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004290 {
4291 $ShowReturn=1;
4292 }
4293 if($ShowReturn)
4294 { # mangled names for template function specializations include return value
4295 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4296 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004297 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004298 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4299 $PureSignature = $ReturnName." ".$PureSignature;
4300 }
4301 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004302 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004303}
4304
4305sub mangle_symbol($$$)
4306{ # mangling for simple methods
4307 # see gcc-4.6.0/gcc/cp/mangle.c
4308 my ($InfoId, $LibVersion, $Compiler) = @_;
4309 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4310 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4311 }
4312 my $Mangled = "";
4313 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004314 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004315 }
4316 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004317 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004318 }
4319 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4320}
4321
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004322sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004323{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004324 my ($InfoId, $LibVersion) = @_;
4325 return "";
4326}
4327
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004328sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004329{ # see gcc-4.6.0/gcc/cp/mangle.c
4330 my ($InfoId, $LibVersion) = @_;
4331 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004332 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004333 my %Repl = ();# SN_ replacements
4334 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4335 {
4336 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4337 if($MangledClass!~/\AN/) {
4338 $MangledClass = "N".$MangledClass;
4339 }
4340 else {
4341 $MangledClass=~s/E\Z//;
4342 }
4343 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4344 $MangledClass=~s/\AN/NV/;
4345 }
4346 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4347 $MangledClass=~s/\AN/NK/;
4348 }
4349 $Mangled .= $MangledClass;
4350 }
4351 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4352 { # mangled by name due to the absence of structured info
4353 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4354 if($MangledNS!~/\AN/) {
4355 $MangledNS = "N".$MangledNS;
4356 }
4357 else {
4358 $MangledNS=~s/E\Z//;
4359 }
4360 $Mangled .= $MangledNS;
4361 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004362 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004363 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004364 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004365 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004366 foreach (@TPos) {
4367 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4368 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004369 }
4370 elsif($TmplParams)
4371 { # remangling mode
4372 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004373 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004374 }
4375 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4376 $Mangled .= "C1";
4377 }
4378 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4379 $Mangled .= "D0";
4380 }
4381 elsif($ShortName)
4382 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004383 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4384 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004385 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004386 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004387 { # "const" global data is mangled as _ZL...
4388 $Mangled .= "L";
4389 }
4390 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004391 if($ShortName=~/\Aoperator(\W.*)\Z/)
4392 {
4393 my $Op = $1;
4394 $Op=~s/\A[ ]+//g;
4395 if(my $OpMngl = $OperatorMangling{$Op}) {
4396 $Mangled .= $OpMngl;
4397 }
4398 else { # conversion operator
4399 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4400 }
4401 }
4402 else {
4403 $Mangled .= length($ShortName).$ShortName;
4404 }
4405 if(@TParams)
4406 { # templates
4407 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004408 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004409 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4410 }
4411 $Mangled .= "E";
4412 }
4413 if(not $ClassId and @TParams) {
4414 add_substitution($ShortName, \%Repl, 0);
4415 }
4416 }
4417 if($ClassId or $NameSpace) {
4418 $Mangled .= "E";
4419 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004420 if(@TParams)
4421 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004422 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004423 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4424 }
4425 }
4426 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4427 {
4428 my @Params = ();
4429 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4430 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4431 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4432 }
4433 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4434 { # checking parameters
4435 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4436 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4437 }
4438 if(not @Params) {
4439 $Mangled .= "v";
4440 }
4441 }
4442 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4443 $Mangled = write_stdcxx_substitution($Mangled);
4444 if($Mangled eq "_Z") {
4445 return "";
4446 }
4447 return $Mangled;
4448}
4449
4450sub correct_incharge($$$)
4451{
4452 my ($InfoId, $LibVersion, $Mangled) = @_;
4453 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4454 {
4455 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004456 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004457 }
4458 }
4459 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4460 {
4461 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004462 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004463 }
4464 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004465 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004466 }
4467 }
4468 return $Mangled;
4469}
4470
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004471sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004472{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004473 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004474 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004475 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004476 return $Name;
4477 }
4478 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004479 while(my $CPos = find_center($TParams, "<"))
4480 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004481 $TParams = substr($TParams, $CPos);
4482 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004483 if($TParams=~s/\A<(.+)>\Z/$1/) {
4484 $Name=~s/<\Q$TParams\E>\Z//;
4485 }
4486 else
4487 { # error
4488 $TParams = "";
4489 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004490 return ($Name, $TParams);
4491}
4492
4493sub get_sub_ns($)
4494{
4495 my $Name = $_[0];
4496 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004497 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004498 {
4499 push(@NS, substr($Name, 0, $CPos));
4500 $Name = substr($Name, $CPos);
4501 $Name=~s/\A:://;
4502 }
4503 return (join("::", @NS), $Name);
4504}
4505
4506sub mangle_ns($$$)
4507{
4508 my ($Name, $LibVersion, $Repl) = @_;
4509 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4510 {
4511 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4512 $Mangled=~s/\AN(.+)E\Z/$1/;
4513 return $Mangled;
4514
4515 }
4516 else
4517 {
4518 my ($MangledNS, $SubNS) = ("", "");
4519 ($SubNS, $Name) = get_sub_ns($Name);
4520 if($SubNS) {
4521 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4522 }
4523 $MangledNS .= length($Name).$Name;
4524 add_substitution($MangledNS, $Repl, 0);
4525 return $MangledNS;
4526 }
4527}
4528
4529sub mangle_param($$$)
4530{
4531 my ($PTid, $LibVersion, $Repl) = @_;
4532 my ($MPrefix, $Mangled) = ("", "");
4533 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004534 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004535 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004536 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004537 if(not $BaseType_Name) {
4538 return "";
4539 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004540 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004541 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004542 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4543 while($Suffix=~/(&|\*|const)\Z/)
4544 {
4545 if($Suffix=~s/[ ]*&\Z//) {
4546 $MPrefix .= "R";
4547 }
4548 if($Suffix=~s/[ ]*\*\Z//) {
4549 $MPrefix .= "P";
4550 }
4551 if($Suffix=~s/[ ]*const\Z//)
4552 {
4553 if($MPrefix=~/R|P/
4554 or $Suffix=~/&|\*/) {
4555 $MPrefix .= "K";
4556 }
4557 }
4558 if($Suffix=~s/[ ]*volatile\Z//) {
4559 $MPrefix .= "V";
4560 }
4561 #if($Suffix=~s/[ ]*restrict\Z//) {
4562 #$MPrefix .= "r";
4563 #}
4564 }
4565 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4566 $Mangled .= $Token;
4567 }
4568 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4569 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004570 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004571 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004572 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004573 foreach (@TPos) {
4574 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4575 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004576 }
4577 elsif($TmplParams)
4578 { # remangling mode
4579 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004580 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004581 }
4582 my $MangledNS = "";
4583 my ($SubNS, $SName) = get_sub_ns($ShortName);
4584 if($SubNS) {
4585 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4586 }
4587 $MangledNS .= length($SName).$SName;
4588 if(@TParams) {
4589 add_substitution($MangledNS, $Repl, 0);
4590 }
4591 $Mangled .= "N".$MangledNS;
4592 if(@TParams)
4593 { # templates
4594 $Mangled .= "I";
4595 foreach my $TParam (@TParams) {
4596 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4597 }
4598 $Mangled .= "E";
4599 }
4600 $Mangled .= "E";
4601 }
4602 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4603 {
4604 if($BaseType{"Type"} eq "MethodPtr") {
4605 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4606 }
4607 else {
4608 $Mangled .= "PF";
4609 }
4610 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4611 my @Params = keys(%{$BaseType{"Param"}});
4612 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4613 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4614 }
4615 if(not @Params) {
4616 $Mangled .= "v";
4617 }
4618 $Mangled .= "E";
4619 }
4620 elsif($BaseType{"Type"} eq "FieldPtr")
4621 {
4622 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4623 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4624 }
4625 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4626 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4627 {
4628 if($Mangled eq $Optimized)
4629 {
4630 if($ShortName!~/::/)
4631 { # remove "N ... E"
4632 if($MPrefix) {
4633 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4634 }
4635 else {
4636 $Mangled=~s/\AN(.+)E\Z/$1/g;
4637 }
4638 }
4639 }
4640 else {
4641 $Mangled = $Optimized;
4642 }
4643 }
4644 add_substitution($Mangled, $Repl, 1);
4645 return $Mangled;
4646}
4647
4648sub mangle_template_param($$$)
4649{ # types + literals
4650 my ($TParam, $LibVersion, $Repl) = @_;
4651 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4652 return mangle_param($TPTid, $LibVersion, $Repl);
4653 }
4654 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4655 { # class_name<1u>::method(...)
4656 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4657 }
4658 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4659 { # class_name<(signed char)1>::method(...)
4660 return "L".$IntrinsicMangling{$1}.$2."E";
4661 }
4662 elsif($TParam eq "true")
4663 { # class_name<true>::method(...)
4664 return "Lb1E";
4665 }
4666 elsif($TParam eq "false")
4667 { # class_name<true>::method(...)
4668 return "Lb0E";
4669 }
4670 else { # internal error
4671 return length($TParam).$TParam;
4672 }
4673}
4674
4675sub add_substitution($$$)
4676{
4677 my ($Value, $Repl, $Rec) = @_;
4678 if($Rec)
4679 { # subtypes
4680 my @Subs = ($Value);
4681 while($Value=~s/\A(R|P|K)//) {
4682 push(@Subs, $Value);
4683 }
4684 foreach (reverse(@Subs)) {
4685 add_substitution($_, $Repl, 0);
4686 }
4687 return;
4688 }
4689 return if($Value=~/\AS(\d*)_\Z/);
4690 $Value=~s/\AN(.+)E\Z/$1/g;
4691 return if(defined $Repl->{$Value});
4692 return if(length($Value)<=1);
4693 return if($StdcxxMangling{$Value});
4694 # check for duplicates
4695 my $Base = $Value;
4696 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4697 {
4698 my $Num = $Repl->{$Type};
4699 my $Replace = macro_mangle($Num);
4700 $Base=~s/\Q$Replace\E/$Type/;
4701 }
4702 if(my $OldNum = $Repl->{$Base})
4703 {
4704 $Repl->{$Value} = $OldNum;
4705 return;
4706 }
4707 my @Repls = sort {$b<=>$a} values(%{$Repl});
4708 if(@Repls) {
4709 $Repl->{$Value} = $Repls[0]+1;
4710 }
4711 else {
4712 $Repl->{$Value} = -1;
4713 }
4714 # register duplicates
4715 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004716 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004717 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4718 {
4719 next if($Base eq $Type);
4720 my $Num = $Repl->{$Type};
4721 my $Replace = macro_mangle($Num);
4722 $Base=~s/\Q$Type\E/$Replace/;
4723 $Repl->{$Base} = $Repl->{$Value};
4724 }
4725}
4726
4727sub macro_mangle($)
4728{
4729 my $Num = $_[0];
4730 if($Num==-1) {
4731 return "S_";
4732 }
4733 else
4734 {
4735 my $Code = "";
4736 if($Num<10)
4737 { # S0_, S1_, S2_, ...
4738 $Code = $Num;
4739 }
4740 elsif($Num>=10 and $Num<=35)
4741 { # SA_, SB_, SC_, ...
4742 $Code = chr(55+$Num);
4743 }
4744 else
4745 { # S10_, S11_, S12_
4746 $Code = $Num-26; # 26 is length of english alphabet
4747 }
4748 return "S".$Code."_";
4749 }
4750}
4751
4752sub write_stdcxx_substitution($)
4753{
4754 my $Mangled = $_[0];
4755 if($StdcxxMangling{$Mangled}) {
4756 return $StdcxxMangling{$Mangled};
4757 }
4758 else
4759 {
4760 my @Repls = keys(%StdcxxMangling);
4761 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4762 foreach my $MangledType (@Repls)
4763 {
4764 my $Replace = $StdcxxMangling{$MangledType};
4765 #if($Mangled!~/$Replace/) {
4766 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4767 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4768 #}
4769 }
4770 }
4771 return $Mangled;
4772}
4773
4774sub write_substitution($$)
4775{
4776 my ($Mangled, $Repl) = @_;
4777 if(defined $Repl->{$Mangled}
4778 and my $MnglNum = $Repl->{$Mangled}) {
4779 $Mangled = macro_mangle($MnglNum);
4780 }
4781 else
4782 {
4783 my @Repls = keys(%{$Repl});
4784 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4785 # FIXME: how to apply replacements? by num or by pos
4786 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4787 foreach my $MangledType (@Repls)
4788 {
4789 my $Replace = macro_mangle($Repl->{$MangledType});
4790 if($Mangled!~/$Replace/) {
4791 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4792 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4793 }
4794 }
4795 }
4796 return $Mangled;
4797}
4798
4799sub delete_keywords($)
4800{
4801 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004802 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004803 return $TypeName;
4804}
4805
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004806sub uncover_typedefs($$)
4807{
4808 my ($TypeName, $LibVersion) = @_;
4809 return "" if(not $TypeName);
4810 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4811 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4812 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004813 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004814 while($TypeName_New ne $TypeName_Pre)
4815 {
4816 $TypeName_Pre = $TypeName_New;
4817 my $TypeName_Copy = $TypeName_New;
4818 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004819 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004820 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004821 if(not $Intrinsic_Keywords{$1}) {
4822 $Words{$1} = 1;
4823 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004824 }
4825 foreach my $Word (keys(%Words))
4826 {
4827 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4828 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004829 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004830 if($BaseType_Name=~/\([\*]+\)/)
4831 { # FuncPtr
4832 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4833 {
4834 my $Type_Suffix = $1;
4835 $TypeName_New = $BaseType_Name;
4836 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004837 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004838 }
4839 }
4840 }
4841 else
4842 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004843 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004844 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004845 }
4846 }
4847 }
4848 }
4849 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4850}
4851
4852sub isInternal($)
4853{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004854 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4855 {
4856 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4857 {
4858 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4859 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4860 return 1;
4861 }
4862 }
4863 }
4864 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004865}
4866
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004867sub getDataVal($$)
4868{
4869 my ($InfoId, $TypeId) = @_;
4870 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4871 {
4872 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4873 {
4874 if(defined $LibInfo{$Version}{"info_type"}{$1}
4875 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004876 {
4877 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004878 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004879 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4880 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004881 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004882 if(my $Addr = getTreeAttr_Op($1)) {
4883 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004884 }
4885 }
4886 }
4887 }
4888 else {
4889 return getInitVal($1, $TypeId);
4890 }
4891 }
4892 }
4893 return undef;
4894}
4895
4896sub getInitVal($$)
4897{
4898 my ($InfoId, $TypeId) = @_;
4899 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4900 {
4901 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4902 {
4903 if($InfoType eq "integer_cst")
4904 {
4905 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004906 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004907 { # characters
4908 $Val = chr($Val);
4909 }
4910 return $Val;
4911 }
4912 elsif($InfoType eq "string_cst") {
4913 return getNodeStrCst($InfoId);
4914 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004915 elsif($InfoType eq "var_decl")
4916 {
4917 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4918 return $Name;
4919 }
4920 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004921 }
4922 }
4923 return undef;
4924}
4925
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004926sub set_Class_And_Namespace($)
4927{
4928 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004929 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004930 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004931 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004932 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004933 my $NSInfoId = $1;
4934 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4935 {
4936 if($InfoType eq "namespace_decl") {
4937 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4938 }
4939 elsif($InfoType eq "record_type") {
4940 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4941 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004942 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004943 }
4944 }
4945 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4946 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004947 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004948 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004949 { # skip
4950 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004951 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004952 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004953
4954 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004955}
4956
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004957sub debugMangling($)
4958{
4959 my $LibVersion = $_[0];
4960 my %Mangled = ();
4961 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4962 {
4963 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4964 {
4965 if($Mngl=~/\A(_Z|\?)/) {
4966 $Mangled{$Mngl}=$InfoId;
4967 }
4968 }
4969 }
4970 translateSymbols(keys(%Mangled), $LibVersion);
4971 foreach my $Mngl (keys(%Mangled))
4972 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004973 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4974 my $U2 = $tr_name{$Mngl};
4975 if($U1 ne $U2) {
4976 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004977 }
4978 }
4979}
4980
4981sub linkSymbol($)
4982{ # link symbols from shared libraries
4983 # with the symbols from header files
4984 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004985 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004986 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004987 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4988 or $EMERGENCY_MODE_48)
4989 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4990 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03004991 # GCC 4.8.[012] doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004992 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004993 {
4994 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4995 return correct_incharge($InfoId, $Version, $Mangled);
4996 }
4997 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004998 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004999 or not $BinaryOnly
5000 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005001 { # 1. --headers-only mode
5002 # 2. not mangled src-only symbols
5003 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
5004 return $Mangled;
5005 }
5006 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005007 }
5008 return "";
5009}
5010
5011sub setLanguage($$)
5012{
5013 my ($LibVersion, $Lang) = @_;
5014 if(not $UserLang) {
5015 $COMMON_LANGUAGE{$LibVersion} = $Lang;
5016 }
5017}
5018
5019sub getSymbolInfo($)
5020{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005021 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005022 if(isInternal($InfoId)) {
5023 return;
5024 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005025 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
5026 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005027 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
5028 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005029 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005030 return;
5031 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005032 setFuncAccess($InfoId);
5033 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005034 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
5035 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005036 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005037 return;
5038 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005039
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005040 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005041 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005042 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005043 if(not defined $TypeInfo{$Version}{$Return}
5044 or not $TypeInfo{$Version}{$Return}{"Name"})
5045 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005046 delete($SymbolInfo{$Version}{$InfoId});
5047 return;
5048 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005049 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005050 }
5051 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5052 {
5053 if(defined $MissedTypedef{$Version}{$Rid})
5054 {
5055 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5056 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5057 }
5058 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005059 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005060 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5061 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005062 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005063 my $Orig = getFuncOrig($InfoId);
5064 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005065 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5066 {
5067 delete($SymbolInfo{$Version}{$InfoId});
5068 return;
5069 }
5070
5071 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005072 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005073 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005074 return;
5075 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005076
5077 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005078 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005079 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5080
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005081 my @TParams = getTParams($Orig, "Func");
5082 if(not @TParams)
5083 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005084 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005085 return;
5086 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005087 foreach my $Pos (0 .. $#TParams)
5088 {
5089 my $Val = $TParams[$Pos];
5090 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5091
5092 if($Tmpl)
5093 {
5094 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5095 {
5096 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5097 }
5098 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005099 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005100
5101 if($Tmpl)
5102 {
5103 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5104 {
5105 if($Pos>$#TParams)
5106 {
5107 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5108 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5109 }
5110 }
5111 }
5112
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005113 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5114 { # operator<< <T>, operator>> <T>
5115 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5116 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005117 if(@TParams) {
5118 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5119 }
5120 else {
5121 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5122 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005123 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005124 }
5125 else
5126 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005127 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005128 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005129 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5130 {
5131 if($OSgroup eq "windows")
5132 { # cut the offset
5133 $MnglName=~s/\@\d+\Z//g;
5134 }
5135 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5136
5137 # NOTE: mangling of some symbols may change depending on GCC version
5138 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5139 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5140 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005141
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005142 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005143 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005144 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005145 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005146 return;
5147 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005148 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005149 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005150 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005151 if($Skip)
5152 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005153 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005154 return;
5155 }
5156 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005157 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5158 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5159 }
5160
5161 if(set_Class_And_Namespace($InfoId))
5162 {
5163 delete($SymbolInfo{$Version}{$InfoId});
5164 return;
5165 }
5166
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005167 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5168 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005169 if(not defined $TypeInfo{$Version}{$ClassId}
5170 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5171 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005172 delete($SymbolInfo{$Version}{$InfoId});
5173 return;
5174 }
5175 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005176 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5177 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005178 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005179 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005180 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005181 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005182 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005183 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005184 }
5185 if($COMMON_LANGUAGE{$Version} eq "C++")
5186 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005187 # C++ or --headers-only mode
5188 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005189 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005190 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5191 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005192 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005193 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005194 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005195 if(my $Mangled = linkSymbol($InfoId)) {
5196 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005197 }
5198 }
5199 if($OStarget eq "windows")
5200 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005201 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005202 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005203 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005204 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005205 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005206 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005207 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005208 }
5209 }
5210 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005211 else
5212 { # not mangled in C
5213 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5214 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005215 if(not $CheckHeadersOnly
5216 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5217 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5218 {
5219 my $Incorrect = 0;
5220
5221 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5222 {
5223 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5224 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5225 { # mangled in the TU dump, but not mangled in the library
5226 $Incorrect = 1;
5227 }
5228 }
5229 else
5230 {
5231 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5232 { # all C++ functions are not mangled in the TU dump
5233 $Incorrect = 1;
5234 }
5235 }
5236 if($Incorrect)
5237 {
5238 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5239 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5240 }
5241 }
5242 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005243 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005244 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005245 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005246 return;
5247 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005248 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005249 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005250 { # identify virtual and pure virtual functions
5251 # NOTE: constructors cannot be virtual
5252 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5253 # in the TU dump, so taking it from the original symbol
5254 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5255 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5256 { # NOTE: D2 destructors are not present in a v-table
5257 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5258 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005259 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005260 if(isInline($InfoId)) {
5261 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005262 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005263 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005264 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5265 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005266 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5267 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005268 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005269 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005270 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005271 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005272 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005273 }
5274 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005275 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5276 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005277 if(not $ExtraDump)
5278 {
5279 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5280 { # non-target symbols
5281 delete($SymbolInfo{$Version}{$InfoId});
5282 return;
5283 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005284 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005285 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005286 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5287 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5288 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5289 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005290 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005291 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5292 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005293 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005294 return;
5295 }
5296 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005297 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005298 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005299 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005300 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005301 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005302 return;
5303 }
5304 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005305 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005306 }
5307 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005308 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5309 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5310 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005311 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005312 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5313 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005314 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005315 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005316 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005317 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005318 }
5319 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005320 if(getFuncLink($InfoId) eq "Static") {
5321 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005322 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005323 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5324 {
5325 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5326 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005327 if($Unmangled=~/\.\_\d/)
5328 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005329 delete($SymbolInfo{$Version}{$InfoId});
5330 return;
5331 }
5332 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005333 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005334
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005335 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5336 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005337 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005338 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5339 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005340 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005341
5342 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5343 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5344 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005345
5346 if($ExtraDump) {
5347 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5348 }
5349}
5350
5351sub guessHeader($)
5352{
5353 my $InfoId = $_[0];
5354 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5355 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5356 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5357 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5358 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5359 {
5360 if(get_filename($HPath) eq $Header)
5361 {
5362 my $HDir = get_filename(get_dirname($HPath));
5363 if($HDir ne "include"
5364 and $HDir=~/\A[a-z]+\Z/i) {
5365 return join_P($HDir, $Header);
5366 }
5367 }
5368 }
5369 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005370}
5371
5372sub isInline($)
5373{ # "body: undefined" in the tree
5374 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005375 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5376 {
5377 if($Info=~/ undefined /i) {
5378 return 0;
5379 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005380 }
5381 return 1;
5382}
5383
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005384sub hasThrow($)
5385{
5386 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5387 {
5388 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5389 return getTreeAttr_Unql($1, "unql");
5390 }
5391 }
5392 return 1;
5393}
5394
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005395sub getTypeId($)
5396{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005397 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5398 {
5399 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5400 return $1;
5401 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005402 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005403 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005404}
5405
5406sub setTypeMemb($$)
5407{
5408 my ($TypeId, $TypeAttr) = @_;
5409 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005410 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005411 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005412 if($TypeType eq "Enum")
5413 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005414 my $MInfoId = getTreeAttr_Csts($TypeId);
5415 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005416 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005417 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5418 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005419 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005420 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5421 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005422 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005423 }
5424 }
5425 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5426 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005427 my $MInfoId = getTreeAttr_Flds($TypeId);
5428 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005429 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005430 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5431 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005432 if(not $IType or $IType ne "field_decl")
5433 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005434
5435 if($IType eq "var_decl")
5436 { # static field
5437 $StaticFields = 1;
5438 }
5439
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005440 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005441 next;
5442 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005443 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005444 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005445 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005446 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005447 }
5448 if(not $StructMembName)
5449 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005450 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005451 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005452 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005453 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5454 if(isAnon($UnnamedTName))
5455 { # rename unnamed fields to unnamed0, unnamed1, ...
5456 $StructMembName = "unnamed".($UnnamedPos++);
5457 }
5458 }
5459 }
5460 if(not $StructMembName)
5461 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005462 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005463 next;
5464 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005465 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005466 if(defined $MissedTypedef{$Version}{$MembTypeId})
5467 {
5468 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5469 $MembTypeId = $AddedTid;
5470 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005471 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005472
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005473 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5474 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005475 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005476 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005477 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5478 }
5479 if($MInfo=~/spec:\s*mutable /)
5480 { # mutable fields
5481 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005482 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005483 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005484 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5485 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005486 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005487 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005488 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005489 }
5490 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005491 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005492 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5493 { # template
5494 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5495 }
5496 else {
5497 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5498 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005499 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005500
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005501 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005502 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005503 }
5504 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005505
5506 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005507}
5508
5509sub setFuncParams($)
5510{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005511 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005512 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005513
5514 my $FType = getFuncType($InfoId);
5515
5516 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005517 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005518 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5519 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005520 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005521 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005522 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5523 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005524 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005525 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5526 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005527 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005528 else
5529 { # skip
5530 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005531 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005532 # skip "this"-parameter
5533 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005534 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005535 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005536 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005537 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005538 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5539 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5540 if(not $ParamName)
5541 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005542 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005543 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005544 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5545 {
5546 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5547 $ParamTypeId = $AddedTid;
5548 }
5549 }
5550 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005551 if(not $PType or $PType eq "Unknown") {
5552 return 1;
5553 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005554 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005555 if(not $PTName) {
5556 return 1;
5557 }
5558 if($PTName eq "void") {
5559 last;
5560 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005561 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005562 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005563 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005564 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005565 $ParamInfoId = getNextElem($ParamInfoId);
5566 next;
5567 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005568 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005569
5570 if(my %Base = get_BaseType($ParamTypeId, $Version))
5571 {
5572 if(defined $Base{"Template"}) {
5573 return 1;
5574 }
5575 }
5576
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005577 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005578 if(my $Algn = getAlgn($ParamInfoId)) {
5579 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5580 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005581 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5582 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005583 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005584 }
5585 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005586 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005587 if($ParamName ne "this" or $FType ne "Method") {
5588 $PPos += 1;
5589 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005590 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005591 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005592 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005593 }
5594 return 0;
5595}
5596
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005597sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005598{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005599 my ($InfoId, $Vtt_Pos) = @_;
5600 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005601 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005602 my $FType = getFuncType($InfoId);
5603
5604 if($FType eq "Method")
5605 {
5606 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005607 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005608 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005609 if(not $ParamListElemId)
5610 { # foo(...)
5611 return 1;
5612 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005613 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005614 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005615 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005616 { # actual params: may differ from formal args
5617 # formal int*const
5618 # actual: int*
5619 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005620 {
5621 $Vtt_Pos=-1;
5622 $ParamListElemId = getNextElem($ParamListElemId);
5623 next;
5624 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005625 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5626 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005627 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005628 $HaveVoid = 1;
5629 last;
5630 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005631 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005632 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005633 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5634 {
5635 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5636 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5637 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005638 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005639 }
5640 }
5641 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5642 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005643 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005644 { # params
5645 if($OldId ne $ParamTypeId)
5646 {
5647 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5648 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5649
5650 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5651 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5652 }
5653 }
5654 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005655 }
5656 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005657 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005658 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005659 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5660 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005661 if($PurpType eq "nop_expr")
5662 { # func ( const char* arg = (const char*)(void*)0 )
5663 $PurpId = getTreeAttr_Op($PurpId);
5664 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005665 my $Val = getInitVal($PurpId, $ParamTypeId);
5666 if(defined $Val) {
5667 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5668 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005669 }
5670 }
5671 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005672 if($Pos!=0 or $FType ne "Method") {
5673 $PPos += 1;
5674 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005675 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005676 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005677 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005678}
5679
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005680sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005681{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005682 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5683 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005684 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5685 return $1;
5686 }
5687 }
5688 return "";
5689}
5690
5691sub getTreeAttr_Chain($)
5692{
5693 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5694 {
5695 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5696 return $1;
5697 }
5698 }
5699 return "";
5700}
5701
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005702sub getTreeAttr_Unql($)
5703{
5704 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5705 {
5706 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5707 return $1;
5708 }
5709 }
5710 return "";
5711}
5712
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005713sub getTreeAttr_Scpe($)
5714{
5715 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5716 {
5717 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5718 return $1;
5719 }
5720 }
5721 return "";
5722}
5723
5724sub getTreeAttr_Type($)
5725{
5726 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5727 {
5728 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5729 return $1;
5730 }
5731 }
5732 return "";
5733}
5734
5735sub getTreeAttr_Name($)
5736{
5737 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5738 {
5739 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5740 return $1;
5741 }
5742 }
5743 return "";
5744}
5745
5746sub getTreeAttr_Mngl($)
5747{
5748 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5749 {
5750 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5751 return $1;
5752 }
5753 }
5754 return "";
5755}
5756
5757sub getTreeAttr_Prms($)
5758{
5759 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5760 {
5761 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5762 return $1;
5763 }
5764 }
5765 return "";
5766}
5767
5768sub getTreeAttr_Fncs($)
5769{
5770 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5771 {
5772 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5773 return $1;
5774 }
5775 }
5776 return "";
5777}
5778
5779sub getTreeAttr_Csts($)
5780{
5781 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5782 {
5783 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5784 return $1;
5785 }
5786 }
5787 return "";
5788}
5789
5790sub getTreeAttr_Purp($)
5791{
5792 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5793 {
5794 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5795 return $1;
5796 }
5797 }
5798 return "";
5799}
5800
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005801sub getTreeAttr_Op($)
5802{
5803 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5804 {
5805 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5806 return $1;
5807 }
5808 }
5809 return "";
5810}
5811
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005812sub getTreeAttr_Valu($)
5813{
5814 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5815 {
5816 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5817 return $1;
5818 }
5819 }
5820 return "";
5821}
5822
5823sub getTreeAttr_Flds($)
5824{
5825 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5826 {
5827 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5828 return $1;
5829 }
5830 }
5831 return "";
5832}
5833
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005834sub getTreeAttr_Binf($)
5835{
5836 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5837 {
5838 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5839 return $1;
5840 }
5841 }
5842 return "";
5843}
5844
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005845sub getTreeAttr_Args($)
5846{
5847 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5848 {
5849 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005850 return $1;
5851 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005852 }
5853 return "";
5854}
5855
5856sub getTreeValue($)
5857{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005858 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5859 {
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03005860 if($Info=~/(low|int)[ ]*:[ ]*([^ ]+) /) {
5861 return $2;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005862 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005863 }
5864 return "";
5865}
5866
5867sub getTreeAccess($)
5868{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005869 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005870 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005871 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5872 {
5873 my $Access = $1;
5874 if($Access eq "prot") {
5875 return "protected";
5876 }
5877 elsif($Access eq "priv") {
5878 return "private";
5879 }
5880 }
5881 elsif($Info=~/ protected /)
5882 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005883 return "protected";
5884 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005885 elsif($Info=~/ private /)
5886 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005887 return "private";
5888 }
5889 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005890 return "public";
5891}
5892
5893sub setFuncAccess($)
5894{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005895 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005896 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005897 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005898 }
5899 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005900 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005901 }
5902}
5903
5904sub setTypeAccess($$)
5905{
5906 my ($TypeId, $TypeAttr) = @_;
5907 my $Access = getTreeAccess($TypeId);
5908 if($Access eq "protected") {
5909 $TypeAttr->{"Protected"} = 1;
5910 }
5911 elsif($Access eq "private") {
5912 $TypeAttr->{"Private"} = 1;
5913 }
5914}
5915
5916sub setFuncKind($)
5917{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005918 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5919 {
5920 if($Info=~/pseudo tmpl/) {
5921 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5922 }
5923 elsif($Info=~/ constructor /) {
5924 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5925 }
5926 elsif($Info=~/ destructor /) {
5927 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5928 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005929 }
5930}
5931
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005932sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005933{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005934 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5935 {
5936 if($Info=~/spec[ ]*:[ ]*pure /) {
5937 return "PureVirt";
5938 }
5939 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5940 return "Virt";
5941 }
5942 elsif($Info=~/ pure\s+virtual /)
5943 { # support for old GCC versions
5944 return "PureVirt";
5945 }
5946 elsif($Info=~/ virtual /)
5947 { # support for old GCC versions
5948 return "Virt";
5949 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005950 }
5951 return "";
5952}
5953
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005954sub getFuncLink($)
5955{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005956 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5957 {
5958 if($Info=~/link[ ]*:[ ]*static /) {
5959 return "Static";
5960 }
5961 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005962 return $1;
5963 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005964 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005965 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005966}
5967
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005968sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005969{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005970 my ($Symbol, $LibVersion) = @_;
5971 return "" if(not $Symbol or not $LibVersion);
5972 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5973 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005974 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005975 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5976 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5977 }
5978 }
5979 if($NS)
5980 {
5981 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5982 return $NS;
5983 }
5984 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005985 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005986 while($NS=~s/::[^:]+\Z//)
5987 {
5988 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5989 return $NS;
5990 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005991 }
5992 }
5993 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005994
5995 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005996}
5997
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005998sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005999{
6000 my ($TypeName, $LibVersion) = @_;
6001 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006002 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006003 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006004 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6005 return $NS;
6006 }
6007 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006008 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006009 while($NS=~s/::[^:]+\Z//)
6010 {
6011 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6012 return $NS;
6013 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006014 }
6015 }
6016 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006017 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006018}
6019
6020sub getNameSpace($)
6021{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006022 my $InfoId = $_[0];
6023 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006024 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006025 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006026 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006027 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006028 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006029 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
6030 {
6031 my $NameSpace = getTreeStr($1);
6032 if($NameSpace eq "::")
6033 { # global namespace
6034 return "";
6035 }
6036 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
6037 $NameSpace = $BaseNameSpace."::".$NameSpace;
6038 }
6039 $NestedNameSpaces{$Version}{$NameSpace} = 1;
6040 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006041 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006042 else {
6043 return "";
6044 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006045 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006046 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006047 { # inside data type
6048 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6049 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006050 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006051 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006052 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006053 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006054}
6055
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006056sub getEnumMembVal($)
6057{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006058 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006059 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006060 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6061 {
6062 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6063 {
6064 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6065 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6066 return getTreeValue($1);
6067 }
6068 else
6069 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6070 return getTreeValue($1);
6071 }
6072 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006073 }
6074 }
6075 return "";
6076}
6077
6078sub getSize($)
6079{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006080 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6081 {
6082 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6083 return getTreeValue($1);
6084 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006085 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006086 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006087}
6088
6089sub getAlgn($)
6090{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006091 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6092 {
6093 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6094 return $1;
6095 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006096 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006097 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006098}
6099
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006100sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006101{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006102 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6103 {
6104 if($Info=~/ bitfield /) {
6105 return getSize($_[0]);
6106 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006107 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006108 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006109}
6110
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006111sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006112{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006113 if(my $Chan = getTreeAttr_Chan($_[0])) {
6114 return $Chan;
6115 }
6116 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6117 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006118 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006119 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006120}
6121
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006122sub registerHeader($$)
6123{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006124 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006125 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006126 return "";
6127 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006128 if(is_abs($Header) and not -f $Header)
6129 { # incorrect absolute path
6130 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006131 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006132 if(skipHeader($Header, $LibVersion))
6133 { # skip
6134 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006135 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006136 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6137 {
6138 detect_header_includes($Header_Path, $LibVersion);
6139
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006140 if(defined $Tolerance and $Tolerance=~/3/)
6141 { # 3 - skip headers that include non-Linux headers
6142 if($OSgroup ne "windows")
6143 {
6144 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6145 {
6146 if(specificHeader($Inc, "windows")) {
6147 return "";
6148 }
6149 }
6150 }
6151 }
6152
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006153 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6154 { # redirect
6155 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6156 or skipHeader($RHeader_Path, $LibVersion))
6157 { # skip
6158 return "";
6159 }
6160 $Header_Path = $RHeader_Path;
6161 }
6162 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6163 { # skip
6164 return "";
6165 }
6166
6167 if(my $HName = get_filename($Header_Path))
6168 { # register
6169 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6170 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6171 }
6172
6173 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6174 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006175 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006176 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006177 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006178 }
6179
6180 if($CheckHeadersOnly
6181 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6182 { # /usr/include/c++/4.6.1/...
6183 $STDCXX_TESTING = 1;
6184 }
6185
6186 return $Header_Path;
6187 }
6188 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006189}
6190
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006191sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006192{
6193 my ($Dir, $WithDeps, $LibVersion) = @_;
6194 $Dir=~s/[\/\\]+\Z//g;
6195 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006196 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006197
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006198 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006199 if($WithDeps)
6200 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006201 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6202 return;
6203 }
6204 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6205 $Mode = "DepsOnly";
6206 }
6207 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006208 else
6209 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006210 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6211 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6212 return;
6213 }
6214 }
6215 $Header_Dependency{$LibVersion}{$Dir} = 1;
6216 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6217 if($Mode eq "DepsOnly")
6218 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006219 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006220 $Header_Dependency{$LibVersion}{$Path} = 1;
6221 }
6222 return;
6223 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006224 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006225 {
6226 if($WithDeps)
6227 {
6228 my $SubDir = $Path;
6229 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6230 { # register all sub directories
6231 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6232 }
6233 }
6234 next if(is_not_header($Path));
6235 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006236 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006237 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006238 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6239 }
6240 }
6241 if(get_filename($Dir) eq "include")
6242 { # search for "lib/include/" directory
6243 my $LibDir = $Dir;
6244 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006245 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006246 }
6247 }
6248}
6249
6250sub parse_redirect($$$)
6251{
6252 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006253 my @Errors = ();
6254 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6255 push(@Errors, $1);
6256 }
6257 my $Redirect = "";
6258 foreach (@Errors)
6259 {
6260 s/\s{2,}/ /g;
6261 if(/(only|must\ include
6262 |update\ to\ include
6263 |replaced\ with
6264 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006265 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006266 {
6267 $Redirect = $2;
6268 last;
6269 }
6270 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6271 {
6272 $Redirect = $2;
6273 last;
6274 }
6275 elsif(/this\ header\ should\ not\ be\ used
6276 |programs\ should\ not\ directly\ include
6277 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6278 |is\ not\ supported\ API\ for\ general\ use
6279 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006280 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006281 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6282 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6283 }
6284 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006285 if($Redirect)
6286 {
6287 $Redirect=~s/\A<//g;
6288 $Redirect=~s/>\Z//g;
6289 }
6290 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006291}
6292
6293sub parse_includes($$)
6294{
6295 my ($Content, $Path) = @_;
6296 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006297 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006298 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006299 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006300 my $Method = substr($Header, 0, 1, "");
6301 substr($Header, length($Header)-1, 1, "");
6302 $Header = path_format($Header, $OSgroup);
6303 if($Method eq "\"" or is_abs($Header))
6304 {
6305 if(-e join_P(get_dirname($Path), $Header))
6306 { # relative path exists
6307 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006308 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006309 else
6310 { # include "..." that doesn't exist is equal to include <...>
6311 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006312 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006313 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006314 else {
6315 $Includes{$Header} = 1;
6316 }
6317 }
6318 if($ExtraInfo)
6319 {
6320 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6321 { # FT_FREETYPE_H
6322 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006323 }
6324 }
6325 return \%Includes;
6326}
6327
6328sub ignore_path($)
6329{
6330 my $Path = $_[0];
6331 if($Path=~/\~\Z/)
6332 {# skipping system backup files
6333 return 1;
6334 }
6335 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6336 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6337 return 1;
6338 }
6339 return 0;
6340}
6341
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006342sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006343{
6344 my ($ArrRef, $W) = @_;
6345 return if(length($W)<2);
6346 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6347}
6348
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006349sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006350{
6351 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006352
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006353 $H1=~s/\.[a-z]+\Z//ig;
6354 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006355
6356 my $Hname1 = get_filename($H1);
6357 my $Hname2 = get_filename($H2);
6358 my $HDir1 = get_dirname($H1);
6359 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006360 my $Dirname1 = get_filename($HDir1);
6361 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006362
6363 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6364 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6365
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006366 if($_[0] eq $_[1]
6367 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006368 return 0;
6369 }
6370 elsif($H1=~/\A\Q$H2\E/) {
6371 return 1;
6372 }
6373 elsif($H2=~/\A\Q$H1\E/) {
6374 return -1;
6375 }
6376 elsif($HDir1=~/\Q$Hname1\E/i
6377 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006378 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006379 return -1;
6380 }
6381 elsif($HDir2=~/\Q$Hname2\E/i
6382 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006383 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006384 return 1;
6385 }
6386 elsif($Hname1=~/\Q$Dirname1\E/i
6387 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006388 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006389 return -1;
6390 }
6391 elsif($Hname2=~/\Q$Dirname2\E/i
6392 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006393 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006394 return 1;
6395 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006396 elsif($Hname1=~/(config|lib|util)/i
6397 and $Hname2!~/(config|lib|util)/i)
6398 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006399 return -1;
6400 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006401 elsif($Hname2=~/(config|lib|util)/i
6402 and $Hname1!~/(config|lib|util)/i)
6403 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006404 return 1;
6405 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006406 else
6407 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006408 my $R1 = checkRelevance($H1);
6409 my $R2 = checkRelevance($H2);
6410 if($R1 and not $R2)
6411 { # libebook/e-book.h
6412 return -1;
6413 }
6414 elsif($R2 and not $R1)
6415 { # libebook/e-book.h
6416 return 1;
6417 }
6418 else
6419 {
6420 return (lc($H1) cmp lc($H2));
6421 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006422 }
6423}
6424
6425sub searchForHeaders($)
6426{
6427 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006428
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006429 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006430 registerGccHeaders();
6431
6432 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6433 { # c++ standard include paths
6434 registerCppHeaders();
6435 }
6436
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006437 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006438 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6439 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006440 {
6441 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006442 if($SystemRoot)
6443 {
6444 if(is_abs($Path)) {
6445 $Path = $SystemRoot.$Path;
6446 }
6447 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006448 if(not -e $Path) {
6449 exitStatus("Access_Error", "can't access \'$Path\'");
6450 }
6451 elsif(-f $Path) {
6452 exitStatus("Access_Error", "\'$Path\' - not a directory");
6453 }
6454 elsif(-d $Path)
6455 {
6456 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006457 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006458 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6459 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006460 }
6461 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006462 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006463 }
6464 }
6465 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006466 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006467 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6468 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006469
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006470 # registering directories
6471 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6472 {
6473 next if(not -e $Path);
6474 $Path = get_abs_path($Path);
6475 $Path = path_format($Path, $OSgroup);
6476 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006477 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006478 }
6479 elsif(-f $Path)
6480 {
6481 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006482 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006483 and not $LocalIncludes{$Dir})
6484 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006485 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006486 # if(my $OutDir = get_dirname($Dir))
6487 # { # registering the outer directory
6488 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6489 # and not $LocalIncludes{$OutDir}) {
6490 # registerDir($OutDir, 0, $LibVersion);
6491 # }
6492 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006493 }
6494 }
6495 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006496
6497 # clean memory
6498 %RegisteredDirs = ();
6499
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006500 # registering headers
6501 my $Position = 0;
6502 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6503 {
6504 if(is_abs($Dest) and not -e $Dest) {
6505 exitStatus("Access_Error", "can't access \'$Dest\'");
6506 }
6507 $Dest = path_format($Dest, $OSgroup);
6508 if(is_header($Dest, 1, $LibVersion))
6509 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006510 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006511 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6512 }
6513 }
6514 elsif(-d $Dest)
6515 {
6516 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006517 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006518 {
6519 next if(ignore_path($Path));
6520 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006521 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006522 push(@Registered, $HPath);
6523 }
6524 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006525 @Registered = sort {sortHeaders($a, $b)} @Registered;
6526 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006527 foreach my $Path (@Registered) {
6528 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6529 }
6530 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03006531 elsif(not defined $SkipUnidentified) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006532 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6533 }
6534 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006535
6536 if(defined $Tolerance and $Tolerance=~/4/)
6537 { # 4 - skip headers included by others
6538 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6539 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006540 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006541 delete($Registered_Headers{$LibVersion}{$Path});
6542 }
6543 }
6544 }
6545
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006546 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6547 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006548 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006549 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006550 if(is_abs($Header) and not -f $Header) {
6551 exitStatus("Access_Error", "can't access file \'$Header\'");
6552 }
6553 $Header = path_format($Header, $OSgroup);
6554 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6555 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006556 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006557 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006558 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03006559 elsif($SkipUnidentified) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006560 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6561 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006562 }
6563 }
6564 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6565 { # set relative paths (for duplicates)
6566 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6567 { # search for duplicates
6568 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6569 my $Prefix = get_dirname($FirstPath);
6570 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6571 { # detect a shortest distinguishing prefix
6572 my $NewPrefix = $1;
6573 my %Identity = ();
6574 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6575 {
6576 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6577 $Identity{$Path} = $1;
6578 }
6579 }
6580 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006581 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006582 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6583 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6584 }
6585 last;
6586 }
6587 $Prefix = $NewPrefix; # increase prefix
6588 }
6589 }
6590 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006591
6592 # clean memory
6593 %HeaderName_Paths = ();
6594
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006595 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6596 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006597 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006598 my ($Pos, $PairPos) = (-1, -1);
6599 my ($Path, $PairPath) = ();
6600 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6601 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6602 foreach my $Header_Path (@Paths)
6603 {
6604 if(get_filename($Header_Path) eq $PairName)
6605 {
6606 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6607 $PairPath = $Header_Path;
6608 }
6609 if(get_filename($Header_Path) eq $HeaderName)
6610 {
6611 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6612 $Path = $Header_Path;
6613 }
6614 }
6615 if($PairPos!=-1 and $Pos!=-1
6616 and int($PairPos)<int($Pos))
6617 {
6618 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6619 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6620 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6621 }
6622 }
6623 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6624 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6625 }
6626}
6627
6628sub detect_real_includes($$)
6629{
6630 my ($AbsPath, $LibVersion) = @_;
6631 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6632 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6633 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6634 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6635 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006636 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6637
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006638 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6639 return () if(not $Path);
6640 open(PREPROC, $Path);
6641 while(<PREPROC>)
6642 {
6643 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6644 {
6645 my $Include = path_format($1, $OSgroup);
6646 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6647 next;
6648 }
6649 if($Include eq $AbsPath) {
6650 next;
6651 }
6652 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6653 }
6654 }
6655 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006656 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6657}
6658
6659sub detect_header_includes($$)
6660{
6661 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006662 return if(not $LibVersion or not $Path);
6663 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6664 return;
6665 }
6666 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6667
6668 if(not -e $Path) {
6669 return;
6670 }
6671
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006672 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006673 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6674 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006675 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006676 {
6677 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006678 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006679 }
6680 if($RedirectPath ne $Path) {
6681 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6682 }
6683 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006684 else
6685 { # can't find
6686 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6687 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006688 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006689 if(my $Inc = parse_includes($Content, $Path))
6690 {
6691 foreach my $Include (keys(%{$Inc}))
6692 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006693 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006694
6695 if(defined $Tolerance and $Tolerance=~/4/)
6696 {
6697 if(my $HPath = identifyHeader($Include, $LibVersion))
6698 {
6699 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6700 }
6701 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006702 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006703 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006704}
6705
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006706sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006707{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006708 my $Path = $_[0];
6709 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006710 if($OStarget eq "symbian")
6711 {
6712 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6713 { # epoc32/include/libc/{stdio, ...}.h
6714 return 1;
6715 }
6716 }
6717 else
6718 {
6719 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6720 { # /usr/include/{stdio, ...}.h
6721 return 1;
6722 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006723 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006724 return 0;
6725}
6726
6727sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006728{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006729 my $Dir = $_[0];
6730 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006731 if($OStarget eq "symbian")
6732 {
6733 if(get_filename($OutDir) eq "libc"
6734 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6735 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6736 return 1;
6737 }
6738 }
6739 else
6740 { # linux
6741 if($OutDir eq "/usr/include"
6742 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6743 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6744 return 1;
6745 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006746 }
6747 return 0;
6748}
6749
6750sub detect_recursive_includes($$)
6751{
6752 my ($AbsPath, $LibVersion) = @_;
6753 return () if(not $AbsPath);
6754 if(isCyclical(\@RecurInclude, $AbsPath)) {
6755 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6756 }
6757 my ($AbsDir, $Name) = separate_path($AbsPath);
6758 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006759 { # system GLIBC internals
6760 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006761 }
6762 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6763 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6764 }
6765 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006766
6767 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6768 { # skip /usr/include/c++/*/ headers
6769 return () if(not $ExtraInfo);
6770 }
6771
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006772 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006773 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006774 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006775 { # check "real" (non-"model") include paths
6776 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6777 pop(@RecurInclude);
6778 return @Paths;
6779 }
6780 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6781 detect_header_includes($AbsPath, $LibVersion);
6782 }
6783 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6784 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006785 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006786 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006787 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006788 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006789 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006790 if(-f $Candidate) {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03006791 $HPath = realpath_F($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006792 }
6793 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006794 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006795 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006796 { # search for the nearest header
6797 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006798 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006799 if(-f $Candidate) {
6800 $HPath = $Candidate;
6801 }
6802 }
6803 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006804 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006805 }
6806 next if(not $HPath);
6807 if($HPath eq $AbsPath) {
6808 next;
6809 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006810
6811 if($Debug)
6812 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006813# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6814# {
6815# print STDERR "$AbsPath -> $HPath\n";
6816# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006817 }
6818
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006819 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6820 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006821 { # only include <...>, skip include "..." prefixes
6822 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6823 }
6824 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6825 {
6826 if($IncPath eq $AbsPath) {
6827 next;
6828 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006829 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6830 if($RIncType==-1)
6831 { # include "..."
6832 $RIncType = $IncType;
6833 }
6834 elsif($RIncType==2)
6835 {
6836 if($IncType!=-1) {
6837 $RIncType = $IncType;
6838 }
6839 }
6840 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006841 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6842 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6843 }
6844 }
6845 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6846 {
6847 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6848 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6849 { # distinguish math.h from glibc and math.h from the tested library
6850 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6851 last;
6852 }
6853 }
6854 }
6855 pop(@RecurInclude);
6856 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6857}
6858
6859sub find_in_framework($$$)
6860{
6861 my ($Header, $Framework, $LibVersion) = @_;
6862 return "" if(not $Header or not $Framework or not $LibVersion);
6863 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6864 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6865 }
6866 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6867 {
6868 if(get_filename($Dependency) eq $Framework
6869 and -f get_dirname($Dependency)."/".$Header) {
6870 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6871 }
6872 }
6873 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6874}
6875
6876sub find_in_defaults($)
6877{
6878 my $Header = $_[0];
6879 return "" if(not $Header);
6880 if(defined $Cache{"find_in_defaults"}{$Header}) {
6881 return $Cache{"find_in_defaults"}{$Header};
6882 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006883 foreach my $Dir (@DefaultIncPaths,
6884 @DefaultGccPaths,
6885 @DefaultCppPaths,
6886 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006887 {
6888 next if(not $Dir);
6889 if(-f $Dir."/".$Header) {
6890 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6891 }
6892 }
6893 return ($Cache{"find_in_defaults"}{$Header}="");
6894}
6895
6896sub cmp_paths($$)
6897{
6898 my ($Path1, $Path2) = @_;
6899 my @Parts1 = split(/[\/\\]/, $Path1);
6900 my @Parts2 = split(/[\/\\]/, $Path2);
6901 foreach my $Num (0 .. $#Parts1)
6902 {
6903 my $Part1 = $Parts1[$Num];
6904 my $Part2 = $Parts2[$Num];
6905 if($GlibcDir{$Part1}
6906 and not $GlibcDir{$Part2}) {
6907 return 1;
6908 }
6909 elsif($GlibcDir{$Part2}
6910 and not $GlibcDir{$Part1}) {
6911 return -1;
6912 }
6913 elsif($Part1=~/glib/
6914 and $Part2!~/glib/) {
6915 return 1;
6916 }
6917 elsif($Part1!~/glib/
6918 and $Part2=~/glib/) {
6919 return -1;
6920 }
6921 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6922 return $CmpRes;
6923 }
6924 }
6925 return 0;
6926}
6927
6928sub checkRelevance($)
6929{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006930 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006931 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006932
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006933 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006934 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006935 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006936
6937 my $Name = lc(get_filename($Path));
6938 my $Dir = lc(get_dirname($Path));
6939
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006940 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006941
6942 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006943 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006944 my $Len = length($Token);
6945 next if($Len<=1);
6946 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6947 { # include/evolution-data-server-1.4/libebook/e-book.h
6948 return 1;
6949 }
6950 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006951 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006952 return 1;
6953 }
6954 }
6955 return 0;
6956}
6957
6958sub checkFamily(@)
6959{
6960 my @Paths = @_;
6961 return 1 if($#Paths<=0);
6962 my %Prefix = ();
6963 foreach my $Path (@Paths)
6964 {
6965 if($SystemRoot) {
6966 $Path = cut_path_prefix($Path, $SystemRoot);
6967 }
6968 if(my $Dir = get_dirname($Path))
6969 {
6970 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6971 $Prefix{$Dir} += 1;
6972 $Prefix{get_dirname($Dir)} += 1;
6973 }
6974 }
6975 foreach (sort keys(%Prefix))
6976 {
6977 if(get_depth($_)>=3
6978 and $Prefix{$_}==$#Paths+1) {
6979 return 1;
6980 }
6981 }
6982 return 0;
6983}
6984
6985sub isAcceptable($$$)
6986{
6987 my ($Header, $Candidate, $LibVersion) = @_;
6988 my $HName = get_filename($Header);
6989 if(get_dirname($Header))
6990 { # with prefix
6991 return 1;
6992 }
6993 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6994 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6995 return 1;
6996 }
6997 if(checkRelevance($Candidate))
6998 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6999 return 1;
7000 }
7001 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
7002 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
7003 # /usr/include/qt4/Qt/qsslconfiguration.h
7004 return 1;
7005 }
7006 if($OStarget eq "symbian")
7007 {
7008 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
7009 return 1;
7010 }
7011 }
7012 return 0;
7013}
7014
7015sub isRelevant($$$)
7016{ # disallow to search for "abstract" headers in too deep directories
7017 my ($Header, $Candidate, $LibVersion) = @_;
7018 my $HName = get_filename($Header);
7019 if($OStarget eq "symbian")
7020 {
7021 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
7022 return 0;
7023 }
7024 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007025 if($OStarget ne "bsd")
7026 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007027 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
7028 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
7029 return 0;
7030 }
7031 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007032 if($OStarget ne "windows")
7033 {
7034 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
7035 { # skip /usr/include/wine/msvcrt
7036 return 0;
7037 }
7038 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007039 if(not get_dirname($Header)
7040 and $Candidate=~/[\/\\]wx[\/\\]/)
7041 { # do NOT search in system /wx/ directory
7042 # for headers without a prefix: sstream.h
7043 return 0;
7044 }
7045 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7046 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7047 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7048 return 0;
7049 }
7050 if($Candidate=~/[\/\\]asm-/
7051 and (my $Arch = getArch($LibVersion)) ne "unknown")
7052 { # arch-specific header files
7053 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7054 {# skip ../asm-arm/ if using x86 architecture
7055 return 0;
7056 }
7057 }
7058 my @Candidates = getSystemHeaders($HName, $LibVersion);
7059 if($#Candidates==1)
7060 { # unique header
7061 return 1;
7062 }
7063 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7064 if($#SCandidates==1)
7065 { # unique name
7066 return 1;
7067 }
7068 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7069 if(get_depth($Candidate)-$SystemDepth>=5)
7070 { # abstract headers in too deep directories
7071 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7072 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7073 return 0;
7074 }
7075 }
7076 if($Header eq "parser.h"
7077 and $Candidate!~/\/libxml2\//)
7078 { # select parser.h from xml2 library
7079 return 0;
7080 }
7081 if(not get_dirname($Header)
7082 and keys(%{$SystemHeaders{$HName}})>=3)
7083 { # many headers with the same name
7084 # like thread.h included without a prefix
7085 if(not checkFamily(@Candidates)) {
7086 return 0;
7087 }
7088 }
7089 return 1;
7090}
7091
7092sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007093{ # cache function
7094 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7095 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7096 }
7097 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7098}
7099
7100sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007101{
7102 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007103 if(-f $Header) {
7104 return $Header;
7105 }
7106 if(is_abs($Header) and not -f $Header)
7107 { # incorrect absolute path
7108 return "";
7109 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007110 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007111 { # too abstract configuration headers
7112 return "";
7113 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007114 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007115 if($OSgroup ne "windows")
7116 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007117 if(defined $WinHeaders{lc($HName)}
7118 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007119 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007120 return "";
7121 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007122 }
7123 if($OSgroup ne "macos")
7124 {
7125 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007126 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007127 return "";
7128 }
7129 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007130
7131 if(defined $ObsoleteHeaders{$HName})
7132 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007133 return "";
7134 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007135 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7136 {
7137 if(defined $AlienHeaders{$HName}
7138 or defined $AlienHeaders{$Header})
7139 { # alien headers from other systems
7140 return "";
7141 }
7142 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007143
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007144 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007145 { # search in default paths
7146 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007147 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007148 }
7149 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007150 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007151 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007152 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007153 }
7154 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7155 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7156 {
7157 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007158 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007159 }
7160 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007161 # error
7162 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007163}
7164
7165sub getSystemHeaders($$)
7166{
7167 my ($Header, $LibVersion) = @_;
7168 my @Candidates = ();
7169 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7170 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007171 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007172 next;
7173 }
7174 push(@Candidates, $Candidate);
7175 }
7176 return @Candidates;
7177}
7178
7179sub cut_path_prefix($$)
7180{
7181 my ($Path, $Prefix) = @_;
7182 return $Path if(not $Prefix);
7183 $Prefix=~s/[\/\\]+\Z//;
7184 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7185 return $Path;
7186}
7187
7188sub is_default_include_dir($)
7189{
7190 my $Dir = $_[0];
7191 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007192 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007193}
7194
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007195sub identifyHeader($$)
7196{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007197 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007198 if(not $Header) {
7199 return "";
7200 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007201 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007202 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7203 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007204 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007205 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007206}
7207
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007208sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007209{ # search for header by absolute path, relative path or name
7210 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007211 if(-f $Header)
7212 { # it's relative or absolute path
7213 return get_abs_path($Header);
7214 }
7215 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7216 and my $HeaderDir = find_in_defaults($Header))
7217 { # search for libc headers in the /usr/include
7218 # for non-libc target library before searching
7219 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007220 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007221 }
7222 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7223 { # search in the target library paths
7224 return $Path;
7225 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007226 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007227 { # search in the internal GCC include paths
7228 return $DefaultGccHeader{$Header};
7229 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007230 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007231 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007232 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007233 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007234 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007235 { # search in the default G++ include paths
7236 return $DefaultCppHeader{$Header};
7237 }
7238 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7239 { # search everywhere in the system
7240 return $AnyPath;
7241 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007242 elsif($OSgroup eq "macos")
7243 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7244 if(my $Dir = get_dirname($Header))
7245 {
7246 my $RelPath = "Headers\/".get_filename($Header);
7247 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007248 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007249 }
7250 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007251 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007252 # cannot find anything
7253 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007254}
7255
7256sub getLocation($)
7257{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007258 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7259 {
7260 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007261 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007262 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007263 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007264 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007265}
7266
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007267sub getNameByInfo($)
7268{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007269 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007270 {
7271 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7272 {
7273 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7274 {
7275 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7276 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007277 my $Str = $1;
7278 if($CppMode{$Version}
7279 and $Str=~/\Ac99_(.+)\Z/)
7280 {
7281 if($CppKeywords_A{$1}) {
7282 $Str=$1;
7283 }
7284 }
7285 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007286 }
7287 }
7288 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007289 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007290 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007291}
7292
7293sub getTreeStr($)
7294{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007295 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007296 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007297 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7298 {
7299 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007300 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007301 and $Str=~/\Ac99_(.+)\Z/)
7302 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007303 if($CppKeywords_A{$1}) {
7304 $Str=$1;
7305 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007306 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007307 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007308 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007309 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007310 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007311}
7312
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007313sub getFuncShortName($)
7314{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007315 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007316 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007317 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007318 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007319 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007320 {
7321 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7322 {
7323 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7324 return "operator ".$RName;
7325 }
7326 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007327 }
7328 else
7329 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007330 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7331 {
7332 if(my $Ind = $Operator_Indication{$1}) {
7333 return "operator".$Ind;
7334 }
7335 elsif(not $UnknownOperator{$1})
7336 {
7337 printMsg("WARNING", "unknown operator $1");
7338 $UnknownOperator{$1} = 1;
7339 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007340 }
7341 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007342 }
7343 else
7344 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007345 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7346 return getTreeStr($1);
7347 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007348 }
7349 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007350 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007351}
7352
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007353sub getFuncReturn($)
7354{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007355 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7356 {
7357 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7358 {
7359 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7360 return $1;
7361 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007362 }
7363 }
7364 return "";
7365}
7366
7367sub getFuncOrig($)
7368{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007369 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7370 {
7371 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7372 return $1;
7373 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007374 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007375 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007376}
7377
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007378sub unmangleArray(@)
7379{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007380 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007381 { # MSVC mangling
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007382 if(defined $DisabledMSVCUnmangling) {
7383 return @_;
7384 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007385 my $UndNameCmd = get_CmdPath("undname");
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007386 if(not $UndNameCmd)
7387 {
7388 if($OSgroup eq "windows") {
7389 exitStatus("Not_Found", "can't find \"undname\"");
7390 }
7391 elsif(not defined $DisabledMSVCUnmangling)
7392 {
7393 printMsg("WARNING", "can't find \"undname\", disable MSVC unmangling");
7394 $DisabledMSVCUnmangling = 1;
7395 return @_;
7396 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007397 }
7398 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007399 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007400 }
7401 else
7402 { # GCC mangling
7403 my $CppFiltCmd = get_CmdPath("c++filt");
7404 if(not $CppFiltCmd) {
7405 exitStatus("Not_Found", "can't find c++filt in PATH");
7406 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007407 if(not defined $CPPFILT_SUPPORT_FILE)
7408 {
7409 my $Info = `$CppFiltCmd -h 2>&1`;
7410 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7411 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007412 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007413 if($CPPFILT_SUPPORT_FILE)
7414 { # new versions of c++filt can take a file
7415 if($#_>$MAX_CPPFILT_FILE_SIZE)
7416 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7417 # this is fixed in the oncoming version of Binutils
7418 my @Half = splice(@_, 0, ($#_+1)/2);
7419 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007420 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007421 else
7422 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007423 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7424 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7425 if($?==139)
7426 { # segmentation fault
7427 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7428 }
7429 return split(/\n/, $Res);
7430 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007431 }
7432 else
7433 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007434 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7435 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007436 my @Half = splice(@_, 0, ($#_+1)/2);
7437 return (unmangleArray(@Half), unmangleArray(@_))
7438 }
7439 else
7440 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007441 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007442 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7443 if($?==139)
7444 { # segmentation fault
7445 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7446 }
7447 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007448 }
7449 }
7450 }
7451}
7452
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007453sub get_ChargeLevel($$)
7454{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007455 my ($Symbol, $LibVersion) = @_;
7456 return "" if($Symbol!~/\A(_Z|\?)/);
7457 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7458 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007459 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007460 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007461 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007462 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007463 return "[in-charge]";
7464 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007465 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007466 return "[not-in-charge]";
7467 }
7468 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007469 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007470 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007471 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007472 return "[in-charge]";
7473 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007474 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007475 return "[not-in-charge]";
7476 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007477 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007478 return "[in-charge-deleting]";
7479 }
7480 }
7481 }
7482 else
7483 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007484 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007485 return "[in-charge]";
7486 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007487 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007488 return "[not-in-charge]";
7489 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007490 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007491 return "[in-charge]";
7492 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007493 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007494 return "[not-in-charge]";
7495 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007496 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007497 return "[in-charge-deleting]";
7498 }
7499 }
7500 return "";
7501}
7502
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007503sub get_Signature_M($$)
7504{
7505 my ($Symbol, $LibVersion) = @_;
7506 my $Signature_M = $tr_name{$Symbol};
7507 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7508 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007509 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007510 }
7511 return $Signature_M;
7512}
7513
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007514sub get_Signature($$)
7515{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007516 my ($Symbol, $LibVersion) = @_;
7517 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7518 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007519 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007520 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007521 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03007522
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007523 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007524
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007525 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007526 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007527 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7528 {
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007529 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
7530 $ClassName=~s/\bstruct //g;
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007531
7532 if(index($Symbol, "_ZTV")==0) {
7533 return "vtable for $ClassName [data]";
7534 }
7535
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007536 $Signature .= $ClassName."::";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007537 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7538 $Signature .= "~";
7539 }
7540 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007541 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007542 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007543 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007544 }
7545 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007546 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007547 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007548 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7549 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007550 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007551 else
7552 {
7553 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007554 }
7555 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007556 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007557 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007558 if($Pos eq "") {
7559 next;
7560 }
7561
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007562 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007563 if(not $ParamTypeId) {
7564 next;
7565 }
7566
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007567 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007568 if(not $ParamTypeName) {
7569 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7570 }
7571 foreach my $Typedef (keys(%ChangedTypedef))
7572 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007573 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7574 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7575 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007576 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007577 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7578 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007579 if($ParamName eq "this"
7580 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007581 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007582 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007583 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007584 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007585 }
7586 else {
7587 push(@ParamArray, $ParamTypeName);
7588 }
7589 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007590 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7591 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007592 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007593 }
7594 else
7595 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007596 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007597 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007598 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007599 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007600 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007601 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7602 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007603 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007604 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007605 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7606 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007607 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007608 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007609 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7610 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007611 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007612 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007613 }
7614 }
7615 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007616 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007617 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007618 }
7619 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007620 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007621 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007622 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007623}
7624
7625sub create_member_decl($$)
7626{
7627 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007628 if($TName=~/\([\*]+\)/)
7629 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007630 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7631 return $TName;
7632 }
7633 else
7634 {
7635 my @ArraySizes = ();
7636 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7637 push(@ArraySizes, $1);
7638 }
7639 return $TName." ".$Member.join("", @ArraySizes);
7640 }
7641}
7642
7643sub getFuncType($)
7644{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007645 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7646 {
7647 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7648 {
7649 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7650 {
7651 if($Type eq "method_type") {
7652 return "Method";
7653 }
7654 elsif($Type eq "function_type") {
7655 return "Function";
7656 }
7657 else {
7658 return "Other";
7659 }
7660 }
7661 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007662 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007663 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007664}
7665
7666sub getFuncTypeId($)
7667{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007668 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7669 {
7670 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7671 return $1;
7672 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007673 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007674 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007675}
7676
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007677sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007678{ # "._N" or "$_N" in older GCC versions
7679 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007680}
7681
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007682sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007683{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007684 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7685 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007686 }
7687
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007688 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007689
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007690 if($_[1] ne "S")
7691 {
7692 $N=~s/\A[ ]+//g;
7693 $N=~s/[ ]+\Z//g;
7694 $N=~s/[ ]{2,}/ /g;
7695 }
7696
7697 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007698
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007699 $N=~s/\b(const|volatile) ([\w\:]+)([\*&,>]|\Z)/$2 $1$3/g; # "const void" to "void const"
7700
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007701 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007702
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007703 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7704 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007705
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007706 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007707
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007708 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007709
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007710 if($_[1] eq "S")
7711 {
7712 if(index($N, "operator")!=-1) {
7713 $N=~s/\b(operator[ ]*)> >/$1>>/;
7714 }
7715 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007716
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +03007717 $N=~s/,([^ ])/, $1/g;
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007718
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007719 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007720}
7721
7722sub get_HeaderDeps($$)
7723{
7724 my ($AbsPath, $LibVersion) = @_;
7725 return () if(not $AbsPath or not $LibVersion);
7726 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7727 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7728 }
7729 my %IncDir = ();
7730 detect_recursive_includes($AbsPath, $LibVersion);
7731 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7732 {
7733 next if(not $HeaderPath);
7734 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7735 my $Dir = get_dirname($HeaderPath);
7736 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7737 {
7738 my $Dep = $Dir;
7739 if($Prefix)
7740 {
7741 if($OSgroup eq "windows")
7742 { # case insensitive seach on windows
7743 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7744 next;
7745 }
7746 }
7747 elsif($OSgroup eq "macos")
7748 { # seach in frameworks
7749 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7750 {
7751 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7752 {# frameworks
7753 my ($HFramework, $HName) = ($1, $2);
7754 $Dep = $HFramework;
7755 }
7756 else
7757 {# mismatch
7758 next;
7759 }
7760 }
7761 }
7762 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7763 { # Linux, FreeBSD
7764 next;
7765 }
7766 }
7767 if(not $Dep)
7768 { # nothing to include
7769 next;
7770 }
7771 if(is_default_include_dir($Dep))
7772 { # included by the compiler
7773 next;
7774 }
7775 if(get_depth($Dep)==1)
7776 { # too short
7777 next;
7778 }
7779 if(isLibcDir($Dep))
7780 { # do NOT include /usr/include/{sys,bits}
7781 next;
7782 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007783 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007784 }
7785 }
7786 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7787 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7788}
7789
7790sub sortIncPaths($$)
7791{
7792 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007793 if(not $ArrRef or $#{$ArrRef}<0) {
7794 return $ArrRef;
7795 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007796 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7797 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007798 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007799 return $ArrRef;
7800}
7801
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007802sub sortDeps($$$)
7803{
7804 if($Header_Dependency{$_[2]}{$_[0]}
7805 and not $Header_Dependency{$_[2]}{$_[1]}) {
7806 return 1;
7807 }
7808 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7809 and $Header_Dependency{$_[2]}{$_[1]}) {
7810 return -1;
7811 }
7812 return 0;
7813}
7814
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007815sub join_P($$)
7816{
7817 my $S = "/";
7818 if($OSgroup eq "windows") {
7819 $S = "\\";
7820 }
7821 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007822}
7823
7824sub get_namespace_additions($)
7825{
7826 my $NameSpaces = $_[0];
7827 my ($Additions, $AddNameSpaceId) = ("", 1);
7828 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7829 {
7830 next if($SkipNameSpaces{$Version}{$NS});
7831 next if(not $NS or $NameSpaces->{$NS}==-1);
7832 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7833 next if($NS=~/\A__/i);
7834 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007835 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007836 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7837 my @NS_Parts = split(/::/, $NS);
7838 next if($#NS_Parts==-1);
7839 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7840 foreach my $NS_Part (@NS_Parts)
7841 {
7842 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7843 $TypeDecl_Suffix .= "}";
7844 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007845 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007846 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7847 $Additions.=" $TypeDecl\n $FuncDecl\n";
7848 $AddNameSpaceId+=1;
7849 }
7850 return $Additions;
7851}
7852
7853sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007854{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007855 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007856 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007857 if($Fmt eq "windows")
7858 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007859 $Path=~s/\//\\/g;
7860 $Path=lc($Path);
7861 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007862 else
7863 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007864 $Path=~s/\\/\//g;
7865 }
7866 return $Path;
7867}
7868
7869sub inc_opt($$)
7870{
7871 my ($Path, $Style) = @_;
7872 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007873 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007874 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007875 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007876 return "-I\"".path_format($Path, "unix")."\"";
7877 }
7878 elsif($OSgroup eq "macos"
7879 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007880 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007881 return "-F".esc(get_dirname($Path));
7882 }
7883 else {
7884 return "-I".esc($Path);
7885 }
7886 }
7887 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007888 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007889 }
7890 return "";
7891}
7892
7893sub platformSpecs($)
7894{
7895 my $LibVersion = $_[0];
7896 my $Arch = getArch($LibVersion);
7897 if($OStarget eq "symbian")
7898 { # options for GCCE compiler
7899 my %Symbian_Opts = map {$_=>1} (
7900 "-D__GCCE__",
7901 "-DUNICODE",
7902 "-fexceptions",
7903 "-D__SYMBIAN32__",
7904 "-D__MARM_INTERWORK__",
7905 "-D_UNICODE",
7906 "-D__S60_50__",
7907 "-D__S60_3X__",
7908 "-D__SERIES60_3X__",
7909 "-D__EPOC32__",
7910 "-D__MARM__",
7911 "-D__EABI__",
7912 "-D__MARM_ARMV5__",
7913 "-D__SUPPORT_CPP_EXCEPTIONS__",
7914 "-march=armv5t",
7915 "-mapcs",
7916 "-mthumb-interwork",
7917 "-DEKA2",
7918 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7919 );
7920 return join(" ", keys(%Symbian_Opts));
7921 }
7922 elsif($OSgroup eq "windows"
7923 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7924 { # add options to MinGW compiler
7925 # to simulate the MSVC compiler
7926 my %MinGW_Opts = map {$_=>1} (
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007927 "-D__unaligned=\" \"",
7928 "-D__nullptr=\"nullptr\"",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007929 "-D_WIN32",
7930 "-D_STDCALL_SUPPORTED",
7931 "-D__int64=\"long long\"",
7932 "-D__int32=int",
7933 "-D__int16=short",
7934 "-D__int8=char",
7935 "-D__possibly_notnullterminated=\" \"",
7936 "-D__nullterminated=\" \"",
7937 "-D__nullnullterminated=\" \"",
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007938 "-D__assume=\" \"",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007939 "-D__w64=\" \"",
7940 "-D__ptr32=\" \"",
7941 "-D__ptr64=\" \"",
7942 "-D__forceinline=inline",
7943 "-D__inline=inline",
7944 "-D__uuidof(x)=IID()",
7945 "-D__try=",
7946 "-D__except(x)=",
7947 "-D__declspec(x)=__attribute__((x))",
7948 "-D__pragma(x)=",
7949 "-D_inline=inline",
7950 "-D__forceinline=__inline",
7951 "-D__stdcall=__attribute__((__stdcall__))",
7952 "-D__cdecl=__attribute__((__cdecl__))",
7953 "-D__fastcall=__attribute__((__fastcall__))",
7954 "-D__thiscall=__attribute__((__thiscall__))",
7955 "-D_stdcall=__attribute__((__stdcall__))",
7956 "-D_cdecl=__attribute__((__cdecl__))",
7957 "-D_fastcall=__attribute__((__fastcall__))",
7958 "-D_thiscall=__attribute__((__thiscall__))",
7959 "-DSHSTDAPI_(x)=x",
7960 "-D_MSC_EXTENSIONS",
7961 "-DSECURITY_WIN32",
7962 "-D_MSC_VER=1500",
7963 "-D_USE_DECLSPECS_FOR_SAL",
7964 "-D__noop=\" \"",
7965 "-DDECLSPEC_DEPRECATED=\" \"",
7966 "-D__builtin_alignof(x)=__alignof__(x)",
7967 "-DSORTPP_PASS");
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007968 if($Arch eq "x86")
7969 {
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007970 $MinGW_Opts{"-D_X86_=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007971 $MinGW_Opts{"-D_M_IX86=300"}=1;
7972 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007973 elsif($Arch eq "x86_64")
7974 {
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007975 $MinGW_Opts{"-D_AMD64_=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007976 $MinGW_Opts{"-D_M_AMD64=300"}=1;
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007977 $MinGW_Opts{"-D_M_X64=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007978 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007979 elsif($Arch eq "ia64")
7980 {
7981 $MinGW_Opts{"-D_IA64_=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007982 $MinGW_Opts{"-D_M_IA64=300"}=1;
7983 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007984 return join(" ", sort keys(%MinGW_Opts));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007985 }
7986 return "";
7987}
7988
7989my %C_Structure = map {$_=>1} (
7990# FIXME: Can't separate union and struct data types before dumping,
7991# so it sometimes cause compilation errors for unknown reason
7992# when trying to declare TYPE* tmp_add_class_N
7993# This is a list of such structures + list of other C structures
7994 "sigval",
7995 "sigevent",
7996 "sigaction",
7997 "sigvec",
7998 "sigstack",
7999 "timeval",
8000 "timezone",
8001 "rusage",
8002 "rlimit",
8003 "wait",
8004 "flock",
8005 "stat",
8006 "_stat",
8007 "stat32",
8008 "_stat32",
8009 "stat64",
8010 "_stat64",
8011 "_stati64",
8012 "if_nameindex",
8013 "usb_device",
8014 "sigaltstack",
8015 "sysinfo",
8016 "timeLocale",
8017 "tcp_debug",
8018 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008019 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008020 "timespec",
8021 "random_data",
8022 "drand48_data",
8023 "_IO_marker",
8024 "_IO_FILE",
8025 "lconv",
8026 "sched_param",
8027 "tm",
8028 "itimerspec",
8029 "_pthread_cleanup_buffer",
8030 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008031 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008032 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008033 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008034 "sigcontext",
8035 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008036 # Mac
8037 "_timex",
8038 "_class_t",
8039 "_category_t",
8040 "_class_ro_t",
8041 "_protocol_t",
8042 "_message_ref_t",
8043 "_super_message_ref_t",
8044 "_ivar_t",
8045 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008046);
8047
8048sub getCompileCmd($$$)
8049{
8050 my ($Path, $Opt, $Inc) = @_;
8051 my $GccCall = $GCC_PATH;
8052 if($Opt) {
8053 $GccCall .= " ".$Opt;
8054 }
8055 $GccCall .= " -x ";
8056 if($OSgroup eq "macos") {
8057 $GccCall .= "objective-";
8058 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04008059
8060 if($EMERGENCY_MODE_48)
8061 { # workaround for GCC 4.8 (C only)
8062 $GccCall .= "c++";
8063 }
8064 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008065 { # compile as "C++" header
8066 # to obtain complete dump using GCC 4.0
8067 $GccCall .= "c++-header";
8068 }
8069 else
8070 { # compile as "C++" source
8071 # GCC 3.3 cannot compile headers
8072 $GccCall .= "c++";
8073 }
8074 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008075 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008076 $GccCall .= " ".$Opts;
8077 }
8078 # allow extra qualifications
8079 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008080 $GccCall .= " -fpermissive";
8081 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008082 if($NoStdInc)
8083 {
8084 $GccCall .= " -nostdinc";
8085 $GccCall .= " -nostdinc++";
8086 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008087 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008088 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008089 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008090 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008091 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008092 if($Inc)
8093 { # include paths
8094 $GccCall .= " ".$Inc;
8095 }
8096 return $GccCall;
8097}
8098
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008099sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008100{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008101 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008102 my %HeaderElems = (
8103 # Types
8104 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008105 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008106 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8107 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008108 "time.h" => ["time_t"],
8109 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008110 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8111 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008112 "stdbool.h" => ["_Bool"],
8113 "rpc/xdr.h" => ["bool_t"],
8114 "in_systm.h" => ["n_long", "n_short"],
8115 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008116 "arpa/inet.h" => ["fw_src", "ip_src"],
8117 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008118 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008119 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008120 );
8121 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008122 foreach (keys(%HeaderElems))
8123 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008124 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008125 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008126 }
8127 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008128 my %Types = ();
8129 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8130 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008131 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008132 }
8133 if(keys(%Types))
8134 {
8135 my %AddHeaders = ();
8136 foreach my $Type (keys(%Types))
8137 {
8138 if(my $Header = $AutoPreamble{$Type})
8139 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008140 if(my $Path = identifyHeader($Header, $LibVersion))
8141 {
8142 if(skipHeader($Path, $LibVersion)) {
8143 next;
8144 }
8145 $Path = path_format($Path, $OSgroup);
8146 $AddHeaders{$Path}{"Type"} = $Type;
8147 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008148 }
8149 }
8150 }
8151 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008152 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008153 }
8154 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008155 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008156}
8157
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008158sub checkCTags($)
8159{
8160 my $Path = $_[0];
8161 if(not $Path) {
8162 return;
8163 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008164 my $CTags = undef;
8165
8166 if($OSgroup eq "bsd")
8167 { # use ectags on BSD
8168 $CTags = get_CmdPath("ectags");
8169 if(not $CTags) {
8170 printMsg("WARNING", "can't find \'ectags\' program");
8171 }
8172 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008173 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008174 $CTags = get_CmdPath("ctags");
8175 }
8176 if(not $CTags)
8177 {
8178 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008179 return;
8180 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008181
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008182 if($OSgroup ne "linux")
8183 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008184 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkodd172162016-10-04 19:41:25 +03008185 if($Info!~/universal|exuberant/i)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008186 {
8187 printMsg("WARNING", "incompatible version of \'ctags\' program");
8188 return;
8189 }
8190 }
8191
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008192 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008193 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008194 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008195 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008196 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008197 open(CTAGS, "<", $Out);
8198 while(my $Line = <CTAGS>)
8199 {
8200 chomp($Line);
8201 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008202 if(defined $Intrinsic_Keywords{$Name})
8203 { # noise
8204 next;
8205 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008206 if($Type eq "n")
8207 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008208 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008209 next;
8210 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008211 if(index($Scpe, "struct:")==0) {
8212 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008213 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008214 if(index($Scpe, "namespace:")==0)
8215 {
8216 if($Scpe=~s/\Anamespace://) {
8217 $Name = $Scpe."::".$Name;
8218 }
8219 }
8220 $TUnit_NameSpaces{$Version}{$Name} = 1;
8221 }
8222 elsif($Type eq "p")
8223 {
8224 if(not $Scpe or index($Scpe, "namespace:")==0) {
8225 $TUnit_Funcs{$Version}{$Name} = 1;
8226 }
8227 }
8228 elsif($Type eq "x")
8229 {
8230 if(not $Scpe or index($Scpe, "namespace:")==0) {
8231 $TUnit_Vars{$Version}{$Name} = 1;
8232 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008233 }
8234 }
8235 close(CTAGS);
8236}
8237
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008238sub preChange($$)
8239{
8240 my ($HeaderPath, $IncStr) = @_;
8241
8242 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8243 my $Content = undef;
8244
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008245 if(not defined $MinGWCompat and $OStarget eq "windows"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008246 and get_dumpmachine($GCC_PATH)=~/mingw/i
8247 and $MinGWMode{$Version}!=-1)
8248 { # modify headers to compile by MinGW
8249 if(not $Content)
8250 { # preprocessing
8251 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8252 }
8253 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8254 { # __asm { ... }
8255 $MinGWMode{$Version}=1;
8256 }
8257 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8258 { # comments after preprocessing
8259 $MinGWMode{$Version}=1;
8260 }
8261 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8262 { # 0xffui8
8263 $MinGWMode{$Version}=1;
8264 }
8265
8266 if($MinGWMode{$Version}) {
8267 printMsg("INFO", "Using MinGW compatibility mode");
8268 }
8269 }
8270
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008271 if(defined $CxxIncompat and ($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8272 and $CppMode{$Version}!=-1 and not $CPP_HEADERS)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008273 { # rename C++ keywords in C code
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008274 printMsg("INFO", "Checking the code for C++ keywords");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008275 if(not $Content)
8276 { # preprocessing
8277 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8278 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008279
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008280 my $RegExp_C = join("|", keys(%CppKeywords_C));
8281 my $RegExp_F = join("|", keys(%CppKeywords_F));
8282 my $RegExp_O = join("|", keys(%CppKeywords_O));
8283
8284 my $Detected = undef;
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008285 my $Sentence_O = undef;
8286 my $Sentence_N = undef;
8287 my $Regex = undef;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008288
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008289 $Regex = qr/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*([\,\)\;\.\[]|\-\>|\:\s*\d))/;
8290 while($Content=~/$Regex/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008291 { # MATCH:
8292 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008293 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008294 # unsigned private: 8;
8295 # DO NOT MATCH:
8296 # #pragma GCC visibility push(default)
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008297 $Sentence_O = "$1$2$3$4";
8298 $Sentence_N = "$1$2c99_$3$4";
8299
8300 if($Sentence_O=~/\s+decltype\(/)
8301 { # C++
8302 # decltype(nullptr)
8303 last;
8304 }
8305 else
8306 {
8307 $Content=~s/$Regex/$Sentence_N/g;
8308 $CppMode{$Version} = 1;
8309 if(not defined $Detected) {
8310 $Detected = $Sentence_O;
8311 }
8312 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008313 }
8314 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8315 { # MATCH:
8316 # int delete(...);
8317 # int explicit(...);
8318 # DO NOT MATCH:
8319 # void operator delete(...)
8320 $CppMode{$Version} = 1;
8321 $Detected = "$1$2$3" if(not defined $Detected);
8322 }
8323 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8324 { # MATCH:
8325 # int bool;
8326 # DO NOT MATCH:
8327 # bool X;
8328 # return *this;
8329 # throw;
8330 $CppMode{$Version} = 1;
8331 $Detected = "$1$2$3" if(not defined $Detected);
8332 }
8333 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8334 { # MATCH:
8335 # int operator(...);
8336 # DO NOT MATCH:
8337 # int operator()(...);
8338 $CppMode{$Version} = 1;
8339 $Detected = "$1$2$3" if(not defined $Detected);
8340 }
8341 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8342 { # MATCH:
8343 # int foo(int operator);
8344 # int foo(int operator, int other);
8345 # DO NOT MATCH:
8346 # int operator,(...);
8347 $CppMode{$Version} = 1;
8348 $Detected = "$1$2$3" if(not defined $Detected);
8349 }
8350 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8351 { # MATCH:
8352 # int foo(gboolean *bool);
8353 # DO NOT MATCH:
8354 # void setTabEnabled(int index, bool);
8355 $CppMode{$Version} = 1;
8356 $Detected = "$1$2$3" if(not defined $Detected);
8357 }
8358 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8359 { # MATCH:
8360 # int foo(int* this);
8361 # int bar(int this);
8362 # int baz(int throw);
8363 # DO NOT MATCH:
8364 # foo(X, this);
8365 $CppMode{$Version} = 1;
8366 $Detected = "$1$2$3$4" if(not defined $Detected);
8367 }
8368 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8369 { # MATCH:
8370 # struct template {...};
8371 # extern template foo(...);
8372 $CppMode{$Version} = 1;
8373 $Detected = "$1$2" if(not defined $Detected);
8374 }
8375
8376 if($CppMode{$Version} == 1)
8377 {
8378 if($Debug)
8379 {
8380 $Detected=~s/\A\s+//g;
8381 printMsg("INFO", "Detected code: \"$Detected\"");
8382 }
8383 }
8384
8385 # remove typedef enum NAME NAME;
8386 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8387 my $N = 0;
8388 while($N<=$#FwdTypedefs-1)
8389 {
8390 my $S = $FwdTypedefs[$N];
8391 if($S eq $FwdTypedefs[$N+1])
8392 {
8393 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008394 $CppMode{$Version} = 1;
8395
8396 if($Debug) {
8397 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8398 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008399 }
8400 $N+=2;
8401 }
8402
8403 if($CppMode{$Version}==1) {
8404 printMsg("INFO", "Using C++ compatibility mode");
8405 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008406 else {
8407 printMsg("INFO", "C++ keywords in the C code are not found");
8408 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008409 }
8410
8411 if($CppMode{$Version}==1
8412 or $MinGWMode{$Version}==1)
8413 {
8414 my $IPath = $TMP_DIR."/dump$Version.i";
8415 writeFile($IPath, $Content);
8416 return $IPath;
8417 }
8418
8419 return undef;
8420}
8421
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008422sub getDump()
8423{
8424 if(not $GCC_PATH) {
8425 exitStatus("Error", "internal error - GCC path is not set");
8426 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008427
8428 my @Headers = keys(%{$Registered_Headers{$Version}});
8429 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8430
8431 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8432
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008433 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008434 my $HeaderPath = $TmpHeaderPath;
8435
8436 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008437 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008438 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8439 {
8440 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008441 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008442 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008443 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008444 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8445 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008446 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008447 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008448 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008449 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8450 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8451 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008452 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008453 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008454
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008455 if($ExtraInfo)
8456 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008457 if($IncludeString) {
8458 writeFile($ExtraInfo."/include-string", $IncludeString);
8459 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008460 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8461 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008462
8463 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8464 {
8465 my $REDIR = "";
8466 foreach my $P1 (sort @Redirects) {
8467 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8468 }
8469 writeFile($ExtraInfo."/include-redirect", $REDIR);
8470 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008471 }
8472
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008473 if(not keys(%{$TargetHeaders{$Version}}))
8474 { # Target headers
8475 addTargetHeaders($Version);
8476 }
8477
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008478 # clean memory
8479 %RecursiveIncludes = ();
8480 %Header_Include_Prefix = ();
8481 %Header_Includes = ();
8482
8483 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008484 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008485 delete($Cache{"detect_header_includes"});
8486 delete($Cache{"selectSystemHeader"});
8487
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008488 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008489 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8490 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008491
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008492 if($ExtraInfo)
8493 { # extra information for other tools
8494 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8495 }
8496
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008497 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008498 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008499 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008500
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008501 if($COMMON_LANGUAGE{$Version} eq "C++") {
8502 checkCTags($Pre);
8503 }
8504
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008505 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8506 { # try to correct the preprocessor output
8507 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008508 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008509
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008510 if($COMMON_LANGUAGE{$Version} eq "C++")
8511 { # add classes and namespaces to the dump
8512 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008513 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008514 or $MinGWMode{$Version}==1) {
8515 $CHdump .= " -fpreprocessed";
8516 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008517 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008518 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008519 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008520 chdir($ORIG_DIR);
8521 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8522 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008523 my $Content = readFile($ClassDump);
8524 foreach my $ClassInfo (split(/\n\n/, $Content))
8525 {
8526 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8527 {
8528 my $CName = $1;
8529 next if($CName=~/\A(__|_objc_|_opaque_)/);
8530 $TUnit_NameSpaces{$Version}{$CName} = -1;
8531 if($CName=~/\A[\w:]+\Z/)
8532 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008533 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008534 }
8535 if($CName=~/(\w[\w:]*)::/)
8536 { # namespaces
8537 my $NS = $1;
8538 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8539 $TUnit_NameSpaces{$Version}{$NS} = 1;
8540 }
8541 }
8542 }
8543 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8544 { # read v-tables (advanced approach)
8545 my ($CName, $VTable) = ($1, $2);
8546 $ClassVTable_Content{$Version}{$CName} = $VTable;
8547 }
8548 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008549 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8550 { # add user-defined namespaces
8551 $TUnit_NameSpaces{$Version}{$NS} = 1;
8552 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008553 if($Debug)
8554 { # debug mode
8555 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008556 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008557 }
8558 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008559 }
8560
8561 # add namespaces and classes
8562 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8563 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008564 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008565 }
8566 # some GCC versions don't include class methods to the TU dump by default
8567 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008568 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008569 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8570 {
8571 next if($C_Structure{$CName});
8572 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008573 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008574 if(not $Force and $GCC_44
8575 and $OSgroup eq "linux")
8576 { # optimization for linux with GCC >= 4.4
8577 # disable this code by -force option
8578 if(index($CName, "::")!=-1)
8579 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008580 next;
8581 }
8582 }
8583 else
8584 {
8585 if($CName=~/\A(.+)::[^:]+\Z/
8586 and $TUnit_Classes{$Version}{$1})
8587 { # classes inside other classes
8588 next;
8589 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008590 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008591 if(defined $TUnit_Funcs{$Version}{$CName})
8592 { # the same name for a function and type
8593 next;
8594 }
8595 if(defined $TUnit_Vars{$Version}{$CName})
8596 { # the same name for a variable and type
8597 next;
8598 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008599 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8600 }
8601 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008602 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008603 }
8604 }
8605 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8606 # create TU dump
8607 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008608 if($UserLang eq "C") {
8609 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8610 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008611 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008612 or $MinGWMode{$Version}==1) {
8613 $TUdump .= " -fpreprocessed";
8614 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008615 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008616 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8617 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008618 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008619 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008620 if($?)
8621 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008622 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008623 { # try to recompile
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008624 # FIXME: handle errors and try to recompile
8625 if($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008626 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008627 { # add auto preamble headers and try again
8628 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008629 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008630 foreach my $Num (0 .. $#Headers)
8631 {
8632 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008633 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8634 {
8635 push_U($Include_Preamble{$Version}, $Path);
8636 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008637 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008638 }
8639 resetLogging($Version);
8640 $TMP_DIR = tempdir(CLEANUP=>1);
8641 return getDump();
8642 }
8643 elsif($Cpp0xMode{$Version}!=-1
8644 and ($Errors=~/\Q-std=c++0x\E/
8645 or $Errors=~/is not a class or namespace/))
8646 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008647 if(check_gcc($GCC_PATH, "4.6"))
8648 {
8649 $Cpp0xMode{$Version}=-1;
8650 printMsg("INFO", "Enabling c++0x mode");
8651 resetLogging($Version);
8652 $TMP_DIR = tempdir(CLEANUP=>1);
8653 $CompilerOptions{$Version} .= " -std=c++0x";
8654 return getDump();
8655 }
8656 else {
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008657 printMsg("WARNING", "Probably c++0x element detected");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008658 }
8659
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008660 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008661 #elsif($MinGWMode{$Version}==1)
8662 #{ # disable MinGW mode and try again
8663 # $MinGWMode{$Version}=-1;
8664 # resetLogging($Version);
8665 # $TMP_DIR = tempdir(CLEANUP=>1);
8666 # return getDump();
8667 #}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008668 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008669 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008670 else {
8671 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008672 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008673 printMsg("ERROR", "some errors occurred when compiling headers");
8674 printErrorLog($Version);
8675 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008676 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008677 }
8678 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008679 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008680 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008681
8682 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8683 return $TUs[0];
8684 }
8685 else
8686 {
8687 my $Msg = "can't compile header(s)";
8688 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8689 $Msg .= "\nDid you install G++?";
8690 }
8691 exitStatus("Cannot_Compile", $Msg);
8692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008693}
8694
8695sub cmd_file($)
8696{
8697 my $Path = $_[0];
8698 return "" if(not $Path or not -e $Path);
8699 if(my $CmdPath = get_CmdPath("file")) {
8700 return `$CmdPath -b \"$Path\"`;
8701 }
8702 return "";
8703}
8704
8705sub getIncString($$)
8706{
8707 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008708 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008709 my $String = "";
8710 foreach (@{$ArrRef}) {
8711 $String .= " ".inc_opt($_, $Style);
8712 }
8713 return $String;
8714}
8715
8716sub getIncPaths(@)
8717{
8718 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008719 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008720 if($INC_PATH_AUTODETECT{$Version})
8721 { # auto-detecting dependencies
8722 my %Includes = ();
8723 foreach my $HPath (@HeaderPaths)
8724 {
8725 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8726 {
8727 if($Skip_Include_Paths{$Version}{$Dir}) {
8728 next;
8729 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008730 if($SystemRoot)
8731 {
8732 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8733 next;
8734 }
8735 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008736 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008737 }
8738 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008739 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008740 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008741 }
8742 }
8743 else
8744 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008745 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008746 }
8747 return \@IncPaths;
8748}
8749
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008750sub push_U($@)
8751{ # push unique
8752 if(my $Array = shift @_)
8753 {
8754 if(@_)
8755 {
8756 my %Exist = map {$_=>1} @{$Array};
8757 foreach my $Elem (@_)
8758 {
8759 if(not defined $Exist{$Elem})
8760 {
8761 push(@{$Array}, $Elem);
8762 $Exist{$Elem} = 1;
8763 }
8764 }
8765 }
8766 }
8767}
8768
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008769sub callPreprocessor($$$)
8770{
8771 my ($Path, $Inc, $LibVersion) = @_;
8772 return "" if(not $Path or not -f $Path);
8773 my $IncludeString=$Inc;
8774 if(not $Inc) {
8775 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8776 }
8777 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008778 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008779 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008780 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008781}
8782
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008783sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008784{ # native "find" is much faster than File::Find (~6x)
8785 # also the File::Find doesn't support --maxdepth N option
8786 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008787 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008788 return () if(not $Path or not -e $Path);
8789 if($OSgroup eq "windows")
8790 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008791 $Path = get_abs_path($Path);
8792 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008793 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008794 if($MaxDepth!=1) {
8795 $Cmd .= " /S";
8796 }
8797 if($Type eq "d") {
8798 $Cmd .= " /AD";
8799 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008800 elsif($Type eq "f") {
8801 $Cmd .= " /A-D";
8802 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008803 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008804 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008805 {
8806 if(not $UseRegex)
8807 { # FIXME: how to search file names in MS shell?
8808 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008809 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008810 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008811 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008812 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008813 }
8814 my @AbsPaths = ();
8815 foreach my $File (@Files)
8816 {
8817 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008818 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008819 }
8820 if($Type eq "f" and not -f $File)
8821 { # skip dirs
8822 next;
8823 }
8824 push(@AbsPaths, path_format($File, $OSgroup));
8825 }
8826 if($Type eq "d") {
8827 push(@AbsPaths, $Path);
8828 }
8829 return @AbsPaths;
8830 }
8831 else
8832 {
8833 my $FindCmd = get_CmdPath("find");
8834 if(not $FindCmd) {
8835 exitStatus("Not_Found", "can't find a \"find\" command");
8836 }
8837 $Path = get_abs_path($Path);
8838 if(-d $Path and -l $Path
8839 and $Path!~/\/\Z/)
8840 { # for directories that are symlinks
8841 $Path.="/";
8842 }
8843 my $Cmd = $FindCmd." \"$Path\"";
8844 if($MaxDepth) {
8845 $Cmd .= " -maxdepth $MaxDepth";
8846 }
8847 if($Type) {
8848 $Cmd .= " -type $Type";
8849 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008850 if($Name and not $UseRegex)
8851 { # wildcards
8852 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008853 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008854 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008855 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008856 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8857 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008858 my @Files = split(/\n/, $Res);
8859 if($Name and $UseRegex)
8860 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008861 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008862 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008863 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008864 }
8865}
8866
8867sub unpackDump($)
8868{
8869 my $Path = $_[0];
8870 return "" if(not $Path or not -e $Path);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008871
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008872 $Path = get_abs_path($Path);
8873 $Path = path_format($Path, $OSgroup);
8874 my ($Dir, $FileName) = separate_path($Path);
8875 my $UnpackDir = $TMP_DIR."/unpack";
8876 rmtree($UnpackDir);
8877 mkpath($UnpackDir);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008878
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008879 if($FileName=~s/\Q.zip\E\Z//g)
8880 { # *.zip
8881 my $UnzipCmd = get_CmdPath("unzip");
8882 if(not $UnzipCmd) {
8883 exitStatus("Not_Found", "can't find \"unzip\" command");
8884 }
8885 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008886 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008887 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008888 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008889 }
8890 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008891 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008892 if(not @Contents) {
8893 exitStatus("Error", "can't extract \'$Path\'");
8894 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008895 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008896 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008897 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008898 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008899 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008900 if($OSgroup eq "windows")
8901 { # -xvzf option is not implemented in tar.exe (2003)
8902 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8903 my $TarCmd = get_CmdPath("tar");
8904 if(not $TarCmd) {
8905 exitStatus("Not_Found", "can't find \"tar\" command");
8906 }
8907 my $GzipCmd = get_CmdPath("gzip");
8908 if(not $GzipCmd) {
8909 exitStatus("Not_Found", "can't find \"gzip\" command");
8910 }
8911 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008912 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008913 if($?) {
8914 exitStatus("Error", "can't extract \'$Path\'");
8915 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008916 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008917 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008918 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008919 }
8920 chdir($ORIG_DIR);
8921 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008922 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008923 if(not @Contents) {
8924 exitStatus("Error", "can't extract \'$Path\'");
8925 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008926 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008927 }
8928 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008929 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008930 my $TarCmd = get_CmdPath("tar");
8931 if(not $TarCmd) {
8932 exitStatus("Not_Found", "can't find \"tar\" command");
8933 }
8934 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008935 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008936 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008937 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008938 }
8939 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008940 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008941 if(not @Contents) {
8942 exitStatus("Error", "can't extract \'$Path\'");
8943 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008944 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008945 }
8946 }
8947}
8948
8949sub createArchive($$)
8950{
8951 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008952 if(not $To) {
8953 $To = ".";
8954 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008955 if(not $Path or not -e $Path
8956 or not -d $To) {
8957 return "";
8958 }
8959 my ($From, $Name) = separate_path($Path);
8960 if($OSgroup eq "windows")
8961 { # *.zip
8962 my $ZipCmd = get_CmdPath("zip");
8963 if(not $ZipCmd) {
8964 exitStatus("Not_Found", "can't find \"zip\"");
8965 }
8966 my $Pkg = $To."/".$Name.".zip";
8967 unlink($Pkg);
8968 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008969 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008970 if($?)
8971 { # cannot allocate memory (or other problems with "zip")
8972 unlink($Path);
8973 exitStatus("Error", "can't pack the ABI dump: ".$!);
8974 }
8975 chdir($ORIG_DIR);
8976 unlink($Path);
8977 return $Pkg;
8978 }
8979 else
8980 { # *.tar.gz
8981 my $TarCmd = get_CmdPath("tar");
8982 if(not $TarCmd) {
8983 exitStatus("Not_Found", "can't find \"tar\"");
8984 }
8985 my $GzipCmd = get_CmdPath("gzip");
8986 if(not $GzipCmd) {
8987 exitStatus("Not_Found", "can't find \"gzip\"");
8988 }
8989 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8990 unlink($Pkg);
8991 chdir($From);
8992 system($TarCmd, "-czf", $Pkg, $Name);
8993 if($?)
8994 { # cannot allocate memory (or other problems with "tar")
8995 unlink($Path);
8996 exitStatus("Error", "can't pack the ABI dump: ".$!);
8997 }
8998 chdir($ORIG_DIR);
8999 unlink($Path);
9000 return $To."/".$Name.".tar.gz";
9001 }
9002}
9003
9004sub is_header_file($)
9005{
9006 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
9007 return $_[0];
9008 }
9009 return 0;
9010}
9011
9012sub is_not_header($)
9013{
9014 if($_[0]=~/\.\w+\Z/
9015 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
9016 return 1;
9017 }
9018 return 0;
9019}
9020
9021sub is_header($$$)
9022{
9023 my ($Header, $UserDefined, $LibVersion) = @_;
9024 return 0 if(-d $Header);
9025 if(-f $Header) {
9026 $Header = get_abs_path($Header);
9027 }
9028 else
9029 {
9030 if(is_abs($Header))
9031 { # incorrect absolute path
9032 return 0;
9033 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009034 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009035 $Header = $HPath;
9036 }
9037 else
9038 { # can't find header
9039 return 0;
9040 }
9041 }
9042 if($Header=~/\.\w+\Z/)
9043 { # have an extension
9044 return is_header_file($Header);
9045 }
9046 else
9047 {
9048 if($UserDefined==2)
9049 { # specified on the command line
9050 if(cmd_file($Header)!~/HTML|XML/i) {
9051 return $Header;
9052 }
9053 }
9054 elsif($UserDefined)
9055 { # specified in the XML-descriptor
9056 # header file without an extension
9057 return $Header;
9058 }
9059 else
9060 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04009061 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009062 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009063 { # !~/HTML|XML|shared|dynamic/i
9064 return $Header;
9065 }
9066 }
9067 }
9068 return 0;
9069}
9070
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009071sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009072{
9073 my $LibVersion = $_[0];
9074 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9075 {
9076 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009077 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009078
9079 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9080 detect_recursive_includes($RegHeader, $LibVersion);
9081 }
9082
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009083 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9084 {
9085 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009086
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009087 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009088 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9089 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009090 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009091 }
9092 }
9093 }
9094}
9095
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009096sub familiarDirs($$)
9097{
9098 my ($D1, $D2) = @_;
9099 if($D1 eq $D2) {
9100 return 1;
9101 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009102
9103 my $U1 = index($D1, "/usr/");
9104 my $U2 = index($D2, "/usr/");
9105
9106 if($U1==0 and $U2!=0) {
9107 return 0;
9108 }
9109
9110 if($U2==0 and $U1!=0) {
9111 return 0;
9112 }
9113
9114 if(index($D2, $D1."/")==0) {
9115 return 1;
9116 }
9117
9118 # /usr/include/DIR
9119 # /home/user/DIR
9120
9121 my $DL = get_depth($D1);
9122
9123 my @Dirs1 = ($D1);
9124 while($DL - get_depth($D1)<=2
9125 and get_depth($D1)>=4
9126 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9127 push(@Dirs1, $D1);
9128 }
9129
9130 my @Dirs2 = ($D2);
9131 while(get_depth($D2)>=4
9132 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9133 push(@Dirs2, $D2);
9134 }
9135
9136 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009137 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009138 foreach my $P2 (@Dirs2)
9139 {
9140
9141 if($P1 eq $P2) {
9142 return 1;
9143 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009144 }
9145 }
9146 return 0;
9147}
9148
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009149sub readHeaders($)
9150{
9151 $Version = $_[0];
9152 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9153 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009154 if($Debug)
9155 { # debug mode
9156 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009157 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009158 }
9159 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009160}
9161
9162sub prepareTypes($)
9163{
9164 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009165 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009166 { # support for old ABI dumps
9167 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009168 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009169 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009170 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9171 if($TName=~/\A(\w+)::(\w+)/) {
9172 my ($P1, $P2) = ($1, $2);
9173 if($P1 eq $P2) {
9174 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009175 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009176 else {
9177 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9178 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009179 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009180 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009181 }
9182 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009183 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009184 { # support for old ABI dumps
9185 # V < 2.5: array size == "number of elements"
9186 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009187 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009188 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009189 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009190 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009191 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009192 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009193 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009194 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009195 $Size *= $Base{"Size"};
9196 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009197 }
9198 else
9199 { # array[] is a pointer
9200 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009201 }
9202 }
9203 }
9204 }
9205 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009206 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009207 { # support for old ABI dumps
9208 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009209 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009210 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009211 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009212 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009213 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009214 my %Type = get_Type($TypeId, $LibVersion);
9215 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9216 my %Type2 = get_Type($TypeId_2, $V2);
9217 if($Type{"Size"} ne $Type2{"Size"}) {
9218 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009219 }
9220 }
9221 }
9222 }
9223}
9224
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009225sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009226{
9227 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009228
9229 if(not keys(%{$SymbolInfo{$LibVersion}}))
9230 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009231 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009232 {
9233 if($CheckHeadersOnly) {
9234 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9235 }
9236 else {
9237 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9238 }
9239 }
9240 }
9241
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009242 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009243 if(not checkDump(1, "2.10")
9244 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009245 { # different formats
9246 $Remangle = 1;
9247 }
9248 if($CheckHeadersOnly)
9249 { # different languages
9250 if($UserLang)
9251 { # --lang=LANG for both versions
9252 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9253 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9254 {
9255 if($UserLang eq "C++")
9256 { # remangle symbols
9257 $Remangle = 1;
9258 }
9259 elsif($UserLang eq "C")
9260 { # remove mangling
9261 $Remangle = -1;
9262 }
9263 }
9264 }
9265 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009266
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009267 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009268 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009269 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009270 { # support for old ABI dumps
9271 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9272 {
9273 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9274 {
9275 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9276 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009277 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009278 if(defined $DVal and $DVal ne "")
9279 {
9280 if($TName eq "char") {
9281 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9282 }
9283 elsif($TName eq "bool") {
9284 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9285 }
9286 }
9287 }
9288 }
9289 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009290 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009291 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009292 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9293 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009294 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009295 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9296 # + support for old ABI dumps
9297 next;
9298 }
9299 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009300 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009301 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009302 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009303 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009304
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009305 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009306 if(not checkDump(1, "2.12")
9307 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009308 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009309 if($ShortName eq "operator>>")
9310 {
9311 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9312 { # corrected mangling of operator>>
9313 $SRemangle = 1;
9314 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009315 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009316 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9317 {
9318 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9319 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9320 { # corrected mangling of const global data
9321 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9322 # and incorrectly mangled by old ACC versions
9323 $SRemangle = 1;
9324 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009325 }
9326 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009327 if(not $CheckHeadersOnly)
9328 { # support for old ABI dumps
9329 if(not checkDump(1, "2.17")
9330 or not checkDump(2, "2.17"))
9331 {
9332 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9333 {
9334 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9335 {
9336 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9337 {
9338 $MnglName = $ShortName;
9339 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9340 }
9341 }
9342 }
9343 }
9344 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009345 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009346 { # support for old ABI dumps: some symbols are not mangled in old dumps
9347 # mangle both sets of symbols (old and new)
9348 # NOTE: remangling all symbols by the same mangler
9349 if($MnglName=~/\A_ZN(V|)K/)
9350 { # mangling may be incorrect on old ABI dumps
9351 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009352 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009353 }
9354 if($MnglName=~/\A_ZN(K|)V/)
9355 { # mangling may be incorrect on old ABI dumps
9356 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009357 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009358 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009359 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9360 or (not $ClassID and $CheckHeadersOnly)
9361 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9362 { # support for old ABI dumps, GCC >= 4.0
9363 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009364 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009365 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009366 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009367 $MangledNames{$LibVersion}{$MnglName} = 1;
9368 }
9369 }
9370 }
9371 elsif($Remangle==-1)
9372 { # remove mangling
9373 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009374 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009375 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009376 if(not $MnglName) {
9377 next;
9378 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009379
9380 # NOTE: duplicated entries in the ABI Dump
9381 if(defined $CompleteSignature{$LibVersion}{$MnglName})
9382 {
9383 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9384 {
9385 if($SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} eq "p1")
9386 {
9387 next;
9388 }
9389 }
9390 }
9391
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009392 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9393 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009394 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9395
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009396 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009397 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009398 { # support for old dumps
9399 # add "Volatile" attribute
9400 if($MnglName=~/_Z(K|)V/) {
9401 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9402 }
9403 }
9404 # symbol and its symlink have same signatures
9405 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009406 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009407 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009408
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009409 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9410 {
9411 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009412
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009413 if($SymVer{$LibVersion}{$Alias}) {
9414 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9415 }
9416 }
9417
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009418 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009419 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009420 }
9421 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9422 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9423 }
9424 if($ExtendedCheck)
9425 { # --ext option
9426 addExtension($LibVersion);
9427 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009428
9429 # clean memory
9430 delete($SymbolInfo{$LibVersion});
9431
9432 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009433 { # detect allocable classes with public exported constructors
9434 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009435 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009436 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009437 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009438 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009439 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9440 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009441 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009442 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009443 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009444 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009445 $AllocableClass{$LibVersion}{$ClassName} = 1;
9446 }
9447 }
9448 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009449 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009450 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009451 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009452 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009453 if($CheckHeadersOnly)
9454 {
9455 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9456 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9457 { # all symbols except non-virtual inline
9458 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9459 }
9460 }
9461 else {
9462 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009463 }
9464 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009465 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009466 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009467 }
9468 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009469 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009470 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009471 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009472 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009473 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009474 if(defined $Base{"Type"}
9475 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009476 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009477 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009478 if($Name=~/<([^<>\s]+)>/)
9479 {
9480 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9481 $ReturnedClass{$LibVersion}{$Tid} = 1;
9482 }
9483 }
9484 else {
9485 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9486 }
9487 }
9488 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009489 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009490 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009491 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009492 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009493 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009494 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009495 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009496 if($Base{"Type"}=~/Struct|Class/)
9497 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009498 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009499 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9500 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009501 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009502 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009503 }
9504 }
9505 }
9506 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009507
9508 # mapping {short name => symbols}
9509 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009510 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009511 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009512 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009513 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009514 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009515 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009516 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009517 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9518 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009519 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009520 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009521 }
9522 }
9523 }
9524 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009525
9526 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009527 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009528 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009529 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009530 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009531 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9532 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009533 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009534 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009535 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009536 $ClassNames{$LibVersion}{$TName} = 1;
9537 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009538 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009539 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9540 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009541 }
9542 }
9543 }
9544 }
9545 }
9546}
9547
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009548sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009549{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009550 my ($Tid, $LibVersion) = @_;
9551 if(not $Tid) {
9552 return $Tid;
9553 }
9554
9555 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9556 {
9557 if($TName_Tid{$LibVersion}{$Name}) {
9558 return $TName_Tid{$LibVersion}{$Name};
9559 }
9560 }
9561
9562 return $Tid;
9563}
9564
9565sub register_SymbolUsage($$$)
9566{
9567 my ($InfoId, $UsedType, $LibVersion) = @_;
9568
9569 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9570 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9571 {
9572 register_TypeUsage($RTid, $UsedType, $LibVersion);
9573 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9574 }
9575 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9576 {
9577 register_TypeUsage($FCid, $UsedType, $LibVersion);
9578 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9579
9580 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9581 { # register "this" pointer
9582 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9583 }
9584 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9585 { # register "this" pointer (const method)
9586 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9587 }
9588 }
9589 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9590 {
9591 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9592 {
9593 register_TypeUsage($PTid, $UsedType, $LibVersion);
9594 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9595 }
9596 }
9597 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9598 {
9599 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9600 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9601 register_TypeUsage($TTid, $UsedType, $LibVersion);
9602 }
9603 }
9604}
9605
9606sub register_TypeUsage($$$)
9607{
9608 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009609 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009610 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009611 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009612 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009613 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009614 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009615 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009616
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009617 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009618 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009619 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009620 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009621 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009622 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9623 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9624 }
9625 }
9626
9627 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9628 {
9629 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009630 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009631 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009632 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9633 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009634 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009635 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9636 {
9637 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9638 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009639 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009640 }
9641 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009642 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009643 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009644 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009645 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9646 {
9647 register_TypeUsage($MTid, $UsedType, $LibVersion);
9648 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009649 }
9650 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009651 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009652 or $TInfo{"Type"} eq "MethodPtr"
9653 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009654 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009655 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009656 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009657 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009658 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009659 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009660 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9661 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009662 }
9663 }
9664 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009665 if($TInfo{"Type"} eq "FieldPtr")
9666 {
9667 if(my $RTid = $TInfo{"Return"}) {
9668 register_TypeUsage($RTid, $UsedType, $LibVersion);
9669 }
9670 if(my $CTid = $TInfo{"Class"}) {
9671 register_TypeUsage($CTid, $UsedType, $LibVersion);
9672 }
9673 }
9674 if($TInfo{"Type"} eq "MethodPtr")
9675 {
9676 if(my $CTid = $TInfo{"Class"}) {
9677 register_TypeUsage($CTid, $UsedType, $LibVersion);
9678 }
9679 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009680 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009681 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009682 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009683 $UsedType->{$TypeId} = 1;
9684 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9685 {
9686 register_TypeUsage($BTid, $UsedType, $LibVersion);
9687 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9688 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009689 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009690 else
9691 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9692 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009693 }
9694 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009695}
9696
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009697sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009698{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009699 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9700
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009701 if($Level eq "Dump")
9702 {
9703 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9704 { # TODO: check if this symbol is from
9705 # base classes of other target symbols
9706 return 1;
9707 }
9708 }
9709
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009710 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9711 { # stdc++ interfaces
9712 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009713 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009714
9715 my $Target = 0;
9716 if(my $Header = $SInfo->{"Header"}) {
9717 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9718 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009719 if($ExtendedCheck)
9720 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009721 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009722 $Target = 1;
9723 }
9724 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009725 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009726 {
9727 if($Target)
9728 {
9729 if($Level eq "Dump")
9730 { # dumped
9731 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009732 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009733 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009734 return 1;
9735 }
9736 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009737 else {
9738 return 1;
9739 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009740 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009741 elsif($Level eq "Source")
9742 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009743 return 1;
9744 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009745 elsif($Level eq "Binary")
9746 { # checked
9747 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9748 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9749 return 1;
9750 }
9751 }
9752 }
9753 }
9754 else
9755 { # library is available
9756 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9757 { # exported symbols
9758 return 1;
9759 }
9760 if($Level eq "Dump")
9761 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009762 if($BinaryOnly)
9763 {
9764 if($SInfo->{"Data"})
9765 {
9766 if($Target) {
9767 return 1;
9768 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009769 }
9770 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009771 else
9772 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009773 if($Target) {
9774 return 1;
9775 }
9776 }
9777 }
9778 elsif($Level eq "Source")
9779 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009780 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009781 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009782 { # skip LOCAL symbols
9783 if($Target) {
9784 return 1;
9785 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009786 }
9787 }
9788 elsif($Level eq "Binary")
9789 { # checked
9790 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9791 {
9792 if($Target) {
9793 return 1;
9794 }
9795 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009796 }
9797 }
9798 return 0;
9799}
9800
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009801sub cleanDump($)
9802{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009803 my $LibVersion = $_[0];
9804 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9805 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009806 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9807 {
9808 delete($SymbolInfo{$LibVersion}{$InfoId});
9809 next;
9810 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009811 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009812 if(not $MnglName)
9813 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009814 delete($SymbolInfo{$LibVersion}{$InfoId});
9815 next;
9816 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009817 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009818 if(not $ShortName)
9819 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009820 delete($SymbolInfo{$LibVersion}{$InfoId});
9821 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009822 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009823 if($MnglName eq $ShortName)
9824 { # remove duplicate data
9825 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009826 }
9827 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9828 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9829 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009830 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9831 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9832 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009833 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009834 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009835 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009836 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009837 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9838 {
9839 delete($TypeInfo{$LibVersion}{$Tid});
9840 next;
9841 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009842 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009843 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009844 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009845 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9846 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9847 }
9848 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009849 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9850 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9851 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009852 }
9853}
9854
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009855sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009856{
9857 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009858
9859 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9860 {
9861 if(defined $TypeInfo{$LibVersion}{$Dupl})
9862 {
9863 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9864 { # duplicate
9865 return 0;
9866 }
9867 }
9868 }
9869
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009870 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9871
9872 if(isBuiltIn($THeader)) {
9873 return 0;
9874 }
9875
9876 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9877 return 0;
9878 }
9879
9880 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9881 return 0;
9882 }
9883
9884 if(selfTypedef($Tid, $LibVersion)) {
9885 return 0;
9886 }
9887
9888 if(not isTargetType($Tid, $LibVersion)) {
9889 return 0;
9890 }
9891
9892 return 0;
9893}
9894
9895sub isTargetType($$)
9896{
9897 my ($Tid, $LibVersion) = @_;
9898
9899 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9900 { # derived
9901 return 1;
9902 }
9903
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009904 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009905 { # NOTE: header is defined to source if undefined (DWARF dumps)
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009906 if(not is_target_header($THeader, $LibVersion))
9907 { # from target headers
9908 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009909 }
9910 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009911 else
9912 { # NOTE: if type is defined in source
9913 if($UsedDump{$LibVersion}{"Public"})
9914 {
9915 if(isPrivateABI($Tid, $LibVersion)) {
9916 return 0;
9917 }
9918 else {
9919 return 1;
9920 }
9921 }
9922 else {
9923 return 0;
9924 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +03009925 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009926
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +03009927 if($SkipInternalTypes)
9928 {
9929 if($TypeInfo{$LibVersion}{$Tid}{"Name"}=~/($SkipInternalTypes)/)
9930 {
9931 return 0;
9932 }
9933 }
9934
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009935 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009936}
9937
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009938sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009939{ # remove unused data types from the ABI dump
9940 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009941
9942 my %UsedType = ();
9943
9944 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009945 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009946 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009947 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009948 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009949 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009950 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009951 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009952 next;
9953 }
9954
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009955 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009956 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009957 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009958 {
9959 my %Tree = ();
9960 register_TypeUsage($Tid, \%Tree, $LibVersion);
9961
9962 my $Tmpl = 0;
9963 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9964 {
9965 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9966 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9967 {
9968 $Tmpl = 1;
9969 last;
9970 }
9971 }
9972 if(not $Tmpl)
9973 {
9974 foreach (keys(%Tree)) {
9975 $UsedType{$_} = 1;
9976 }
9977 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009978 }
9979 }
9980 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009981
9982 my %Delete = ();
9983
9984 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009985 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009986 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009987 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009988 next;
9989 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009990
9991 if($Kind eq "Extra")
9992 {
9993 my %Tree = ();
9994 register_TypeUsage($Tid, \%Tree, $LibVersion);
9995
9996 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9997 {
9998 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9999 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
10000 {
10001 $Delete{$Tid} = 1;
10002 last;
10003 }
10004 }
10005 }
10006 else
10007 {
10008 # remove type
10009 delete($TypeInfo{$LibVersion}{$Tid});
10010 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010011 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010012
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010013 if($Kind eq "Extra")
10014 { # remove duplicates
10015 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
10016 {
10017 if($UsedType{$Tid})
10018 { # All & Extended
10019 next;
10020 }
10021
10022 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10023
10024 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
10025 delete($TypeInfo{$LibVersion}{$Tid});
10026 }
10027 }
10028 }
10029
10030 foreach my $Tid (keys(%Delete))
10031 {
10032 delete($TypeInfo{$LibVersion}{$Tid});
10033 }
10034}
10035
10036sub check_Completeness($$)
10037{
10038 my ($Info, $LibVersion) = @_;
10039
10040 # data types
10041 if(defined $Info->{"Memb"})
10042 {
10043 foreach my $Pos (keys(%{$Info->{"Memb"}}))
10044 {
10045 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
10046 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
10047 }
10048 }
10049 }
10050 if(defined $Info->{"Base"})
10051 {
10052 foreach my $Bid (keys(%{$Info->{"Base"}})) {
10053 check_TypeInfo($Bid, $LibVersion);
10054 }
10055 }
10056 if(defined $Info->{"BaseType"}) {
10057 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
10058 }
10059 if(defined $Info->{"TParam"})
10060 {
10061 foreach my $Pos (keys(%{$Info->{"TParam"}}))
10062 {
10063 my $TName = $Info->{"TParam"}{$Pos}{"name"};
10064 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
10065 next;
10066 }
10067 if($TName eq "_BoolType") {
10068 next;
10069 }
10070 if($TName=~/\Asizeof\(/) {
10071 next;
10072 }
10073 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
10074 check_TypeInfo($Tid, $LibVersion);
10075 }
10076 else
10077 {
10078 if(defined $Debug) {
10079 printMsg("WARNING", "missed type $TName");
10080 }
10081 }
10082 }
10083 }
10084
10085 # symbols
10086 if(defined $Info->{"Param"})
10087 {
10088 foreach my $Pos (keys(%{$Info->{"Param"}}))
10089 {
10090 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10091 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10092 }
10093 }
10094 }
10095 if(defined $Info->{"Return"}) {
10096 check_TypeInfo($Info->{"Return"}, $LibVersion);
10097 }
10098 if(defined $Info->{"Class"}) {
10099 check_TypeInfo($Info->{"Class"}, $LibVersion);
10100 }
10101}
10102
10103sub check_TypeInfo($$)
10104{
10105 my ($Tid, $LibVersion) = @_;
10106
10107 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10108 return;
10109 }
10110 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10111
10112 if(defined $TypeInfo{$LibVersion}{$Tid})
10113 {
10114 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10115 printMsg("ERROR", "missed type name ($Tid)");
10116 }
10117 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10118 }
10119 else {
10120 printMsg("ERROR", "missed type id $Tid");
10121 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010122}
10123
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010124sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010125{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010126 my ($TypeId, $LibVersion) = @_;
10127 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010128 if($Type{"Type"} eq "Typedef")
10129 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010130 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010131 if($Base{"Type"}=~/Class|Struct/)
10132 {
10133 if($Type{"Name"} eq $Base{"Name"}) {
10134 return 1;
10135 }
10136 elsif($Type{"Name"}=~/::(\w+)\Z/)
10137 {
10138 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10139 { # QPointer<QWidget>::QPointer
10140 return 1;
10141 }
10142 }
10143 }
10144 }
10145 return 0;
10146}
10147
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010148sub addExtension($)
10149{
10150 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010151 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010152 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +030010153 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010154 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010155 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10156 $TName=~s/\A(struct|union|class|enum) //;
10157 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010158
10159 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10160 "Header" => "extended.h",
10161 "ShortName" => $Symbol,
10162 "MnglName" => $Symbol,
10163 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10164 );
10165
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010166 $ExtendedSymbols{$Symbol} = 1;
10167 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10168 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010169 }
10170 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010171 $ExtendedSymbols{"external_func_0"} = 1;
10172 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10173 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010174}
10175
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010176sub findMethod($$$)
10177{
10178 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010179 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010180 {
10181 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10182 return $VirtMethodInClass;
10183 }
10184 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10185 return $VirtMethodInBaseClasses;
10186 }
10187 }
10188 return "";
10189}
10190
10191sub findMethod_Class($$$)
10192{
10193 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010194 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010195 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10196 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10197 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10198 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10199 { # search for interface with the same parameters suffix (overridden)
10200 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10201 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010202 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10203 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010204 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10205 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010206 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10207 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10208 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10209 return $Candidate;
10210 }
10211 }
10212 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010213 else
10214 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010215 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10216 return $Candidate;
10217 }
10218 }
10219 }
10220 }
10221 return "";
10222}
10223
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010224sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010225{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010226 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010227 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010228 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010229 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10230 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010231 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010232 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010233 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010234 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10235 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010236 { # pure virtual D2-destructors are marked as "virt" in the dump
10237 # virtual D2-destructors are NOT marked as "virt" in the dump
10238 # both destructors are not presented in the v-table
10239 next;
10240 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010241 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010242 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10243 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010244 }
10245}
10246
10247sub registerOverriding($)
10248{
10249 my $LibVersion = $_[0];
10250 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010251 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010252 foreach my $ClassName (@Classes)
10253 {
10254 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10255 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010256 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10257 { # pure virtuals
10258 next;
10259 }
10260 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10261 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010262 {
10263 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10264 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10265 { # both overridden virtual methods
10266 # and implemented pure virtual methods
10267 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10268 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10269 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10270 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010271 }
10272 }
10273 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10274 delete($VirtualTable{$LibVersion}{$ClassName});
10275 }
10276 }
10277}
10278
10279sub setVirtFuncPositions($)
10280{
10281 my $LibVersion = $_[0];
10282 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10283 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010284 my ($Num, $Rel) = (1, 0);
10285
10286 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010287 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010288 if($UsedDump{$LibVersion}{"DWARF"}) {
10289 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10290 }
10291 else {
10292 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10293 }
10294 foreach my $VirtFunc (@Funcs)
10295 {
10296 if($UsedDump{$LibVersion}{"DWARF"}) {
10297 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10298 }
10299 else {
10300 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10301 }
10302
10303 # set relative positions
10304 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10305 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10306 { # relative position excluding added and removed virtual functions
10307 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10308 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10309 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10310 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010311 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010312 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010313 }
10314 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010315 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010316 {
10317 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010318 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010319 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010320 }
10321 }
10322}
10323
10324sub get_sub_classes($$$)
10325{
10326 my ($ClassId, $LibVersion, $Recursive) = @_;
10327 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10328 my @Subs = ();
10329 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10330 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010331 if($Recursive)
10332 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010333 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10334 push(@Subs, $SubSubId);
10335 }
10336 }
10337 push(@Subs, $SubId);
10338 }
10339 return @Subs;
10340}
10341
10342sub get_base_classes($$$)
10343{
10344 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010345 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010346 return () if(not defined $ClassType{"Base"});
10347 my @Bases = ();
10348 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10349 keys(%{$ClassType{"Base"}}))
10350 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010351 if($Recursive)
10352 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010353 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10354 push(@Bases, $SubBaseId);
10355 }
10356 }
10357 push(@Bases, $BaseId);
10358 }
10359 return @Bases;
10360}
10361
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010362sub getVTable_Model($$)
10363{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010364 my ($ClassId, $LibVersion) = @_;
10365 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10366 my @Elements = ();
10367 foreach my $BaseId (@Bases, $ClassId)
10368 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010369 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010370 {
10371 if(defined $VirtualTable{$LibVersion}{$BName})
10372 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010373 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10374 if($UsedDump{$LibVersion}{"DWARF"}) {
10375 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10376 }
10377 else {
10378 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10379 }
10380 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010381 push(@Elements, $VFunc);
10382 }
10383 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010384 }
10385 }
10386 return @Elements;
10387}
10388
10389sub getVShift($$)
10390{
10391 my ($ClassId, $LibVersion) = @_;
10392 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10393 my $VShift = 0;
10394 foreach my $BaseId (@Bases)
10395 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010396 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010397 {
10398 if(defined $VirtualTable{$LibVersion}{$BName}) {
10399 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10400 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010401 }
10402 }
10403 return $VShift;
10404}
10405
10406sub getShift($$)
10407{
10408 my ($ClassId, $LibVersion) = @_;
10409 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10410 my $Shift = 0;
10411 foreach my $BaseId (@Bases)
10412 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010413 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010414 {
10415 if($Size!=1)
10416 { # not empty base class
10417 $Shift+=$Size;
10418 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010419 }
10420 }
10421 return $Shift;
10422}
10423
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010424sub getVTable_Size($$)
10425{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010426 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010427 my $Size = 0;
10428 # three approaches
10429 if(not $Size)
10430 { # real size
10431 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10432 $Size = keys(%VTable);
10433 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010434 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010435 if(not $Size)
10436 { # shared library symbol size
10437 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10438 $Size /= $WORD_SIZE{$LibVersion};
10439 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010440 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010441 if(not $Size)
10442 { # model size
10443 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10444 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10445 }
10446 }
10447 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010448}
10449
10450sub isCopyingClass($$)
10451{
10452 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010453 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010454}
10455
10456sub isLeafClass($$)
10457{
10458 my ($ClassId, $LibVersion) = @_;
10459 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10460}
10461
10462sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010463{ # check structured type for public fields
10464 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010465}
10466
10467sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010468{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010469 my ($TypePtr, $Skip, $Start, $End) = @_;
10470 return 0 if(not $TypePtr);
10471 if($End==-1) {
10472 $End = keys(%{$TypePtr->{"Memb"}})-1;
10473 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030010474 foreach my $MemPos (sort {int($a)<=>int($b)} keys(%{$TypePtr->{"Memb"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010475 {
10476 if($Skip and $Skip->{$MemPos})
10477 { # skip removed/added fields
10478 next;
10479 }
10480 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10481 {
10482 if(isPublic($TypePtr, $MemPos)) {
10483 return ($MemPos+1);
10484 }
10485 }
10486 }
10487 return 0;
10488}
10489
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010490sub isReserved($)
10491{ # reserved fields == private
10492 my $MName = $_[0];
10493 if($MName=~/reserved|padding|f_spare/i) {
10494 return 1;
10495 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010496 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010497 return 1;
10498 }
10499 if($MName=~/(pad\d+)/i) {
10500 return 1;
10501 }
10502 return 0;
10503}
10504
10505sub isPublic($$)
10506{
10507 my ($TypePtr, $FieldPos) = @_;
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010508
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010509 return 0 if(not $TypePtr);
10510 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10511 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010512
10513 my $Access = $TypePtr->{"Memb"}{$FieldPos}{"access"};
10514 if($Access eq "private")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010515 { # by access in C++ language
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010516 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010517 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010518
10519 # by name in C language
10520 # TODO: add other methods to detect private members
10521 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030010522 if($MName=~/priv|abidata|parent_object|impl/i)
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010523 { # C-styled private data
10524 return 0;
10525 }
10526 if(lc($MName) eq "abi")
10527 { # ABI information/reserved field
10528 return 0;
10529 }
10530 if(isReserved($MName))
10531 { # reserved fields
10532 return 0;
10533 }
10534
10535 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010536}
10537
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010538sub getVTable_Real($$)
10539{
10540 my ($ClassName, $LibVersion) = @_;
10541 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10542 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010543 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010544 if(defined $Type{"VTable"}) {
10545 return %{$Type{"VTable"}};
10546 }
10547 }
10548 return ();
10549}
10550
10551sub cmpVTables($)
10552{
10553 my $ClassName = $_[0];
10554 my $Res = cmpVTables_Real($ClassName, 1);
10555 if($Res==-1) {
10556 $Res = cmpVTables_Model($ClassName);
10557 }
10558 return $Res;
10559}
10560
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010561sub cmpVTables_Model($)
10562{
10563 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010564 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010565 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010566 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010567 return 1;
10568 }
10569 }
10570 return 0;
10571}
10572
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010573sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010574{
10575 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010576 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10577 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010578 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010579 my %VTable_Old = getVTable_Real($ClassName, 1);
10580 my %VTable_New = getVTable_Real($ClassName, 2);
10581 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010582 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010583 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010584 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010585 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010586 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10587 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010588 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010589 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010590 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010591 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010592 my $Entry1 = $VTable_Old{$Offset};
10593 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010594 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010595 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010596 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010597 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010598
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010599 $Entry1 = simpleVEntry($Entry1);
10600 $Entry2 = simpleVEntry($Entry2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010601
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030010602 if($Entry1=~/ 0x/ or $Entry2=~/ 0x/)
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010603 { # NOTE: problem with vtable-dumper
10604 next;
10605 }
10606
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010607 if($Entry1 ne $Entry2)
10608 { # register as changed
10609 if($Entry1=~/::([^:]+)\Z/)
10610 {
10611 my $M1 = $1;
10612 if($Entry2=~/::([^:]+)\Z/)
10613 {
10614 my $M2 = $1;
10615 if($M1 eq $M2)
10616 { # overridden
10617 next;
10618 }
10619 }
10620 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010621 if(differentDumps("G"))
10622 {
10623 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10624 {
10625 # GCC 4.6.1: -0x00000000000000010
10626 # GCC 4.7.0: -16
10627 next;
10628 }
10629 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010630 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010631 }
10632 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010633 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010634}
10635
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010636sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010637{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010638 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010639 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10640 {
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010641 my $ClassId = $TName_Tid{1}{$ClassName};
10642 if(isPrivateABI($ClassId, 1)) {
10643 next;
10644 }
10645
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010646 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010647 { # already registered
10648 next;
10649 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010650 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010651 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010652 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010653 foreach my $Symbol (@Affected)
10654 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010655 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010656 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010657 "Target"=>$ClassName);
10658 }
10659 }
10660 }
10661}
10662
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010663sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010664{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010665 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010666 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010667 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010668 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010669 next if(not $ClassId);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010670
10671 if(isPrivateABI($ClassId, 1)) {
10672 next;
10673 }
10674
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010675 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010676 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010677 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010678 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010679 if($TName_Tid{1}{$ClassName}
10680 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010681 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010682 if(defined $CompleteSignature{1}{$Symbol}
10683 and $CompleteSignature{1}{$Symbol}{"Virt"})
10684 { # override some method in v.1
10685 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010686 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010687 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010688 }
10689 }
10690 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010691 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010692 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010693 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010694 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010695 if($TName_Tid{2}{$ClassName}
10696 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010697 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010698 if(defined $CompleteSignature{2}{$Symbol}
10699 and $CompleteSignature{2}{$Symbol}{"Virt"})
10700 { # override some method in v.2
10701 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010702 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010703 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010704 }
10705 }
10706 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010707 if($Level eq "Binary")
10708 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010709 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010710 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10711 { # check replacements, including pure virtual methods
10712 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10713 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010714 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010715 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10716 if($AddedPos==$RemovedPos)
10717 {
10718 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10719 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10720 last; # other methods will be reported as "added" or "removed"
10721 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010722 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010723 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10724 {
10725 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10726 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010727 next;
10728 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010729 my $ProblemType = "Virtual_Replacement";
10730 my @Affected = ($RemovedVFunc);
10731 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10732 { # pure methods
10733 if(not isUsedClass($ClassId, 1, $Level))
10734 { # not a parameter of some exported method
10735 next;
10736 }
10737 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010738
10739 # affected all methods (both virtual and non-virtual ones)
10740 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10741 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010742 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010743 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010744 foreach my $AffectedInt (@Affected)
10745 {
10746 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10747 { # affected exported methods only
10748 next;
10749 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010750 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10751 next;
10752 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010753 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10754 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010755 "Target"=>get_Signature($AddedVFunc, 2),
10756 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10757 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010758 }
10759 }
10760 }
10761 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010762 if(not checkDump(1, "2.0")
10763 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010764 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010765 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010766 return;
10767 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010768 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010769 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010770 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010771 next if(not $ClassId_Old);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010772
10773 if(isPrivateABI($ClassId_Old, 1)) {
10774 next;
10775 }
10776
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010777 if(not isCreatable($ClassId_Old, 1))
10778 { # skip classes without public constructors (including auto-generated)
10779 # example: class has only a private exported or private inline constructor
10780 next;
10781 }
10782 if($ClassName=~/>/)
10783 { # skip affected template instances
10784 next;
10785 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010786 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010787 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010788 if(not $ClassId_New) {
10789 next;
10790 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010791 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010792 if($Class_New{"Type"}!~/Class|Struct/)
10793 { # became typedef
10794 if($Level eq "Binary") {
10795 next;
10796 }
10797 if($Level eq "Source")
10798 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010799 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010800 if($Class_New{"Type"}!~/Class|Struct/) {
10801 next;
10802 }
10803 $ClassId_New = $Class_New{"Tid"};
10804 }
10805 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010806
10807 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10808 { # incomplete info in the ABI dump
10809 next;
10810 }
10811
10812
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010813 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10814 my @Bases_New = sort {$Class_New{"Base"}{$a}{"pos"}<=>$Class_New{"Base"}{$b}{"pos"}} keys(%{$Class_New{"Base"}});
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010815
10816 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10817 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10818
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010819 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010820 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10821 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010822 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10823 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010824 my $Shift_Old = getShift($ClassId_Old, 1);
10825 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010826 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010827 my ($Added, $Removed) = (0, 0);
10828 my @StableBases_Old = ();
10829 foreach my $BaseId (@Bases_Old)
10830 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010831 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010832 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010833 push(@StableBases_Old, $BaseId);
10834 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010835 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010836 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010837 { # removed base
10838 # excluding namespace::SomeClass to SomeClass renaming
10839 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010840 if($Level eq "Binary")
10841 { # Binary-level
10842 if($Shift_Old ne $Shift_New)
10843 { # affected fields
10844 if(havePubFields(\%Class_Old)) {
10845 $ProblemKind .= "_And_Shift";
10846 }
10847 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10848 $ProblemKind .= "_And_Size";
10849 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010850 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010851 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10852 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010853 { # affected v-table
10854 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010855 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010856 }
10857 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010858 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010859 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10860 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010861 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10862 {
10863 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10864 if($ProblemKind=~/VTable/) {
10865 $VTableChanged_M{$SubName}=1;
10866 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010867 }
10868 }
10869 foreach my $Interface (@Affected)
10870 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010871 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10872 next;
10873 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010874 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010875 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010876 "Target"=>$BaseName,
10877 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10878 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10879 "Shift"=>abs($Shift_New-$Shift_Old) );
10880 }
10881 $Removed+=1;
10882 }
10883 }
10884 my @StableBases_New = ();
10885 foreach my $BaseId (@Bases_New)
10886 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010887 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010888 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010889 push(@StableBases_New, $BaseId);
10890 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010891 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010892 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010893 { # added base
10894 # excluding namespace::SomeClass to SomeClass renaming
10895 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010896 if($Level eq "Binary")
10897 { # Binary-level
10898 if($Shift_Old ne $Shift_New)
10899 { # affected fields
10900 if(havePubFields(\%Class_Old)) {
10901 $ProblemKind .= "_And_Shift";
10902 }
10903 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10904 $ProblemKind .= "_And_Size";
10905 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010906 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010907 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10908 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010909 { # affected v-table
10910 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010911 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010912 }
10913 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010914 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010915 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10916 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010917 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10918 {
10919 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10920 if($ProblemKind=~/VTable/) {
10921 $VTableChanged_M{$SubName}=1;
10922 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010923 }
10924 }
10925 foreach my $Interface (@Affected)
10926 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010927 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10928 next;
10929 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010930 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010931 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010932 "Target"=>$BaseName,
10933 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10934 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10935 "Shift"=>abs($Shift_New-$Shift_Old) );
10936 }
10937 $Added+=1;
10938 }
10939 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010940 if($Level eq "Binary")
10941 { # Binary-level
10942 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010943 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10944 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010945 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010946 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010947 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010948 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010949 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010950 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10951 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010952 if($NewPos!=$OldPos)
10953 { # changed position of the base class
10954 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010955 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010956 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10957 next;
10958 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010959 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10960 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010961 "Target"=>$BaseName,
10962 "Old_Value"=>$OldPos-1,
10963 "New_Value"=>$NewPos-1 );
10964 }
10965 }
10966 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10967 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10968 { # became non-virtual base
10969 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10970 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010971 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10972 next;
10973 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010974 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10975 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010976 "Target"=>$BaseName );
10977 }
10978 }
10979 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10980 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10981 { # became virtual base
10982 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10983 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010984 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10985 next;
10986 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010987 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10988 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010989 "Target"=>$BaseName );
10990 }
10991 }
10992 }
10993 }
10994 # detect size changes in base classes
10995 if($Shift_Old!=$Shift_New)
10996 { # size of allocable class
10997 foreach my $BaseId (@StableBases_Old)
10998 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010999 my %BaseType = get_Type($BaseId, 1);
11000 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011001 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011002 if($Size_Old ne $Size_New
11003 and $Size_Old and $Size_New)
11004 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011005 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011006 if(isCopyingClass($BaseId, 1)) {
11007 $ProblemType = "Size_Of_Copying_Class";
11008 }
11009 elsif($AllocableClass{1}{$BaseType{"Name"}})
11010 {
11011 if($Size_New>$Size_Old)
11012 { # increased size
11013 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011014 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011015 else
11016 { # decreased size
11017 $ProblemType = "Size_Of_Allocable_Class_Decreased";
11018 if(not havePubFields(\%Class_Old))
11019 { # affected class has no public members
11020 next;
11021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011022 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011023 }
11024 next if(not $ProblemType);
11025 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
11026 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011027 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
11028 next;
11029 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011030 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
11031 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011032 "Target"=>$BaseType{"Name"},
11033 "Old_Size"=>$Size_Old*$BYTE_SIZE,
11034 "New_Size"=>$Size_New*$BYTE_SIZE );
11035 }
11036 }
11037 }
11038 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011039 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011040 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011041 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011042 { # compare virtual tables size in base classes
11043 my $VShift_Old = getVShift($ClassId_Old, 1);
11044 my $VShift_New = getVShift($ClassId_New, 2);
11045 if($VShift_Old ne $VShift_New)
11046 { # changes in the base class or changes in the list of base classes
11047 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
11048 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
11049 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011050 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011051 foreach my $BaseId (@AllBases_Old)
11052 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011053 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011054 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011055 { # lost base
11056 next;
11057 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011058 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
11059 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011060 if($VSize_Old!=$VSize_New)
11061 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011062 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011063 { # TODO: affected non-virtual methods?
11064 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011065 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
11066 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011067 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011068 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011069 { # skip interfaces that have not changed the absolute virtual position
11070 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011071 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011072 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
11073 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011074 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011075 $VTableChanged_M{$BaseType{"Name"}} = 1;
11076 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011077 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
11078 { # the reason of the layout change: added virtual functions
11079 next if($VirtualReplacement{$VirtFunc});
11080 my $ProblemType = "Added_Virtual_Method";
11081 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
11082 $ProblemType = "Added_Pure_Virtual_Method";
11083 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011084 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011085 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011086 "Target"=>get_Signature($VirtFunc, 2) );
11087 }
11088 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
11089 { # the reason of the layout change: removed virtual functions
11090 next if($VirtualReplacement{$VirtFunc});
11091 my $ProblemType = "Removed_Virtual_Method";
11092 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11093 $ProblemType = "Removed_Pure_Virtual_Method";
11094 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011095 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011096 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011097 "Target"=>get_Signature($VirtFunc, 1) );
11098 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011099 }
11100 }
11101 }
11102 }
11103 }
11104 }
11105 }
11106}
11107
11108sub isCreatable($$)
11109{
11110 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011111 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011112 or isCopyingClass($ClassId, $LibVersion)) {
11113 return 1;
11114 }
11115 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11116 { # Fix for incomplete data: if this class has
11117 # a base class then it should also has a constructor
11118 return 1;
11119 }
11120 if($ReturnedClass{$LibVersion}{$ClassId})
11121 { # returned by some method of this class
11122 # or any other class
11123 return 1;
11124 }
11125 return 0;
11126}
11127
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011128sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011129{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011130 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011131 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11132 { # parameter of some exported method
11133 return 1;
11134 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011135 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11136 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011137 { # method from target class
11138 return 1;
11139 }
11140 return 0;
11141}
11142
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011143sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011144{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011145 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011146 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011147 # - virtual
11148 # - pure-virtual
11149 # - non-virtual
11150 if($CompleteSignature{1}{$Interface}{"Data"})
11151 { # global data is not affected
11152 return;
11153 }
11154 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011155 if(not $Class_Id) {
11156 return;
11157 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011158 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011159 if(cmpVTables_Real($CName, 1)==0)
11160 { # no changes
11161 return;
11162 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011163 $CheckedTypes{$Level}{$CName} = 1;
11164 if($Level eq "Binary")
11165 { # Binary-level
11166 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11167 and not isUsedClass($Class_Id, 1, $Level))
11168 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011169 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011170 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011171 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011172 }
11173 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11174 {
11175 if(defined $VirtualTable{2}{$CName}{$Func}
11176 and defined $CompleteSignature{2}{$Func})
11177 {
11178 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11179 and $CompleteSignature{2}{$Func}{"PureVirt"})
11180 { # became pure virtual
11181 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11182 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011183 "Target"=>get_Signature_M($Func, 1) );
11184 $VTableChanged_M{$CName} = 1;
11185 }
11186 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11187 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11188 { # became non-pure virtual
11189 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11190 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011191 "Target"=>get_Signature_M($Func, 1) );
11192 $VTableChanged_M{$CName} = 1;
11193 }
11194 }
11195 }
11196 if($Level eq "Binary")
11197 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011198 # check virtual table structure
11199 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11200 {
11201 next if($Interface eq $AddedVFunc);
11202 next if($VirtualReplacement{$AddedVFunc});
11203 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11204 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11205 { # pure virtual methods affect all others (virtual and non-virtual)
11206 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011207 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011208 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011209 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011210 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011211 elsif(not defined $VirtualTable{1}{$CName}
11212 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011213 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011214 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011215 { # became polymorphous class, added v-table pointer
11216 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011217 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011218 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011219 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011220 }
11221 else
11222 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011223 my $VSize_Old = getVTable_Size($CName, 1);
11224 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011225 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011226 if(isCopyingClass($Class_Id, 1))
11227 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11228 my $ProblemType = "Added_Virtual_Method";
11229 if(isLeafClass($Class_Id, 1)) {
11230 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11231 }
11232 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11233 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011234 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011235 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011236 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011237 else
11238 {
11239 my $ProblemType = "Added_Virtual_Method";
11240 if(isLeafClass($Class_Id, 1)) {
11241 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11242 }
11243 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11244 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011245 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011246 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011247 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011248 }
11249 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011250 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11251 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011252 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011253 if(defined $VirtualTable{1}{$CName}
11254 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011255 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011256 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11257 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011258
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011259 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011260 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011261 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11262 foreach my $ASymbol (@Affected)
11263 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011264 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11265 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011266 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011267 next;
11268 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011269 }
11270 $CheckedSymbols{$Level}{$ASymbol} = 1;
11271 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11272 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011273 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011274 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011275 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011276 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011277 }
11278 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011279 else {
11280 # safe
11281 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011282 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011283 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11284 {
11285 next if($VirtualReplacement{$RemovedVFunc});
11286 if($RemovedVFunc eq $Interface
11287 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11288 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011289 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011290 next;
11291 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011292 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011293 { # became non-polymorphous class, removed v-table pointer
11294 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11295 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011296 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011297 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011298 }
11299 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11300 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11301 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011302 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011303 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011304 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11305 next;
11306 }
11307 my $VPos_New = -1;
11308 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011309 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011310 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11311 }
11312 else
11313 {
11314 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011315 next;
11316 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011317 }
11318 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11319 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11320 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11321 {
11322 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11323 foreach my $ASymbol (@Affected)
11324 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011325 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11326 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011327 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011328 next;
11329 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011330 }
11331 my $ProblemType = "Removed_Virtual_Method";
11332 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11333 $ProblemType = "Removed_Pure_Virtual_Method";
11334 }
11335 $CheckedSymbols{$Level}{$ASymbol} = 1;
11336 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11337 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011338 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011339 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011340 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011341 }
11342 }
11343 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011344 }
11345 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011346 else
11347 { # Source-level
11348 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011349 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011350 next if($Interface eq $AddedVFunc);
11351 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011352 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011353 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11354 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011355 "Target"=>get_Signature($AddedVFunc, 2) );
11356 }
11357 }
11358 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11359 {
11360 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11361 {
11362 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11363 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011364 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011365 }
11366 }
11367 }
11368}
11369
11370sub find_MemberPair_Pos_byName($$)
11371{
11372 my ($Member_Name, $Pair_Type) = @_;
11373 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11374 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11375 {
11376 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11377 {
11378 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11379 $Name=~s/\A[_]+|[_]+\Z//g;
11380 if($Name eq $Member_Name) {
11381 return $MemberPair_Pos;
11382 }
11383 }
11384 }
11385 return "lost";
11386}
11387
11388sub find_MemberPair_Pos_byVal($$)
11389{
11390 my ($Member_Value, $Pair_Type) = @_;
11391 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11392 {
11393 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11394 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11395 return $MemberPair_Pos;
11396 }
11397 }
11398 return "lost";
11399}
11400
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011401sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011402{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011403 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011404 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011405 if( $_->{"T1"} eq $_[0]
11406 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011407 {
11408 return 1;
11409 }
11410 }
11411 return 0;
11412}
11413
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011414sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011415{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011416 my %IDs = (
11417 "T1" => $_[0],
11418 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011419 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011420 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011421}
11422
11423sub isRenamed($$$$$)
11424{
11425 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11426 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11427 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011428 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011429 if(not defined $Type2->{"Memb"}{$MemPos}) {
11430 return "";
11431 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011432 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011433 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011434
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011435 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11436 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011437 if($MemberPair_Pos_Rev eq "lost")
11438 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011439 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11440 { # base type match
11441 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011442 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011443 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11444 { # exact type match
11445 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011446 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011447 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11448 { # size match
11449 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011450 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011451 if(isReserved($Pair_Name))
11452 { # reserved fields
11453 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011454 }
11455 }
11456 return "";
11457}
11458
11459sub isLastElem($$)
11460{
11461 my ($Pos, $TypeRef) = @_;
11462 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030011463 if($Name=~/last|count|max|total|num/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011464 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11465 return 1;
11466 }
11467 elsif($Name=~/END|NLIMITS\Z/)
11468 { # __RLIMIT_NLIMITS
11469 return 1;
11470 }
11471 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11472 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11473 { # NImageFormats, NColorRoles
11474 return 1;
11475 }
11476 return 0;
11477}
11478
11479sub nonComparable($$)
11480{
11481 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011482
11483 my $N1 = $T1->{"Name"};
11484 my $N2 = $T2->{"Name"};
11485
11486 $N1=~s/\A(struct|union|enum) //;
11487 $N2=~s/\A(struct|union|enum) //;
11488
11489 if($N1 ne $N2
11490 and not isAnon($N1)
11491 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011492 { # different names
11493 if($T1->{"Type"} ne "Pointer"
11494 or $T2->{"Type"} ne "Pointer")
11495 { # compare base types
11496 return 1;
11497 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011498 if($N1!~/\Avoid\s*\*/
11499 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011500 {
11501 return 1;
11502 }
11503 }
11504 elsif($T1->{"Type"} ne $T2->{"Type"})
11505 { # different types
11506 if($T1->{"Type"} eq "Class"
11507 and $T2->{"Type"} eq "Struct")
11508 { # "class" to "struct"
11509 return 0;
11510 }
11511 elsif($T2->{"Type"} eq "Class"
11512 and $T1->{"Type"} eq "Struct")
11513 { # "struct" to "class"
11514 return 0;
11515 }
11516 else
11517 { # "class" to "enum"
11518 # "union" to "class"
11519 # ...
11520 return 1;
11521 }
11522 }
11523 return 0;
11524}
11525
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011526sub isOpaque($)
11527{
11528 my $T = $_[0];
11529 if(not defined $T->{"Memb"})
11530 {
11531 return 1;
11532 }
11533 return 0;
11534}
11535
11536sub removeVPtr($)
11537{ # support for old ABI dumps
11538 my $TPtr = $_[0];
11539 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11540 if($#Pos>=1)
11541 {
11542 foreach my $Pos (0 .. $#Pos-1)
11543 {
11544 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11545 }
11546 delete($TPtr->{"Memb"}{$#Pos});
11547 }
11548}
11549
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011550sub isPrivateABI($$)
11551{
11552 my ($TypeId, $LibVersion) = @_;
11553
11554 if($CheckPrivateABI) {
11555 return 0;
11556 }
11557
11558 if(defined $TypeInfo{$LibVersion}{$TypeId}{"PrivateABI"}) {
11559 return 1;
11560 }
11561
11562 return 0;
11563}
11564
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011565sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011566{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011567 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011568 return {} if(not $Type1_Id or not $Type2_Id);
11569
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011570 if(defined $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011571 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011572 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011573 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011574
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011575 my %Type1 = get_Type($Type1_Id, 1);
11576 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011577 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011578 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011579 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011580
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011581 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11582 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011583
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011584 if(defined $UsedDump{1}{"DWARF"})
11585 {
11586 if($Type1_Pure{"Name"} eq "__unknown__"
11587 or $Type2_Pure{"Name"} eq "__unknown__")
11588 { # Error ABI dump
11589 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11590 }
11591 }
11592
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011593 if(isPrivateABI($Type1_Id, 1)) {
11594 return {};
11595 }
11596
11597 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
11598 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11599
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011600 my %SubProblems = ();
11601
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011602 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11603 {
11604 if($Type1_Pure{"Type"}=~/Struct|Union/
11605 and $Type2_Pure{"Type"}=~/Struct|Union/)
11606 {
11607 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11608 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011609 if(not defined $UsedDump{1}{"DWARF"}
11610 and not defined $UsedDump{2}{"DWARF"})
11611 {
11612 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11613 "Target"=>$Type1_Pure{"Name"},
11614 "Type_Name"=>$Type1_Pure{"Name"} );
11615 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011616
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011617 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011618 }
11619 }
11620 }
11621
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011622 if(not $Type1_Pure{"Size"}
11623 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011624 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011625 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11626 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11627 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011628 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011629 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011630 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011631 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011632 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011633 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011634 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011635 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11636 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11637 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011638
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011639 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11640 return {};
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011641 }
11642
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011643 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11644 { # support for old ABI dumps
11645 # _vptr field added in 3.0
11646 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11647 {
11648 if(defined $Type2_Pure{"Memb"}
11649 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11650 {
11651 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11652 delete($Type2_Pure{"Memb"}{0});
11653 }
11654 else {
11655 removeVPtr(\%Type2_Pure);
11656 }
11657 }
11658 }
11659 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11660 {
11661 if(defined $Type1_Pure{"Memb"}
11662 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11663 {
11664 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11665 delete($Type1_Pure{"Memb"}{0});
11666 }
11667 else {
11668 removeVPtr(\%Type1_Pure);
11669 }
11670 }
11671 }
11672 }
11673
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011674 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11675 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011676
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011677 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011678 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11679 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011680 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011681 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11682 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011683 if($Base_1{"Name"} ne $Base_2{"Name"})
11684 {
11685 if(differentDumps("G")
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030011686 or differentDumps("V")
11687 or $SkipTypedefUncover)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011688 { # different GCC versions or different dumps
11689 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11690 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11691 # std::__va_list and __va_list
11692 $Base_1{"Name"}=~s/\A(\w+::)+//;
11693 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011694 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11695 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011696 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011697 }
11698 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11699 and $Base_1{"Name"} ne $Base_2{"Name"})
11700 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011701 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011702 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011703 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011704 {
11705 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11706 "Target"=>$Typedef_1{"Name"},
11707 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011708 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11709 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11710 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011711 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11712 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011713
11714 if(defined $UsedDump{1}{"DWARF"})
11715 {
11716 if($Base1_Pure{"Name"}=~/\b__unknown__\b/
11717 or $Base2_Pure{"Name"}=~/\b__unknown__\b/)
11718 { # Error ABI dump
11719 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11720 }
11721 }
11722
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011723 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011724 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011725 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11726 {
11727 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11728 "Target"=>$Typedef_1{"Name"},
11729 "Type_Name"=>$Typedef_1{"Name"},
11730 "Old_Value"=>$Base_1{"Name"},
11731 "New_Value"=>$Base_2{"Name"} );
11732 }
11733 else
11734 {
11735 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11736 "Target"=>$Typedef_1{"Name"},
11737 "Type_Name"=>$Typedef_1{"Name"},
11738 "Old_Value"=>$Base_1{"Name"},
11739 "New_Value"=>$Base_2{"Name"} );
11740 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011741 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011742 }
11743 }
11744 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11745 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011746 my $TT1 = $Type1_Pure{"Type"};
11747 my $TT2 = $Type2_Pure{"Type"};
11748
11749 if($TT1 ne $TT2
11750 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011751 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011752 my $Short1 = $Type1_Pure{"Name"};
11753 my $Short2 = $Type2_Pure{"Name"};
11754
11755 $Short1=~s/\A\Q$TT1\E //ig;
11756 $Short2=~s/\A\Q$TT2\E //ig;
11757
11758 if($Short1 eq $Short2)
11759 {
11760 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11761 "Target"=>$Type1_Pure{"Name"},
11762 "Type_Name"=>$Type1_Pure{"Name"},
11763 "Old_Value"=>lc($Type1_Pure{"Type"}),
11764 "New_Value"=>lc($Type2_Pure{"Type"}) );
11765 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011766 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011767 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011768 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011769
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011770 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011771
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011772 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11773 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11774 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11775 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011776 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011777 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011778 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011779 {
11780 my $ProblemKind = "DataType_Size";
11781 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011782 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011783 {
11784 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11785 $ProblemKind = "Size_Of_Copying_Class";
11786 }
11787 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11788 {
11789 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11790 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11791 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011792 else
11793 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011794 # descreased size of allocable class
11795 # it has no special effects
11796 }
11797 }
11798 }
11799 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11800 "Target"=>$Type1_Pure{"Name"},
11801 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011802 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011803 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011804 }
11805 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011806 if(defined $Type1_Pure{"BaseType"}
11807 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011808 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011809 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11810 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011811 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011812 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11813 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011814 }
11815 }
11816 }
11817 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11818 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11819 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11820 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11821 { # detect removed and renamed fields
11822 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11823 next if(not $Member_Name);
11824 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);
11825 if($MemberPair_Pos eq "lost")
11826 {
11827 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11828 {
11829 if(isUnnamed($Member_Name))
11830 { # support for old-version dumps
11831 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011832 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011833 next;
11834 }
11835 }
11836 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11837 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011838 $RenamedField{$Member_Pos} = $RenamedTo;
11839 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011840 }
11841 else
11842 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011843 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011844 }
11845 }
11846 elsif($Type1_Pure{"Type"} eq "Enum")
11847 {
11848 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11849 next if($Member_Value1 eq "");
11850 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11851 if($MemberPair_Pos ne "lost")
11852 { # renamed
11853 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11854 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11855 if($MemberPair_Pos_Rev eq "lost")
11856 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011857 $RenamedField{$Member_Pos} = $RenamedTo;
11858 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011859 }
11860 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011861 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011862 }
11863 }
11864 else
11865 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011866 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011867 }
11868 }
11869 }
11870 else
11871 { # related
11872 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11873 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11874 }
11875 }
11876 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11877 { # detect added fields
11878 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11879 next if(not $Member_Name);
11880 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);
11881 if($MemberPair_Pos eq "lost")
11882 {
11883 if(isUnnamed($Member_Name))
11884 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011885 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011886 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011887 next;
11888 }
11889 }
11890 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11891 {
11892 if(not $RenamedField_Rev{$Member_Pos})
11893 { # added
11894 $AddedField{$Member_Pos}=1;
11895 }
11896 }
11897 }
11898 }
11899 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11900 { # detect moved fields
11901 my (%RelPos, %RelPosName, %AbsPos) = ();
11902 my $Pos = 0;
11903 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11904 { # relative positions in 1st version
11905 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11906 next if(not $Member_Name);
11907 if(not $RemovedField{$Member_Pos})
11908 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011909 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011910 $RelPosName{1}{$Pos} = $Member_Name;
11911 $AbsPos{1}{$Pos++} = $Member_Pos;
11912 }
11913 }
11914 $Pos = 0;
11915 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11916 { # relative positions in 2nd version
11917 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11918 next if(not $Member_Name);
11919 if(not $AddedField{$Member_Pos})
11920 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011921 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011922 $RelPosName{2}{$Pos} = $Member_Name;
11923 $AbsPos{2}{$Pos++} = $Member_Pos;
11924 }
11925 }
11926 foreach my $Member_Name (keys(%{$RelPos{1}}))
11927 {
11928 my $RPos1 = $RelPos{1}{$Member_Name};
11929 my $AbsPos1 = $NameToPosA{$Member_Name};
11930 my $Member_Name2 = $Member_Name;
11931 if(my $RenamedTo = $RenamedField{$AbsPos1})
11932 { # renamed
11933 $Member_Name2 = $RenamedTo;
11934 }
11935 my $RPos2 = $RelPos{2}{$Member_Name2};
11936 if($RPos2 ne "" and $RPos1 ne $RPos2)
11937 { # different relative positions
11938 my $AbsPos2 = $NameToPosB{$Member_Name2};
11939 if($AbsPos1 ne $AbsPos2)
11940 { # different absolute positions
11941 my $ProblemType = "Moved_Field";
11942 if(not isPublic(\%Type1_Pure, $AbsPos1))
11943 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011944 if($Level eq "Source") {
11945 next;
11946 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011947 $ProblemType = "Moved_Private_Field";
11948 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011949 if($Level eq "Binary"
11950 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011951 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011952 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011953 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011954 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011955 if($MemSize1 ne $MemSize2) {
11956 $ProblemType .= "_And_Size";
11957 }
11958 }
11959 if($ProblemType eq "Moved_Private_Field") {
11960 next;
11961 }
11962 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11963 "Target"=>$Member_Name,
11964 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011965 "Old_Value"=>$RPos1,
11966 "New_Value"=>$RPos2 );
11967 }
11968 }
11969 }
11970 }
11971 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011972 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011973 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11974 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011975 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011976 if(my $RenamedTo = $RenamedField{$Member_Pos})
11977 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011978 if(defined $Constants{2}{$Member_Name})
11979 {
11980 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11981 { # define OLD NEW
11982 next; # Safe
11983 }
11984 }
11985
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011986 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11987 {
11988 if(isPublic(\%Type1_Pure, $Member_Pos))
11989 {
11990 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11991 "Target"=>$Member_Name,
11992 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011993 "Old_Value"=>$Member_Name,
11994 "New_Value"=>$RenamedTo );
11995 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011996 elsif(isReserved($Member_Name))
11997 {
11998 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11999 "Target"=>$Member_Name,
12000 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012001 "Old_Value"=>$Member_Name,
12002 "New_Value"=>$RenamedTo );
12003 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012004 }
12005 elsif($Type1_Pure{"Type"} eq "Enum")
12006 {
12007 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
12008 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
12009 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012010 "Old_Value"=>$Member_Name,
12011 "New_Value"=>$RenamedTo );
12012 }
12013 }
12014 elsif($RemovedField{$Member_Pos})
12015 { # removed
12016 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12017 {
12018 my $ProblemType = "Removed_Field";
12019 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012020 or isUnnamed($Member_Name))
12021 {
12022 if($Level eq "Source") {
12023 next;
12024 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012025 $ProblemType = "Removed_Private_Field";
12026 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012027 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012028 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012029 {
12030 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
12031 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012032 if(getOffset($MNum-1, \%Type1_Pure, $TypeInfo{1}, getArch(1), $WORD_SIZE{1})!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012033 { # changed offset
12034 $ProblemType .= "_And_Layout";
12035 }
12036 }
12037 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
12038 { # affected size
12039 $ProblemType .= "_And_Size";
12040 }
12041 }
12042 if($ProblemType eq "Removed_Private_Field") {
12043 next;
12044 }
12045 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12046 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012047 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012048 }
12049 elsif($Type2_Pure{"Type"} eq "Union")
12050 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012051 if($Level eq "Binary"
12052 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012053 {
12054 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
12055 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012056 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012057 }
12058 else
12059 {
12060 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
12061 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012062 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012063 }
12064 }
12065 elsif($Type1_Pure{"Type"} eq "Enum")
12066 {
12067 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
12068 "Target"=>$Member_Name,
12069 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012070 "Old_Value"=>$Member_Name );
12071 }
12072 }
12073 else
12074 { # changed
12075 my $MemberPair_Pos = $RelatedField{$Member_Pos};
12076 if($Type1_Pure{"Type"} eq "Enum")
12077 {
12078 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
12079 next if($Member_Value1 eq "");
12080 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
12081 next if($Member_Value2 eq "");
12082 if($Member_Value1 ne $Member_Value2)
12083 {
12084 my $ProblemType = "Enum_Member_Value";
12085 if(isLastElem($Member_Pos, \%Type1_Pure)) {
12086 $ProblemType = "Enum_Last_Member_Value";
12087 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012088 if($SkipConstants{1}{$Member_Name}) {
12089 $ProblemType = "Enum_Private_Member_Value";
12090 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012091 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12092 "Target"=>$Member_Name,
12093 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012094 "Old_Value"=>$Member_Value1,
12095 "New_Value"=>$Member_Value2 );
12096 }
12097 }
12098 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
12099 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012100 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
12101 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
12102
12103 if($Access1 ne "private"
12104 and $Access2 eq "private")
12105 {
12106 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12107 "Target"=>$Member_Name,
12108 "Type_Name"=>$Type1_Pure{"Name"});
12109 }
12110 elsif($Access1 ne "protected"
12111 and $Access1 ne "private"
12112 and $Access2 eq "protected")
12113 {
12114 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12115 "Target"=>$Member_Name,
12116 "Type_Name"=>$Type1_Pure{"Name"});
12117 }
12118
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012119 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12120 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012121 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012122 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12123 $SizeV1 = $BSize1;
12124 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012125 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012126 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12127 $SizeV2 = $BSize2;
12128 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012129 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12130 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012131 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012132 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012133 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012134 {
12135 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12136 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12137 { # field size change (including anon-structures and unions)
12138 # - same types
12139 # - unnamed types
12140 # - bitfields
12141 my $ProblemType = "Field_Size";
12142 if(not isPublic(\%Type1_Pure, $Member_Pos)
12143 or isUnnamed($Member_Name))
12144 { # should not be accessed by applications, goes to "Low Severity"
12145 # example: "abidata" members in GStreamer types
12146 $ProblemType = "Private_".$ProblemType;
12147 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012148 if(not isMemPadded($Member_Pos, $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012149 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012150 if($Type2_Pure{"Type"} ne "Union"
12151 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012152 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012153 if(getOffset($MNum-1, \%Type1_Pure, $TypeInfo{1}, getArch(1), $WORD_SIZE{1})!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012154 { # changed offset
12155 $ProblemType .= "_And_Layout";
12156 }
12157 }
12158 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12159 $ProblemType .= "_And_Type_Size";
12160 }
12161 }
12162 if($ProblemType eq "Private_Field_Size")
12163 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012164 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012165 if($ProblemType eq "Field_Size")
12166 {
12167 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12168 { # Low severity
12169 $ProblemType = "Struct_Field_Size_Increased";
12170 }
12171 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012172 if($ProblemType)
12173 { # register a problem
12174 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12175 "Target"=>$Member_Name,
12176 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012177 "Old_Size"=>$SizeV1,
12178 "New_Size"=>$SizeV2);
12179 }
12180 }
12181 }
12182 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12183 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12184 { # do NOT check bitfield type changes
12185 next;
12186 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012187 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012188 {
12189 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12190 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12191 {
12192 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12193 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012194 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012195 }
12196 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12197 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12198 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012199 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012200 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012201 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012202 }
12203 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012204 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12205 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012206 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012207 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12208 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012209
12210 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012211 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012212 or $ProblemType eq "Field_Type_And_Size"
12213 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012214 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012215 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012216 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012217 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012218 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012219 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012220 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012221 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012222 }
12223 }
12224 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12225 {
12226 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012227 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012228 }
12229 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012230 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012231 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012232 }
12233 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12234 {
12235 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012236 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012237 }
12238 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012239 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012240 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012241 }
12242 }
12243 }
12244
12245 if($Level eq "Source")
12246 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012247 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012248 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012249 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12250 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012251
12252 if($ProblemType eq "Field_Type")
12253 {
12254 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012255 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012256 }
12257 }
12258 }
12259 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012260
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012261 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012262 {
12263 my $ProblemType_Init = $ProblemType;
12264 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012265 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012266 if(not isPublic(\%Type1_Pure, $Member_Pos)
12267 or isUnnamed($Member_Name)) {
12268 $ProblemType = "Private_".$ProblemType;
12269 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012270 if(not isMemPadded($Member_Pos, $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012271 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012272 if($Type2_Pure{"Type"} ne "Union"
12273 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012274 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012275 if(getOffset($MNum-1, \%Type1_Pure, $TypeInfo{1}, getArch(1), $WORD_SIZE{1})!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012276 { # changed offset
12277 $ProblemType .= "_And_Layout";
12278 }
12279 }
12280 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12281 $ProblemType .= "_And_Type_Size";
12282 }
12283 }
12284 }
12285 else
12286 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012287 # TODO: Private_Field_Type rule?
12288
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012289 if(not isPublic(\%Type1_Pure, $Member_Pos)
12290 or isUnnamed($Member_Name)) {
12291 next;
12292 }
12293 }
12294 if($ProblemType eq "Private_Field_Type_And_Size")
12295 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012296 }
12297 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12298 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012299 "Type_Name"=>$Type1_Pure{"Name"});
12300
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012301 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012302 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012303 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012304 }
12305 }
12306 if(not isPublic(\%Type1_Pure, $Member_Pos))
12307 { # do NOT check internal type changes
12308 next;
12309 }
12310 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012311 { # checking member type changes
12312 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12313
12314 my %DupProblems = ();
12315
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012316 foreach my $Sub_SubProblemType (sort keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012317 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012318 foreach my $Sub_SubLocation (sort {length($a)<=>length($b)} sort keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012319 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012320 if(not defined $AllAffected)
12321 {
12322 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12323 next;
12324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012325 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012326
12327 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12328 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12329
12330 if(not defined $AllAffected)
12331 {
12332 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012333 }
12334 }
12335 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012336
12337 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012338 }
12339 }
12340 }
12341 }
12342 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12343 { # checking added members, public and private
12344 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12345 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012346 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012347 if($AddedField{$Member_Pos})
12348 { # added
12349 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12350 {
12351 my $ProblemType = "Added_Field";
12352 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012353 or isUnnamed($Member_Name))
12354 {
12355 if($Level eq "Source") {
12356 next;
12357 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012358 $ProblemType = "Added_Private_Field";
12359 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012360 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012361 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012362 {
12363 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12364 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012365 if(getOffset($MNum-1, \%Type2_Pure, $TypeInfo{2}, getArch(2), $WORD_SIZE{2})!=getOffset($RelatedField_Rev{$MNum-1}, \%Type1_Pure, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012366 { # changed offset
12367 $ProblemType .= "_And_Layout";
12368 }
12369 }
12370 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12371 $ProblemType .= "_And_Size";
12372 }
12373 }
12374 if($ProblemType eq "Added_Private_Field")
12375 { # skip added private fields
12376 next;
12377 }
12378 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12379 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012380 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012381 }
12382 elsif($Type2_Pure{"Type"} eq "Union")
12383 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012384 if($Level eq "Binary"
12385 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012386 {
12387 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12388 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012389 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012390 }
12391 else
12392 {
12393 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12394 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012395 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012396 }
12397 }
12398 elsif($Type2_Pure{"Type"} eq "Enum")
12399 {
12400 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12401 next if($Member_Value eq "");
12402 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12403 "Target"=>$Member_Name,
12404 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012405 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012406 }
12407 }
12408 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012409
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012410 if($Type1_Pure{"Type"} eq "FuncPtr")
12411 {
12412 foreach my $PPos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Param"}}))
12413 {
12414 if(not defined $Type2_Pure{"Param"}{$PPos}) {
12415 next;
12416 }
12417
12418 my $PT1 = $Type1_Pure{"Param"}{$PPos}{"type"};
12419 my $PT2 = $Type2_Pure{"Param"}{$PPos}{"type"};
12420
12421 my $PName = "p".$PPos;
12422
12423 my $FP_SubProblems = mergeTypes($PT1, $PT2, $Level);
12424 my %DupProblems = ();
12425
12426 foreach my $FP_SubProblemType (keys(%{$FP_SubProblems}))
12427 {
12428 foreach my $FP_SubLocation (keys(%{$FP_SubProblems->{$FP_SubProblemType}}))
12429 {
12430 if(not defined $AllAffected)
12431 {
12432 if(defined $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}}) {
12433 next;
12434 }
12435 }
12436
12437 my $NewLocation = ($FP_SubLocation)?$PName."->".$FP_SubLocation:$PName;
12438 $SubProblems{$FP_SubProblemType}{$NewLocation} = $FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation};
12439
12440 if(not defined $AllAffected)
12441 {
12442 $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}} = 1;
12443 }
12444 }
12445 }
12446
12447 %DupProblems = ();
12448 }
12449 }
12450
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012451 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012452 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012453}
12454
12455sub isUnnamed($) {
12456 return $_[0]=~/\Aunnamed\d+\Z/;
12457}
12458
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012459sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012460{
12461 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012462 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12463 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12464 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12465 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012466 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012467 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012468 }
12469 return $TypeName;
12470}
12471
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012472sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012473{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012474 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012475 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012476 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12477 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012478 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012479 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12480 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012481 return () if(not $Type{"Type"});
12482 if($Type{"Type"} ne $Type_Type)
12483 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012484 return () if(not $Type{"BaseType"});
12485 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012486 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012487 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012488 return %Type;
12489}
12490
12491my %TypeSpecAttributes = (
12492 "Const" => 1,
12493 "Volatile" => 1,
12494 "ConstVolatile" => 1,
12495 "Restrict" => 1,
12496 "Typedef" => 1
12497);
12498
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012499sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012500{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012501 my ($TypeId, $Info) = @_;
12502 if(not $TypeId or not $Info
12503 or not $Info->{$TypeId}) {
12504 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012505 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012506 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12507 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12508 }
12509 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012510 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012511 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012512 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012513 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012514 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012515 return %Type;
12516}
12517
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012518sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012519{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012520 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012521 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012522 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12523 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012524 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012525 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12526 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012527 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12528 my $PLevel = 0;
12529 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12530 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012531 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012532 return $PLevel if(not $Type{"BaseType"});
12533 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12534 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12535 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012536}
12537
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012538sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012539{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012540 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012541 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012542 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12543 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012544 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012545 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12546 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012547 return %Type if(not $Type{"BaseType"});
12548 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012549 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012550 return %Type;
12551}
12552
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012553sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012554{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012555 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012556 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012557 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12558 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012559 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012560 my $Qual = "";
12561 if($Type{"Type"} eq "Pointer") {
12562 $Qual .= "*";
12563 }
12564 elsif($Type{"Type"} eq "Ref") {
12565 $Qual .= "&";
12566 }
12567 elsif($Type{"Type"} eq "ConstVolatile") {
12568 $Qual .= "const volatile";
12569 }
12570 elsif($Type{"Type"} eq "Const"
12571 or $Type{"Type"} eq "Volatile"
12572 or $Type{"Type"} eq "Restrict") {
12573 $Qual .= lc($Type{"Type"});
12574 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012575 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012576 return $BQual.$Qual;
12577}
12578
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012579sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012580{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012581 my ($TypeId, $Info) = @_;
12582 if(not $TypeId or not $Info
12583 or not $Info->{$TypeId}) {
12584 return ();
12585 }
12586 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012587 return %Type if(not $Type{"BaseType"});
12588 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012589 {
12590 if($Info->{$BTid}) {
12591 return %{$Info->{$BTid}};
12592 }
12593 else { # something is going wrong
12594 return ();
12595 }
12596 }
12597 else {
12598 return %Type;
12599 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012600}
12601
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012602sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012603{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012604 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012605 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012606 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12607 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012608}
12609
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012610sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012611{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012612 my $Symbol = $_[0];
12613 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12614}
12615
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012616sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012617 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12618}
12619
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012620sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012621{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012622 my ($SInfo, $LibVersion) = @_;
12623
12624 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012625 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012626 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012627 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012628 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012629 return 1;
12630 }
12631 }
12632 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012633 if(my $ShortName = $SInfo->{"ShortName"})
12634 {
12635 if(index($ShortName,"<")!=-1
12636 and index($ShortName,">")!=-1) {
12637 return 1;
12638 }
12639 }
12640
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012641 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012642}
12643
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012644sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012645{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012646 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012647 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012648 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012649 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012650 { # class specialization
12651 return 1;
12652 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012653 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012654 { # method specialization
12655 return 1;
12656 }
12657 }
12658 return 0;
12659}
12660
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012661sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012662{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012663 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012664
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012665 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012666 { # non-public global data
12667 return 0;
12668 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012669
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012670 if(defined $SkipInternalSymbols)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012671 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012672 return 0 if($Symbol=~/($SkipInternalSymbols)/);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012673 }
12674
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012675 if($Symbol=~/\A_Z/)
12676 {
12677 if($Symbol=~/[CD][3-4]E/) {
12678 return 0;
12679 }
12680 }
12681
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012682 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012683 { # support for old ABI dumps in --headers-only mode
12684 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12685 {
12686 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12687 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012688 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012689 if(not $PType or $PType eq "Unknown") {
12690 return 0;
12691 }
12692 }
12693 }
12694 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012695 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012696 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012697 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12698
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012699 if($SkipSymbols{$LibVersion}{$Symbol})
12700 { # user defined symbols to ignore
12701 return 0;
12702 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012703
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012704 if($SymbolsListPath and not $SymbolsList{$Symbol})
12705 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012706 if(not $TargetHeadersPath or not $Header
12707 or not is_target_header($Header, 1))
12708 { # -symbols-list | -headers-list
12709 return 0;
12710 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012711 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012712
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012713 if($AppPath and not $SymbolsList_App{$Symbol})
12714 { # user defined symbols (in application)
12715 return 0;
12716 }
12717
12718 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12719
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012720 if($ClassId)
12721 {
12722 if(not isTargetType($ClassId, $LibVersion)) {
12723 return 0;
12724 }
12725 }
12726
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012727 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12728 if(not $NameSpace and $ClassId)
12729 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012730 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012731 }
12732 if($NameSpace)
12733 { # user defined namespaces to ignore
12734 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12735 return 0;
12736 }
12737 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12738 { # nested namespaces
12739 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12740 return 0;
12741 }
12742 }
12743 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012744 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012745 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012746 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012747 { # --skip-headers or <skip_headers> (not <skip_including>)
12748 if($Skip==1) {
12749 return 0;
12750 }
12751 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012752 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012753 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012754 { # user defined types
12755 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12756
12757 if(not $TypesList{$CName})
12758 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012759 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12760 {
12761 $CName=~s/\A\Q$NS\E\:\://g;
12762 }
12763
12764 if(not $TypesList{$CName})
12765 {
12766 my $Found = 0;
12767
12768 while($CName=~s/\:\:.+?\Z//)
12769 {
12770 if($TypesList{$CName})
12771 {
12772 $Found = 1;
12773 last;
12774 }
12775 }
12776
12777 if(not $Found) {
12778 return 0;
12779 }
12780 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012781 }
12782 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012783
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012784 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12785 { # non-target symbols
12786 return 0;
12787 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012788 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012789 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012790 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12791 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012792 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012793 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12794 { # inline virtual methods
12795 if($Type=~/InlineVirt/) {
12796 return 1;
12797 }
12798 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12799 if(not $Allocable)
12800 { # check bases
12801 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12802 {
12803 if(not isCopyingClass($DCId, $LibVersion))
12804 { # exists a derived class without default c-tor
12805 $Allocable=1;
12806 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012807 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012808 }
12809 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012810 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012811 return 0;
12812 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012813 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012814 else
12815 { # inline non-virtual methods
12816 return 0;
12817 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012818 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012819 }
12820 }
12821 return 1;
12822}
12823
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012824sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012825{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012826 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012827 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12828 {
12829 if(link_symbol($Symbol, 1, "+Deps"))
12830 { # linker can find a new symbol
12831 # in the old-version library
12832 # So, it's not a new symbol
12833 next;
12834 }
12835 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012836 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012837 next;
12838 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012839 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012840 }
12841}
12842
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012843sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012844{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012845 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012846 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12847 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012848 if(link_symbol($Symbol, 2, "+Deps"))
12849 { # linker can find an old symbol
12850 # in the new-version library
12851 next;
12852 }
12853 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012854 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012855 next;
12856 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012857 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012858 }
12859}
12860
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012861sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012862{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012863 my $Level = $_[0];
12864 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012865 { # checking added symbols
12866 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012867 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012868 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012869 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012870 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012871 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012872 { # checking removed symbols
12873 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012874 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012875 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012876 { # skip v-tables for templates, that should not be imported by applications
12877 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012878 if(my $CName = $VTableClass{$Symbol})
12879 {
12880 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12881 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012882 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012883 next;
12884 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012885 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012886
12887 if($SkipSymbols{1}{$Symbol})
12888 { # user defined symbols to ignore
12889 next;
12890 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012891 }
12892 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012893 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012894 }
12895 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12896 { # symbols for pure virtual methods cannot be called by clients
12897 next;
12898 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012899 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012900 }
12901}
12902
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012903sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012904{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012905 my ($LibVersion, $V) = @_;
12906 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12907 return $Cache{"checkDump"}{$LibVersion}{$V};
12908 }
12909 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012910}
12911
12912sub detectAdded_H($)
12913{
12914 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012915 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12916 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012917 if($Level eq "Source")
12918 { # remove symbol version
12919 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12920 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012921
12922 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12923 { # skip artificial constructors
12924 next;
12925 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012926 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012927 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12928 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012929 next;
12930 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012931 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012932 next;
12933 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012934 if(not defined $CompleteSignature{1}{$Symbol}
12935 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12936 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012937 if($UsedDump{2}{"SrcBin"})
12938 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012939 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012940 { # support for old and different (!) ABI dumps
12941 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12942 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012943 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012944 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012945 {
12946 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12947 {
12948 if($Lang eq "C")
12949 { # support for old ABI dumps: missed extern "C" functions
12950 next;
12951 }
12952 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012953 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012954 else
12955 {
12956 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012957 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012958 next;
12959 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012960 }
12961 }
12962 }
12963 }
12964 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012965 }
12966 }
12967}
12968
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012969sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012970{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012971 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012972 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12973 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012974 if($Level eq "Source")
12975 { # remove symbol version
12976 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12977 $Symbol=$SN;
12978 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012979 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12980 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012981 next;
12982 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012983 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012984 next;
12985 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012986 if(not defined $CompleteSignature{2}{$Symbol}
12987 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012988 {
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030012989 if(defined $UsedDump{1}{"DWARF"}
Andrey Ponomarenkoe30363a2016-10-07 19:40:50 +030012990 and defined $UsedDump{2}{"DWARF"}
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030012991 and $Level eq "Source")
12992 {
12993 if(link_symbol($Symbol, 2, "-Deps"))
12994 { # not present in debug-info,
12995 # but present as ELF symbol
12996 next;
12997 }
12998 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012999 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013000 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013001 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013002 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013003 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
13004 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013005 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013006 if($CheckHeadersOnly)
13007 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013008 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
13009 {
13010 if($Lang eq "C")
13011 { # support for old ABI dumps: missed extern "C" functions
13012 next;
13013 }
13014 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013015 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013016 else
13017 {
13018 if(not link_symbol($Symbol, 1, "-Deps"))
13019 { # skip removed inline symbols
13020 next;
13021 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013022 }
13023 }
13024 }
13025 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040013026 if(not checkDump(1, "2.15"))
13027 {
13028 if($Symbol=~/_IT_E\Z/)
13029 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
13030 next;
13031 }
13032 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013033 if(not $CompleteSignature{1}{$Symbol}{"Class"})
13034 {
13035 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
13036 {
13037 if(defined $Constants{2}{$Short})
13038 {
13039 my $Val = $Constants{2}{$Short}{"Value"};
13040 if(defined $Func_ShortName{2}{$Val})
13041 { # old name defined to new
13042 next;
13043 }
13044 }
13045 }
13046
13047 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013048 $RemovedInt{$Level}{$Symbol} = 1;
13049 if($Level eq "Source")
13050 { # search for a source-compatible equivalent
13051 setAlternative($Symbol, $Level);
13052 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013053 }
13054 }
13055}
13056
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013057sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013058{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013059 my $Level = $_[0];
13060 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013061 { # checking added symbols
13062 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013063 next if($CompleteSignature{2}{$Symbol}{"Private"});
13064 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013065 if($Level eq "Binary")
13066 {
13067 if($CompleteSignature{2}{$Symbol}{"InLine"})
13068 {
13069 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
13070 { # skip inline non-virtual functions
13071 next;
13072 }
13073 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013074 }
13075 else
13076 { # Source
13077 if($SourceAlternative_B{$Symbol}) {
13078 next;
13079 }
13080 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013081 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013082 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013083 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013084 { # checking removed symbols
13085 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013086 next if($CompleteSignature{1}{$Symbol}{"Private"});
13087 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013088 if($Level eq "Binary")
13089 {
13090 if($CompleteSignature{1}{$Symbol}{"InLine"})
13091 {
13092 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
13093 { # skip inline non-virtual functions
13094 next;
13095 }
13096 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013097 }
13098 else
13099 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013100 if(my $Alt = $SourceAlternative{$Symbol})
13101 {
13102 if(defined $CompleteSignature{1}{$Alt}
13103 and $CompleteSignature{1}{$Symbol}{"Const"})
13104 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013105 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013106 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013107 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013108 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013109 }
13110 else
13111 { # do NOT show removed symbol
13112 next;
13113 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013114 }
13115 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013116 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013117 }
13118}
13119
13120sub addParamNames($)
13121{
13122 my $LibraryVersion = $_[0];
13123 return if(not keys(%AddIntParams));
13124 my $SecondVersion = $LibraryVersion==1?2:1;
13125 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13126 {
13127 next if(not keys(%{$AddIntParams{$Interface}}));
13128 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013129 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013130 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13131 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013132 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013133 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13134 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13135 {
13136 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13137 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13138 }
13139 }
13140 else {
13141 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13142 }
13143 }
13144 }
13145 }
13146}
13147
13148sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013149{ # detect changed typedefs to show
13150 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013151 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13152 {
13153 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013154 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13155 if(not $BName1 or isAnon($BName1)) {
13156 next;
13157 }
13158 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13159 if(not $BName2 or isAnon($BName2)) {
13160 next;
13161 }
13162 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013163 $ChangedTypedef{$Typedef} = 1;
13164 }
13165 }
13166}
13167
13168sub get_symbol_suffix($$)
13169{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013170 my ($Symbol, $Full) = @_;
13171 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013172 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013173 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013174 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013175 if(not $Full) {
13176 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13177 }
13178 return $Suffix;
13179}
13180
13181sub get_symbol_prefix($$)
13182{
13183 my ($Symbol, $LibVersion) = @_;
13184 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13185 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13186 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013187 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013188 }
13189 return $ShortName;
13190}
13191
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013192sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013193{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013194 my $Symbol = $_[0];
13195 my $PSymbol = $Symbol;
13196 if(not defined $CompleteSignature{2}{$PSymbol}
13197 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13198 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13199 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013200 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013201 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013202 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013203 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013204 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13205 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013206 {
13207 if(defined $CompleteSignature{2}{$PSymbol}
13208 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13209 {
13210 $SourceAlternative{$Symbol} = $PSymbol;
13211 $SourceAlternative_B{$PSymbol} = $Symbol;
13212 if(not defined $CompleteSignature{1}{$PSymbol}
13213 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13214 $SourceReplacement{$Symbol} = $PSymbol;
13215 }
13216 }
13217 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013218 }
13219 else
13220 {
13221 foreach my $Sp ("KV", "VK", "K", "V")
13222 {
13223 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13224 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13225 {
13226 if(defined $CompleteSignature{2}{$PSymbol}
13227 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13228 {
13229 $SourceAlternative{$Symbol} = $PSymbol;
13230 $SourceAlternative_B{$PSymbol} = $Symbol;
13231 if(not defined $CompleteSignature{1}{$PSymbol}
13232 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13233 $SourceReplacement{$Symbol} = $PSymbol;
13234 }
13235 }
13236 }
13237 $PSymbol = $Symbol;
13238 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013239 }
13240 }
13241 }
13242 return "";
13243}
13244
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013245sub getSymKind($$)
13246{
13247 my ($Symbol, $LibVersion) = @_;
13248 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13249 {
13250 return "Global_Data";
13251 }
13252 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13253 {
13254 return "Method";
13255 }
13256 return "Function";
13257}
13258
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013259sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013260{
13261 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013262 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013263
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013264 mergeBases($Level);
13265
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013266 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013267 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013268 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013269 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013270 next;
13271 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013272 if(defined $CompleteSignature{1}{$Symbol}
13273 and $CompleteSignature{1}{$Symbol}{"Header"})
13274 { # double-check added symbol
13275 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013276 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013277 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013278 next;
13279 }
13280 if($Symbol=~/\A(_Z|\?)/)
13281 { # C++
13282 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13283 }
13284 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13285 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013286 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13287 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013288 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013289 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013290 {
13291 if($TName_Tid{1}{$AffectedClass_Name})
13292 { # class should exist in previous version
13293 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13294 { # old v-table is NOT copied by old applications
13295 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13296 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013297 "Target"=>get_Signature($Symbol, 2),
13298 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013299 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013300 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013301 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013302 }
13303 }
13304 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013305 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13306 { # check all removed exported symbols
13307 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013308 next;
13309 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013310 if(defined $CompleteSignature{2}{$Symbol}
13311 and $CompleteSignature{2}{$Symbol}{"Header"})
13312 { # double-check removed symbol
13313 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013314 }
13315 if($CompleteSignature{1}{$Symbol}{"Private"})
13316 { # skip private methods
13317 next;
13318 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013319 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013320 next;
13321 }
13322 $CheckedSymbols{$Level}{$Symbol} = 1;
13323 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13324 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013325 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13326 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013327 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013328 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13329 {
13330 if($TName_Tid{2}{$AffectedClass_Name})
13331 { # class should exist in newer version
13332 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13333 { # old v-table is NOT copied by old applications
13334 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13335 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013336 "Target"=>get_Signature($OverriddenMethod, 1),
13337 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013338 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013339 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013340 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013341 }
13342 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013343 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013344 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013345 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013346 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013347 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013348 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013349 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013350 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013351 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013352 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013353 {
13354 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13355 "Target"=>$tr_name{$Symbol},
13356 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013357 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013358 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013359 else
13360 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013361 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013362 "Target"=>$tr_name{$Symbol},
13363 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013364 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013365 }
13366 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013367 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013368 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013369 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013370 {
13371 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13372 "Target"=>$tr_name{$Symbol},
13373 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013374 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013375 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013376 else
13377 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013378 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013379 "Target"=>$tr_name{$Symbol},
13380 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013381 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013382 }
13383 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013384 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13385 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13386 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13387 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13388 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013389 {
13390 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013391 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013392 $ProblemType = "Global_Data_Symbol_Changed_Type";
13393 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013394 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13395 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013396 "Old_Type"=>$RTName1,
13397 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013398 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013399 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013400 }
13401 }
13402 }
13403 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013404 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013405 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013406 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013407 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013408 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013409 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013410 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013411 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13412 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013413 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013414 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013415 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013416 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013417 }
13418 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013419 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13420 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013421 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013422 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013423 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013424 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013425 }
13426 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013427 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013428 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013429 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013430 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013431 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013432 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013433 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013434 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013435 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013436 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013437 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013438 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013439 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013440 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013441 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013442 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013443 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013444 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013445 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013446 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013447 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013448 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013449 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013450 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013451 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013452 { # "volatile" to non-"volatile"
13453
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013454 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013455 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013456 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013457 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013458 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013459 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013460 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013461 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013462 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013463 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013464 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013465 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013466 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013467 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013468 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013469 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013470 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013471 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13472 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013473 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013474 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013475 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013476 }
13477 }
13478 }
13479 }
13480 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013481 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13482 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013483 $CurrentSymbol = $Symbol;
13484
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013485 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13486 if($Level eq "Source")
13487 { # remove symbol version
13488 $Symbol=$SN;
13489 }
13490 else
13491 { # Binary
13492 if(not $SV)
13493 { # symbol without version
13494 if(my $VSym = $SymVer{1}{$Symbol})
13495 { # the symbol is linked with versioned symbol
13496 if($CompleteSignature{2}{$VSym}{"MnglName"})
13497 { # show report for symbol@ver only
13498 next;
13499 }
13500 elsif(not link_symbol($VSym, 2, "-Deps"))
13501 { # changed version: sym@v1 to sym@v2
13502 # do NOT show report for symbol
13503 next;
13504 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013505 }
13506 }
13507 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013508 my $PSymbol = $Symbol;
13509 if($Level eq "Source"
13510 and my $S = $SourceReplacement{$Symbol})
13511 { # take a source-compatible replacement function
13512 $PSymbol = $S;
13513 }
13514 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013515 { # private symbols
13516 next;
13517 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013518 if(not defined $CompleteSignature{1}{$Symbol}
13519 or not defined $CompleteSignature{2}{$PSymbol})
13520 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013521 next;
13522 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013523 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13524 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13525 { # no mangled name
13526 next;
13527 }
13528 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13529 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013530 { # without a header
13531 next;
13532 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013533
13534 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13535 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13536 { # became pure
13537 next;
13538 }
13539 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13540 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13541 { # became non-pure
13542 next;
13543 }
13544
13545 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13546 { # exported, target, inline virtual and pure virtual
13547 next;
13548 }
13549 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13550 { # exported, target, inline virtual and pure virtual
13551 next;
13552 }
13553
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013554 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013555 {
13556 if($CompleteSignature{1}{$Symbol}{"Data"}
13557 and $CompleteSignature{2}{$PSymbol}{"Data"})
13558 {
13559 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13560 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13561 if(defined $Value1)
13562 {
13563 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13564 if(defined $Value2)
13565 {
13566 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13567 if($Value1 ne $Value2)
13568 {
13569 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13570 "Old_Value"=>$Value1,
13571 "New_Value"=>$Value2,
13572 "Target"=>get_Signature($Symbol, 1) );
13573 }
13574 }
13575 }
13576 }
13577 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013578
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013579 if($CompleteSignature{2}{$PSymbol}{"Private"})
13580 {
13581 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13582 "Target"=>get_Signature_M($PSymbol, 2) );
13583 }
13584 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13585 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13586 {
13587 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13588 "Target"=>get_Signature_M($PSymbol, 2) );
13589 }
13590 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13591 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13592 {
13593 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13594 "Target"=>get_Signature_M($PSymbol, 2) );
13595 }
13596
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013597 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013598 mergeVirtualTables($Symbol, $Level);
13599
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013600 if($COMPILE_ERRORS)
13601 { # if some errors occurred at the compiling stage
13602 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013603 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013604 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013605 { # missed information about parameters in newer version
13606 next;
13607 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013608 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013609 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013610 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013611 next;
13612 }
13613 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013614 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013615 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013616 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013617 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13618 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013619 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13620 "Target"=>get_Signature($Symbol, 1)
13621 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013622 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013623 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013624 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13625 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013626 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013627 "Target"=>get_Signature($Symbol, 1)
13628 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013629 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013630 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13631 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013632 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013633 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013634 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013635 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13636 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13637 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013638 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013639 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013640 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13641 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013642 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013643 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013644 my $ProblemType = "Virtual_Method_Position";
13645 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13646 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013647 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013648 if(isUsedClass($Class_Id, 1, $Level))
13649 {
13650 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013651 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013652 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013653 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13654 next;
13655 }
13656 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013657 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013658 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13659 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013660 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013661 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013662 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013663 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013664 }
13665 }
13666 }
13667 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013668 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13669 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013670 { # do NOT check type changes in pure virtuals
13671 next;
13672 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013673 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013674 if($Symbol=~/\A(_Z|\?)/
13675 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013676 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013677 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013678 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013679 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013680 }
13681 }
13682 else
13683 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013684 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013685 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013686 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013687 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13688 last if($PType2_Name eq "...");
13689 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13690 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013691 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013692 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013693 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013694 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13695 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013696 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13697 $ParamPos_Prev = "lost";
13698 }
13699 }
13700 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013701 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013702 }
13703 if($ParamPos_Prev eq "lost")
13704 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013705 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013706 {
13707 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013708 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013709 $ProblemType = "Added_Unnamed_Parameter";
13710 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013711 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013712 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013713 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013714 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013715 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013716 }
13717 else
13718 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013719 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013720 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013721 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013722 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13723 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013724 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013725 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013726 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013727 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013728 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013729 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013730 "Param_Type"=>$PType2_Name,
13731 "Old_Value"=>$PName_Old,
13732 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013733 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013734 }
13735 }
13736 else
13737 {
13738 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013739 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013740 $ProblemType = "Added_Middle_Unnamed_Parameter";
13741 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013742 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013743 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013744 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013745 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013746 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013747 }
13748 }
13749 }
13750 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013751 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013752 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013753 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013754 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013755 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013756 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013757 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013758 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013759 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013760 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13761 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013762 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013763 }
13764 }
13765 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013766 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013767 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013768 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013769 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13770 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013771 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13772 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013773 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013774 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013775 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013776 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13777 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013778 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13779 $ParamPos_New = "lost";
13780 }
13781 }
13782 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013783 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013784 }
13785 if($ParamPos_New eq "lost")
13786 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013787 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013788 {
13789 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013790 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013791 $ProblemType = "Removed_Unnamed_Parameter";
13792 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013793 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013794 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013795 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013796 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013797 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013798 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013799 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013800 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013801 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013802 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013803 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013804 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013805 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013806 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013807 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013808 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013809 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013810 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013811 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013812 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013813 "Old_Value"=>$PName,
13814 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013815 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013816 }
13817 }
13818 else
13819 {
13820 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013821 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013822 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13823 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013824 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013825 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013826 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013827 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013828 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013829 }
13830 }
13831 }
13832 }
13833 }
13834 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013835 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13836 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013837 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013838
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013839 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013840 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013841 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13842 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013843 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013844
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013845 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013846 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013847 if($SubProblemType eq "Return_Type_And_Size") {
13848 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13849 }
13850 elsif($SubProblemType eq "Return_Type_Format") {
13851 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13852 }
13853 else {
13854 $ProblemTypes{"Global_Data_Type"} = 1;
13855 }
13856
13857 # quals
13858 if($SubProblemType eq "Return_Type"
13859 or $SubProblemType eq "Return_Type_And_Size"
13860 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013861 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013862 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13863 { # const to non-const
13864 if($RR==2) {
13865 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13866 }
13867 else {
13868 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13869 }
13870 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013871 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013872 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13873 { # non-const to const
13874 if($RA==2) {
13875 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13876 }
13877 else {
13878 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13879 }
13880 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013881 }
13882 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013883 }
13884 else
13885 {
13886 # quals
13887 if($SubProblemType eq "Return_Type"
13888 or $SubProblemType eq "Return_Type_And_Size"
13889 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013890 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013891 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013892 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013893 if(addedQual($Old_Value, $New_Value, "volatile"))
13894 {
13895 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13896 if($Level ne "Source"
13897 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13898 $ProblemTypes{"Return_Type"} = 1;
13899 }
13900 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013901 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013902 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13903 {
13904 if($RA==2) {
13905 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13906 }
13907 else {
13908 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13909 }
13910 if($Level ne "Source"
13911 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13912 $ProblemTypes{"Return_Type"} = 1;
13913 }
13914 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013915 }
13916 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013917 if($Level eq "Binary"
13918 and not $CompleteSignature{1}{$Symbol}{"Data"})
13919 {
13920 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13921 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13922 { # if one of the architectures is unknown
13923 # then set other arhitecture to unknown too
13924 ($Arch1, $Arch2) = ("unknown", "unknown");
13925 }
13926 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013927 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013928 {
13929 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13930 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13931 }
13932 else
13933 {
13934 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13935 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13936 }
13937
13938 if($SubProblemType eq "Return_Type_Became_Void")
13939 {
13940 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13941 { # parameters stack has been affected
13942 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013943 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013944 }
13945 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013946 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013947 }
13948 }
13949 }
13950 elsif($SubProblemType eq "Return_Type_From_Void")
13951 {
13952 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13953 { # parameters stack has been affected
13954 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013955 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013956 }
13957 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013958 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013959 }
13960 }
13961 }
13962 elsif($SubProblemType eq "Return_Type"
13963 or $SubProblemType eq "Return_Type_And_Size"
13964 or $SubProblemType eq "Return_Type_Format")
13965 {
13966 if($Conv1{"Method"} ne $Conv2{"Method"})
13967 {
13968 if($Conv1{"Method"} eq "stack")
13969 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013970 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013971 }
13972 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013973 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013974 }
13975 }
13976 else
13977 {
13978 if($Conv1{"Method"} eq "reg")
13979 {
13980 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13981 {
13982 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013983 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013984 }
13985 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013986 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013987 }
13988 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013989 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013990 }
13991 }
13992 }
13993 }
13994 }
13995 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013996
13997 if(not keys(%ProblemTypes))
13998 { # default
13999 $ProblemTypes{$SubProblemType} = 1;
14000 }
14001
14002 foreach my $ProblemType (keys(%ProblemTypes))
14003 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014004 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014005 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014006 }
14007 if($ReturnType1_Id and $ReturnType2_Id)
14008 {
14009 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014010 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
14011
14012 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014013
14014 if($CompleteSignature{1}{$Symbol}{"Data"})
14015 {
14016 if($Level eq "Binary")
14017 {
14018 if(get_PLevel($ReturnType1_Id, 1)==0)
14019 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014020 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014021 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014022
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014023 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
14024 {
14025 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014026 {
14027 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
14028 {
14029 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
14030 last;
14031 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014032 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014033 }
14034 }
14035 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014036 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014037 {
14038 if(defined $GlobalDataObject{1}{$Symbol}
14039 and defined $GlobalDataObject{2}{$Symbol})
14040 {
14041 my $Old_Size = $GlobalDataObject{1}{$Symbol};
14042 my $New_Size = $GlobalDataObject{2}{$Symbol};
14043 if($Old_Size!=$New_Size)
14044 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014045 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014046 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014047 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014048 }
14049 }
14050 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014051 }
14052 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014053
14054 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014055 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014056 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014057 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014058 my $NewLocation = "retval";
14059 if($SubLocation and $SubLocation ne "retval") {
14060 $NewLocation = "retval->".$SubLocation;
14061 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014062 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
14063 }
14064 }
14065
14066 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
14067 {
14068 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
14069 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014070 my $NewLocation = "retval";
14071 if($SubLocation and $SubLocation ne "retval") {
14072 $NewLocation = "retval->".$SubLocation;
14073 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014074 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014075 }
14076 }
14077 }
14078
14079 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014080 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
14081 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
14082 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014083 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014084 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014085 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
14086 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014087 if($ThisPtr1_Id and $ThisPtr2_Id)
14088 {
14089 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014090 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
14091 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014092 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014093 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014094 {
14095 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014096 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014097 }
14098 }
14099 }
14100 }
14101 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014102 if($Level eq "Binary") {
14103 mergeVTables($Level);
14104 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014105 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14106 $CheckedSymbols{$Level}{$Symbol} = 1;
14107 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014108}
14109
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014110sub rmQuals($$)
14111{
14112 my ($Value, $Qual) = @_;
14113 if(not $Qual) {
14114 return $Value;
14115 }
14116 if($Qual eq "all")
14117 { # all quals
14118 $Qual = "const|volatile|restrict";
14119 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014120 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014121 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014122 }
14123 return $Value;
14124}
14125
14126sub cmpBTypes($$$$)
14127{
14128 my ($T1, $T2, $V1, $V2) = @_;
14129 $T1 = uncover_typedefs($T1, $V1);
14130 $T2 = uncover_typedefs($T2, $V2);
14131 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14132}
14133
14134sub addedQual($$$)
14135{
14136 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014137 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014138}
14139
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014140sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014141{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014142 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014143 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014144}
14145
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014146sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014147{
14148 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14149 $Old_Value = uncover_typedefs($Old_Value, $V1);
14150 $New_Value = uncover_typedefs($New_Value, $V2);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014151
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014152 if($Old_Value eq $New_Value)
14153 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014154 return 0;
14155 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014156 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014157 { # without a qual
14158 return 0;
14159 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014160 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014161 { # became non-qual
14162 return 1;
14163 }
14164 else
14165 {
14166 my @BQ1 = getQualModel($Old_Value, $Qual);
14167 my @BQ2 = getQualModel($New_Value, $Qual);
14168 foreach (0 .. $#BQ1)
14169 { # removed qual
14170 if($BQ1[$_]==1
14171 and $BQ2[$_]!=1)
14172 {
14173 return 2;
14174 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014175 }
14176 }
14177 return 0;
14178}
14179
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014180sub getQualModel($$)
14181{
14182 my ($Value, $Qual) = @_;
14183 if(not $Qual) {
14184 return $Value;
14185 }
14186
14187 # cleaning
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014188 while($Value=~/(\w+)/)
14189 {
14190 my $W = $1;
14191
14192 if($W eq $Qual) {
14193 $Value=~s/\b$W\b/\@/g;
14194 }
14195 else {
14196 $Value=~s/\b$W\b//g;
14197 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014198 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014199
14200 $Value=~s/\@/$Qual/g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014201 $Value=~s/[^\*\&\w]+//g;
14202
14203 # modeling
14204 # int*const*const == 011
14205 # int**const == 001
14206 my @Model = ();
14207 my @Elems = split(/[\*\&]/, $Value);
14208 if(not @Elems) {
14209 return (0);
14210 }
14211 foreach (@Elems)
14212 {
14213 if($_ eq $Qual) {
14214 push(@Model, 1);
14215 }
14216 else {
14217 push(@Model, 0);
14218 }
14219 }
14220
14221 return @Model;
14222}
14223
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014224my %StringTypes = map {$_=>1} (
14225 "char*",
14226 "char const*"
14227);
14228
14229my %CharTypes = map {$_=>1} (
14230 "char",
14231 "char const"
14232);
14233
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014234sub showVal($$$)
14235{
14236 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014237 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014238 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014239 if(substr($Value, 0, 2) eq "_Z")
14240 {
14241 if(my $Unmangled = $tr_name{$Value}) {
14242 return $Unmangled;
14243 }
14244 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014245 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014246 { # strings
14247 return "\"$Value\"";
14248 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014249 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014250 { # characters
14251 return "\'$Value\'";
14252 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014253 if($Value eq "")
14254 { # other
14255 return "\'\'";
14256 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014257 return $Value;
14258}
14259
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014260sub getRegs($$$)
14261{
14262 my ($LibVersion, $Symbol, $Pos) = @_;
14263
14264 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14265 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014266 my %Regs = ();
14267 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14268 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014269 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014270 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14271 }
14272 }
14273
14274 return join(", ", sort keys(%Regs));
14275 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014276 elsif(defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}
14277 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}
14278 and not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}{"offset"})
14279 {
14280 return "unknown";
14281 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014282
14283 return undef;
14284}
14285
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014286sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014287{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014288 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014289 if(not $Symbol) {
14290 return;
14291 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014292 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14293 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14294 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14295 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014296 if(not $PType1_Id
14297 or not $PType2_Id) {
14298 return;
14299 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014300
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014301 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014302 { # do not merge "this"
14303 if($PName1 eq "this" or $PName2 eq "this") {
14304 return;
14305 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014306 }
14307
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014308 my %Type1 = get_Type($PType1_Id, 1);
14309 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014310
14311 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14312
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014313 my %BaseType1 = get_BaseType($PType1_Id, 1);
14314 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014315
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014316 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014317
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014318 if($Level eq "Binary")
14319 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014320 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014321 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14322 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14323 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14324 {
14325 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014326 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014327 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014328 }
14329 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14330 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14331 {
14332 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014333 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014334 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014335 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014336 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014337
14338 if(defined $UsedDump{1}{"DWARF"}
14339 and defined $UsedDump{2}{"DWARF"})
14340 {
14341 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14342 {
14343 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14344 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014345
14346 if($Old_Regs ne "unknown"
14347 and $New_Regs ne "unknown")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014348 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014349 if($Old_Regs and $New_Regs)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014350 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014351 if($Old_Regs ne $New_Regs)
14352 {
14353 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14354 "Target"=>$PName1,
14355 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14356 "Old_Value"=>$Old_Regs,
14357 "New_Value"=>$New_Regs );
14358 }
14359 }
14360 elsif($Old_Regs and not $New_Regs)
14361 {
14362 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014363 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014364 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014365 "Old_Value"=>$Old_Regs );
14366 }
14367 elsif(not $Old_Regs and $New_Regs)
14368 {
14369 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14370 "Target"=>$PName1,
14371 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014372 "New_Value"=>$New_Regs );
14373 }
14374 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014375
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014376 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14377 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14378 {
14379 if($Old_Offset ne $New_Offset)
14380 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014381 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14382 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14383
14384 $Old_Offset = $Old_Offset - $Start1;
14385 $New_Offset = $New_Offset - $Start2;
14386
14387 if($Old_Offset ne $New_Offset)
14388 {
14389 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14390 "Target"=>$PName1,
14391 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14392 "Old_Value"=>$Old_Offset,
14393 "New_Value"=>$New_Offset );
14394 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014395 }
14396 }
14397 }
14398 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014399 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014400 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14401 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014402 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014403 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014404 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14405 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014406 if(not checkDump(1, "2.13")
14407 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014408 { # support for old ABI dumps
14409 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014410 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014411 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014412 and $Value_Old eq "false" and $Value_New eq "0")
14413 { # int class::method ( bool p = 0 );
14414 # old ABI dumps: "false"
14415 # new ABI dumps: "0"
14416 $Value_Old = "0";
14417 }
14418 }
14419 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014420 if(not checkDump(1, "2.18")
14421 and checkDump(2, "2.18"))
14422 { # support for old ABI dumps
14423 if(not defined $Value_Old
14424 and substr($Value_New, 0, 2) eq "_Z") {
14425 $Value_Old = $Value_New;
14426 }
14427 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014428 if(defined $Value_Old)
14429 {
14430 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14431 if(defined $Value_New)
14432 {
14433 $Value_New = showVal($Value_New, $PType2_Id, 2);
14434 if($Value_Old ne $Value_New)
14435 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014436 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014437 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014438 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014439 "Old_Value"=>$Value_Old,
14440 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014441 }
14442 }
14443 else
14444 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014445 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014446 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014447 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014448 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014449 }
14450 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014451 elsif(defined $Value_New)
14452 {
14453 $Value_New = showVal($Value_New, $PType2_Id, 2);
14454 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14455 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014456 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014457 "New_Value"=>$Value_New );
14458 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014459 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014460
14461 if($ChkRnmd)
14462 {
14463 if($PName1 and $PName2 and $PName1 ne $PName2
14464 and $PType1_Id!=-1 and $PType2_Id!=-1
14465 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14466 { # except unnamed "..." value list (Id=-1)
14467 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14468 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014469 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014470 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14471 "Old_Value"=>$PName1,
14472 "New_Value"=>$PName2,
14473 "New_Signature"=>get_Signature($Symbol, 2) );
14474 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014475 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014476
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014477 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014478 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014479
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014480 foreach my $SubProblemType (keys(%SubProblems))
14481 { # add new problems, remove false alarms
14482 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14483 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014484
14485 # quals
14486 if($SubProblemType eq "Parameter_Type"
14487 or $SubProblemType eq "Parameter_Type_And_Size"
14488 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014489 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014490 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014491 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014492 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014493 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014494 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014495 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14496 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14497 }
14498 }
14499 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14500 {
14501 if(removedQual($Old_Value, $New_Value, "volatile")) {
14502 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014503 }
14504 }
14505 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14506 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14507 { # int to "int const"
14508 delete($SubProblems{$SubProblemType});
14509 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014510 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014511 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14512 { # "int const" to int
14513 delete($SubProblems{$SubProblemType});
14514 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014515 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14516 { # "const" to non-"const"
14517 if($RR==2) {
14518 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14519 }
14520 else {
14521 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14522 }
14523 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014524 }
14525 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014526
14527 if($Level eq "Source")
14528 {
14529 foreach my $SubProblemType (keys(%SubProblems))
14530 {
14531 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14532 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14533
14534 if($SubProblemType eq "Parameter_Type")
14535 {
14536 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14537 delete($SubProblems{$SubProblemType});
14538 }
14539 }
14540 }
14541 }
14542
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014543 foreach my $SubProblemType (keys(%SubProblems))
14544 { # modify/register problems
14545 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14546 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014547 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14548 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014549
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014550 my $NewProblemType = $SubProblemType;
14551 if($Old_Value eq "..." and $New_Value ne "...")
14552 { # change from "..." to "int"
14553 if($ParamPos1==0)
14554 { # ISO C requires a named argument before "..."
14555 next;
14556 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014557 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014558 }
14559 elsif($New_Value eq "..." and $Old_Value ne "...")
14560 { # change from "int" to "..."
14561 if($ParamPos2==0)
14562 { # ISO C requires a named argument before "..."
14563 next;
14564 }
14565 $NewProblemType = "Parameter_Became_VaList";
14566 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014567 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014568 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014569 {
14570 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014571 if($Arch1 eq "unknown"
14572 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014573 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014574 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014575 ($Arch1, $Arch2) = ("unknown", "unknown");
14576 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014577 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014578 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014579 { # real
14580 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14581 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14582 }
14583 else
14584 { # model
14585 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14586 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14587 }
14588 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014589 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014590 if($Conv1{"Method"} eq "stack")
14591 {
14592 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14593 $NewProblemType = "Parameter_Type_And_Stack";
14594 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014595 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014596 elsif($Conv1{"Method"} eq "reg")
14597 {
14598 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14599 $NewProblemType = "Parameter_Type_And_Register";
14600 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014601 }
14602 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014603 elsif($Conv1{"Method"} ne "unknown"
14604 and $Conv2{"Method"} ne "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014605 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014606 if($Conv1{"Method"} eq "stack") {
14607 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014608 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014609 elsif($Conv1{"Method"} eq "register") {
14610 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014611 }
14612 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014613 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14614 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014615 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014616 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014617 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014618 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014619 "New_Signature"=>get_Signature($Symbol, 2) );
14620 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014621 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014622
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014623 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014624
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014625 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014626 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14627 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014628 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014629 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014630 {
14631 my $NewProblemType = $SubProblemType;
14632 if($SubProblemType eq "DataType_Size")
14633 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014634 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014635 { # stack has been affected
14636 $NewProblemType = "DataType_Size_And_Stack";
14637 }
14638 }
14639 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014640 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014641 }
14642 }
14643}
14644
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014645sub find_ParamPair_Pos_byName($$$)
14646{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014647 my ($Name, $Symbol, $LibVersion) = @_;
14648 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014649 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014650 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14651 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014652 {
14653 return $ParamPos;
14654 }
14655 }
14656 return "lost";
14657}
14658
14659sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14660{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014661 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014662 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014663 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014664 {
14665 next if($Order eq "backward" and $ParamPos>$MediumPos);
14666 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014667 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14668 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014669 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014670 push(@Positions, $ParamPos);
14671 }
14672 }
14673 return @Positions;
14674}
14675
14676sub getTypeIdByName($$)
14677{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014678 my ($TypeName, $LibVersion) = @_;
14679 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014680}
14681
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014682sub diffTypes($$$)
14683{
14684 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14685 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14686 }
14687 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14688 { # skip recursive declarations
14689 return 0;
14690 }
14691
14692 pushType($_[0], $_[1], \@RecurTypes_Diff);
14693 my $Diff = diffTypes_I(@_);
14694 pop(@RecurTypes_Diff);
14695
14696 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14697}
14698
14699sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014700{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014701 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014702
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014703 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14704 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014705
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014706 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14707 { # equal types
14708 return 0;
14709 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014710 if($Type1_Pure{"Name"} eq "void")
14711 { # from void* to something
14712 return 0;
14713 }
Andrey Ponomarenkof9f25c92016-07-26 17:20:17 +030014714 if($Type2_Pure{"Name"} eq "void")
14715 { # from something to void*
14716 return 0;
14717 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014718 if($Type1_Pure{"Name"}=~/\*/
14719 or $Type2_Pure{"Name"}=~/\*/)
14720 { # compared in detectTypeChange()
14721 return 0;
14722 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014723
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014724 my %FloatType = map {$_=>1} (
14725 "float",
14726 "double",
14727 "long double"
14728 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014729
14730 my $T1 = $Type1_Pure{"Type"};
14731 my $T2 = $Type2_Pure{"Type"};
14732
14733 if($T1 eq "Struct"
14734 and $T2 eq "Class")
14735 { # compare as data structures
14736 $T2 = "Struct";
14737 }
14738
14739 if($T1 eq "Class"
14740 and $T2 eq "Struct")
14741 { # compare as data structures
14742 $T1 = "Struct";
14743 }
14744
14745 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014746 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014747 if($T1 eq "Intrinsic"
14748 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014749 { # "int" to "enum"
14750 return 0;
14751 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014752 elsif($T2 eq "Intrinsic"
14753 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014754 { # "enum" to "int"
14755 return 0;
14756 }
14757 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014758 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014759 # ...
14760 return 1;
14761 }
14762 }
14763 else
14764 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014765 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014766 {
14767 if($FloatType{$Type1_Pure{"Name"}}
14768 or $FloatType{$Type2_Pure{"Name"}})
14769 { # "float" to "double"
14770 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014771 if($Level eq "Source")
14772 { # Safe
14773 return 0;
14774 }
14775 else {
14776 return 1;
14777 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014778 }
14779 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014780 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014781 {
14782 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14783 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014784 if(not @Membs1
14785 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014786 { # private
14787 return 0;
14788 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014789 if($#Membs1!=$#Membs2)
14790 { # different number of elements
14791 return 1;
14792 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014793 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014794 {
14795 foreach my $Pos (@Membs1)
14796 { # compare elements by name and value
14797 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14798 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14799 { # different names
14800 return 1;
14801 }
14802 }
14803 }
14804 else
14805 {
14806 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014807 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014808 if($Level eq "Source")
14809 {
14810 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14811 { # different names
14812 return 1;
14813 }
14814 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014815
14816 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14817 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14818
14819 if($MT1{"Name"} ne $MT2{"Name"}
14820 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14821 {
14822 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14823 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14824
14825 if($PL1 ne $PL2)
14826 { # different pointer level
14827 return 1;
14828 }
14829
14830 # compare base types
14831 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14832 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14833
14834 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14835 { # different types
14836 return 1;
14837 }
14838 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014839 }
14840 }
14841 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014842 else
14843 {
14844 # TODO: arrays, etc.
14845 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014846 }
14847 return 0;
14848}
14849
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014850sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014851{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014852 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014853 if(not $Type1_Id or not $Type2_Id) {
14854 return ();
14855 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014856 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014857 my %Type1 = get_Type($Type1_Id, 1);
14858 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014859 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14860 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014861
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030014862 if(defined $SkipTypedefUncover)
14863 {
14864 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}) {
14865 return ();
14866 }
14867
14868 if(cmpBTypes($Type1_Pure{"Name"}, $Type2_Pure{"Name"}, 1, 2)) {
14869 return ();
14870 }
14871 }
14872
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014873 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14874 my %Type2_Base = ($Type2_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type2_Pure{"Tid"}, $TypeInfo{2}):get_BaseType($Type2_Id, 2);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014875
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014876 if(defined $UsedDump{1}{"DWARF"})
14877 {
14878 if($Type1_Pure{"Name"} eq "__unknown__"
14879 or $Type2_Pure{"Name"} eq "__unknown__"
14880 or $Type1_Base{"Name"} eq "__unknown__"
14881 or $Type2_Base{"Name"} eq "__unknown__")
14882 { # Error ABI dump
14883 return ();
14884 }
14885 }
14886
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014887 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14888 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014889 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14890 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14891 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14892 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14893 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14894 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14895 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014896 if($Type1{"Name"} eq $Type2{"Name"})
14897 {
14898 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14899 { # will be reported in mergeTypes() as typedef problem
14900 return ();
14901 }
14902 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14903 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14904 if(%Typedef_1 and %Typedef_2)
14905 {
14906 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14907 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14908 { # const Typedef
14909 return ();
14910 }
14911 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014912 }
14913 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14914 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014915 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014916 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14917 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014918 {
14919 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14920 "Old_Value"=>$Type1_Base{"Name"},
14921 "New_Value"=>$Type2_Base{"Name"},
14922 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014923 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014924 }
14925 else
14926 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014927 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014928 { # format change
14929 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14930 "Old_Value"=>$Type1_Base{"Name"},
14931 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014932 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014933 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014934 }
14935 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14936 {
14937 %{$LocalProblems{$Prefix."_BaseType"}}=(
14938 "Old_Value"=>$Type1_Base{"Name"},
14939 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014940 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014941 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014942 }
14943 }
14944 }
14945 }
14946 elsif($Type1{"Name"} ne $Type2{"Name"})
14947 { # type change
14948 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14949 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014950 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014951 and $Type1_Pure{"Name"} eq "void")
14952 {
14953 %{$LocalProblems{"Return_Type_From_Void"}}=(
14954 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014955 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014956 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014957 elsif($Prefix eq "Return"
14958 and $Type2_Pure{"Name"} eq "void")
14959 {
14960 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14961 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014962 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014963 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014964 else
14965 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014966 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014967 and $Type1{"Size"} and $Type2{"Size"}
14968 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014969 {
14970 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14971 "Old_Value"=>$Type1{"Name"},
14972 "New_Value"=>$Type2{"Name"},
14973 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014974 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014975 }
14976 else
14977 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014978 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014979 { # format change
14980 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14981 "Old_Value"=>$Type1{"Name"},
14982 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014983 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014984 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014985 }
14986 elsif(tNameLock($Type1_Id, $Type2_Id))
14987 { # FIXME: correct this condition
14988 %{$LocalProblems{$Prefix."_Type"}}=(
14989 "Old_Value"=>$Type1{"Name"},
14990 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014991 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014992 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014993 }
14994 }
14995 }
14996 }
14997 }
14998 if($Type1_PLevel!=$Type2_PLevel)
14999 {
15000 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
15001 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
15002 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015003 if($Level eq "Source")
15004 {
15005 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015006 "Old_Value"=>$Type1_PLevel,
15007 "New_Value"=>$Type2_PLevel);
15008 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015009 else
15010 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015011 if($Type2_PLevel>$Type1_PLevel)
15012 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015013 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
15014 "Old_Value"=>$Type1_PLevel,
15015 "New_Value"=>$Type2_PLevel);
15016 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015017 else
15018 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015019 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
15020 "Old_Value"=>$Type1_PLevel,
15021 "New_Value"=>$Type2_PLevel);
15022 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015023 }
15024 }
15025 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040015026 if($Type1_Pure{"Type"} eq "Array"
15027 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015028 { # base_type[N] -> base_type[N]
15029 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015030 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015031 foreach my $SubProblemType (keys(%SubProblems))
15032 {
15033 $SubProblemType=~s/_Type/_BaseType/g;
15034 next if(defined $LocalProblems{$SubProblemType});
15035 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
15036 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
15037 }
15038 }
15039 }
15040 return %LocalProblems;
15041}
15042
15043sub tNameLock($$)
15044{
15045 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015046 my $Changed = 0;
15047 if(differentDumps("G"))
15048 { # different GCC versions
15049 $Changed = 1;
15050 }
15051 elsif(differentDumps("V"))
15052 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015053 if(not checkDump(1, "2.20")
15054 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015055 { # latest names update
15056 # 2.6: added restrict qualifier
15057 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015058 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015059 $Changed = 1;
15060 }
15061 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015062
15063 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
15064 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
15065
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015066 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
15067 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
15068
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015069 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015070 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015071 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015072 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015073 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015074 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015075 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015076 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015077 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015078 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015079 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
15080 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
15081 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015082 { # equal base types
15083 return 0;
15084 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015085
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015086 if(not checkDump(1, "2.13")
15087 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015088 { # broken array names in ABI dumps < 2.13
15089 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015090 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015091 return 0;
15092 }
15093 }
15094
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015095 if(not checkDump(1, "2.6")
15096 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015097 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015098 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015099 and $TN2=~/\brestrict\b/) {
15100 return 0;
15101 }
15102 }
15103
15104 if(not checkDump(1, "2.20")
15105 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015106 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015107 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
15108 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015109 return 0;
15110 }
15111 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015112 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015113 else
15114 {
15115 # typedef struct {...} type_t
15116 # typedef struct type_t {...} type_t
15117 if(index($TN1, " ".$TN2)!=-1)
15118 {
15119 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
15120 return 0;
15121 }
15122 }
15123 if(index($TN2, " ".$TN1)!=-1)
15124 {
15125 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
15126 return 0;
15127 }
15128 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015129
15130 if($TT1 eq "FuncPtr"
15131 and $TT2 eq "FuncPtr")
15132 {
15133 my $TN1_C = $TN1;
15134 my $TN2_C = $TN2;
15135
15136 $TN1_C=~s/\b(struct|union) //g;
15137 $TN2_C=~s/\b(struct|union) //g;
15138
15139 if($TN1_C eq $TN2_C) {
15140 return 0;
15141 }
15142 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015143 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015144
15145 my ($N1, $N2) = ($TN1, $TN2);
15146 $N1=~s/\b(struct|union) //g;
15147 $N2=~s/\b(struct|union) //g;
15148
15149 if($N1 eq $N2)
15150 { # QList<struct QUrl> and QList<QUrl>
15151 return 0;
15152 }
15153
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015154 return 1;
15155}
15156
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015157sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015158{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015159 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015160 if(defined $Cache{"differentDumps"}{$Check}) {
15161 return $Cache{"differentDumps"}{$Check};
15162 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015163 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015164 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015165 if($Check eq "G")
15166 {
15167 if(getGccVersion(1) ne getGccVersion(2))
15168 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015169 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015170 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015171 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015172 if($Check eq "V")
15173 {
15174 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15175 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15176 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015177 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015178 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015179 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015180 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015181 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015182}
15183
15184sub formatVersion($$)
15185{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015186 my ($V, $Digits) = @_;
15187 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015188 return join(".", splice(@Elems, 0, $Digits));
15189}
15190
15191sub htmlSpecChars($)
15192{
15193 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015194 if(not $Str) {
15195 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015196 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015197 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15198 $Str=~s/</&lt;/g;
15199 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15200 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015201 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15202 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015203 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015204 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015205 $Str=~s/\n/<br\/>/g;
15206 $Str=~s/\"/&quot;/g;
15207 $Str=~s/\'/&#39;/g;
15208 return $Str;
15209}
15210
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015211sub xmlSpecChars($)
15212{
15213 my $Str = $_[0];
15214 if(not $Str) {
15215 return $Str;
15216 }
15217
15218 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15219 $Str=~s/</&lt;/g;
15220 $Str=~s/>/&gt;/g;
15221
15222 $Str=~s/\"/&quot;/g;
15223 $Str=~s/\'/&#39;/g;
15224
15225 return $Str;
15226}
15227
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015228sub xmlSpecChars_R($)
15229{
15230 my $Str = $_[0];
15231 if(not $Str) {
15232 return $Str;
15233 }
15234
15235 $Str=~s/&amp;/&/g;
15236 $Str=~s/&lt;/</g;
15237 $Str=~s/&gt;/>/g;
15238
15239 $Str=~s/&quot;/"/g;
15240 $Str=~s/&#39;/'/g;
15241
15242 return $Str;
15243}
15244
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015245sub black_name($)
15246{
15247 my $Name = $_[0];
15248 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15249}
15250
15251sub highLight_Signature($)
15252{
15253 my $Signature = $_[0];
15254 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15255}
15256
15257sub highLight_Signature_Italic_Color($)
15258{
15259 my $Signature = $_[0];
15260 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15261}
15262
15263sub separate_symbol($)
15264{
15265 my $Symbol = $_[0];
15266 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15267 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15268 ($Name, $Spec, $Ver) = ($1, $2, $3);
15269 }
15270 return ($Name, $Spec, $Ver);
15271}
15272
15273sub cut_f_attrs($)
15274{
15275 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15276 return $2;
15277 }
15278 return "";
15279}
15280
15281sub highLight_Signature_PPos_Italic($$$$$)
15282{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015283 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15284 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015285 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15286 my $Return = "";
15287 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15288 $Return = $2;
15289 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015290 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015291 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015292 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015293 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015294 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015295 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015296 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015297 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015298 }
15299 return $Signature;
15300 }
15301 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15302 $Begin.=" " if($Begin!~/ \Z/);
15303 $End = cut_f_attrs($Signature);
15304 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015305 my ($Short, $Params) = split_Signature($Signature);
15306 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015307 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015308 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015309 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015310 $Part=~s/\A\s+|\s+\Z//g;
15311 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15312 if($Part=~/\([\*]+(\w+)\)/i) {
15313 $ParamName = $1;#func-ptr
15314 }
15315 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15316 $ParamName = $1;
15317 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015318 if(not $ParamName)
15319 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015320 push(@Parts, $Part_Styled);
15321 next;
15322 }
15323 if($ItalicParams and not $TName_Tid{1}{$Part}
15324 and not $TName_Tid{2}{$Part})
15325 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015326 my $Style = "<i>$ParamName</i>";
15327
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015328 if($Param_Pos ne ""
15329 and $Pos==$Param_Pos) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015330 $Style = "<span class=\'fp\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015331 }
15332 elsif($ColorParams) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015333 $Style = "<span class=\'color_p\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015334 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015335
15336 $Part_Styled=~s!(\W)$ParamName([\,\)]|\Z)!$1$Style$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015337 }
15338 $Part_Styled=~s/,(\w)/, $1/g;
15339 push(@Parts, $Part_Styled);
15340 }
15341 if(@Parts)
15342 {
15343 foreach my $Num (0 .. $#Parts)
15344 {
15345 if($Num==$#Parts)
15346 { # add ")" to the last parameter
15347 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15348 }
15349 elsif(length($Parts[$Num])<=45) {
15350 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15351 }
15352 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015353 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015354 }
15355 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015356 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015357 }
15358 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015359 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015360 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015361 $Signature=~s!\[\]![&#160;]!g;
15362 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015363 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15364 if($SymbolVersion) {
15365 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15366 }
15367 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015368}
15369
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015370sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015371{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015372 my $Signature = $_[0];
15373 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15374 {
15375 $Signature=~s/\A\Q$ShortName\E\(//g;
15376 cut_f_attrs($Signature);
15377 $Signature=~s/\)\Z//;
15378 return ($ShortName, $Signature);
15379 }
15380
15381 # error
15382 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015383}
15384
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015385sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015386{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015387 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015388 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015389 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15390 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015391 foreach my $Pos (0 .. length($Params) - 1)
15392 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015393 my $S = substr($Params, $Pos, 1);
15394 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015395 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015396 }
15397 if($S eq "," and
15398 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015399 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015400 if($Comma)
15401 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015402 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015403 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015404 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015405 }
15406 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015407 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015408 }
15409 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015410 if(not $Sp)
15411 { # remove spaces
15412 foreach (@Parts)
15413 {
15414 s/\A //g;
15415 s/ \Z//g;
15416 }
15417 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015418 return @Parts;
15419}
15420
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015421sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015422{
15423 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015424 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015425 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015426 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15427 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015428 $Center+=length($1);
15429 }
15430 foreach my $Pos (0 .. length($Sign)-1)
15431 {
15432 my $S = substr($Sign, $Pos, 1);
15433 if($S eq $Target)
15434 {
15435 if($B{"("}==$B{")"}
15436 and $B{"<"}==$B{">"}) {
15437 return $Center;
15438 }
15439 }
15440 if(defined $B{$S}) {
15441 $B{$S}+=1;
15442 }
15443 $Center+=1;
15444 }
15445 return 0;
15446}
15447
15448sub appendFile($$)
15449{
15450 my ($Path, $Content) = @_;
15451 return if(not $Path);
15452 if(my $Dir = get_dirname($Path)) {
15453 mkpath($Dir);
15454 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015455 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015456 print FILE $Content;
15457 close(FILE);
15458}
15459
15460sub writeFile($$)
15461{
15462 my ($Path, $Content) = @_;
15463 return if(not $Path);
15464 if(my $Dir = get_dirname($Path)) {
15465 mkpath($Dir);
15466 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015467 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015468 print FILE $Content;
15469 close(FILE);
15470}
15471
15472sub readFile($)
15473{
15474 my $Path = $_[0];
15475 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015476 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015477 local $/ = undef;
15478 my $Content = <FILE>;
15479 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015480 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015481 $Content=~s/\r/\n/g;
15482 }
15483 return $Content;
15484}
15485
15486sub get_filename($)
15487{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015488 if(defined $Cache{"get_filename"}{$_[0]}) {
15489 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015490 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015491 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15492 return ($Cache{"get_filename"}{$_[0]}=$1);
15493 }
15494 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015495}
15496
15497sub get_dirname($)
15498{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015499 if(defined $Cache{"get_dirname"}{$_[0]}) {
15500 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015501 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015502 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15503 return ($Cache{"get_dirname"}{$_[0]}=$1);
15504 }
15505 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015506}
15507
15508sub separate_path($) {
15509 return (get_dirname($_[0]), get_filename($_[0]));
15510}
15511
15512sub esc($)
15513{
15514 my $Str = $_[0];
15515 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15516 return $Str;
15517}
15518
15519sub readLineNum($$)
15520{
15521 my ($Path, $Num) = @_;
15522 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015523 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015524 foreach (1 ... $Num) {
15525 <FILE>;
15526 }
15527 my $Line = <FILE>;
15528 close(FILE);
15529 return $Line;
15530}
15531
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015532sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015533{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015534 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015535 return () if(not $Path or not -f $Path);
15536 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015537 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15538 {
15539 foreach my $AttrVal (split(/;/, $1))
15540 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015541 if($AttrVal=~/(.+):(.+)/)
15542 {
15543 my ($Name, $Value) = ($1, $2);
15544 $Attributes{$Name} = $Value;
15545 }
15546 }
15547 }
15548 return \%Attributes;
15549}
15550
15551sub is_abs($) {
15552 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15553}
15554
15555sub get_abs_path($)
15556{ # abs_path() should NOT be called for absolute inputs
15557 # because it can change them
15558 my $Path = $_[0];
15559 if(not is_abs($Path)) {
15560 $Path = abs_path($Path);
15561 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030015562 return path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015563}
15564
15565sub get_OSgroup()
15566{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015567 my $N = $Config{"osname"};
15568 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015569 return "macos";
15570 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015571 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015572 return "bsd";
15573 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015574 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015575 return "beos";
15576 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015577 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015578 return "symbian";
15579 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015580 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015581 return "windows";
15582 }
15583 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015584 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015585 }
15586}
15587
15588sub getGccVersion($)
15589{
15590 my $LibVersion = $_[0];
15591 if($GCC_VERSION{$LibVersion})
15592 { # dump version
15593 return $GCC_VERSION{$LibVersion};
15594 }
15595 elsif($UsedDump{$LibVersion}{"V"})
15596 { # old-version dumps
15597 return "unknown";
15598 }
15599 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15600 if(not $GccVersion) {
15601 return "unknown";
15602 }
15603 return $GccVersion;
15604}
15605
15606sub showArch($)
15607{
15608 my $Arch = $_[0];
15609 if($Arch eq "arm"
15610 or $Arch eq "mips") {
15611 return uc($Arch);
15612 }
15613 return $Arch;
15614}
15615
15616sub getArch($)
15617{
15618 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015619
15620 if($TargetArch) {
15621 return $TargetArch;
15622 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015623 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015624 { # dump
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015625 return $CPU_ARCH{$LibVersion};
15626 }
15627 elsif($UsedDump{$LibVersion}{"V"})
15628 { # old-version dumps
15629 return "unknown";
15630 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015631
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015632 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015633}
15634
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015635sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015636{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015637 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015638
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015639 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015640 if(getArch(1) ne getArch(2)
15641 or getArch(1) eq "unknown"
15642 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015643 { # don't show architecture in the header
15644 $ArchInfo="";
15645 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015646 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015647 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015648 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015649 }
15650 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015651 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015652 }
15653 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015654 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015655 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015656
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015657 my $V1 = $Descriptor{1}{"Version"};
15658 my $V2 = $Descriptor{2}{"Version"};
15659
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015660 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15661 {
15662 my $M1 = $UsedDump{1}{"M"};
15663 my $M2 = $UsedDump{2}{"M"};
15664
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015665 my $M1S = $M1;
15666 my $M2S = $M2;
15667
15668 $M1S=~s/(\.so|\.ko)\..+/$1/ig;
15669 $M2S=~s/(\.so|\.ko)\..+/$1/ig;
15670
15671 if($M1S eq $M2S
15672 and $V1 ne "X" and $V2 ne "Y")
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015673 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015674 $Title .= " report for the <span style='color:Blue;'>$M1S</span> $TargetComponent";
15675 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015676 }
15677 else
15678 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015679 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$V1."</span>)";
15680 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$V2."</span>) objects";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015681 }
15682 }
15683 else
15684 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015685 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015686 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015687 }
15688
15689 $Title .= $ArchInfo;
15690
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015691 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015692 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015693 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015694 $Title = "<h1>".$Title."</h1>\n";
15695 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015696}
15697
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015698sub get_CheckedHeaders($)
15699{
15700 my $LibVersion = $_[0];
15701
15702 my @Headers = ();
15703
15704 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15705 {
15706 my $File = get_filename($Path);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015707
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015708 if(not is_target_header($File, $LibVersion)) {
15709 next;
15710 }
15711
15712 if(skipHeader($File, $LibVersion)) {
15713 next;
15714 }
15715
15716 push(@Headers, $Path);
15717 }
15718
15719 return @Headers;
15720}
15721
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015722sub get_SourceInfo()
15723{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015724 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015725
15726 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015727 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015728 $CheckedHeaders = "<a name='Headers'></a>";
15729 if($OldStyle) {
15730 $CheckedHeaders .= "<h2>Header Files (".($#Headers+1).")</h2>";
15731 }
15732 else {
15733 $CheckedHeaders .= "<h2>Header Files <span class='gray'>&nbsp;".($#Headers+1)."&nbsp;</span></h2>";
15734 }
15735 $CheckedHeaders .= "<hr/>\n<div class='h_list'>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015736 foreach my $Header_Path (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015737 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015738 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15739 my $Name = get_filename($Identity);
15740 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15741 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015742 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015743 $CheckedHeaders .= "</div>\n";
15744 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015745 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015746
15747 if(my @Sources = keys(%{$Registered_Sources{1}}))
15748 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015749 $CheckedSources = "<a name='Sources'></a>";
15750 if($OldStyle) {
15751 $CheckedSources .= "<h2>Source Files (".($#Sources+1).")</h2>";
15752 }
15753 else {
15754 $CheckedSources .= "<h2>Source Files <span class='gray'>&nbsp;".($#Sources+1)."&nbsp;</span></h2>";
15755 }
15756 $CheckedSources .= "<hr/>\n<div class='h_list'>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015757 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15758 {
15759 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15760 my $Name = get_filename($Identity);
15761 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15762 $CheckedSources .= $Name.$Comment."<br/>\n";
15763 }
15764 $CheckedSources .= "</div>\n";
15765 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15766 }
15767
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015768 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015769 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015770 $CheckedLibs = "<a name='Libs'></a>";
15771 if($OldStyle) {
15772 $CheckedLibs .= "<h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2>";
15773 }
15774 else {
15775 $CheckedLibs .= "<h2>".get_ObjTitle()." <span class='gray'>&nbsp;".keys(%{$Library_Symbol{1}})."&nbsp;</span></h2>";
15776 }
15777 $CheckedLibs .= "<hr/>\n<div class='lib_list'>\n";
15778 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}})) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015779 $CheckedLibs .= $Library."<br/>\n";
15780 }
15781 $CheckedLibs .= "</div>\n";
15782 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015783 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015784
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015785 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15786}
15787
15788sub get_ObjTitle()
15789{
15790 if(defined $UsedDump{1}{"DWARF"}) {
15791 return "Objects";
15792 }
15793 else {
15794 return ucfirst($SLIB_TYPE)." Libraries";
15795 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015796}
15797
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015798sub get_TypeProblems_Count($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015799{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015800 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015801 my $Type_Problems_Count = 0;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015802
15803 foreach my $Type_Name (sort keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015804 {
15805 my %Kinds_Target = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015806 foreach my $Kind (keys(%{$TypeChanges{$Level}{$Type_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015807 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015808 foreach my $Location (keys(%{$TypeChanges{$Level}{$Type_Name}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015809 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015810 my $Target = $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015811 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015812
15813 if($Severity ne $TargetSeverity) {
15814 next;
15815 }
15816
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015817 if($Kinds_Target{$Kind}{$Target}) {
15818 next;
15819 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015820
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015821 $Kinds_Target{$Kind}{$Target} = 1;
15822 $Type_Problems_Count += 1;
15823 }
15824 }
15825 }
15826 return $Type_Problems_Count;
15827}
15828
15829sub get_Summary($)
15830{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015831 my $Level = $_[0];
15832 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015833 $C_Problems_Low, $T_Problems_Medium, $T_Problems_Low, $I_Other, $T_Other, $C_Other) = (0,0,0,0,0,0,0,0,0,0,0,0);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015834 %{$RESULT{$Level}} = (
15835 "Problems"=>0,
15836 "Warnings"=>0,
15837 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015838 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015839 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015840 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015841 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015842 {
15843 if(not defined $CompatRules{$Level}{$Kind})
15844 { # unknown rule
15845 if(not $UnknownRules{$Level}{$Kind})
15846 { # only one warning
15847 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15848 $UnknownRules{$Level}{$Kind}=1;
15849 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015850 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015851 }
15852 }
15853 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015854 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15855 {
15856 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15857 {
15858 if(not defined $CompatRules{$Level}{$Kind})
15859 { # unknown rule
15860 if(not $UnknownRules{$Level}{$Kind})
15861 { # only one warning
15862 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15863 $UnknownRules{$Level}{$Kind}=1;
15864 }
15865 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15866 }
15867 }
15868 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015869 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015870 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015871 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015872 {
15873 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15874 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015875 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015876 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015877 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015878 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015879 $Added += 1;
15880 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015881 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015882 {
15883 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015884 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015885 }
15886 else
15887 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015888 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015889 $I_Other += 1;
15890 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015891 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015892 $I_Problems_High += 1;
15893 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015894 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015895 $I_Problems_Medium += 1;
15896 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015897 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015898 $I_Problems_Low += 1;
15899 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015900 if(($Severity ne "Low" or $StrictCompat)
15901 and $Severity ne "Safe") {
15902 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015903 }
15904 }
15905 }
15906 }
15907 }
15908 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015909
15910 my %MethodTypeIndex = ();
15911
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015912 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015913 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015914 my @Kinds = sort keys(%{$CompatProblems{$Level}{$Interface}});
15915 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015916 {
15917 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15918 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015919 my @Locs = sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}});
15920 foreach my $Location (@Locs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015921 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015922 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15923 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015924
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015925 if(defined $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target})
15926 { # one location for one type and target
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015927 next;
15928 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015929 $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target} = 1;
15930 $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15931
15932 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015933
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015934 if(($Severity ne "Low" or $StrictCompat)
15935 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015936 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015937 if(my $Sev = $TotalAffected{$Level}{$Interface})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015938 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015939 if($Severity_Val{$Severity}>$Severity_Val{$Sev}) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015940 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015941 }
15942 }
15943 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015944 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015945 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015946 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015947 }
15948 }
15949 }
15950 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015951
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015952 $T_Problems_High = get_TypeProblems_Count("High", $Level);
15953 $T_Problems_Medium = get_TypeProblems_Count("Medium", $Level);
15954 $T_Problems_Low = get_TypeProblems_Count("Low", $Level);
15955 $T_Other = get_TypeProblems_Count("Safe", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015956
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015957 # changed and removed public symbols
15958 my $SCount = keys(%{$CheckedSymbols{$Level}});
15959 if($ExtendedCheck)
15960 { # don't count external_func_0 for constants
15961 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015962 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015963 if($SCount)
15964 {
15965 my %Weight = (
15966 "High" => 100,
15967 "Medium" => 50,
15968 "Low" => 25
15969 );
15970 foreach (keys(%{$TotalAffected{$Level}})) {
15971 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015972 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015973 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015974 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015975 else {
15976 $RESULT{$Level}{"Affected"} = 0;
15977 }
15978
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015979 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15980 if($RESULT{$Level}{"Affected"}>=100) {
15981 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015982 }
15983
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015984 $RESULT{$Level}{"Problems"} += $Removed;
15985 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015986 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015987 if($StrictCompat) {
15988 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15989 }
15990 else {
15991 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15992 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015993
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015994 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015995 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015996 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015997 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015998 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015999 if($Severity eq "Safe")
16000 {
16001 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016002 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016003 elsif($Severity eq "Low")
16004 {
16005 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016006 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016007 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016008 }
16009
16010 if($C_Problems_Low)
16011 {
16012 if($StrictCompat) {
16013 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
16014 }
16015 else {
16016 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016017 }
16018 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016019 if($RESULT{$Level}{"Problems"}
16020 and $RESULT{$Level}{"Affected"}) {
16021 $RESULT{$Level}{"Verdict"} = "incompatible";
16022 }
16023 else {
16024 $RESULT{$Level}{"Verdict"} = "compatible";
16025 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016026
16027 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
16028 if(not $TotalTypes)
16029 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016030 $TotalTypes = keys(%{$TName_Tid{1}});
16031 }
16032
16033 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
16034 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016035 my ($ClangV1, $ClangV2) = ($CLANG_VERSION{1}, $CLANG_VERSION{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016036
16037 my ($TestInfo, $TestResults, $Problem_Summary) = ();
16038
16039 if($ReportFormat eq "xml")
16040 { # XML
16041 # test info
16042 $TestInfo .= " <library>$TargetLibraryName</library>\n";
16043 $TestInfo .= " <version1>\n";
16044 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016045 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016046 if($GccV1) {
16047 $TestInfo .= " <gcc>$GccV1</gcc>\n";
16048 }
16049 elsif($ClangV1) {
16050 $TestInfo .= " <clang>$ClangV1</clang>\n";
16051 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016052 $TestInfo .= " </version1>\n";
16053
16054 $TestInfo .= " <version2>\n";
16055 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016056 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016057 if($GccV2) {
16058 $TestInfo .= " <gcc>$GccV2</gcc>\n";
16059 }
16060 elsif($ClangV2) {
16061 $TestInfo .= " <clang>$ClangV2</clang>\n";
16062 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016063 $TestInfo .= " </version2>\n";
16064 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
16065
16066 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016067 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016068 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016069 $TestResults .= " <headers>\n";
16070 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
16071 {
16072 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
16073 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
16074 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
16075 }
16076 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016077 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016078
16079 if(my @Sources = keys(%{$Registered_Sources{1}}))
16080 {
16081 $TestResults .= " <sources>\n";
16082 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
16083 {
16084 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
16085 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
16086 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
16087 }
16088 $TestResults .= " </sources>\n";
16089 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016090
16091 $TestResults .= " <libs>\n";
16092 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
16093 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016094 # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016095 $TestResults .= " <name>$Library</name>\n";
16096 }
16097 $TestResults .= " </libs>\n";
16098
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016099 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016100 $TestResults .= " <types>".$TotalTypes."</types>\n";
16101
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016102 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
16103 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016104 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
16105
16106 # problem summary
16107 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
16108 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
16109
16110 $Problem_Summary .= " <problems_with_types>\n";
16111 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
16112 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
16113 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
16114 $Problem_Summary .= " <safe>$T_Other</safe>\n";
16115 $Problem_Summary .= " </problems_with_types>\n";
16116
16117 $Problem_Summary .= " <problems_with_symbols>\n";
16118 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
16119 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
16120 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016121 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016122 $Problem_Summary .= " </problems_with_symbols>\n";
16123
16124 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016125 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016126 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016127
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016128 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
16129
16130 return ($TestInfo.$TestResults.$Problem_Summary, "");
16131 }
16132 else
16133 { # HTML
16134 # test info
16135 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016136 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016137
16138 if($TargetComponent eq "library") {
16139 $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
16140 }
16141 else {
16142 $TestInfo .= "<tr><th>Module Name</th><td>$TargetTitle</td></tr>\n";
16143 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016144
16145 my (@VInf1, @VInf2, $AddTestInfo) = ();
16146 if($Arch1 ne "unknown"
16147 and $Arch2 ne "unknown")
16148 { # CPU arch
16149 if($Arch1 eq $Arch2)
16150 { # go to the separate section
Andrey Ponomarenko19b61de2016-08-31 19:45:06 +030016151 $AddTestInfo .= "<tr><th>Arch</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016152 }
16153 else
16154 { # go to the version number
16155 push(@VInf1, showArch($Arch1));
16156 push(@VInf2, showArch($Arch2));
16157 }
16158 }
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030016159 if($Level eq "Binary"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016160 and $OStarget ne "windows")
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016161 {
16162 if($GccV1 ne "unknown"
16163 and $GccV2 ne "unknown")
16164 { # GCC version
16165 if($GccV1 eq $GccV2)
16166 { # go to the separate section
16167 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
16168 }
16169 else
16170 { # go to the version number
16171 push(@VInf1, "gcc ".$GccV1);
16172 push(@VInf2, "gcc ".$GccV2);
16173 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016174 }
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016175 elsif($ClangV1
16176 and $ClangV2)
16177 { # Clang version
16178 if($ClangV1 eq $ClangV2)
16179 { # go to the separate section
16180 $AddTestInfo .= "<tr><th>Clang Version</th><td>$ClangV1</td></tr>\n";
16181 }
16182 else
16183 { # go to the version number
16184 push(@VInf1, "clang ".$ClangV1);
16185 push(@VInf2, "clang ".$ClangV2);
16186 }
16187 }
16188 elsif($GccV1 ne "unknown" and $ClangV2)
16189 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016190 push(@VInf1, "gcc ".$GccV1);
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016191 push(@VInf2, "clang ".$ClangV2);
16192 }
16193 elsif($ClangV1 and $GccV2 ne "unknown")
16194 {
16195 push(@VInf1, "clang ".$ClangV1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016196 push(@VInf2, "gcc ".$GccV2);
16197 }
16198 }
16199 # show long version names with GCC version and CPU architecture name (if different)
16200 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
16201 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
16202 $TestInfo .= $AddTestInfo;
16203 #if($COMMON_LANGUAGE{1}) {
16204 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
16205 #}
16206 if($ExtendedCheck) {
16207 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
16208 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016209 if($JoinReport)
16210 {
16211 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016212 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016213 }
Andrey Ponomarenkodd172162016-10-04 19:41:25 +030016214 elsif($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016215 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016216 }
16217 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016218 $TestInfo .= "</table>\n";
16219
16220 # test results
16221 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016222 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016223
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030016224 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016225 {
16226 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
16227 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
16228 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016229
16230 if(my @Sources = keys(%{$Registered_Sources{1}}))
16231 {
16232 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16233 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16234 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016235
16236 if(not $ExtendedCheck)
16237 {
16238 my $Libs_Link = "0";
16239 $Libs_Link = "<a href='#Libs' style='color:Blue;'>".keys(%{$Library_Symbol{1}})."</a>" if(keys(%{$Library_Symbol{1}})>0);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016240 $TestResults .= "<tr><th>Total ".get_ObjTitle()."</th><td>".($CheckHeadersOnly?"0&#160;(not&#160;analyzed)":$Libs_Link)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016241 }
16242
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016243 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016244
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016245 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016246 if($JoinReport) {
16247 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16248 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016249
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030016250 my $BC_Rate = show_number(100 - $RESULT{$Level}{"Affected"});
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016251
16252 $TestResults .= "<tr><th>Compatibility</th>\n";
16253 if($RESULT{$Level}{"Verdict"} eq "incompatible")
16254 {
16255 my $Cl = "incompatible";
16256 if($BC_Rate>=90) {
16257 $Cl = "warning";
16258 }
16259 elsif($BC_Rate>=80) {
16260 $Cl = "almost_compatible";
16261 }
16262
16263 $TestResults .= "<td class=\'$Cl\'>".$BC_Rate."%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016264 }
16265 else {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016266 $TestResults .= "<td class=\'compatible\'>100%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016267 }
16268 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016269 $TestResults .= "</table>\n";
16270
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016271 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016272 # problem summary
16273 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016274 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016275 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16276
16277 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016278 if($Added>0)
16279 {
16280 if($JoinReport) {
16281 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16282 }
16283 else {
16284 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16285 }
16286 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016287 $META_DATA .= "added:$Added;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016288 $Problem_Summary .= "<tr><th>Added Symbols</th><td>-</td><td".getStyle("I", "Added", $Added).">$Added_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016289
16290 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016291 if($Removed>0)
16292 {
16293 if($JoinReport) {
16294 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16295 }
16296 else {
16297 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16298 }
16299 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016300 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016301 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016302 $Problem_Summary .= "<td>High</td><td".getStyle("I", "Removed", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016303
16304 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016305 $TH_Link = "<a href='#".get_Anchor("Type", $Level, "High")."' style='color:Blue;'>$T_Problems_High</a>" if($T_Problems_High>0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016306 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016307 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016308 $Problem_Summary .= "<td>High</td><td".getStyle("T", "High", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016309
16310 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016311 $TM_Link = "<a href='#".get_Anchor("Type", $Level, "Medium")."' style='color:Blue;'>$T_Problems_Medium</a>" if($T_Problems_Medium>0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016312 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016313 $Problem_Summary .= "<tr><td>Medium</td><td".getStyle("T", "Medium", $T_Problems_Medium).">$TM_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016314
16315 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016316 $TL_Link = "<a href='#".get_Anchor("Type", $Level, "Low")."' style='color:Blue;'>$T_Problems_Low</a>" if($T_Problems_Low>0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016317 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016318 $Problem_Summary .= "<tr><td>Low</td><td".getStyle("T", "Low", $T_Problems_Low).">$TL_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016319
16320 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016321 $IH_Link = "<a href='#".get_Anchor("Symbol", $Level, "High")."' style='color:Blue;'>$I_Problems_High</a>" if($I_Problems_High>0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016322 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016323 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016324 $Problem_Summary .= "<td>High</td><td".getStyle("I", "High", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016325
16326 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016327 $IM_Link = "<a href='#".get_Anchor("Symbol", $Level, "Medium")."' style='color:Blue;'>$I_Problems_Medium</a>" if($I_Problems_Medium>0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016328 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016329 $Problem_Summary .= "<tr><td>Medium</td><td".getStyle("I", "Medium", $I_Problems_Medium).">$IM_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016330
16331 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016332 $IL_Link = "<a href='#".get_Anchor("Symbol", $Level, "Low")."' style='color:Blue;'>$I_Problems_Low</a>" if($I_Problems_Low>0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016333 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016334 $Problem_Summary .= "<tr><td>Low</td><td".getStyle("I", "Low", $I_Problems_Low).">$IL_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016335
16336 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016337 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16338 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016339 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016340 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016341 $Problem_Summary .= "<tr><th>Problems with<br/>Constants</th><td>Low</td><td".getStyle("C", "Low", $C_Problems_Low).">$ChangedConstants_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016342
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016343 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016344 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016345 {
16346 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016347 $Problem_Summary .= "<tr><th>Other Changes<br/>in Data Types</th><td>-</td><td".getStyle("T", "Safe", $T_Other).">$TS_Link</td></tr>\n";
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030016348 $META_DATA .= "type_changes_other:$T_Other;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016349 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016350
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016351 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016352 {
16353 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016354 $Problem_Summary .= "<tr><th>Other Changes<br/>in Symbols</th><td>-</td><td".getStyle("I", "Safe", $I_Other).">$IS_Link</td></tr>\n";
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030016355 $META_DATA .= "interface_changes_other:$I_Other;";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016356 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016357
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016358 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016359 {
16360 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016361 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "Safe", $C_Other).">$CS_Link</td></tr>\n";
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030016362 $META_DATA .= "constant_changes_other:$C_Other;";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016363 }
16364
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016365 $META_DATA .= "tool_version:$TOOL_VERSION";
16366 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016367
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016368 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16369 }
16370}
16371
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016372sub getStyle($$$)
16373{
16374 my ($Subj, $Act, $Num) = @_;
16375 my %Style = (
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016376 "Added"=>"new",
16377 "Removed"=>"failed",
16378 "Safe"=>"passed",
16379 "Low"=>"warning",
16380 "Medium"=>"failed",
16381 "High"=>"failed"
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016382 );
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016383
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016384 if($Num>0) {
16385 return " class='".$Style{$Act}."'";
16386 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016387
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016388 return "";
16389}
16390
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016391sub show_number($)
16392{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016393 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016394 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016395 my $Num = cut_off_number($_[0], 2, 0);
16396 if($Num eq "0")
16397 {
16398 foreach my $P (3 .. 7)
16399 {
16400 $Num = cut_off_number($_[0], $P, 1);
16401 if($Num ne "0") {
16402 last;
16403 }
16404 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016405 }
16406 if($Num eq "0") {
16407 $Num = $_[0];
16408 }
16409 return $Num;
16410 }
16411 return $_[0];
16412}
16413
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016414sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016415{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016416 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016417 if($num!~/\./)
16418 {
16419 $num .= ".";
16420 foreach (1 .. $digs_to_cut-1) {
16421 $num .= "0";
16422 }
16423 }
16424 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16425 {
16426 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16427 $num .= "0";
16428 }
16429 }
16430 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16431 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16432 }
16433 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016434 if($z) {
16435 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16436 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016437 return $num;
16438}
16439
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016440sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016441{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016442 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016443 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016444
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016445 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016446 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16447 {
16448 my $Header = $Constants{1}{$Constant}{"Header"};
16449 if(not $Header)
16450 { # added
16451 $Header = $Constants{2}{$Constant}{"Header"}
16452 }
16453
16454 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16455 {
16456 if(not defined $CompatRules{$Level}{$Kind}) {
16457 next;
16458 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016459 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016460 next;
16461 }
16462 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16463 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016464 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016465
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016466 if($ReportFormat eq "xml")
16467 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016468 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016469 {
16470 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016471 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016472 {
16473 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016474 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16475 {
16476 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16477 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16478 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016479
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016480 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16481 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16482 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016483 if($Overcome) {
16484 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16485 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016486 $CHANGED_CONSTANTS .= " </problem>\n";
16487 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016488 $CHANGED_CONSTANTS .= " </constant>\n";
16489 }
16490 $CHANGED_CONSTANTS .= " </header>\n";
16491 }
16492 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16493 }
16494 else
16495 { # HTML
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016496 my $ProblemsNum = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016497 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016498 {
16499 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016500 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016501 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016502 my $Report = "";
16503
16504 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16505 {
16506 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16507 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016508 $Report .= "<tr>\n<th>1</th>\n<td>".$Change."</td>\n<td>$Effect</td>\n</tr>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016509 $ProblemsNum += 1;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016510 }
16511 if($Report)
16512 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016513 $Report = $ContentDivStart."<table class='ptable'>\n<tr>\n<th width='2%'></th>\n<th width='47%'>Change</th>\n<th>Effect</th>\n</tr>\n".$Report."</table>\n<br/>\n$ContentDivEnd\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016514 $Report = $ContentSpanStart."<span class='ext'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016515 $Report = insertIDs($Report);
16516 }
16517 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016518 }
16519 $CHANGED_CONSTANTS .= "<br/>\n";
16520 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016521 if($CHANGED_CONSTANTS)
16522 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016523 my $Title = "Problems with Constants, $TargetSeverity Severity";
16524 if($TargetSeverity eq "Safe")
16525 { # Safe Changes
16526 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016527 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016528 if($OldStyle) {
16529 $CHANGED_CONSTANTS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$CHANGED_CONSTANTS;
16530 }
16531 else {
16532 $CHANGED_CONSTANTS = "<h2>$Title <span".getStyle("C", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$CHANGED_CONSTANTS;
16533 }
16534 $CHANGED_CONSTANTS = "<a name='".get_Anchor("Constant", $Level, $TargetSeverity)."'></a>\n".$CHANGED_CONSTANTS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016535 }
16536 }
16537 return $CHANGED_CONSTANTS;
16538}
16539
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016540sub getTitle($$$)
16541{
16542 my ($Header, $Library, $NameSpace) = @_;
16543 my $Title = "";
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016544
16545 # if($Library and $Library!~/\.\w+\Z/) {
16546 # $Library .= " (.$LIB_EXT)";
16547 # }
16548
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016549 if($Header and $Library)
16550 {
16551 $Title .= "<span class='h_name'>$Header</span>";
16552 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16553 }
16554 elsif($Library) {
16555 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16556 }
16557 elsif($Header) {
16558 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16559 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016560
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016561 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016562 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016563 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016564
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016565 return $Title;
16566}
16567
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016568sub get_Report_Added($)
16569{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016570 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016571 my $ADDED_INTERFACES = "";
16572 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016573 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016574 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016575 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016576 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016577 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016578 {
16579 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16580 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016581 if($Level eq "Source" and $ReportFormat eq "html")
16582 { # do not show library name in HTML report
16583 $DyLib = "";
16584 }
16585 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016586 }
16587 }
16588 }
16589 if($ReportFormat eq "xml")
16590 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016591 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016592 {
16593 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016594 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016595 {
16596 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016597 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016598 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16599 }
16600 $ADDED_INTERFACES .= " </library>\n";
16601 }
16602 $ADDED_INTERFACES .= " </header>\n";
16603 }
16604 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16605 }
16606 else
16607 { # HTML
16608 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016609 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016610 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016611 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016612 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016613 my %NameSpaceSymbols = ();
16614 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016615 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016616 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016617 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016618 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016619 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16620 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016621 foreach my $Interface (@SortedInterfaces)
16622 {
16623 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016624 my $Signature = get_Signature($Interface, 2);
16625 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016626 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016627 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016628 if($Interface=~/\A(_Z|\?)/)
16629 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016630 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016631 $ADDED_INTERFACES .= insertIDs($ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Interface</b>]</span>\n<br/>\n<br/>\n".$ContentDivEnd."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016632 }
16633 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016634 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016635 }
16636 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016637 else
16638 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016639 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016640 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016641 }
16642 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016643 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016644 }
16645 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016646 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016647 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016648 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016649 }
16650 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016651 if($ADDED_INTERFACES)
16652 {
16653 my $Anchor = "<a name='Added'></a>";
16654 if($JoinReport) {
16655 $Anchor = "<a name='".$Level."_Added'></a>";
16656 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016657 if($OldStyle) {
16658 $ADDED_INTERFACES = "<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES;
16659 }
16660 else {
16661 $ADDED_INTERFACES = "<h2>Added Symbols <span".getStyle("I", "Added", $Added_Number).">&nbsp;$Added_Number&nbsp;</span></h2><hr/>\n".$ADDED_INTERFACES;
16662 }
16663 $ADDED_INTERFACES = $Anchor.$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016664 }
16665 }
16666 return $ADDED_INTERFACES;
16667}
16668
16669sub get_Report_Removed($)
16670{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016671 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016672 my $REMOVED_INTERFACES = "";
16673 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016674 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016675 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016676 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016677 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016678 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016679 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016680 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16681 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016682 if($Level eq "Source" and $ReportFormat eq "html")
16683 { # do not show library name in HTML report
16684 $DyLib = "";
16685 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016686 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016687 }
16688 }
16689 }
16690 if($ReportFormat eq "xml")
16691 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016692 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016693 {
16694 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016695 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016696 {
16697 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016698 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16699 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016700 }
16701 $REMOVED_INTERFACES .= " </library>\n";
16702 }
16703 $REMOVED_INTERFACES .= " </header>\n";
16704 }
16705 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16706 }
16707 else
16708 { # HTML
16709 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016710 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016711 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016712 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016713 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016714 my %NameSpaceSymbols = ();
16715 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016716 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016717 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016718 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016719 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016720 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16721 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016722 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016723 {
16724 $Removed_Number += 1;
16725 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016726 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016727 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016728 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016729 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016730 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016731 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016732 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016733 $REMOVED_INTERFACES .= insertIDs($ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Symbol</b>]</span>\n<br/>\n<br/>\n".$ContentDivEnd."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016734 }
16735 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016736 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016737 }
16738 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016739 else
16740 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016741 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016742 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016743 }
16744 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016745 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016746 }
16747 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016748 }
16749 }
16750 $REMOVED_INTERFACES .= "<br/>\n";
16751 }
16752 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016753 if($REMOVED_INTERFACES)
16754 {
16755 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16756 if($JoinReport) {
16757 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16758 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016759 if($OldStyle) {
16760 $REMOVED_INTERFACES = "<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES;
16761 }
16762 else {
16763 $REMOVED_INTERFACES = "<h2>Removed Symbols <span".getStyle("I", "Removed", $Removed_Number).">&nbsp;$Removed_Number&nbsp;</span></h2><hr/>\n".$REMOVED_INTERFACES;
16764 }
16765
16766 $REMOVED_INTERFACES = $Anchor.$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016767 }
16768 }
16769 return $REMOVED_INTERFACES;
16770}
16771
16772sub getXmlParams($$)
16773{
16774 my ($Content, $Problem) = @_;
16775 return "" if(not $Content or not $Problem);
16776 my %XMLparams = ();
16777 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16778 {
16779 my $Macro = "\@".lc($Attr);
16780 if($Content=~/\Q$Macro\E/) {
16781 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16782 }
16783 }
16784 my @PString = ();
16785 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016786 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016787 }
16788 if(@PString) {
16789 return " ".join(" ", @PString);
16790 }
16791 else {
16792 return "";
16793 }
16794}
16795
16796sub addMarkup($)
16797{
16798 my $Content = $_[0];
16799 # auto-markup
16800 $Content=~s/\n[ ]*//; # spaces
16801 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16802 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016803 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016804 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16805 if($Content=~/\ANOTE:/)
16806 { # notes
16807 $Content=~s!(NOTE):!<b>$1</b>:!g;
16808 }
16809 else {
16810 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16811 }
16812 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16813 my @Keywords = (
16814 "void",
16815 "const",
16816 "static",
16817 "restrict",
16818 "volatile",
16819 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016820 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016821 );
16822 my $MKeys = join("|", @Keywords);
16823 foreach (@Keywords) {
16824 $MKeys .= "|non-".$_;
16825 }
16826 $Content=~s!(added\s*|to\s*|from\s*|became\s*)($MKeys)([^\w-]|\Z)!$1<b>$2</b>$3!ig; # intrinsic types, modifiers
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016827
16828 # Markdown
16829 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16830 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016831 return $Content;
16832}
16833
16834sub applyMacroses($$$$)
16835{
16836 my ($Level, $Kind, $Content, $Problem) = @_;
16837 return "" if(not $Content or not $Problem);
16838 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16839 $Content = addMarkup($Content);
16840 # macros
16841 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16842 {
16843 my $Macro = "\@".lc($Attr);
16844 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016845 if(not defined $Value
16846 or $Value eq "") {
16847 next;
16848 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016849
16850 if(index($Content, $Macro)==-1) {
16851 next;
16852 }
16853
16854 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16855 and $Kind!~/_Type_/
16856 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016857 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016858 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016859 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016860 $Value = black_name($Value);
16861 }
16862 elsif($Value=~/\s/) {
16863 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16864 }
16865 elsif($Value=~/\A\d+\Z/
16866 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16867 { # bits to bytes
16868 if($Value % $BYTE_SIZE)
16869 { # bits
16870 if($Value==1) {
16871 $Value = "<b>".$Value."</b> bit";
16872 }
16873 else {
16874 $Value = "<b>".$Value."</b> bits";
16875 }
16876 }
16877 else
16878 { # bytes
16879 $Value /= $BYTE_SIZE;
16880 if($Value==1) {
16881 $Value = "<b>".$Value."</b> byte";
16882 }
16883 else {
16884 $Value = "<b>".$Value."</b> bytes";
16885 }
16886 }
16887 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016888 else
16889 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016890 $Value = "<b>".htmlSpecChars($Value)."</b>";
16891 }
16892 $Content=~s/\Q$Macro\E/$Value/g;
16893 }
16894
16895 if($Content=~/(\A|[^\@\w])\@\w/)
16896 {
16897 if(not $IncompleteRules{$Level}{$Kind})
16898 { # only one warning
16899 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16900 $IncompleteRules{$Level}{$Kind} = 1;
16901 }
16902 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016903 return $Content;
16904}
16905
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016906sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016907{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016908 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016909 my $INTERFACE_PROBLEMS = "";
16910 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016911
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016912 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016913 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016914 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16915 if($SV and defined $CompatProblems{$Level}{$SN}) {
16916 next;
16917 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016918 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16919 my $DyLib = $Symbol_Library{1}{$Symbol};
16920 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
16921 { # Symbol with Version
16922 $DyLib = $Symbol_Library{1}{$VSym};
16923 }
16924 if(not $DyLib)
16925 { # const global data
16926 $DyLib = "";
16927 }
16928 if($Level eq "Source" and $ReportFormat eq "html")
16929 { # do not show library name in HTML report
16930 $DyLib = "";
16931 }
16932
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016933 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016934 {
16935 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016936 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016937 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016938 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16939 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016940 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016941 if($Severity eq $TargetSeverity)
16942 {
16943 $SymbolChanges{$Symbol}{$Kind} = $CompatProblems{$Level}{$Symbol}{$Kind};
16944 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016945 }
16946 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016947 }
16948 }
16949 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016950
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016951 if($ReportFormat eq "xml")
16952 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016953 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016954 {
16955 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016956 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016957 {
16958 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016959 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16960 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016961 {
16962 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016963 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016964 {
16965 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16966 {
16967 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016968 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016969
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016970 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16971 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16972 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16973 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16974 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016975 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16976 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16977 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016978 $INTERFACE_PROBLEMS .= " </problem>\n";
16979 }
16980 }
16981 $INTERFACE_PROBLEMS .= " </symbol>\n";
16982 }
16983 $INTERFACE_PROBLEMS .= " </library>\n";
16984 }
16985 $INTERFACE_PROBLEMS .= " </header>\n";
16986 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016987 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016988 }
16989 else
16990 { # HTML
16991 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016992 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016993 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016994 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016995 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016996 my (%NameSpaceSymbols, %NewSignature) = ();
16997 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016998 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016999 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017000 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017001 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017002 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030017003 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} sort keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017004 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017005 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017006 my $Signature = get_Signature($Symbol, 1);
17007 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017008 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030017009 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017010 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017011 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017012 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017013 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017014 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017015 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017016 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017017 }
17018 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17019 {
17020 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017021 $SYMBOL_REPORT .= "<tr>\n<th>$ProblemNum</th>\n<td>".$Change."</td>\n<td>".$Effect."</td>\n</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017022 $ProblemNum += 1;
17023 $ProblemsNum += 1;
17024 }
17025 }
17026 }
17027 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017028 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017029 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017030 my $ShowSymbol = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017031 if($Signature) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017032 $ShowSymbol = highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017033 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017034
17035 if($NameSpace)
17036 {
17037 $SYMBOL_REPORT = cut_Namespace($SYMBOL_REPORT, $NameSpace);
17038 $ShowSymbol = cut_Namespace($ShowSymbol, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017039 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017040
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017041 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowSymbol;
17042 if($OldStyle) {
17043 $INTERFACE_PROBLEMS .= " ($ProblemNum)";
17044 }
17045 else {
17046 $INTERFACE_PROBLEMS .= " <span".getStyle("I", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>";
17047 }
17048 $INTERFACE_PROBLEMS .= $ContentSpanEnd."<br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017049 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017050
17051 if(my $NSign = $NewSignature{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017052 { # argument list changed to
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017053 if($NameSpace) {
17054 $NSign = cut_Namespace($NSign, $NameSpace);
17055 }
17056 $INTERFACE_PROBLEMS .= "\n<span class='new_sign_lbl'>changed to:</span>\n<br/>\n<span class='new_sign'>".highLight_Signature_Italic_Color($NSign)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017057 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017058
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017059 if($Symbol=~/\A(_Z|\?)/) {
17060 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
17061 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017062
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017063 $INTERFACE_PROBLEMS .= "<table class='ptable'>\n<tr>\n<th width='2%'></th>\n<th width='47%'>Change</th>\n<th>Effect</th>\n</tr>\n$SYMBOL_REPORT</table>\n<br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017064 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017065 }
17066 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017067 $INTERFACE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017068 }
17069 }
17070 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017071
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017072 if($INTERFACE_PROBLEMS)
17073 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017074 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
17075 my $Title = "Problems with Symbols, $TargetSeverity Severity";
17076 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017077 { # Safe Changes
17078 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017079 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017080 if($OldStyle) {
17081 $INTERFACE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$INTERFACE_PROBLEMS;
17082 }
17083 else {
17084 $INTERFACE_PROBLEMS = "<h2>$Title <span".getStyle("I", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$INTERFACE_PROBLEMS;
17085 }
17086 $INTERFACE_PROBLEMS = "<a name=\'".get_Anchor("Symbol", $Level, $TargetSeverity)."\'></a><a name=\'".get_Anchor("Interface", $Level, $TargetSeverity)."\'></a>\n".$INTERFACE_PROBLEMS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017087 }
17088 }
17089 return $INTERFACE_PROBLEMS;
17090}
17091
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017092sub cut_Namespace($$)
17093{
17094 my ($N, $Ns) = @_;
17095 $N=~s/\b\Q$Ns\E:://g;
17096 return $N;
17097}
17098
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017099sub get_Report_TypeProblems($$)
17100{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017101 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017102 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017103
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017104 my %ReportMap = ();
17105 my %TypeChanges_Sev = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017106
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017107 foreach my $TypeName (keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017108 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017109 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
17110
17111 foreach my $Kind (keys(%{$TypeChanges{$Level}{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017112 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017113 foreach my $Location (keys(%{$TypeChanges{$Level}{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017114 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017115 my $Target = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017116 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017117
17118 if($Severity eq $TargetSeverity)
17119 {
17120 $ReportMap{$HeaderName}{$TypeName} = 1;
17121 $TypeChanges_Sev{$TypeName}{$Kind}{$Location} = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017122 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017123 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017124 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017125 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017126
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017127 if($ReportFormat eq "xml")
17128 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017129 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017130 {
17131 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017132 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017133 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017134 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017135 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017136 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017137 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017138 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017139 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017140 $Kinds_Locations{$Kind}{$Location} = 1;
17141
17142 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17143 if($Kinds_Target{$Kind}{$Target}) {
17144 next;
17145 }
17146 $Kinds_Target{$Kind}{$Target} = 1;
17147
17148 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017149 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
17150 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
17151 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
17152 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
17153 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017154 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
17155 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
17156 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017157 $TYPE_PROBLEMS .= " </problem>\n";
17158 }
17159 }
Andrey Ponomarenkof9f25c92016-07-26 17:20:17 +030017160 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
17161 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017162 $TYPE_PROBLEMS .= showVTables($TypeName);
17163 }
17164 $TYPE_PROBLEMS .= " </type>\n";
17165 }
17166 $TYPE_PROBLEMS .= " </header>\n";
17167 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017168 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017169 }
17170 else
17171 { # HTML
17172 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017173 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017174 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017175 my (%NameSpace_Type) = ();
17176 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017177 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017178 }
17179 foreach my $NameSpace (sort keys(%NameSpace_Type))
17180 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017181 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017182 my @SortedTypes = sort {lc(show_Type($a, 0, 1)) cmp lc(show_Type($b, 0, 1))} keys(%{$NameSpace_Type{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017183 foreach my $TypeName (@SortedTypes)
17184 {
17185 my $ProblemNum = 1;
17186 my $TYPE_REPORT = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017187 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017188
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017189 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017190 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017191 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017192 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017193 $Kinds_Locations{$Kind}{$Location} = 1;
17194
17195 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17196 if($Kinds_Target{$Kind}{$Target}) {
17197 next;
17198 }
17199 $Kinds_Target{$Kind}{$Target} = 1;
17200
17201 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017202 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17203 {
17204 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017205 $TYPE_REPORT .= "<tr>\n<th>$ProblemNum</th>\n<td>".$Change."</td>\n<td>$Effect</td>\n</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017206 $ProblemNum += 1;
17207 $ProblemsNum += 1;
17208 }
17209 }
17210 }
17211 $ProblemNum -= 1;
17212 if($TYPE_REPORT)
17213 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017214 my $Affected = getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017215 my $ShowVTables = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017216 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017217 $ShowVTables = showVTables($TypeName);
17218 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017219
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017220 my $ShowType = show_Type($TypeName, 1, 1);
17221
17222 if($NameSpace)
17223 {
17224 $TYPE_REPORT = cut_Namespace($TYPE_REPORT, $NameSpace);
17225 $ShowType = cut_Namespace($ShowType, $NameSpace);
17226 $Affected = cut_Namespace($Affected, $NameSpace);
17227 $ShowVTables = cut_Namespace($ShowVTables, $NameSpace);
17228 }
17229
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017230 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowType;
17231 if($OldStyle) {
17232 $TYPE_PROBLEMS .= " ($ProblemNum)";
17233 }
17234 else {
17235 $TYPE_PROBLEMS .= " <span".getStyle("T", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>";
17236 }
17237 $TYPE_PROBLEMS .= $ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017238 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
17239 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
17240 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
17241 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017242 }
17243 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017244 $TYPE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017245 }
17246 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017247
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017248 if($TYPE_PROBLEMS)
17249 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017250 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
17251 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017252 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017253 { # Safe Changes
17254 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017255 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017256 if($OldStyle) {
17257 $TYPE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$TYPE_PROBLEMS;
17258 }
17259 else {
17260 $TYPE_PROBLEMS = "<h2>$Title <span".getStyle("T", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$TYPE_PROBLEMS;
17261 }
17262 $TYPE_PROBLEMS = "<a name=\'".get_Anchor("Type", $Level, $TargetSeverity)."\'></a>\n".$TYPE_PROBLEMS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017263 }
17264 }
17265 return $TYPE_PROBLEMS;
17266}
17267
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017268sub show_Type($$$)
17269{
17270 my ($Name, $Html, $LibVersion) = @_;
17271 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
17272 $TType = lc($TType);
17273 if($TType=~/struct|union|enum/) {
17274 $Name=~s/\A\Q$TType\E //g;
17275 }
17276 if($Html) {
17277 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
17278 }
17279 else {
17280 $Name = $TType." ".$Name;
17281 }
17282 return $Name;
17283}
17284
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017285sub get_Anchor($$$)
17286{
17287 my ($Kind, $Level, $Severity) = @_;
17288 if($JoinReport)
17289 {
17290 if($Severity eq "Safe") {
17291 return "Other_".$Level."_Changes_In_".$Kind."s";
17292 }
17293 else {
17294 return $Kind."_".$Level."_Problems_".$Severity;
17295 }
17296 }
17297 else
17298 {
17299 if($Severity eq "Safe") {
17300 return "Other_Changes_In_".$Kind."s";
17301 }
17302 else {
17303 return $Kind."_Problems_".$Severity;
17304 }
17305 }
17306}
17307
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017308sub showVTables($)
17309{
17310 my $TypeName = $_[0];
17311 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017312 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017313 if(defined $Type1{"VTable"}
17314 and keys(%{$Type1{"VTable"}}))
17315 {
17316 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017317 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017318 if(defined $Type2{"VTable"}
17319 and keys(%{$Type2{"VTable"}}))
17320 {
17321 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17322 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017323 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017324 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017325 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17326 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017327 }
17328 my $VTABLES = "";
17329 if($ReportFormat eq "xml")
17330 { # XML
17331 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017332 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017333 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017334 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017335 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17336 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017337 $VTABLES .= " </entry>\n";
17338 }
17339 $VTABLES .= " </vtable>\n\n";
17340 }
17341 else
17342 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017343 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017344 $VTABLES .= "<tr><th>Offset</th>";
17345 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017346 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017347 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017348 {
17349 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017350
17351 my $E1 = $Entries{$Index}{"E1"};
17352 my $E2 = $Entries{$Index}{"E2"};
17353
17354 if($E1 ne $E2
17355 and $E1!~/ 0x/
17356 and $E2!~/ 0x/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017357 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017358 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017359 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017360 $Color1 = " class='failed'";
17361 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017362 }
17363 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017364 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017365 }
17366 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017367 $VTABLES .= "<tr><th>".$Index."</th>\n";
17368 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17369 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017370 }
17371 $VTABLES .= "</table><br/>\n";
17372 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017373 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017374 }
17375 return $VTABLES;
17376 }
17377 }
17378 return "";
17379}
17380
17381sub simpleVEntry($)
17382{
17383 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017384 if(not defined $VEntry
17385 or $VEntry eq "") {
17386 return "";
17387 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017388
17389 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017390 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17391 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17392 if($VEntry=~/\A_ZThn.+\Z/) {
17393 $VEntry = "non-virtual thunk";
17394 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017395 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017396 # support for old GCC versions
17397 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17398 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17399 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017400 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17401 return $VEntry;
17402}
17403
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017404sub adjustParamPos($$$)
17405{
17406 my ($Pos, $Symbol, $LibVersion) = @_;
17407 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17408 {
17409 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17410 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17411 {
17412 return $Pos-1;
17413 }
17414
17415 return $Pos;
17416 }
17417
17418 return undef;
17419}
17420
17421sub getParamPos($$$)
17422{
17423 my ($Name, $Symbol, $LibVersion) = @_;
17424
17425 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17426 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17427 {
17428 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17429 foreach (keys(%{$Info->{"Param"}}))
17430 {
17431 if($Info->{"Param"}{$_}{"name"} eq $Name)
17432 {
17433 return $_;
17434 }
17435 }
17436 }
17437
17438 return undef;
17439}
17440
17441sub getParamName($)
17442{
17443 my $Loc = $_[0];
17444 $Loc=~s/\->.*//g;
17445 return $Loc;
17446}
17447
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017448sub getAffectedSymbols($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017449{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017450 my ($Level, $Target_TypeName, $Kinds_Locations) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017451
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017452 my $LIMIT = 10;
17453 if(defined $AffectLimit) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017454 $LIMIT = $AffectLimit;
17455 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017456
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017457 my @Kinds = sort keys(%{$Kinds_Locations});
17458 my %KLocs = ();
17459 foreach my $Kind (@Kinds)
17460 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017461 my @Locs = sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$Kinds_Locations->{$Kind}});
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017462 $KLocs{$Kind} = \@Locs;
17463 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017464
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017465 my %SymLocKind = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017466 foreach my $Symbol (sort keys(%{$TypeProblemsIndex{$Level}{$Target_TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017467 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017468 if(index($Symbol, "_Z")==0
17469 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017470 { # duplicated problems for C2 constructors, D2 and D0 destructors
17471 next;
17472 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017473
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017474 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017475 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017476 foreach my $Loc (@{$KLocs{$Kind}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017477 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017478 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017479 next;
17480 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017481
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017482 if(index($Symbol, "\@")!=-1
17483 or index($Symbol, "\$")!=-1)
17484 {
17485 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17486
17487 if($Level eq "Source")
17488 { # remove symbol version
17489 $Symbol = $SN;
17490 }
17491
17492 if($SV and defined $CompatProblems{$Level}{$SN}
17493 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
17494 { # duplicated problems for versioned symbols
17495 next;
17496 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017497 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017498
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017499 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017500 if($Type_Name ne $Target_TypeName) {
17501 next;
17502 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017503
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017504 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017505 last;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017506 }
17507 }
17508 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017509
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017510 %KLocs = (); # clear
17511
17512 my %SymSel = ();
17513 my $Num = 0;
17514 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymLocKind))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017515 {
17516 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17517 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017518 foreach my $Kind (sort keys(%{$SymLocKind{$Symbol}{$Loc}}))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017519 {
17520 $SymSel{$Symbol}{"Loc"} = $Loc;
17521 $SymSel{$Symbol}{"Kind"} = $Kind;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017522 last LOOP;
17523 }
17524 }
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017525
17526 $Num += 1;
17527
17528 if($Num>=$LIMIT) {
17529 last;
17530 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017531 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017532
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017533 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017534
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017535 if($ReportFormat eq "xml")
17536 { # XML
17537 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017538
17539 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017540 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017541 my $Kind = $SymSel{$Symbol}{"Kind"};
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017542 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017543
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017544 my $PName = getParamName($Loc);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017545 my $Desc = getAffectDesc($Level, $Symbol, $Kind, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017546
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017547 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017548 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017549 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017550 $Target .= " param=\"$PName\"";
17551 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017552 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017553 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017554 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017555 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017556 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017557 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017558 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017559
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017560 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017561 $Target .= " field=\"$1\"";
17562 }
17563
17564 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017565 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017566 $Affected .= " </symbol>\n";
17567 }
17568 $Affected .= " </affected>\n";
17569 }
17570 else
17571 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017572 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017573 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017574 my $Kind = $SymSel{$Symbol}{"Kind"};
17575 my $Loc = $SymSel{$Symbol}{"Loc"};
17576
17577 my $Desc = getAffectDesc($Level, $Symbol, $Kind, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017578 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017579 my $PName = getParamName($Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017580 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17581
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017582 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017583 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017584 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017585
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017586 if(keys(%SymLocKind)>$LIMIT) {
17587 $Affected .= " <b>...</b>\n<br/>\n"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017588 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017589
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017590 $Affected = "<div class='affected'>".$Affected."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017591 if($Affected)
17592 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017593 my $Num = keys(%SymLocKind);
17594 my $Per = show_number($Num*100/keys(%{$CheckedSymbols{$Level}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017595 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017596 $Affected = $ContentSpanStart_Affected."[+] affected symbols: $Num ($Per\%)".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017597 }
17598 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017599
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017600 return $Affected;
17601}
17602
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017603sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017604{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017605 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017606 if($L2=~/\A(retval|this)\b/
17607 and $L1!~/\A(retval|this)\b/)
17608 {
17609 if($L1!~/\-\>/) {
17610 return 1;
17611 }
17612 elsif($L2=~/\-\>/) {
17613 return 1;
17614 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017615 }
17616 return 0;
17617}
17618
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017619sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017620{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017621 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017622
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017623 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017624
17625 my $Location_I = $Location;
17626 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17627
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017628 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017629
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017630 if($Kind eq "Overridden_Virtual_Method"
17631 or $Kind eq "Overridden_Virtual_Method_B") {
17632 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17633 }
17634 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17635 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017636 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17637
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017638 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17639 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017640 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17641 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17642
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017643 if($ClassName eq $Problem{"Type_Name"}) {
17644 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17645 }
17646 else {
17647 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17648 }
17649 }
17650 else
17651 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017652 my $TypeID = undef;
17653
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017654 if($Location=~/retval/)
17655 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017656 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017657 push(@Sentence, "Field \'".$Location."\' in return value");
17658 }
17659 else {
17660 push(@Sentence, "Return value");
17661 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017662
17663 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017664 }
17665 elsif($Location=~/this/)
17666 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017667 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017668 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17669 }
17670 else {
17671 push(@Sentence, "\'this\' pointer");
17672 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017673
17674 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017675 }
17676 else
17677 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017678
17679 my $PName = getParamName($Location);
17680 my $PPos = getParamPos($PName, $Symbol, 1);
17681
17682 if(index($Location, "->")!=-1) {
17683 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017684 }
17685 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017686 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017687 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017688 if($PName) {
17689 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017690 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017691
17692 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17693 }
17694
17695 if($Location!~/this/)
17696 {
17697 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017698 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017699 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017700 push(@Sentence, "(pointer)");
17701 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017702 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017703 push(@Sentence, "(reference)");
17704 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017705 }
17706 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017707
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017708 if($Location eq "this") {
17709 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17710 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017711 else
17712 {
17713 my $Location_T = $Location;
17714 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17715
17716 my $TypeID_Problem = $TypeID;
17717 if($Location_T) {
17718 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17719 }
17720
17721 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17722 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17723 }
17724 else {
17725 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17726 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017727 }
17728 }
17729 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017730 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017731 push(@Sentence, " This is a symbol from an external library that may use the \'$TargetLibraryName\' library and change the ABI after recompiling.");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017732 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017733
17734 my $Sent = join(" ", @Sentence);
17735
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017736 $Sent=~s/->/./g;
17737
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017738 if($ReportFormat eq "xml")
17739 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017740 $Sent=~s/'//g;
17741 }
17742
17743 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017744}
17745
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017746sub getFieldType($$$)
17747{
17748 my ($Location, $TypeId, $LibVersion) = @_;
17749
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017750 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017751
17752 foreach my $Name (@Fields)
17753 {
17754 my %Info = get_BaseType($TypeId, $LibVersion);
17755
17756 foreach my $Pos (keys(%{$Info{"Memb"}}))
17757 {
17758 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17759 {
17760 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17761 last;
17762 }
17763 }
17764 }
17765
17766 return $TypeId;
17767}
17768
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017769sub get_XmlSign($$)
17770{
17771 my ($Symbol, $LibVersion) = @_;
17772 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17773 my $Report = "";
17774 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17775 {
17776 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017777 my $Type = $Info->{"Param"}{$Pos}{"type"};
17778 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017779 foreach my $Typedef (keys(%ChangedTypedef))
17780 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017781 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17782 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17783 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017784 }
17785 $Report .= " <param pos=\"$Pos\">\n";
17786 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017787 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017788 $Report .= " </param>\n";
17789 }
17790 if(my $Return = $Info->{"Return"})
17791 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017792 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017793 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017794 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017795 $Report .= " </retval>\n";
17796 }
17797 return $Report;
17798}
17799
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017800sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017801{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017802 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017803 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017804 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017805 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017806 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17807 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017808 next;
17809 }
17810 $Report .= " <symbol name=\"$Symbol\">\n";
17811 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017812 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017813 {
17814 if(defined $CompleteSignature{1}{$Symbol}
17815 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17816 {
17817 $P1 = get_XmlSign($Symbol, 1);
17818 $S1 = get_Signature($Symbol, 1);
17819 }
17820 elsif($Symbol=~/\A(_Z|\?)/) {
17821 $S1 = $tr_name{$Symbol};
17822 }
17823 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017824 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017825 {
17826 if(defined $CompleteSignature{2}{$Symbol}
17827 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17828 {
17829 $P2 = get_XmlSign($Symbol, 2);
17830 $S2 = get_Signature($Symbol, 2);
17831 }
17832 elsif($Symbol=~/\A(_Z|\?)/) {
17833 $S2 = $tr_name{$Symbol};
17834 }
17835 }
17836 if($S1)
17837 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017838 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017839 $Report .= $P1;
17840 $Report .= " </old>\n";
17841 }
17842 if($S2 and $S2 ne $S1)
17843 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017844 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017845 $Report .= $P2;
17846 $Report .= " </new>\n";
17847 }
17848 $Report .= " </symbol>\n";
17849 }
17850 $Report .= "</symbols_info>\n";
17851 return $Report;
17852}
17853
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017854sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017855{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017856 my ($Level, $Report) = @_;
17857 if($ReportFormat eq "xml") {
17858 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017859 }
17860 if($StdOut)
17861 { # --stdout option
17862 print STDOUT $Report;
17863 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017864 else
17865 {
17866 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017867 mkpath(get_dirname($RPath));
17868
17869 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17870 print REPORT $Report;
17871 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017872 }
17873}
17874
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017875sub getReport($)
17876{
17877 my $Level = $_[0];
17878 if($ReportFormat eq "xml")
17879 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017880 if($Level eq "Join")
17881 {
17882 my $Report = "<reports>\n";
17883 $Report .= getReport("Binary");
17884 $Report .= getReport("Source");
17885 $Report .= "</reports>\n";
17886 return $Report;
17887 }
17888 else
17889 {
17890 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17891 my ($Summary, $MetaData) = get_Summary($Level);
17892 $Report .= $Summary."\n";
17893 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17894 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017895
17896 # additional symbols info (if needed)
17897 # $Report .= get_Report_SymbolsInfo($Level);
17898
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017899 $Report .= "</report>\n";
17900 return $Report;
17901 }
17902 }
17903 else
17904 { # HTML
17905 my $CssStyles = readModule("Styles", "Report.css");
17906 my $JScripts = readModule("Scripts", "Sections.js");
17907 if($Level eq "Join")
17908 {
17909 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17910 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017911 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017912 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17913 my $Description = "API/ABI compatibility report for the $TargetTitle $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017914 my ($BSummary, $BMetaData) = get_Summary("Binary");
17915 my ($SSummary, $SMetaData) = get_Summary("Source");
17916 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>";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017917 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017918 <br/>
17919 <div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017920 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17921 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017922 </div>";
17923 $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>";
17924 $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>";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017925 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017926 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017927 return $Report;
17928 }
17929 else
17930 {
17931 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017932 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17933 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17934 my $Description = "$Level compatibility report for the ".$TargetTitle." ".$TargetComponent." between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017935 if($Level eq "Binary")
17936 {
17937 if(getArch(1) eq getArch(2)
17938 and getArch(1) ne "unknown") {
17939 $Description .= " on ".showArch(getArch(1));
17940 }
17941 }
17942 my $Report = "<!-\- $MetaData -\->\n".composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."\n<body>\n<div><a name='Top'></a>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017943 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017944 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17945 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17946 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017947 $Report .= "</div>\n<br/><br/><br/>\n";
17948 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017949 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017950 return $Report;
17951 }
17952 }
17953}
17954
17955sub createReport()
17956{
17957 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017958 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017959 writeReport("Join", getReport("Join"));
17960 }
17961 elsif($DoubleReport)
17962 { # default
17963 writeReport("Binary", getReport("Binary"));
17964 writeReport("Source", getReport("Source"));
17965 }
17966 elsif($BinaryOnly)
17967 { # --binary
17968 writeReport("Binary", getReport("Binary"));
17969 }
17970 elsif($SourceOnly)
17971 { # --source
17972 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017973 }
17974}
17975
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017976sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017977{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017978 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017979
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017980 $Footer .= "<hr/>\n";
17981 $Footer .= "<div class='footer' align='right'>";
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030017982 $Footer .= "<i>Generated by <a href='".$HomePage{"Dev"}."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;</i>\n";
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017983 $Footer .= "</div>\n";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017984 $Footer .= "<br/>\n";
17985
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017986 return $Footer;
17987}
17988
17989sub get_Report_Problems($$)
17990{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017991 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017992
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017993 my $Report = get_Report_TypeProblems($Severity, $Level);
17994 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017995 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017996 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017997
17998 if($Severity eq "Low" or $Severity eq "Safe") {
17999 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018000 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030018001
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018002 if($ReportFormat eq "html")
18003 {
18004 if($Report)
18005 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018006 if($JoinReport)
18007 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040018008 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018009 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
18010 }
18011 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040018012 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018013 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018014 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018015 else
18016 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040018017 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018018 $Report = "<a name=\'Other_Changes\'></a>".$Report;
18019 }
18020 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040018021 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018022 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018023 }
18024 }
18025 }
18026 return $Report;
18027}
18028
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018029sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018030{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018031 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +030018032
18033 my $Head = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
18034 $Head .= "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n";
18035 $Head .= "<head>\n";
18036 $Head .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
18037 $Head .= "<meta name=\"keywords\" content=\"$Keywords\" />\n";
18038 $Head .= "<meta name=\"description\" content=\"$Description\" />\n";
18039 $Head .= "<title>$Title</title>\n";
18040 $Head .= "<style type=\"text/css\">\n$Styles</style>\n";
18041 $Head .= "<script type=\"text/javascript\" language=\"JavaScript\">\n<!--\n$Scripts\n-->\n</script>\n";
18042 $Head .= "</head>\n";
18043
18044 return $Head;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018045}
18046
18047sub insertIDs($)
18048{
18049 my $Text = $_[0];
18050 while($Text=~/CONTENT_ID/)
18051 {
18052 if(int($Content_Counter)%2) {
18053 $ContentID -= 1;
18054 }
18055 $Text=~s/CONTENT_ID/c_$ContentID/;
18056 $ContentID += 1;
18057 $Content_Counter += 1;
18058 }
18059 return $Text;
18060}
18061
18062sub checkPreprocessedUnit($)
18063{
18064 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018065 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018066 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018067 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018068
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018069 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018070 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018071 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018072 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018073 chomp($Line);
18074 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018075 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018076 $CurHeader = path_format($1, $OSgroup);
18077 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018078 $CurClass = "";
18079
18080 if(index($CurHeader, $TMP_DIR)==0) {
18081 next;
18082 }
18083
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018084 if(substr($CurHeaderName, 0, 1) eq "<")
18085 { # <built-in>, <command-line>, etc.
18086 $CurHeaderName = "";
18087 $CurHeader = "";
18088 }
18089
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018090 if($ExtraInfo)
18091 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018092 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018093 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
18094 }
18095 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018096 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018097 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018098 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018099 if($CurHeaderName)
18100 {
18101 if(not $Include_Neighbors{$Version}{$CurHeaderName}
18102 and not $Registered_Headers{$Version}{$CurHeader})
18103 { # not a target
18104 next;
18105 }
18106 if(not is_target_header($CurHeaderName, 1)
18107 and not is_target_header($CurHeaderName, 2))
18108 { # user-defined header
18109 next;
18110 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018111 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018112 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018113
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018114 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018115 {
18116 my ($Name, $Value) = ($1, $2);
18117 if(not $Constants{$Version}{$Name}{"Access"})
18118 {
18119 $Constants{$Version}{$Name}{"Access"} = "public";
18120 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018121 if($CurHeaderName) {
18122 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
18123 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018124 }
18125 }
18126 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
18127 $Constants{$Version}{$1}{"Access"} = "private";
18128 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018129 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018130 else
18131 {
18132 if(defined $ExtraDump)
18133 {
18134 if($Line=~/(\w+)\s*\(/)
18135 { # functions
18136 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18137 }
18138 #elsif($Line=~/(\w+)\s*;/)
18139 #{ # data
18140 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18141 #}
18142 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
18143 $CurClass = $2;
18144 }
18145 }
18146 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018147 }
18148 close(PREPROC);
18149 foreach my $Constant (keys(%{$Constants{$Version}}))
18150 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018151 if($Constants{$Version}{$Constant}{"Access"} eq "private")
18152 {
18153 delete($Constants{$Version}{$Constant});
18154 next;
18155 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040018156 if(not $ExtraDump and ($Constant=~/_h\Z/i
18157 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018158 { # skip
18159 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018160 }
18161 else {
18162 delete($Constants{$Version}{$Constant}{"Access"});
18163 }
18164 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018165 if($Debug)
18166 {
18167 mkpath($DEBUG_PATH{$Version});
18168 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
18169 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018170}
18171
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018172sub uncoverConstant($$)
18173{
18174 my ($LibVersion, $Constant) = @_;
18175 return "" if(not $LibVersion or not $Constant);
18176 return $Constant if(isCyclical(\@RecurConstant, $Constant));
18177 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
18178 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
18179 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018180
18181 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018182 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018183 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
18184 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018185 {
18186 push(@RecurConstant, $Constant);
18187 my $Uncovered = uncoverConstant($LibVersion, $Value);
18188 if($Uncovered ne "") {
18189 $Value = $Uncovered;
18190 }
18191 pop(@RecurConstant);
18192 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018193
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018194 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018195 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018196 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
18197 }
18198 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
18199}
18200
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018201sub simpleConstant($$)
18202{
18203 my ($LibVersion, $Value) = @_;
18204 if($Value=~/\W/)
18205 {
18206 my $Value_Copy = $Value;
18207 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
18208 {
18209 my $Word = $1;
18210 if($Value!~/$Word\s*\(/)
18211 {
18212 my $Val = uncoverConstant($LibVersion, $Word);
18213 if($Val ne "")
18214 {
18215 $Value=~s/\b$Word\b/$Val/g;
18216 }
18217 }
18218 }
18219 }
18220 return $Value;
18221}
18222
18223sub computeValue($)
18224{
18225 my $Value = $_[0];
18226
18227 if($Value=~/\A\((-?[\d]+)\)\Z/) {
18228 return $1;
18229 }
18230
18231 if($Value=~/\A[\d\-\+()]+\Z/) {
18232 return eval($Value);
18233 }
18234
18235 return $Value;
18236}
18237
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018238my %IgnoreConstant = map {$_=>1} (
18239 "VERSION",
18240 "VERSIONCODE",
18241 "VERNUM",
18242 "VERS_INFO",
18243 "PATCHLEVEL",
18244 "INSTALLPREFIX",
18245 "VBUILD",
18246 "VPATCH",
18247 "VMINOR",
18248 "BUILD_STRING",
18249 "BUILD_TIME",
18250 "PACKAGE_STRING",
18251 "PRODUCTION",
18252 "CONFIGURE_COMMAND",
18253 "INSTALLDIR",
18254 "BINDIR",
18255 "CONFIG_FILE_PATH",
18256 "DATADIR",
18257 "EXTENSION_DIR",
18258 "INCLUDE_PATH",
18259 "LIBDIR",
18260 "LOCALSTATEDIR",
18261 "SBINDIR",
18262 "SYSCONFDIR",
18263 "RELEASE",
18264 "SOURCE_ID",
18265 "SUBMINOR",
18266 "MINOR",
18267 "MINNOR",
18268 "MINORVERSION",
18269 "MAJOR",
18270 "MAJORVERSION",
18271 "MICRO",
18272 "MICROVERSION",
18273 "BINARY_AGE",
18274 "INTERFACE_AGE",
18275 "CORE_ABI",
18276 "PATCH",
18277 "COPYRIGHT",
18278 "TIMESTAMP",
18279 "REVISION",
18280 "PACKAGE_TAG",
18281 "PACKAGEDATE",
18282 "NUMVERSION",
18283 "Release",
18284 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018285);
18286
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018287sub constantFilter($$$)
18288{
18289 my ($Name, $Value, $Level) = @_;
18290
18291 if($Level eq "Binary")
18292 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018293 if($Name=~/_t\Z/)
18294 { # __malloc_ptr_t
18295 return 1;
18296 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018297 foreach (keys(%IgnoreConstant))
18298 {
18299 if($Name=~/(\A|_)$_(_|\Z)/)
18300 { # version
18301 return 1;
18302 }
18303 if(/\A[A-Z].*[a-z]\Z/)
18304 {
18305 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18306 { # version
18307 return 1;
18308 }
18309 }
18310 }
18311 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18312 { # version
18313 return 1;
18314 }
18315 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18316 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18317 return 1;
18318 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018319
18320 if($Value=~/\A["'].*['"]/i)
18321 { # string
18322 return 0;
18323 }
18324
18325 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18326 { # static int gcry_pth_init
18327 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018328 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018329 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018330 return 1;
18331 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018332 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018333 { # foo(p)
18334 return 1;
18335 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018336 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018337 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018338 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018339 return 1;
18340 }
18341 }
18342
18343 return 0;
18344}
18345
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018346sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018347{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018348 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018349 foreach my $Constant (keys(%{$Constants{1}}))
18350 {
18351 if($SkipConstants{1}{$Constant})
18352 { # skipped by the user
18353 next;
18354 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018355
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018356 if(my $Header = $Constants{1}{$Constant}{"Header"})
18357 {
18358 if(not is_target_header($Header, 1)
18359 and not is_target_header($Header, 2))
18360 { # user-defined header
18361 next;
18362 }
18363 }
18364 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018365 next;
18366 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018367
18368 my $Old_Value = uncoverConstant(1, $Constant);
18369
18370 if(constantFilter($Constant, $Old_Value, $Level))
18371 { # separate binary and source problems
18372 next;
18373 }
18374
18375 if(not defined $Constants{2}{$Constant}{"Value"})
18376 { # removed
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030018377 if(not defined $SkipRemovedConstants)
18378 {
18379 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18380 "Target"=>$Constant,
18381 "Old_Value"=>$Old_Value );
18382 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018383 next;
18384 }
18385
18386 if($Constants{2}{$Constant}{"Value"} eq "")
18387 { # empty value
18388 # TODO: implement a rule
18389 next;
18390 }
18391
18392 my $New_Value = uncoverConstant(2, $Constant);
18393
18394 my $Old_Value_Pure = $Old_Value;
18395 my $New_Value_Pure = $New_Value;
18396
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018397 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18398 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18399 $New_Value_Pure=~s/(\W)\s+/$1/g;
18400 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018401
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018402 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018403
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018404 if($New_Value_Pure ne $Old_Value_Pure)
18405 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018406 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18407 { # complex values
18408 next;
18409 }
18410 if(computeValue($Old_Value) eq computeValue($New_Value))
18411 { # expressions
18412 next;
18413 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018414 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18415 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18416 next;
18417 }
18418 if($Old_Value eq "0" and $New_Value eq "NULL")
18419 { # 0 => NULL
18420 next;
18421 }
18422 if($Old_Value eq "NULL" and $New_Value eq "0")
18423 { # NULL => 0
18424 next;
18425 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018426 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018427 "Target"=>$Constant,
18428 "Old_Value"=>$Old_Value,
18429 "New_Value"=>$New_Value );
18430 }
18431 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018432
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030018433 if(defined $SkipAddedConstants) {
18434 return;
18435 }
18436
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018437 foreach my $Constant (keys(%{$Constants{2}}))
18438 {
18439 if(not defined $Constants{1}{$Constant}{"Value"})
18440 {
18441 if($SkipConstants{2}{$Constant})
18442 { # skipped by the user
18443 next;
18444 }
18445
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018446 if(my $Header = $Constants{2}{$Constant}{"Header"})
18447 {
18448 if(not is_target_header($Header, 1)
18449 and not is_target_header($Header, 2))
18450 { # user-defined header
18451 next;
18452 }
18453 }
18454 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018455 next;
18456 }
18457
18458 my $New_Value = uncoverConstant(2, $Constant);
18459 if(not defined $New_Value or $New_Value eq "") {
18460 next;
18461 }
18462
18463 if(constantFilter($Constant, $New_Value, $Level))
18464 { # separate binary and source problems
18465 next;
18466 }
18467
18468 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18469 "Target"=>$Constant,
18470 "New_Value"=>$New_Value );
18471 }
18472 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018473}
18474
18475sub convert_integer($)
18476{
18477 my $Value = $_[0];
18478 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018479 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018480 return hex($Value);
18481 }
18482 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018483 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018484 return oct($Value);
18485 }
18486 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018487 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018488 return oct($Value);
18489 }
18490 else {
18491 return $Value;
18492 }
18493}
18494
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018495sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018496{
18497 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018498 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018499 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018500 {
18501 if($LibVersion==1)
18502 {
18503 printMsg("WARNING", "checking headers only");
18504 $CheckHeadersOnly = 1;
18505 }
18506 else {
18507 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18508 }
18509 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018510
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018511 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018512 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018513 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018514
18515 if($CheckUndefined)
18516 {
18517 my %UndefinedLibs = ();
18518
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018519 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18520
18521 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018522 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018523 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018524 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018525 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018526 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018527 if($Symbol_Library{$LibVersion}{$Symbol}
18528 or $DepSymbol_Library{$LibVersion}{$Symbol})
18529 { # exported by target library
18530 next;
18531 }
18532 if(index($Symbol, '@')!=-1)
18533 { # exported default symbol version (@@)
18534 $Symbol=~s/\@/\@\@/;
18535 if($Symbol_Library{$LibVersion}{$Symbol}
18536 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18537 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018538 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018539 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018540 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18541 $UndefinedLibs{$Path} = 1;
18542 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018543 }
18544 }
18545 }
18546 if($ExtraInfo)
18547 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018548 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018549 {
18550 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018551 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018552 foreach (@Paths)
18553 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018554 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018555 my ($Dir, $Name) = separate_path($_);
18556
18557 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018558 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018559 }
18560
18561 $Name = parse_libname($Name, "name", $OStarget);
18562 $Name=~s/\Alib//;
18563
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018564 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018565 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018566
18567 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18568 {
18569 $LibString = " -L".esc($Dir).$LibString;
18570 }
18571
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018572 writeFile($ExtraInfo."/libs-string", $LibString);
18573 }
18574 }
18575 }
18576
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018577 if($ExtraInfo) {
18578 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18579 }
18580
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018581 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018582 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018583 if($#LibPaths!=-1)
18584 {
18585 if(not keys(%{$Symbol_Library{$LibVersion}}))
18586 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018587 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018588 printMsg("WARNING", "checking headers only");
18589 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018590 }
18591 }
18592 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018593
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018594 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018595 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018596}
18597
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018598my %Prefix_Lib_Map=(
18599 # symbols for autodetecting library dependencies (by prefix)
18600 "pthread_" => ["libpthread"],
18601 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18602 "cairo_" => ["libcairo"],
18603 "gtk_" => ["libgtk-x11-2.0"],
18604 "atk_" => ["libatk-1.0"],
18605 "gdk_" => ["libgdk-x11-2.0"],
18606 "gl" => ["libGL"],
18607 "glu" => ["libGLU"],
18608 "popt" => ["libpopt"],
18609 "Py" => ["libpython"],
18610 "jpeg_" => ["libjpeg"],
18611 "BZ2_" => ["libbz2"],
18612 "Fc" => ["libfontconfig"],
18613 "Xft" => ["libXft"],
18614 "SSL_" => ["libssl"],
18615 "sem_" => ["libpthread"],
18616 "snd_" => ["libasound"],
18617 "art_" => ["libart_lgpl_2"],
18618 "dbus_g" => ["libdbus-glib-1"],
18619 "GOMP_" => ["libgomp"],
18620 "omp_" => ["libgomp"],
18621 "cms" => ["liblcms"]
18622);
18623
18624my %Pattern_Lib_Map=(
18625 "SL[a-z]" => ["libslang"]
18626);
18627
18628my %Symbol_Lib_Map=(
18629 # symbols for autodetecting library dependencies (by name)
18630 "pow" => "libm",
18631 "fmod" => "libm",
18632 "sin" => "libm",
18633 "floor" => "libm",
18634 "cos" => "libm",
18635 "dlopen" => "libdl",
18636 "deflate" => "libz",
18637 "inflate" => "libz",
18638 "move_panel" => "libpanel",
18639 "XOpenDisplay" => "libX11",
18640 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018641 "clock_gettime" => "librt",
18642 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018643);
18644
18645sub find_SymbolLibs($$)
18646{
18647 my ($LibVersion, $Symbol) = @_;
18648
18649 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18650 { # debug symbols
18651 return ();
18652 }
18653
18654 my %Paths = ();
18655
18656 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18657 {
18658 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18659 $Paths{$Path} = 1;
18660 }
18661 }
18662
18663 if(my $SymbolPrefix = getPrefix($Symbol))
18664 {
18665 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18666 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18667 }
18668
18669 if(not keys(%Paths))
18670 {
18671 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18672 {
18673 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18674 {
18675 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18676 $Paths{$Path} = 1;
18677 }
18678 }
18679 }
18680 }
18681
18682 if(not keys(%Paths))
18683 {
18684 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18685 {
18686 if($Symbol=~/\A$Prefix/)
18687 {
18688 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18689 {
18690 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18691 $Paths{$Path} = 1;
18692 }
18693 }
18694 }
18695 }
18696 }
18697
18698 if(not keys(%Paths))
18699 {
18700 if($SymbolPrefix)
18701 { # try to find a library by symbol prefix
18702 if($SymbolPrefix eq "inotify" and
18703 index($Symbol, "\@GLIBC")!=-1)
18704 {
18705 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18706 $Paths{$Path} = 1;
18707 }
18708 }
18709 else
18710 {
18711 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18712 $Paths{$Path} = 1;
18713 }
18714 }
18715 }
18716 }
18717
18718 if(my @Paths = keys(%Paths)) {
18719 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18720 }
18721 }
18722 return keys(%Paths);
18723}
18724
18725sub get_LibPath_Prefix($$)
18726{
18727 my ($LibVersion, $Prefix) = @_;
18728
18729 $Prefix = lc($Prefix);
18730 $Prefix=~s/[_]+\Z//g;
18731
18732 foreach ("-2", "2", "-1", "1", "")
18733 { # libgnome-2.so
18734 # libxml2.so
18735 # libdbus-1.so
18736 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18737 return $Path;
18738 }
18739 }
18740 return "";
18741}
18742
18743sub getPrefix($)
18744{
18745 my $Str = $_[0];
18746 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18747 { # XmuValidArea: Xmu
18748 return $1;
18749 }
18750 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18751 { # snfReadFont: snf
18752 return $1;
18753 }
18754 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18755 { # XRRTimes: XRR
18756 return $1;
18757 }
18758 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18759 { # H5HF_delete: H5
18760 return $1;
18761 }
18762 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18763 { # alarm_event_add: alarm_
18764 return $1;
18765 }
18766 elsif($Str=~/\A(([a-z])\2{1,})/i)
18767 { # ffopen
18768 return $1;
18769 }
18770 return "";
18771}
18772
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018773sub getSymbolSize($$)
18774{ # size from the shared library
18775 my ($Symbol, $LibVersion) = @_;
18776 return 0 if(not $Symbol);
18777 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18778 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18779 {
18780 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18781 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18782 {
18783 if($Size<0) {
18784 return -$Size;
18785 }
18786 }
18787 }
18788 return 0;
18789}
18790
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018791sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018792{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18793 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018794 my ($Name, $Type) = @_;
18795
18796 # single
18797 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018798 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018799 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018800 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018801 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018802
18803 # double
18804 if($Name=~/$DEFAULT_STD_PARMS/)
18805 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018806 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018807 {
18808 my ($ShortName, $FuncParams) = split_Signature($Name);
18809
18810 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18811 {
18812 if(index($FParam, "<")!=-1)
18813 {
18814 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18815 my $FParam_N = canonifyName($FParam, "T");
18816 if($FParam_N ne $FParam) {
18817 $Name=~s/\Q$FParam\E/$FParam_N/g;
18818 }
18819 }
18820 }
18821 }
18822 elsif($Type eq "T")
18823 {
18824 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18825
18826 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018827 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018828 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018829 my $FParam = $TParams[0];
18830 foreach my $Pos (1 .. $#TParams)
18831 {
18832 my $TParam = $TParams[$Pos];
18833 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18834 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18835 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018836 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018837 }
18838 }
18839 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018840 if($Type eq "S") {
18841 return formatName($Name, "S");
18842 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018843 return $Name;
18844}
18845
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018846sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018847{
18848 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018849 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018850 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018851 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018852 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018853 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018854 next if($tr_name{$Symbol});
18855 $Symbol=~s/[\@\$]+(.*)\Z//;
18856 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018857 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018858 elsif(index($Symbol, "?")==0)
18859 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018860 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018861 }
18862 else
18863 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018864 $tr_name{$Symbol} = $Symbol;
18865 $mangled_name_gcc{$Symbol} = $Symbol;
18866 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018867 }
18868 }
18869 if($#MnglNames1 > -1)
18870 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018871 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018872 foreach my $MnglName (@MnglNames1)
18873 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018874 if(my $Unmangled = pop(@UnmangledNames))
18875 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018876 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018877 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18878 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18879 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018880 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018881 and $tr_name{$MnglName}=~/vtable for (.+)/)
18882 { # bind class name and v-table symbol
18883 my $ClassName = $1;
18884 $ClassVTable{$ClassName} = $MnglName;
18885 $VTableClass{$MnglName} = $ClassName;
18886 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018887 }
18888 }
18889 }
18890 if($#MnglNames2 > -1)
18891 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018892 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018893 foreach my $MnglName (@MnglNames2)
18894 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018895 if(my $Unmangled = pop(@UnmangledNames))
18896 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018897 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018898 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18899 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018900 }
18901 }
18902 return \%tr_name;
18903}
18904
18905sub link_symbol($$$)
18906{
18907 my ($Symbol, $RunWith, $Deps) = @_;
18908 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18909 return 1;
18910 }
18911 if($Deps eq "+Deps")
18912 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018913 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018914 return 1;
18915 }
18916 }
18917 return 0;
18918}
18919
18920sub link_symbol_internal($$$)
18921{
18922 my ($Symbol, $RunWith, $Where) = @_;
18923 return 0 if(not $Where or not $Symbol);
18924 if($Where->{$RunWith}{$Symbol})
18925 { # the exact match by symbol name
18926 return 1;
18927 }
18928 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18929 { # indirect symbol version, i.e.
18930 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018931 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018932 if($Where->{$RunWith}{$VSym}) {
18933 return 1;
18934 }
18935 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018936 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018937 if($Sym and $Ver)
18938 { # search for the symbol with the same version
18939 # or without version
18940 if($Where->{$RunWith}{$Sym})
18941 { # old: foo@v|foo@@v
18942 # new: foo
18943 return 1;
18944 }
18945 if($Where->{$RunWith}{$Sym."\@".$Ver})
18946 { # old: foo|foo@@v
18947 # new: foo@v
18948 return 1;
18949 }
18950 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18951 { # old: foo|foo@v
18952 # new: foo@@v
18953 return 1;
18954 }
18955 }
18956 return 0;
18957}
18958
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018959sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018960{
18961 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018962 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018963 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018964 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018965 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018966 my $NM = get_CmdPath("nm");
18967 if(not $NM) {
18968 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018969 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018970 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018971 while(<APP>)
18972 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018973 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018974 push(@Imported, $1);
18975 }
18976 }
18977 close(APP);
18978 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018979 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018980 {
18981 my $DumpBinCmd = get_CmdPath("dumpbin");
18982 if(not $DumpBinCmd) {
18983 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18984 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018985 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018986 while(<APP>)
18987 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018988 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18989 push(@Imported, $1);
18990 }
18991 }
18992 close(APP);
18993 }
18994 else
18995 {
18996 my $ReadelfCmd = get_CmdPath("readelf");
18997 if(not $ReadelfCmd) {
18998 exitStatus("Not_Found", "can't find \"readelf\"");
18999 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019000 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019001 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019002 while(<APP>)
19003 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019004 if(defined $symtab)
19005 { # do nothing with symtab
19006 if(index($_, "'.dynsym'")!=-1)
19007 { # dynamic table
19008 $symtab = undef;
19009 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019010 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019011 elsif(index($_, "'.symtab'")!=-1)
19012 { # symbol table
19013 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019014 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019015 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019016 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019017 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
19018 if($Ndx eq "UND")
19019 { # only imported symbols
19020 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019021 }
19022 }
19023 }
19024 close(APP);
19025 }
19026 return @Imported;
19027}
19028
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019029my %ELF_BIND = map {$_=>1} (
19030 "WEAK",
19031 "GLOBAL"
19032);
19033
19034my %ELF_TYPE = map {$_=>1} (
19035 "FUNC",
19036 "IFUNC",
19037 "OBJECT",
19038 "COMMON"
19039);
19040
19041my %ELF_VIS = map {$_=>1} (
19042 "DEFAULT",
19043 "PROTECTED"
19044);
19045
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019046sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019047{ # read the line of 'readelf' output corresponding to the symbol
19048 my @Info = split(/\s+/, $_[0]);
19049 # Num: Value Size Type Bind Vis Ndx Name
19050 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019051 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019052 shift(@Info); # spaces
19053 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019054
19055 if($#Info==7)
19056 { # UND SYMBOL (N)
19057 if($Info[7]=~/\(\d+\)/) {
19058 pop(@Info);
19059 }
19060 }
19061
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019062 if($#Info!=6)
19063 { # other lines
19064 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019065 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019066 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019067 return () if(not defined $ELF_BIND{$Info[3]});
19068 return () if(not defined $ELF_VIS{$Info[4]});
19069 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
19070 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
19071 return ();
19072 }
19073 if($OStarget eq "symbian")
19074 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
19075 if(index($Info[6], "_._.absent_export_")!=-1)
19076 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
19077 return ();
19078 }
19079 $Info[6]=~s/\@.+//g; # remove version
19080 }
19081 if(index($Info[2], "0x") == 0)
19082 { # size == 0x3d158
19083 $Info[2] = hex($Info[2]);
19084 }
19085 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019086}
19087
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019088sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019089{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019090 my ($LibVersion, $Name) = @_;
19091 return "" if(not $LibVersion or not $Name);
19092 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
19093 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019094 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019095 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
19096}
19097
19098sub get_LibPath_I($$)
19099{
19100 my ($LibVersion, $Name) = @_;
19101 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019102 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019103 if(-f $Name)
19104 { # absolute path
19105 return $Name;
19106 }
19107 else
19108 { # broken
19109 return "";
19110 }
19111 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019112 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019113 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019114 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019115 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019116 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019117 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019118 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019119 }
19120 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
19121 { # ldconfig default paths
19122 return $DefaultPath;
19123 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019124 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019125 { # search in default linker directories
19126 # and then in all system paths
19127 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019128 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019129 }
19130 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019131 if(not defined $Cache{"checkSystemFiles"}) {
19132 checkSystemFiles();
19133 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019134 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
19135 return $AllObjects[0];
19136 }
19137 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
19138 {
19139 if($ShortName ne $Name)
19140 { # FIXME: check this case
19141 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
19142 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019143 }
19144 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019145 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019146 # can't find
19147 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019148}
19149
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019150sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019151{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019152 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
19153 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019154
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019155 my $Real_Path = realpath_F($Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019156
19157 if(not $Real_Path)
19158 { # broken link
19159 return ();
19160 }
19161
19162 my $Lib_Name = get_filename($Real_Path);
19163
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019164 if($ExtraInfo)
19165 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019166 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019167 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019168 }
19169
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019170 if($IsNeededLib)
19171 {
19172 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
19173 return ();
19174 }
19175 }
19176 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019177 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019178
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019179 push(@RecurLib, $Lib_Name);
19180 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019181 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
19182
19183 if(not $IsNeededLib)
19184 { # special cases: libstdc++ and libc
19185 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
19186 {
19187 if($ShortName eq "libstdc++")
19188 { # libstdc++.so.6
19189 $STDCXX_TESTING = 1;
19190 }
19191 elsif($ShortName eq "libc")
19192 { # libc-2.11.3.so
19193 $GLIBC_TESTING = 1;
19194 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019195 }
19196 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019197 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019198 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019199 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019200 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019201 mkpath(get_dirname($DebugPath));
19202 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019203 if($OStarget eq "macos")
19204 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019205 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019206 if(not $NM) {
19207 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019208 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019209 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019210 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019211 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019212 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019213 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019214 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019215 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019216 else
19217 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019218 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019219 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019220 while(<LIB>)
19221 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019222 if($CheckUndefined)
19223 {
19224 if(not $IsNeededLib)
19225 {
19226 if(/ U _([\w\$]+)\s*\Z/)
19227 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019228 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019229 next;
19230 }
19231 }
19232 }
19233
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019234 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019235 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019236 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019237 if($IsNeededLib)
19238 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019239 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019240 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019241 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19242 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019243 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019244 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019245 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019246 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019247 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19248 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019249 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19250 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019251 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019252 setLanguage($LibVersion, "C++");
19253 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019254 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019255 }
19256 }
19257 }
19258 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019259
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019260 if($Deps)
19261 {
19262 if($LIB_TYPE eq "dynamic")
19263 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019264
19265 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019266 if(not $OtoolCmd) {
19267 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019268 }
19269
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019270 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19271 while(<LIB>)
19272 {
19273 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
19274 and $1 ne $Lib_Path) {
19275 $NeededLib{$1} = 1;
19276 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019277 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019278 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019279 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019280 }
19281 }
19282 elsif($OStarget eq "windows")
19283 { # Windows *.dll, *.lib
19284 my $DumpBinCmd = get_CmdPath("dumpbin");
19285 if(not $DumpBinCmd) {
19286 exitStatus("Not_Found", "can't find \"dumpbin\"");
19287 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019288 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019289 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019290 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019291 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019292 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019293 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019294 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019295 else
19296 { # write to pipe
19297 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019298 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019299 while(<LIB>)
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019300 {
19301 my $realname = undef;
19302 if($LIB_TYPE eq "dynamic")
19303 {
19304 # 1197 4AC 0000A620 SetThreadStackGuarantee
19305 # 1198 4AD SetThreadToken (forwarded to ...)
19306 # 3368 _o2i_ECPublicKey
19307 # 1 0 00005B30 ??0?N = ... (with pdb)
19308 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
19309 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
19310 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
19311 { # dynamic, static and forwarded symbols
19312 $realname = $1;
19313 }
19314 }
19315 else
19316 { # static
19317 if(/\A\s{10,}\d*\s+([\w\?\@]+)\s*\Z/i)
19318 {
19319 # 16 IID_ISecurityInformation
19320 $realname = $1;
19321 }
19322 }
19323
19324 if($realname)
19325 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019326 if($IsNeededLib)
19327 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019328 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019329 {
19330 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19331 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19332 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019333 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019334 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019335 {
19336 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19337 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019338 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19339 {
19340 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19341 setLanguage($LibVersion, "C++");
19342 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019343 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019344 }
19345 }
19346 }
19347 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019348
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019349 if($Deps)
19350 {
19351 if($LIB_TYPE eq "dynamic")
19352 { # dependencies
19353 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19354 while(<LIB>)
19355 {
19356 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19357 and $1 ne $Lib_Path) {
19358 $NeededLib{path_format($1, $OSgroup)} = 1;
19359 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019360 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019361 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019362 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019363 }
19364 }
19365 else
19366 { # Unix; *.so, *.a
19367 # Symbian: *.dso, *.lib
19368 my $ReadelfCmd = get_CmdPath("readelf");
19369 if(not $ReadelfCmd) {
19370 exitStatus("Not_Found", "can't find \"readelf\"");
19371 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019372 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019373 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019374 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019375 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019376 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019377 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019378 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019379 else
19380 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019381 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019382 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019383 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019384 while(<LIB>)
19385 {
19386 if($LIB_TYPE eq "dynamic")
19387 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019388 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019389 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019390 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019391 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019392 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019393 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019394 # do nothing with symtab
19395 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019396 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019397 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019398 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019399 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019400 next;
19401 }
19402 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019403 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019404 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019405 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019406 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019407 if($CheckUndefined)
19408 {
19409 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019410 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019411 }
19412 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019413 next;
19414 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019415 if($Bind eq "WEAK")
19416 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019417 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019418 if($Weak eq "-Weak")
19419 { # skip WEAK symbols
19420 next;
19421 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019422 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019423 my $Short = $Symbol;
19424 $Short=~s/\@.+//g;
19425 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019426 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019427 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19428 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019429 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019430 if($IsNeededLib)
19431 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019432 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019433 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019434 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19435 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019436 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019437 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019438 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019439 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019440 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19441 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19442 if($Vers)
19443 {
19444 if($LIB_EXT eq "so")
19445 { # value
19446 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19447 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19448 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019449 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019450 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19451 {
19452 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19453 setLanguage($LibVersion, "C++");
19454 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019455 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019456 }
19457 }
19458 }
19459 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019460
19461 if($Deps and $LIB_TYPE eq "dynamic")
19462 { # dynamic library specifics
19463 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19464 open(LIB, $Cmd." |");
19465
19466 while(<LIB>)
19467 {
19468 if(/NEEDED.+\[([^\[\]]+)\]/)
19469 { # dependencies:
19470 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19471 $NeededLib{$1} = 1;
19472 }
19473 }
19474
19475 close(LIB);
19476 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019477 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019478 if($Vers)
19479 {
19480 if(not $IsNeededLib and $LIB_EXT eq "so")
19481 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019482 my %Found = ();
19483
19484 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019485 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019486 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019487 next if(index($Symbol,"\@")==-1);
19488 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019489 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019490 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019491 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019492 if($Symbol_SameValue ne $Symbol
19493 and index($Symbol_SameValue,"\@")==-1)
19494 {
19495 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019496 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019497 last;
19498 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019499 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019500 }
19501 }
19502
19503 # default
19504 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19505 {
19506 next if(defined $Found{$Symbol});
19507 next if(index($Symbol,"\@\@")==-1);
19508
19509 if($Symbol=~/\A([^\@]*)\@\@/
19510 and not $SymVer{$LibVersion}{$1})
19511 {
19512 $SymVer{$LibVersion}{$1} = $Symbol;
19513 $Found{$Symbol} = 1;
19514 }
19515 }
19516
19517 # non-default
19518 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19519 {
19520 next if(defined $Found{$Symbol});
19521 next if(index($Symbol,"\@")==-1);
19522
19523 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19524 and not $SymVer{$LibVersion}{$1})
19525 {
19526 $SymVer{$LibVersion}{$1} = $Symbol;
19527 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019528 }
19529 }
19530 }
19531 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019532 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019533 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019534 foreach my $DyLib (sort keys(%NeededLib))
19535 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019536 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19537
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019538 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19539 {
19540 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19541 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19542 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019543 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019544 }
19545 }
19546 pop(@RecurLib);
19547 return $Library_Symbol{$LibVersion};
19548}
19549
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019550sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019551{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019552 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019553 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019554 return keys(%Prefixes);
19555}
19556
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019557sub get_prefixes_I($$)
19558{
19559 foreach my $P (@{$_[0]})
19560 {
19561 my @Parts = reverse(split(/[\/\\]+/, $P));
19562 my $Name = $Parts[0];
19563 foreach (1 .. $#Parts)
19564 {
19565 $_[1]->{$Name}{$P} = 1;
19566 last if($_>4 or $Parts[$_] eq "include");
19567 $Name = $Parts[$_].$SLASH.$Name;
19568 }
19569 }
19570}
19571
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019572sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019573{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019574 $Cache{"checkSystemFiles"} = 1;
19575
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019576 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019577
19578 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019579 {
19580 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019581
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019582 my @Files = cmd_find($DevelPath,"f");
19583 foreach my $Link (cmd_find($DevelPath,"l"))
19584 { # add symbolic links
19585 if(-f $Link) {
19586 push(@Files, $Link);
19587 }
19588 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019589
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019590 # search for headers in /usr/lib
19591 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19592 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19593 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019594
19595 # search for libraries in /usr/lib (including symbolic links)
19596 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19597 foreach my $Path (@Libs)
19598 {
19599 my $N = get_filename($Path);
19600 $SystemObjects{$N}{$Path} = 1;
19601 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019602 }
19603 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019604
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019605 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019606 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019607 next if(not -d $DevelPath);
19608 # search for all header files in the /usr/include
19609 # with or without extension (ncurses.h, QtCore, ...)
19610 push(@SysHeaders, cmd_find($DevelPath,"f"));
19611 foreach my $Link (cmd_find($DevelPath,"l"))
19612 { # add symbolic links
19613 if(-f $Link) {
19614 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019615 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019616 }
19617 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019618 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019619}
19620
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019621sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019622{
19623 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019624 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019625 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19626 {
19627 if(not -e $Dest) {
19628 exitStatus("Access_Error", "can't access \'$Dest\'");
19629 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019630 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019631 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19632 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019633 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019634 }
19635 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019636 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019637}
19638
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019639sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019640{
19641 my ($Path, $LibVersion) = @_;
19642 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019643 my $Name = get_filename($Path);
19644 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019645 return 1;
19646 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019647 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019648 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19649 return 1;
19650 }
19651 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19652 {
19653 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19654 return 1;
19655 }
19656 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019657 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019658 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019659 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019660 return 1;
19661 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019662 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019663 return 1;
19664 }
19665 }
19666 return 0;
19667}
19668
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019669sub specificHeader($$)
19670{
19671 my ($Header, $Spec) = @_;
19672 my $Name = get_filename($Header);
19673
19674 if($Spec eq "windows")
19675 {# MS Windows
19676 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19677 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19678 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19679 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19680 my @Dirs = (
19681 "win32",
19682 "win64",
19683 "win",
19684 "windows",
19685 "msvcrt"
19686 ); # /gsf-win32/
19687 if(my $DIRs = join("|", @Dirs)) {
19688 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19689 }
19690 }
19691 elsif($Spec eq "macos")
19692 { # Mac OS
19693 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19694 }
19695
19696 return 0;
19697}
19698
19699sub skipAlienHeader($)
19700{
19701 my $Path = $_[0];
19702 my $Name = get_filename($Path);
19703 my $Dir = get_dirname($Path);
19704
19705 if($Tolerance=~/2/)
19706 { # 2 - skip internal headers
19707 my @Terms = (
19708 "p",
19709 "priv",
19710 "int",
19711 "impl",
19712 "implementation",
19713 "internal",
19714 "private",
19715 "old",
19716 "compat",
19717 "debug",
19718 "test",
19719 "gen"
19720 );
19721
19722 my @Dirs = (
19723 "private",
19724 "priv",
19725 "port",
19726 "impl",
19727 "internal",
19728 "detail",
19729 "details",
19730 "old",
19731 "compat",
19732 "debug",
19733 "config",
19734 "compiler",
19735 "platform",
19736 "test"
19737 );
19738
19739 if(my $TERMs = join("|", @Terms)) {
19740 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19741 }
19742 if(my $DIRs = join("|", @Dirs)) {
19743 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19744 }
19745
19746 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19747 }
19748
19749 if($Tolerance=~/1/)
19750 { # 1 - skip non-Linux headers
19751 if($OSgroup ne "windows")
19752 {
19753 if(specificHeader($Path, "windows")) {
19754 return 1;
19755 }
19756 }
19757 if($OSgroup ne "macos")
19758 {
19759 if(specificHeader($Path, "macos")) {
19760 return 1;
19761 }
19762 }
19763 }
19764
19765 # valid
19766 return 0;
19767}
19768
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019769sub skipHeader($$)
19770{
19771 my ($Path, $LibVersion) = @_;
19772 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019773 if(defined $Cache{"skipHeader"}{$Path}) {
19774 return $Cache{"skipHeader"}{$Path};
19775 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019776 if(defined $Tolerance and $Tolerance=~/1|2/)
19777 { # --tolerant
19778 if(skipAlienHeader($Path)) {
19779 return ($Cache{"skipHeader"}{$Path} = 1);
19780 }
19781 }
19782 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19783 return 0;
19784 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019785 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19786}
19787
19788sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019789{ # returns:
19790 # 1 - if header should NOT be included and checked
19791 # 2 - if header should NOT be included, but should be checked
19792 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019793 my $Name = get_filename($Path);
19794 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019795 return $Kind;
19796 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019797 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19798 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019799 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019800 if(index($Path, $D)!=-1)
19801 {
19802 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19803 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19804 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019805 }
19806 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019807 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19808 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019809 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019810 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19811 {
19812 if($Name=~/$P/) {
19813 return $Kind;
19814 }
19815 if($P=~/[\/\\]/ and $Path=~/$P/) {
19816 return $Kind;
19817 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019818 }
19819 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019820
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019821 return 0;
19822}
19823
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019824sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019825{
19826 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019827 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019828 { # system directory
19829 return;
19830 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019831 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019832 { # already registered
19833 return;
19834 }
19835 foreach my $Path (find_libs($Dir,"",1))
19836 {
19837 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019838 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019839 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019840 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019841 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19842}
19843
19844sub registerObject($$)
19845{
19846 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019847
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019848 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019849 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Mattias Ellert01e41222015-12-19 23:34:57 +010019850 if($OStarget=~/linux|bsd|gnu/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019851 {
19852 if(my $SONAME = getSONAME($Path)) {
19853 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19854 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019855 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019856 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19857 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019858 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019859
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019860 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019861 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019862 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019863 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019864 if($ObjArch ne getArch_GCC($LibVersion))
19865 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19866 $CheckedArch{$LibVersion} = 1;
19867 printMsg("WARNING", "the architectures of input objects and the used GCC compiler are not equal, please change the compiler by --gcc-path=PATH option.");
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019868 }
19869 }
19870 }
19871}
19872
19873sub getArch_Object($)
19874{
19875 my $Path = $_[0];
19876
19877 my %MachineType = (
19878 "14C" => "x86",
19879 "8664" => "x86_64",
19880 "1C0" => "arm",
19881 "200" => "ia64"
19882 );
19883
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019884 my %ArchName = (
19885 "s390:31-bit" => "s390",
19886 "s390:64-bit" => "s390x",
19887 "powerpc:common" => "ppc32",
19888 "powerpc:common64" => "ppc64",
19889 "i386:x86-64" => "x86_64",
19890 "mips:3000" => "mips",
19891 "sparc:v8plus" => "sparcv9"
19892 );
19893
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019894 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019895 {
19896 my $DumpbinCmd = get_CmdPath("dumpbin");
19897 if(not $DumpbinCmd) {
19898 exitStatus("Not_Found", "can't find \"dumpbin\"");
19899 }
19900
19901 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19902 my $Out = `$Cmd`;
19903
19904 if($Out=~/(\w+)\smachine/)
19905 {
19906 if(my $Type = $MachineType{uc($1)})
19907 {
19908 return $Type;
19909 }
19910 }
19911 }
Mattias Ellert01e41222015-12-19 23:34:57 +010019912 elsif($OStarget=~/linux|bsd|gnu/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019913 {
19914 my $ObjdumpCmd = get_CmdPath("objdump");
19915 if(not $ObjdumpCmd) {
19916 exitStatus("Not_Found", "can't find \"objdump\"");
19917 }
19918
19919 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019920
19921 if($OSgroup eq "windows") {
19922 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19923 }
19924 else {
19925 $Cmd = "LANG=$LOCALE ".$Cmd;
19926 }
19927 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019928
19929 if($Out=~/architecture:\s+([\w\-\:]+)/)
19930 {
19931 my $Arch = $1;
19932 if($Arch=~s/\:(.+)//)
19933 {
19934 my $Suffix = $1;
19935
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019936 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019937 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019938 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019939 }
19940 }
19941
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019942 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019943 $Arch = "x86";
19944 }
19945
19946 if($Arch eq "x86-64") {
19947 $Arch = "x86_64";
19948 }
19949
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019950 if($Arch eq "ia64-elf64") {
19951 $Arch = "ia64";
19952 }
19953
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019954 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019955 }
19956 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019957 elsif($OStarget=~/macos/)
19958 {
19959 my $OtoolCmd = get_CmdPath("otool");
19960 if(not $OtoolCmd) {
19961 exitStatus("Not_Found", "can't find \"otool\"");
19962 }
19963
19964 my $Cmd = $OtoolCmd." -hv -arch all \"$Path\"";
19965 my $Out = qx/$Cmd/;
19966
19967 if($Out=~/X86_64/i) {
19968 return "x86_64";
19969 }
19970 elsif($Out=~/X86/i) {
19971 return "x86";
19972 }
19973 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019974 else
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019975 {
19976 exitStatus("Error", "Not implemented yet");
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019977 # TODO
19978 }
19979
19980 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019981}
19982
19983sub getSONAME($)
19984{
19985 my $Path = $_[0];
19986 return if(not $Path);
19987 if(defined $Cache{"getSONAME"}{$Path}) {
19988 return $Cache{"getSONAME"}{$Path};
19989 }
19990 my $ObjdumpCmd = get_CmdPath("objdump");
19991 if(not $ObjdumpCmd) {
19992 exitStatus("Not_Found", "can't find \"objdump\"");
19993 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019994 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019995 if($OSgroup eq "windows") {
19996 $SonameCmd .= " | find \"SONAME\"";
19997 }
19998 else {
19999 $SonameCmd .= " | grep SONAME";
20000 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020001 if(my $SonameInfo = `$SonameCmd`)
20002 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020003 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
20004 return ($Cache{"getSONAME"}{$Path} = $1);
20005 }
20006 }
20007 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020008}
20009
20010sub getSOPaths_Dest($$)
20011{
20012 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020013 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020014 return ();
20015 }
20016 if(-f $Dest)
20017 {
20018 if(not parse_libname($Dest, "name", $OStarget)) {
20019 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
20020 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020021 registerObject($Dest, $LibVersion);
20022 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020023 return ($Dest);
20024 }
20025 elsif(-d $Dest)
20026 {
20027 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020028 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020029 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020030 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
20031 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020032 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020033 { # all files and symlinks that match the name of a library
20034 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
20035 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020036 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020037 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020038 }
20039 }
20040 }
20041 else
20042 { # search for all files and symlinks
20043 foreach my $Path (find_libs($Dest,"",""))
20044 {
20045 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020046 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020047 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020048 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020049 }
20050 if($OSgroup eq "macos")
20051 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020052 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020053 {
20054 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020055 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020056 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020057 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
20058 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020059 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020060 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020061 }
20062 }
20063 }
20064 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020065 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020066 }
20067 else {
20068 return ();
20069 }
20070}
20071
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020072sub realpath_F($)
20073{
20074 my $Path = $_[0];
20075 return path_format(realpath($Path), $OSgroup);
20076}
20077
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020078sub isCyclical($$)
20079{
20080 my ($Stack, $Value) = @_;
20081 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020082}
20083
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020084sub getGCC_Opts($)
20085{ # to use in module
20086 my $LibVersion = $_[0];
20087
20088 my @Opts = ();
20089
20090 if($CompilerOptions{$LibVersion})
20091 { # user-defined options
20092 push(@Opts, $CompilerOptions{$LibVersion});
20093 }
20094 if($GccOptions)
20095 { # additional
20096 push(@Opts, $GccOptions);
20097 }
20098
20099 if(@Opts) {
20100 return join(" ", @Opts);
20101 }
20102
20103 return undef;
20104}
20105
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040020106sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020107{
20108 my $LibVersion = $_[0];
20109
20110 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
20111 return $Cache{"getArch_GCC"}{$LibVersion};
20112 }
20113
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030020114 if(not $GCC_PATH) {
20115 return undef;
20116 }
20117
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020118 my $Arch = undef;
20119
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030020120 if(my $Target = get_dumpmachine($GCC_PATH))
20121 {
20122 if($Target=~/x86_64/) {
20123 $Arch = "x86_64";
20124 }
20125 elsif($Target=~/i[3-6]86/) {
20126 $Arch = "x86";
20127 }
20128 elsif($Target=~/\Aarm/i) {
20129 $Arch = "arm";
20130 }
20131 }
20132
20133 if(not $Arch)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020134 {
20135 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
20136
20137 my $Cmd = $GCC_PATH." test.c -o test";
20138 if(my $Opts = getGCC_Opts($LibVersion))
20139 { # user-defined options
20140 $Cmd .= " ".$Opts;
20141 }
20142
20143 chdir($TMP_DIR);
20144 system($Cmd);
20145 chdir($ORIG_DIR);
20146
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020147 my $EX = join_P($TMP_DIR, "test");
20148
20149 if($OSgroup eq "windows") {
20150 $EX = join_P($TMP_DIR, "test.exe");
20151 }
20152
20153 $Arch = getArch_Object($EX);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020154
20155 unlink("$TMP_DIR/test.c");
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020156 unlink($EX);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020157 }
20158
20159 if(not $Arch) {
20160 exitStatus("Error", "can't check ARCH type");
20161 }
20162
20163 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
20164}
20165
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020166sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020167{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020168 my $LibVersion = $_[0];
20169
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020170 my $Size = undef;
20171
20172 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020173 if(my $Arch = getArch($LibVersion))
20174 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040020175 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020176 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020177 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020178 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
20179 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020180 }
20181 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020182
20183 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020184 {
20185 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020186
20187 my $Cmd = $GCC_PATH." -E -dD empty.h";
20188 if(my $Opts = getGCC_Opts($LibVersion))
20189 { # user-defined options
20190 $Cmd .= " ".$Opts;
20191 }
20192
20193 chdir($TMP_DIR);
20194 my $Defines = `$Cmd`;
20195 chdir($ORIG_DIR);
20196
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020197 unlink("$TMP_DIR/empty.h");
20198
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020199 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
20200 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020201 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020202 }
20203 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
20204 { # GCC 3
20205 my $PTRDIFF = $1;
20206 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020207 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020208 }
20209 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020210 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020211 }
20212 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020213 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020214
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020215 if(not $Size) {
20216 exitStatus("Error", "can't check WORD size");
20217 }
20218
20219 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020220}
20221
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020222sub getWordSize($)
20223{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020224 return $WORD_SIZE{$_[0]};
20225}
20226
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020227sub majorVersion($)
20228{
20229 my $V = $_[0];
20230 return 0 if(not $V);
20231 my @VParts = split(/\./, $V);
20232 return $VParts[0];
20233}
20234
20235sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020236{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020237 my ($V1, $V2) = @_;
20238 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020239 my @V1Parts = split(/\./, $V1);
20240 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020241 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
20242 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020243 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
20244 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
20245 }
20246 return -1 if($#V1Parts < $#V2Parts);
20247 return 1 if($#V1Parts > $#V2Parts);
20248 return 0;
20249}
20250
20251sub read_ABI_Dump($$)
20252{
20253 my ($LibVersion, $Path) = @_;
20254 return if(not $LibVersion or not -e $Path);
20255 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020256 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020257 { # input *.abi
20258 $FilePath = $Path;
20259 }
20260 else
20261 { # input *.abi.tar.gz
20262 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020263 if(not isDump_U($FilePath)) {
20264 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20265 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020266 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020267
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020268 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020269
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020270 my $Line = readLineNum($FilePath, 0);
20271 if($Line=~/xml/)
20272 { # XML format
20273 loadModule("XmlDump");
20274 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020275 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020276 else
20277 { # Perl Data::Dumper format (default)
20278 open(DUMP, $FilePath);
20279 local $/ = undef;
20280 my $Content = <DUMP>;
20281 close(DUMP);
20282
20283 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
20284 { # remove temp file
20285 unlink($FilePath);
20286 }
20287 if($Content!~/};\s*\Z/) {
20288 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20289 }
20290 $ABI = eval($Content);
20291 if(not $ABI) {
20292 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
20293 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020294 }
20295 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020296 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020297 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020298 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020299 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020300 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020301 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020302 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030020303 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020304
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020305 if($ABI->{"PublicABI"}) {
20306 $UsedDump{$LibVersion}{"Public"} = 1;
20307 }
20308
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020309 if($ABI->{"ABI_DUMP_VERSION"})
20310 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020311 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020312 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020313 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020314 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020315 }
20316 else
20317 { # support for old ABI dumps
20318 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020319 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020320 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020321 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020322 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020323
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020324 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020325 {
20326 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (allowed only 2.0<=V<=$ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020327 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020328
20329 if(defined $ABI->{"ABI_DUMPER_VERSION"})
20330 { # DWARF ABI Dump
20331 $UseConv_Real{$LibVersion}{"P"} = 1;
20332 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
20333
20334 $UsedDump{$LibVersion}{"DWARF"} = 1;
20335
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030020336 if(not $TargetComponent_Opt)
20337 {
20338 if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
20339 $TargetComponent = "module";
20340 }
20341 else {
20342 $TargetComponent = "object";
20343 }
20344 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020345 }
20346
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020347 if(not checkDump($LibVersion, "2.11"))
20348 { # old ABI dumps
20349 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020350 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020351 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020352 { # ABI dump created with --binary option
20353 $UsedDump{$LibVersion}{"BinOnly"} = 1;
20354 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020355 else
20356 { # default
20357 $UsedDump{$LibVersion}{"SrcBin"} = 1;
20358 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020359
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020360 if(defined $ABI->{"Mode"}
20361 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020362 { # --ext option
20363 $ExtendedCheck = 1;
20364 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020365 if($ABI->{"Extra"}) {
20366 $ExtraDump = 1;
20367 }
20368
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020369 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020370 {
20371 $UsedDump{$LibVersion}{"L"} = $Lang;
20372 setLanguage($LibVersion, $Lang);
20373 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020374 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020375 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020376 }
20377 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020378 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020379 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020380 if(not $TInfo)
20381 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020382 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020383 }
20384 my %Tid_TDid = ();
20385 foreach my $TDid (keys(%{$TInfo}))
20386 {
20387 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
20388 {
20389 $MAX_ID = $Tid if($Tid>$MAX_ID);
20390 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020391 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020392 }
20393 }
20394 my %NewID = ();
20395 foreach my $Tid (keys(%Tid_TDid))
20396 {
20397 my @TDids = keys(%{$Tid_TDid{$Tid}});
20398 if($#TDids>=1)
20399 {
20400 foreach my $TDid (@TDids)
20401 {
20402 if($TDid) {
20403 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20404 }
20405 else
20406 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020407 my $ID = ++$MAX_ID;
20408
20409 $NewID{$TDid}{$Tid} = $ID;
20410 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20411 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020412 }
20413 }
20414 }
20415 else
20416 {
20417 my $TDid = $TDids[0];
20418 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20419 }
20420 }
20421 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20422 {
20423 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20424 if(defined $Info{"BaseType"})
20425 {
20426 my $Bid = $Info{"BaseType"}{"Tid"};
20427 my $BDid = $Info{"BaseType"}{"TDid"};
20428 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020429 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020430 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20431 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20432 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020433 }
20434 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20435 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020436 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020437 read_Machine_DumpInfo($ABI, $LibVersion);
20438 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020439 if(not $SymbolInfo{$LibVersion})
20440 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020441 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020442 }
20443 if(not keys(%{$SymbolInfo{$LibVersion}}))
20444 { # validation of old-version dumps
20445 if(not $ExtendedCheck) {
20446 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20447 }
20448 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020449 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020450 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020451 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020452 else
20453 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020454 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020455 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020456 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020457 }
20458 if(not $DepSymbols)
20459 { # Cannot reconstruct DepSymbols. This may result in false
20460 # positives if the old dump is for library 2. Not a problem if
20461 # old dumps are only from old libraries.
20462 $DepSymbols = {};
20463 }
20464 foreach my $Symbol (keys(%{$DepSymbols})) {
20465 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20466 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020467 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020468 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020469
20470 if(my $V = $TargetVersion{$LibVersion}) {
20471 $Descriptor{$LibVersion}{"Version"} = $V;
20472 }
20473 else {
20474 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20475 }
20476
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020477 if(not keys(%{$SkipTypes{$LibVersion}}))
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020478 { # if not defined by -skip-types option
20479 if(defined $ABI->{"SkipTypes"})
20480 {
20481 foreach my $TName (keys(%{$ABI->{"SkipTypes"}}))
20482 {
20483 $SkipTypes{$LibVersion}{$TName} = 1;
20484 }
20485 }
20486 if(defined $ABI->{"OpaqueTypes"})
20487 { # support for old dumps
20488 foreach my $TName (keys(%{$ABI->{"OpaqueTypes"}}))
20489 {
20490 $SkipTypes{$LibVersion}{$TName} = 1;
20491 }
20492 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020493 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020494
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020495 if(not keys(%{$SkipSymbols{$LibVersion}}))
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020496 { # if not defined by -skip-symbols option
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020497 if(defined $ABI->{"SkipSymbols"}) {
20498 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20499 }
20500 if(defined $ABI->{"SkipInterfaces"})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020501 { # support for old dumps
20502 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20503 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020504 if(defined $ABI->{"InternalInterfaces"})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020505 { # support for old dumps
20506 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20507 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020508 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020509 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020510
20511 if(not $TargetHeaders{$LibVersion})
20512 { # if not defined by -headers-list option
20513 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20514 }
20515
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020516 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020517 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020518 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030020519
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020520 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020521 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020522 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020523
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020524 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020525 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020526
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020527 if(not checkDump($LibVersion, "2.10.1")
20528 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020529 { # support for old ABI dumps: added target headers
20530 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020531 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020532 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020533
20534 if(not $ABI->{"PublicABI"})
20535 {
20536 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20537 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20538 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020539 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020540 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020541 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020542 if(defined $ABI->{"GccConstants"})
20543 { # 3.0
20544 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20545 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20546 }
20547 }
20548
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020549 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020550 if(not $NestedNameSpaces{$LibVersion})
20551 { # support for old dumps
20552 # Cannot reconstruct NameSpaces. This may affect design
20553 # of the compatibility report.
20554 $NestedNameSpaces{$LibVersion} = {};
20555 }
20556 # target system type
20557 # needed to adopt HTML report
20558 if(not $DumpSystem)
20559 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020560 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020561 }
20562 # recreate environment
20563 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20564 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020565 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020566 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020567 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20568 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020569 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020570 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020571 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020572 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20573 {
20574 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20575 setLanguage($LibVersion, "C++");
20576 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020577 }
20578 }
20579 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020580 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20581 {
20582 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20583 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20584 }
20585 }
20586
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020587 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020588 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020589 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020590 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020591 {
20592 if(not $Symbol_Library{$LibVersion}{$MnglName}
20593 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20594 push(@VFunc, $MnglName);
20595 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020596 }
20597 }
20598 translateSymbols(@VFunc, $LibVersion);
20599 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020600 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20601
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020602 if(not checkDump($LibVersion, "3.0"))
20603 { # support for old ABI dumps
20604 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20605 {
20606 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20607 {
20608 if(ref($BaseType) eq "HASH") {
20609 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20610 }
20611 }
20612 }
20613 }
20614
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020615 if(not checkDump($LibVersion, "3.2"))
20616 { # support for old ABI dumps
20617 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20618 {
20619 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20620 {
20621 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20622 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20623 }
20624 }
20625 }
20626
20627 # repair target headers list
20628 delete($TargetHeaders{$LibVersion});
20629 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020630 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20631 }
20632 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20633 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020634 }
20635
20636 # non-target constants from anon enums
20637 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20638 {
20639 if(not $ExtraDump
20640 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20641 {
20642 delete($Constants{$LibVersion}{$Name});
20643 }
20644 }
20645 }
20646
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020647 if(not checkDump($LibVersion, "2.20"))
20648 { # support for old ABI dumps
20649 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20650 {
20651 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20652
20653 if($TType=~/Struct|Union|Enum|Typedef/)
20654 { # repair complex types first
20655 next;
20656 }
20657
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020658 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020659 {
20660 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20661 if($BType=~/Struct|Union|Enum/i)
20662 {
20663 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20664 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20665 }
20666 }
20667 }
20668 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20669 {
20670 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20671 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20672 if($TType=~/Struct|Union|Enum/) {
20673 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20674 }
20675 }
20676 }
20677
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020678 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020679 { # NOTE: order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020680 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20681 { # support for old ABI dumps < 2.0 (ACC 1.22)
20682 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20683 {
20684 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20685 {
20686 if($Access ne "public") {
20687 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20688 }
20689 }
20690 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20691 }
20692 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20693 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020694 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20695 { # support for old ABI dumps
20696 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20697 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020698 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20699 { # DWARF ABI Dumps
20700 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20701 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020702 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20703 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20704 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020705
20706 # support for old formatting of type names
20707 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = formatName($TypeInfo{$LibVersion}{$TypeId}{"Name"}, "T");
20708
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020709 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20710 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020711 {
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +030020712 foreach my $SubId (keys(%{$TInfo{"Base"}}))
20713 {
20714 if($SubId eq $TypeId)
20715 { # Fix erroneus ABI dump
20716 delete($TypeInfo{$LibVersion}{$TypeId}{"Base"}{$SubId});
20717 next;
20718 }
20719
20720 $Class_SubClasses{$LibVersion}{$SubId}{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020721 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020722 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020723 if($TInfo{"Type"} eq "MethodPtr")
20724 {
20725 if(defined $TInfo{"Param"})
20726 { # support for old ABI dumps <= 1.17
20727 if(not defined $TInfo{"Param"}{"0"})
20728 {
20729 my $Max = keys(%{$TInfo{"Param"}});
20730 foreach my $Pos (1 .. $Max) {
20731 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20732 }
20733 delete($TInfo{"Param"}{$Max});
20734 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20735 }
20736 }
20737 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020738 if($TInfo{"BaseType"} eq $TypeId)
20739 { # fix ABI dump
20740 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20741 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020742
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020743 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020744 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020745 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020746 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020747 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20748 if(not $BName)
20749 { # broken type
20750 next;
20751 }
20752 if($TInfo{"Name"} eq $BName)
20753 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020754 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020755 next;
20756 }
20757 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20758 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020759 }
20760 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020761 }
20762 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20763 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020764 $TName_Tid{$LibVersion}{$TInfo{"Name"}} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020765 }
20766 }
20767
20768 if(not checkDump($LibVersion, "2.15"))
20769 { # support for old ABI dumps
20770 my %Dups = ();
20771 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20772 {
20773 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020774 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020775 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20776 { # remove template decls
20777 delete($SymbolInfo{$LibVersion}{$InfoId});
20778 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020779 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020780 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020781 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20782 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020783 { # templates
20784 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020785 }
20786 }
20787 }
20788
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020789 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20790 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020791 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20792 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20793 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20794 { # support for old ABI dumps (< 3.1)
20795 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20796 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20797 { # add "this" first parameter
20798 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20799 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20800
20801 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20802 {
20803 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20804 foreach my $Pos (reverse(0 .. $#Pos)) {
20805 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20806 }
20807 }
20808 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20809 }
20810 }
20811
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020812 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20813 { # ABI dumps have no mangled names for C-functions
20814 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20815 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020816 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20817 { # support for old ABI dumps
20818 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20819 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020820 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20821 { # DWARF ABI Dumps
20822 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20823 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020824 }
20825
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020826 $Descriptor{$LibVersion}{"Dump"} = 1;
20827}
20828
20829sub read_Machine_DumpInfo($$)
20830{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020831 my ($ABI, $LibVersion) = @_;
20832 if($ABI->{"Arch"}) {
20833 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020834 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020835 if($ABI->{"WordSize"}) {
20836 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020837 }
20838 else
20839 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020840 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020841 }
20842 if(not $WORD_SIZE{$LibVersion})
20843 { # support for old dumps (<1.23)
20844 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20845 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020846 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020847 }
20848 else
20849 {
20850 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020851 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020852 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020853 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20854 { # any "pointer"-type
20855 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020856 last;
20857 }
20858 }
20859 if($PSize)
20860 { # a pointer type size
20861 $WORD_SIZE{$LibVersion} = $PSize;
20862 }
20863 else {
20864 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20865 }
20866 }
20867 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020868 if($ABI->{"GccVersion"}) {
20869 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020870 }
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030020871 elsif($ABI->{"ClangVersion"}) {
20872 $CLANG_VERSION{$LibVersion} = $ABI->{"ClangVersion"};
20873 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020874}
20875
20876sub read_Libs_DumpInfo($$)
20877{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020878 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020879 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20880 if(not $Library_Symbol{$LibVersion})
20881 { # support for old dumps
20882 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20883 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020884 if(keys(%{$Library_Symbol{$LibVersion}})
20885 and not $DumpAPI) {
20886 $Descriptor{$LibVersion}{"Libs"} = "OK";
20887 }
20888}
20889
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020890sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020891{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020892 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020893
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020894 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020895 and not $DumpAPI) {
20896 $Descriptor{$LibVersion}{"Headers"} = "OK";
20897 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020898 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020899 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020900 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020901 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020902 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020903
20904 if(keys(%{$ABI->{"Sources"}})
20905 and not $DumpAPI) {
20906 $Descriptor{$LibVersion}{"Sources"} = "OK";
20907 }
20908 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020909 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020910 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20911 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20912 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020913}
20914
20915sub find_libs($$$)
20916{
20917 my ($Path, $Type, $MaxDepth) = @_;
20918 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020919 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020920}
20921
20922sub createDescriptor($$)
20923{
20924 my ($LibVersion, $Path) = @_;
20925 if(not $LibVersion or not $Path
20926 or not -e $Path) {
20927 return "";
20928 }
20929 if(-d $Path)
20930 { # directory with headers files and shared objects
20931 return "
20932 <version>
20933 ".$TargetVersion{$LibVersion}."
20934 </version>
20935
20936 <headers>
20937 $Path
20938 </headers>
20939
20940 <libs>
20941 $Path
20942 </libs>";
20943 }
20944 else
20945 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020946 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020947 { # standard XML-descriptor
20948 return readFile($Path);
20949 }
20950 elsif(is_header($Path, 2, $LibVersion))
20951 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020952 $CheckHeadersOnly = 1;
20953
20954 if($LibVersion==1) {
20955 $TargetVersion{$LibVersion} = "X";
20956 }
20957
20958 if($LibVersion==2) {
20959 $TargetVersion{$LibVersion} = "Y";
20960 }
20961
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020962 return "
20963 <version>
20964 ".$TargetVersion{$LibVersion}."
20965 </version>
20966
20967 <headers>
20968 $Path
20969 </headers>
20970
20971 <libs>
20972 none
20973 </libs>";
20974 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020975 else
20976 { # standard XML-descriptor
20977 return readFile($Path);
20978 }
20979 }
20980}
20981
20982sub detect_lib_default_paths()
20983{
20984 my %LPaths = ();
20985 if($OSgroup eq "bsd")
20986 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020987 if(my $LdConfig = get_CmdPath("ldconfig"))
20988 {
20989 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20990 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020991 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20992 {
20993 my $Name = "lib".$1;
20994 if(not defined $LPaths{$Name}) {
20995 $LPaths{$Name} = $2;
20996 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020997 }
20998 }
20999 }
21000 else {
21001 printMsg("WARNING", "can't find ldconfig");
21002 }
21003 }
21004 else
21005 {
21006 if(my $LdConfig = get_CmdPath("ldconfig"))
21007 {
21008 if($SystemRoot and $OSgroup eq "linux")
21009 { # use host (x86) ldconfig with the target (arm) ld.so.conf
21010 if(-e $SystemRoot."/etc/ld.so.conf") {
21011 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
21012 }
21013 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021014 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
21015 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021016 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
21017 {
21018 my ($Name, $Path) = ($1, $2);
21019 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021020 if(not defined $LPaths{$Name})
21021 { # get first element from the list of available paths
21022
21023 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
21024 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
21025 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
21026
21027 $LPaths{$Name} = $Path;
21028 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021029 }
21030 }
21031 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040021032 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021033 printMsg("WARNING", "can't find ldconfig");
21034 }
21035 }
21036 return \%LPaths;
21037}
21038
21039sub detect_bin_default_paths()
21040{
21041 my $EnvPaths = $ENV{"PATH"};
21042 if($OSgroup eq "beos") {
21043 $EnvPaths.=":".$ENV{"BETOOLS"};
21044 }
21045 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021046 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021047 {
21048 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021049 next if(not $Path);
21050 if($SystemRoot
21051 and $Path=~/\A\Q$SystemRoot\E\//)
21052 { # do NOT use binaries from target system
21053 next;
21054 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021055 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021056 }
21057}
21058
21059sub detect_inc_default_paths()
21060{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021061 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021062 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021063 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021064 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021065 next if(index($Line, "/cc1plus ")!=-1);
21066
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021067 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
21068 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030021069 my $Path = realpath_F($1);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021070 if(index($Path, "c++")!=-1
21071 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021072 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021073 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021074 if(not defined $MAIN_CPP_DIR
21075 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
21076 $MAIN_CPP_DIR = $Path;
21077 }
21078 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021079 elsif(index($Path, "gcc")!=-1) {
21080 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021081 }
21082 else
21083 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021084 if($Path=~/local[\/\\]+include/)
21085 { # local paths
21086 next;
21087 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021088 if($SystemRoot
21089 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
21090 { # The GCC include path for user headers is not a part of the system root
21091 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
21092 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
21093 next;
21094 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021095 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021096 }
21097 }
21098 }
21099 unlink("$TMP_DIR/empty.h");
21100 return %DPaths;
21101}
21102
21103sub detect_default_paths($)
21104{
21105 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
21106 my $Search = $_[0];
21107 if($Search!~/inc/) {
21108 $HSearch = 0;
21109 }
21110 if($Search!~/lib/) {
21111 $LSearch = 0;
21112 }
21113 if($Search!~/bin/) {
21114 $BSearch = 0;
21115 }
21116 if($Search!~/gcc/) {
21117 $GSearch = 0;
21118 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021119 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021120 { # <search_headers> section of the XML descriptor
21121 # do NOT search for systems headers
21122 $HSearch = 0;
21123 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021124 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030021125 { # <search_libs> section of the XML descriptor
21126 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021127 $LSearch = 0;
21128 }
21129 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
21130 { # additional search paths
21131 next if($Type eq "include" and not $HSearch);
21132 next if($Type eq "lib" and not $LSearch);
21133 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021134 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021135 }
21136 if($OSgroup ne "windows")
21137 { # unix-like
21138 foreach my $Type ("include", "lib", "bin")
21139 { # automatic detection of system "devel" directories
21140 next if($Type eq "include" and not $HSearch);
21141 next if($Type eq "lib" and not $LSearch);
21142 next if($Type eq "bin" and not $BSearch);
21143 my ($UsrDir, $RootDir) = ("/usr", "/");
21144 if($SystemRoot and $Type ne "bin")
21145 { # 1. search for target headers and libraries
21146 # 2. use host commands: ldconfig, readelf, etc.
21147 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
21148 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021149 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021150 if(-d $RootDir."/".$Type)
21151 { # if "/lib" is symbolic link
21152 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021153 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021154 }
21155 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021156 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021157 }
21158 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021159 if(-d $UsrDir)
21160 {
21161 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021162 if(-d $UsrDir."/".$Type)
21163 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021164 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021165 }
21166 }
21167 }
21168 }
21169 if($BSearch)
21170 {
21171 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021172 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021173 }
21174 # check environment variables
21175 if($OSgroup eq "beos")
21176 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021177 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021178 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021179 if($_ eq ".") {
21180 next;
21181 }
21182 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
21183 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
21184 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021185 }
21186 }
21187 if($HSearch)
21188 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021189 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
21190 split(/:|;/, $ENV{"BEINCLUDES"})
21191 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021192 }
21193 if($LSearch)
21194 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021195 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
21196 split(/:|;/, $ENV{"BELIBRARIES"}),
21197 split(/:|;/, $ENV{"LIBRARY_PATH"})
21198 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021199 }
21200 }
21201 if($LSearch)
21202 { # using linker to get system paths
21203 if(my $LPaths = detect_lib_default_paths())
21204 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021205 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021206 foreach my $Name (keys(%{$LPaths}))
21207 {
21208 if($SystemRoot
21209 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
21210 { # wrong ldconfig configuration
21211 # check your <sysroot>/etc/ld.so.conf
21212 next;
21213 }
21214 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021215 if(my $Dir = get_dirname($LPaths->{$Name})) {
21216 $Dirs{$Dir} = 1;
21217 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021218 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021219 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021220 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021221 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021222 }
21223 if($BSearch)
21224 {
21225 if($CrossGcc)
21226 { # --cross-gcc=arm-linux-gcc
21227 if(-e $CrossGcc)
21228 { # absolute or relative path
21229 $GCC_PATH = get_abs_path($CrossGcc);
21230 }
21231 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
21232 { # command name
21233 $GCC_PATH = $CrossGcc;
21234 }
21235 else {
21236 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
21237 }
21238 if($GCC_PATH=~/\s/) {
21239 $GCC_PATH = "\"".$GCC_PATH."\"";
21240 }
21241 }
21242 }
21243 if($GSearch)
21244 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021245 if(not $CrossGcc)
21246 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021247 $GCC_PATH = get_CmdPath("gcc");
21248 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021249 if(not $GCC_PATH)
21250 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021251 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021252 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021253 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021254 { # select the latest version
21255 @GCCs = sort {$b cmp $a} @GCCs;
21256 if(check_gcc($GCCs[0], "3"))
21257 {
21258 $GCC_PATH = $GCCs[0];
21259 last;
21260 }
21261 }
21262 }
21263 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021264 if(not $GCC_PATH) {
21265 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
21266 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021267
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021268 my $GCC_Ver = get_dumpversion($GCC_PATH);
21269 if($GCC_Ver eq "4.8")
21270 { # on Ubuntu -dumpversion returns 4.8 for gcc 4.8.4
21271 my $Info = `$GCC_PATH --version`;
21272
21273 if($Info=~/gcc\s+(|\([^()]+\)\s+)(\d+\.\d+\.\d+)/)
21274 { # gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
21275 # gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)
21276 $GCC_Ver = $2;
21277 }
21278 }
21279
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030021280 if($OStarget=~/macos/)
21281 {
21282 my $Info = `$GCC_PATH --version`;
21283
21284 if($Info=~/clang/i) {
21285 printMsg("WARNING", "doesn't work with clang, please install GCC instead (and select it by -gcc-path option)");
21286 }
21287 }
21288
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021289 if($GCC_Ver)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021290 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021291 my $GccTarget = get_dumpmachine($GCC_PATH);
21292
21293 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021294 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021295 $OStarget = "linux";
21296 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021297 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021298 elsif($GccTarget=~/symbian/)
21299 {
21300 $OStarget = "symbian";
21301 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
21302 }
21303
21304 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
21305
21306 # check GCC version
21307 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
21308 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021309 # introduced in 4.8 and fixed in 4.8.3
21310 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update GCC to 4.8.3 or downgrade it to 4.7. You can use a local GCC installation by --gcc-path=PATH option.");
21311
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021312 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021313 }
21314 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021315 else {
21316 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021317 }
21318 }
21319 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021320 {
21321 # GCC standard paths
21322 if($GCC_PATH and not $NoStdInc)
21323 {
21324 my %DPaths = detect_inc_default_paths();
21325 @DefaultCppPaths = @{$DPaths{"Cpp"}};
21326 @DefaultGccPaths = @{$DPaths{"Gcc"}};
21327 @DefaultIncPaths = @{$DPaths{"Inc"}};
21328 push_U($SystemPaths{"include"}, @DefaultIncPaths);
21329 }
21330
21331 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021332 my $IncPath = "/usr/include";
21333 if($SystemRoot) {
21334 $IncPath = $SystemRoot.$IncPath;
21335 }
21336 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021337 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021338 }
21339 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021340
21341 if($ExtraInfo)
21342 {
21343 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
21344 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
21345 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021346}
21347
21348sub getLIB_EXT($)
21349{
21350 my $Target = $_[0];
21351 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
21352 return $Ext;
21353 }
21354 return $OS_LibExt{$LIB_TYPE}{"default"};
21355}
21356
21357sub getAR_EXT($)
21358{
21359 my $Target = $_[0];
21360 if(my $Ext = $OS_Archive{$Target}) {
21361 return $Ext;
21362 }
21363 return $OS_Archive{"default"};
21364}
21365
21366sub get_dumpversion($)
21367{
21368 my $Cmd = $_[0];
21369 return "" if(not $Cmd);
21370 if($Cache{"get_dumpversion"}{$Cmd}) {
21371 return $Cache{"get_dumpversion"}{$Cmd};
21372 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021373 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021374 chomp($V);
21375 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
21376}
21377
21378sub get_dumpmachine($)
21379{
21380 my $Cmd = $_[0];
21381 return "" if(not $Cmd);
21382 if($Cache{"get_dumpmachine"}{$Cmd}) {
21383 return $Cache{"get_dumpmachine"}{$Cmd};
21384 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021385 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021386 chomp($Machine);
21387 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
21388}
21389
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021390sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021391{
21392 my $Cmd = $_[0];
21393 return "" if(not $Cmd);
21394 my @Options = (
21395 "--version",
21396 "-help"
21397 );
21398 foreach my $Opt (@Options)
21399 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021400 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021401 if($Info) {
21402 return 1;
21403 }
21404 }
21405 return 0;
21406}
21407
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021408sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021409{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021410 my ($Cmd, $ReqVer) = @_;
21411 return 0 if(not $Cmd or not $ReqVer);
21412 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
21413 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021414 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021415 if(my $GccVer = get_dumpversion($Cmd))
21416 {
21417 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
21418 if(cmpVersions($GccVer, $ReqVer)>=0) {
21419 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
21420 }
21421 }
21422 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021423}
21424
21425sub get_depth($)
21426{
21427 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021428 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021429 }
21430 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
21431}
21432
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021433sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021434{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021435 return if($Cache{"registerGccHeaders"}); # this function should be called once
21436
21437 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021438 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021439 my @Headers = cmd_find($Path,"f");
21440 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21441 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021442 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021443 my $FileName = get_filename($HPath);
21444 if(not defined $DefaultGccHeader{$FileName})
21445 { # skip duplicated
21446 $DefaultGccHeader{$FileName} = $HPath;
21447 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021448 }
21449 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021450 $Cache{"registerGccHeaders"} = 1;
21451}
21452
21453sub registerCppHeaders()
21454{
21455 return if($Cache{"registerCppHeaders"}); # this function should be called once
21456
21457 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021458 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021459 my @Headers = cmd_find($CppDir,"f");
21460 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21461 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021462 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021463 my $FileName = get_filename($Path);
21464 if(not defined $DefaultCppHeader{$FileName})
21465 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021466 $DefaultCppHeader{$FileName} = $Path;
21467 }
21468 }
21469 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021470 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021471}
21472
21473sub parse_libname($$$)
21474{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021475 return "" if(not $_[0]);
21476 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21477 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021478 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021479 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21480}
21481
21482sub parse_libname_I($$$)
21483{
21484 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021485
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021486 if($Target eq "symbian") {
21487 return parse_libname_symbian($Name, $Type);
21488 }
21489 elsif($Target eq "windows") {
21490 return parse_libname_windows($Name, $Type);
21491 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021492
21493 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021494 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021495 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021496 { # libSDL-1.2.so.0.7.1
21497 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021498 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021499 if($Type eq "name")
21500 { # libSDL-1.2
21501 # libwbxml2
21502 return $2;
21503 }
21504 elsif($Type eq "name+ext")
21505 { # libSDL-1.2.so
21506 # libwbxml2.so
21507 return $1;
21508 }
21509 elsif($Type eq "version")
21510 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021511 if(defined $7
21512 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021513 { # 0.7.1
21514 return $7;
21515 }
21516 else
21517 { # libc-2.5.so (=>2.5 version)
21518 my $MV = $5;
21519 $MV=~s/\A[\-\_]+//g;
21520 return $MV;
21521 }
21522 }
21523 elsif($Type eq "short")
21524 { # libSDL
21525 # libwbxml2
21526 return $3;
21527 }
21528 elsif($Type eq "shortest")
21529 { # SDL
21530 # wbxml
21531 return shortest_name($3);
21532 }
21533 }
21534 return "";# error
21535}
21536
21537sub parse_libname_symbian($$)
21538{
21539 my ($Name, $Type) = @_;
21540 my $Ext = getLIB_EXT("symbian");
21541 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21542 { # libpthread{00010001}.dso
21543 if($Type eq "name")
21544 { # libpthread{00010001}
21545 return $2;
21546 }
21547 elsif($Type eq "name+ext")
21548 { # libpthread{00010001}.dso
21549 return $1;
21550 }
21551 elsif($Type eq "version")
21552 { # 00010001
21553 my $V = $4;
21554 $V=~s/\{(.+)\}/$1/;
21555 return $V;
21556 }
21557 elsif($Type eq "short")
21558 { # libpthread
21559 return $3;
21560 }
21561 elsif($Type eq "shortest")
21562 { # pthread
21563 return shortest_name($3);
21564 }
21565 }
21566 return "";# error
21567}
21568
21569sub parse_libname_windows($$)
21570{
21571 my ($Name, $Type) = @_;
21572 my $Ext = getLIB_EXT("windows");
21573 if($Name=~/((.+?)\.$Ext)\Z/)
21574 { # netapi32.dll
21575 if($Type eq "name")
21576 { # netapi32
21577 return $2;
21578 }
21579 elsif($Type eq "name+ext")
21580 { # netapi32.dll
21581 return $1;
21582 }
21583 elsif($Type eq "version")
21584 { # DLL version embedded
21585 # at binary-level
21586 return "";
21587 }
21588 elsif($Type eq "short")
21589 { # netapi32
21590 return $2;
21591 }
21592 elsif($Type eq "shortest")
21593 { # netapi
21594 return shortest_name($2);
21595 }
21596 }
21597 return "";# error
21598}
21599
21600sub shortest_name($)
21601{
21602 my $Name = $_[0];
21603 # remove prefix
21604 $Name=~s/\A(lib|open)//;
21605 # remove suffix
21606 $Name=~s/[\W\d_]+\Z//i;
21607 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21608 return $Name;
21609}
21610
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021611sub createSymbolsList($$$$$)
21612{
21613 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021614
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021615 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021616 prepareSymbols(1);
21617
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021618 my %SymbolHeaderLib = ();
21619 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021620
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021621 # Get List
21622 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21623 {
21624 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021625 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021626 next;
21627 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021628 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021629 { # skip other symbols
21630 next;
21631 }
21632 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21633 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021634 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021635 next;
21636 }
21637 my $DyLib = $Symbol_Library{1}{$Symbol};
21638 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021639 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021640 next;
21641 }
21642 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21643 $Total+=1;
21644 }
21645 # Draw List
21646 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21647 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21648 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21649 {
21650 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21651 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021652 my %NS_Symbol = ();
21653 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021654 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021655 }
21656 foreach my $NameSpace (sort keys(%NS_Symbol))
21657 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021658 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021659 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21660 foreach my $Symbol (@SortedInterfaces)
21661 {
21662 my $SubReport = "";
21663 my $Signature = get_Signature($Symbol, 1);
21664 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021665 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021666 }
21667 if($Symbol=~/\A(_Z|\?)/)
21668 {
21669 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021670 $SubReport = insertIDs($ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Symbol</b>]</span><br/><br/>".$ContentDivEnd."\n");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021671 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021672 else {
21673 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21674 }
21675 }
21676 else
21677 {
21678 if($Signature) {
21679 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21680 }
21681 else {
21682 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21683 }
21684 }
21685 $SYMBOLS_LIST .= $SubReport;
21686 }
21687 }
21688 $SYMBOLS_LIST .= "<br/>\n";
21689 }
21690 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021691 # clear info
21692 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21693 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21694 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21695 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021696 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021697 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021698 my $CssStyles = readModule("Styles", "SymbolsList.css");
21699 my $JScripts = readModule("Scripts", "Sections.js");
21700 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021701 my $Title = "$LName: public symbols";
21702 my $Keywords = "$LName, API, symbols";
21703 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021704 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021705 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021706 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021707 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021708 writeFile($SaveTo, $SYMBOLS_LIST);
21709}
21710
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021711sub add_target_libs($)
21712{
21713 foreach (@{$_[0]}) {
21714 $TargetLibs{$_} = 1;
21715 }
21716}
21717
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021718sub is_target_lib($)
21719{
21720 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021721 if(not $LName) {
21722 return 0;
21723 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030021724 if($OSgroup eq "windows") {
21725 $LName = lc($LName);
21726 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021727 if($TargetLibraryName
21728 and $LName!~/\Q$TargetLibraryName\E/) {
21729 return 0;
21730 }
21731 if(keys(%TargetLibs)
21732 and not $TargetLibs{$LName}
21733 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21734 return 0;
21735 }
21736 return 1;
21737}
21738
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021739sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021740{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021741 my ($H, $V) = @_;
21742 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021743 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021744 if($TargetHeaders{$V}{$H}) {
21745 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021746 }
21747 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021748 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021749}
21750
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021751sub readLibs($)
21752{
21753 my $LibVersion = $_[0];
21754 if($OStarget eq "windows")
21755 { # dumpbin.exe will crash
21756 # without VS Environment
21757 check_win32_env();
21758 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021759 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021760 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021761 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021762}
21763
21764sub dump_sorting($)
21765{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021766 my $Hash = $_[0];
21767 return [] if(not $Hash);
21768 my @Keys = keys(%{$Hash});
21769 return [] if($#Keys<0);
21770 if($Keys[0]=~/\A\d+\Z/)
21771 { # numbers
21772 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021773 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021774 else
21775 { # strings
21776 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021777 }
21778}
21779
21780sub printMsg($$)
21781{
21782 my ($Type, $Msg) = @_;
21783 if($Type!~/\AINFO/) {
21784 $Msg = $Type.": ".$Msg;
21785 }
21786 if($Type!~/_C\Z/) {
21787 $Msg .= "\n";
21788 }
21789 if($Quiet)
21790 { # --quiet option
21791 appendFile($COMMON_LOG_PATH, $Msg);
21792 }
21793 else
21794 {
21795 if($Type eq "ERROR") {
21796 print STDERR $Msg;
21797 }
21798 else {
21799 print $Msg;
21800 }
21801 }
21802}
21803
21804sub exitStatus($$)
21805{
21806 my ($Code, $Msg) = @_;
21807 printMsg("ERROR", $Msg);
21808 exit($ERROR_CODE{$Code});
21809}
21810
21811sub exitReport()
21812{ # the tool has run without any errors
21813 printReport();
21814 if($COMPILE_ERRORS)
21815 { # errors in headers may add false positives/negatives
21816 exit($ERROR_CODE{"Compile_Error"});
21817 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021818 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21819 { # --binary
21820 exit($ERROR_CODE{"Incompatible"});
21821 }
21822 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21823 { # --source
21824 exit($ERROR_CODE{"Incompatible"});
21825 }
21826 elsif($RESULT{"Source"}{"Problems"}
21827 or $RESULT{"Binary"}{"Problems"})
21828 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021829 exit($ERROR_CODE{"Incompatible"});
21830 }
21831 else {
21832 exit($ERROR_CODE{"Compatible"});
21833 }
21834}
21835
21836sub readRules($)
21837{
21838 my $Kind = $_[0];
21839 if(not -f $RULES_PATH{$Kind}) {
21840 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21841 }
21842 my $Content = readFile($RULES_PATH{$Kind});
21843 while(my $Rule = parseTag(\$Content, "rule"))
21844 {
21845 my $RId = parseTag(\$Rule, "id");
21846 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21847 foreach my $Prop (@Properties) {
21848 if(my $Value = parseTag(\$Rule, lc($Prop)))
21849 {
21850 $Value=~s/\n[ ]*//;
21851 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21852 }
21853 }
21854 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21855 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21856 }
21857 else {
21858 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21859 }
21860 }
21861}
21862
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021863sub getReportPath($)
21864{
21865 my $Level = $_[0];
21866 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21867 if($Level eq "Binary")
21868 {
21869 if($BinaryReportPath)
21870 { # --bin-report-path
21871 return $BinaryReportPath;
21872 }
21873 elsif($OutputReportPath)
21874 { # --report-path
21875 return $OutputReportPath;
21876 }
21877 else
21878 { # default
21879 return $Dir."/abi_compat_report.$ReportFormat";
21880 }
21881 }
21882 elsif($Level eq "Source")
21883 {
21884 if($SourceReportPath)
21885 { # --src-report-path
21886 return $SourceReportPath;
21887 }
21888 elsif($OutputReportPath)
21889 { # --report-path
21890 return $OutputReportPath;
21891 }
21892 else
21893 { # default
21894 return $Dir."/src_compat_report.$ReportFormat";
21895 }
21896 }
21897 else
21898 {
21899 if($OutputReportPath)
21900 { # --report-path
21901 return $OutputReportPath;
21902 }
21903 else
21904 { # default
21905 return $Dir."/compat_report.$ReportFormat";
21906 }
21907 }
21908}
21909
21910sub printStatMsg($)
21911{
21912 my $Level = $_[0];
21913 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21914}
21915
21916sub listAffected($)
21917{
21918 my $Level = $_[0];
21919 my $List = "";
21920 foreach (keys(%{$TotalAffected{$Level}}))
21921 {
21922 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21923 { # skip "Low"-severity problems
21924 next;
21925 }
21926 $List .= "$_\n";
21927 }
21928 my $Dir = get_dirname(getReportPath($Level));
21929 if($Level eq "Binary") {
21930 writeFile($Dir."/abi_affected.txt", $List);
21931 }
21932 elsif($Level eq "Source") {
21933 writeFile($Dir."/src_affected.txt", $List);
21934 }
21935}
21936
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021937sub printReport()
21938{
21939 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021940 createReport();
21941 if($JoinReport or $DoubleReport)
21942 {
21943 if($RESULT{"Binary"}{"Problems"}
21944 or $RESULT{"Source"}{"Problems"}) {
21945 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021946 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021947 else {
21948 printMsg("INFO", "result: COMPATIBLE");
21949 }
21950 printStatMsg("Binary");
21951 printStatMsg("Source");
21952 if($ListAffected)
21953 { # --list-affected
21954 listAffected("Binary");
21955 listAffected("Source");
21956 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021957 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021958 elsif($BinaryOnly)
21959 {
21960 if($RESULT{"Binary"}{"Problems"}) {
21961 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21962 }
21963 else {
21964 printMsg("INFO", "result: COMPATIBLE");
21965 }
21966 printStatMsg("Binary");
21967 if($ListAffected)
21968 { # --list-affected
21969 listAffected("Binary");
21970 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021971 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021972 elsif($SourceOnly)
21973 {
21974 if($RESULT{"Source"}{"Problems"}) {
21975 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21976 }
21977 else {
21978 printMsg("INFO", "result: COMPATIBLE");
21979 }
21980 printStatMsg("Source");
21981 if($ListAffected)
21982 { # --list-affected
21983 listAffected("Source");
21984 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021985 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021986 if($StdOut)
21987 {
21988 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021989 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021990 printMsg("INFO", "compatibility report has been generated to stdout");
21991 }
21992 else
21993 { # default
21994 printMsg("INFO", "compatibility reports have been generated to stdout");
21995 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021996 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021997 else
21998 {
21999 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022000 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022001 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
22002 }
22003 elsif($DoubleReport)
22004 { # default
22005 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
22006 }
22007 elsif($BinaryOnly)
22008 { # --binary
22009 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
22010 }
22011 elsif($SourceOnly)
22012 { # --source
22013 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
22014 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022015 }
22016}
22017
22018sub check_win32_env()
22019{
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022020 if(not $ENV{"VCINSTALLDIR"}
22021 or not $ENV{"INCLUDE"}) {
22022 exitStatus("Error", "can't start without VC environment (vcvars64.bat)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022023 }
22024}
22025
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022026sub diffSets($$)
22027{
22028 my ($S1, $S2) = @_;
22029 my @SK1 = keys(%{$S1});
22030 my @SK2 = keys(%{$S2});
22031 if($#SK1!=$#SK2) {
22032 return 1;
22033 }
22034 foreach my $K1 (@SK1)
22035 {
22036 if(not defined $S2->{$K1}) {
22037 return 1;
22038 }
22039 }
22040 return 0;
22041}
22042
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022043sub defaultDumpPath($$)
22044{
22045 my ($N, $V) = @_;
22046 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
22047}
22048
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022049sub create_ABI_Dump()
22050{
22051 if(not -e $DumpAPI) {
22052 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
22053 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022054
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022055 if(isDump($DumpAPI)) {
22056 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022057 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022058 else {
22059 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022060 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022061
22062 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022063 { # set to default: N
22064 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022065 }
22066
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022067 initLogging(1);
22068 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022069
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022070 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022071 if($OutputDumpPath)
22072 { # user defined path
22073 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022074 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022075 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
22076
22077 if(not $Archive and not $StdOut)
22078 { # check archive utilities
22079 if($OSgroup eq "windows")
22080 { # using zip
22081 my $ZipCmd = get_CmdPath("zip");
22082 if(not $ZipCmd) {
22083 exitStatus("Not_Found", "can't find \"zip\"");
22084 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022085 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022086 else
22087 { # using tar and gzip
22088 my $TarCmd = get_CmdPath("tar");
22089 if(not $TarCmd) {
22090 exitStatus("Not_Found", "can't find \"tar\"");
22091 }
22092 my $GzipCmd = get_CmdPath("gzip");
22093 if(not $GzipCmd) {
22094 exitStatus("Not_Found", "can't find \"gzip\"");
22095 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022096 }
22097 }
22098
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022099 if(not $Descriptor{1}{"Dump"})
22100 {
22101 if(not $CheckHeadersOnly) {
22102 readLibs(1);
22103 }
22104 if($CheckHeadersOnly) {
22105 setLanguage(1, "C++");
22106 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022107 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022108 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022109 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022110 if(not $Descriptor{1}{"Dump"})
22111 {
22112 if($Descriptor{1}{"Headers"}) {
22113 readHeaders(1);
22114 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022115 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022116 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022117 if(not keys(%{$SymbolInfo{1}}))
22118 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022119 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022120 {
22121 if($CheckHeadersOnly) {
22122 exitStatus("Empty_Set", "the set of public symbols is empty");
22123 }
22124 else {
22125 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
22126 }
22127 }
22128 }
22129 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022130 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022131 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
22132 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022133 if($ExtraDump)
22134 { # add unmangled names to the ABI dump
22135 my @Names = ();
22136 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
22137 {
22138 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
22139 push(@Names, $MnglName);
22140 }
22141 }
22142 translateSymbols(@Names, 1);
22143 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
22144 {
22145 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
22146 {
22147 if(my $Unmangled = $tr_name{$MnglName})
22148 {
22149 if($MnglName ne $Unmangled) {
22150 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
22151 }
22152 }
22153 }
22154 }
22155 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022156
22157 my %GccConstants = (); # built-in GCC constants
22158 foreach my $Name (keys(%{$Constants{1}}))
22159 {
22160 if(not defined $Constants{1}{$Name}{"Header"})
22161 {
22162 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
22163 delete($Constants{1}{$Name});
22164 }
22165 }
22166
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022167 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022168 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022169 "TypeInfo" => $TypeInfo{1},
22170 "SymbolInfo" => $SymbolInfo{1},
22171 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022172 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022173 "SymbolVersion" => $SymVer{1},
22174 "LibraryVersion" => $Descriptor{1}{"Version"},
22175 "LibraryName" => $TargetLibraryName,
22176 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022177 "SkipTypes" => $SkipTypes{1},
22178 "SkipSymbols" => $SkipSymbols{1},
22179 "SkipNameSpaces" => $SkipNameSpaces{1},
22180 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022181 "Headers" => \%HeadersInfo,
22182 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022183 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022184 "NameSpaces" => $NestedNameSpaces{1},
22185 "Target" => $OStarget,
22186 "Arch" => getArch(1),
22187 "WordSize" => $WORD_SIZE{1},
22188 "GccVersion" => get_dumpversion($GCC_PATH),
22189 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
22190 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
22191 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022192 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022193 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022194 }
22195 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022196 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022197 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022198 if($ExtendedCheck)
22199 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022200 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022201 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022202 if($BinaryOnly)
22203 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022204 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022205 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022206 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022207 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022208 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022209 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
22210 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022211 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022212
22213 my $ABI_DUMP = "";
22214 if($UseXML)
22215 {
22216 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022217 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022218 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022219 else
22220 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022221 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022222 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022223 if($StdOut)
22224 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022225 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022226 printMsg("INFO", "ABI dump has been generated to stdout");
22227 return;
22228 }
22229 else
22230 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022231 my ($DDir, $DName) = separate_path($DumpPath);
22232 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022233 if(not $Archive) {
22234 $DPath = $DumpPath;
22235 }
22236
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022237 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022238
22239 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022240 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022241 close(DUMP);
22242
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022243 if(not -s $DPath) {
22244 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
22245 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022246 if($Archive) {
22247 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022248 }
22249
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022250 if($OutputDumpPath) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022251 printMsg("INFO", "dump path: $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022252 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022253 else {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022254 printMsg("INFO", "dump path: $DumpPath");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022255 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022256 # printMsg("INFO", "you can transfer this dump everywhere and use instead of the ".$Descriptor{1}{"Version"}." version descriptor");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022257 }
22258}
22259
22260sub quickEmptyReports()
22261{ # Quick "empty" reports
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022262 # ~4 times faster than merging equal dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022263 # NOTE: the dump contains the "LibraryVersion" attribute
22264 # if you change the version, then your dump will be different
22265 # OVERCOME: use -v1 and v2 options for comparing dumps
22266 # and don't change version in the XML descriptor (and dumps)
22267 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022268 if($Descriptor{1}{"Path"} eq $Descriptor{2}{"Path"}
22269 or -s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022270 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022271 my $FilePath1 = $Descriptor{1}{"Path"};
22272 my $FilePath2 = $Descriptor{2}{"Path"};
22273
22274 if(not isDump_U($FilePath1)) {
22275 $FilePath1 = unpackDump($FilePath1);
22276 }
22277
22278 if(not isDump_U($FilePath2)) {
22279 $FilePath2 = unpackDump($FilePath2);
22280 }
22281
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022282 if($FilePath1 and $FilePath2)
22283 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022284 my $Line = readLineNum($FilePath1, 0);
22285 if($Line=~/xml/)
22286 { # XML format
22287 # is not supported yet
22288 return;
22289 }
22290
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022291 local $/ = undef;
22292
22293 open(DUMP1, $FilePath1);
22294 my $Content1 = <DUMP1>;
22295 close(DUMP1);
22296
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022297 my $Eq = 0;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022298
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022299 if($FilePath1 eq $FilePath2) {
22300 $Eq = 1;
22301 }
22302
22303 if(not $Eq)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022304 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022305 open(DUMP2, $FilePath2);
22306 my $Content2 = <DUMP2>;
22307 close(DUMP2);
22308
22309 if($Content1 eq $Content2) {
22310 $Eq = 1;
22311 }
22312
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022313 # clean memory
22314 undef $Content2;
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022315 }
22316
22317 if($Eq)
22318 {
22319 printMsg("INFO", "Input ABI dumps are equal, so generating quick empty report");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022320 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022321 my $ABIdump = eval($Content1);
22322
22323 # clean memory
22324 undef $Content1;
22325
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022326 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022327 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022328 }
22329 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022330 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022331 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
22332 }
22333 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022334 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022335 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
22336 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022337 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022338
22339 foreach (keys(%{$Registered_Headers{1}})) {
22340 $TargetHeaders{1}{$_} = 1;
22341 }
22342
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022343 read_Libs_DumpInfo($ABIdump, 1);
22344 read_Machine_DumpInfo($ABIdump, 1);
22345 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022346
22347 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
22348 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
22349
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022350 foreach my $S (keys(%{$ABIdump->{"SymbolInfo"}}))
22351 {
22352 if(my $Class = $ABIdump->{"SymbolInfo"}{$S}{"Class"})
22353 {
22354 if(defined $ABIdump->{"TypeInfo"}{$Class}{"PrivateABI"}) {
22355 next;
22356 }
22357 }
22358
22359 my $Access = $ABIdump->{"SymbolInfo"}{$S}{"Access"};
22360 if($Access ne "private")
22361 {
22362 $CheckedSymbols{"Binary"}{$S} = 1;
22363 $CheckedSymbols{"Source"}{$S} = 1;
22364 }
22365 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022366
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022367 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
22368 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022369
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030022370 if(not defined $Descriptor{1}{"Version"}) {
22371 $Descriptor{1}{"Version"} = "X";
22372 }
22373
22374 if(not defined $Descriptor{2}{"Version"}) {
22375 $Descriptor{2}{"Version"} = "Y";
22376 }
22377
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022378 if(defined $ABIdump->{"ABI_DUMPER_VERSION"})
22379 {
22380 $UsedDump{1}{"DWARF"} = 1;
22381 $UsedDump{2}{"DWARF"} = 1;
22382
22383 $UsedDump{1}{"M"} = $ABIdump->{"LibraryName"};
22384 $UsedDump{2}{"M"} = $ABIdump->{"LibraryName"};
22385 }
22386
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022387 exitReport();
22388 }
22389 }
22390 }
22391}
22392
22393sub initLogging($)
22394{
22395 my $LibVersion = $_[0];
22396 # create log directory
22397 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
22398 if($OutputLogPath{$LibVersion})
22399 { # user-defined by -log-path option
22400 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
22401 }
22402 if($LogMode ne "n") {
22403 mkpath($LOG_DIR);
22404 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022405 $LOG_PATH{$LibVersion} = join_P(get_abs_path($LOG_DIR), $LOG_FILE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022406 if($Debug)
22407 { # debug directory
22408 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022409
22410 if(not $ExtraInfo)
22411 { # enable --extra-info
22412 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
22413 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022414 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022415 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022416}
22417
22418sub writeLog($$)
22419{
22420 my ($LibVersion, $Msg) = @_;
22421 if($LogMode ne "n") {
22422 appendFile($LOG_PATH{$LibVersion}, $Msg);
22423 }
22424}
22425
22426sub resetLogging($)
22427{
22428 my $LibVersion = $_[0];
22429 if($LogMode!~/a|n/)
22430 { # remove old log
22431 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022432 if($Debug) {
22433 rmtree($DEBUG_PATH{$LibVersion});
22434 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022435 }
22436}
22437
22438sub printErrorLog($)
22439{
22440 my $LibVersion = $_[0];
22441 if($LogMode ne "n") {
22442 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
22443 }
22444}
22445
22446sub isDump($)
22447{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022448 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
22449 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022450 return $1;
22451 }
22452 return 0;
22453}
22454
22455sub isDump_U($)
22456{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022457 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022458 return $1;
22459 }
22460 return 0;
22461}
22462
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022463sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022464{
22465 # read input XML descriptors or ABI dumps
22466 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022467 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022468 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022469 if(not -e $Descriptor{1}{"Path"}) {
22470 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022471 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022472
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022473 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022474 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022475 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022476 if(not -e $Descriptor{2}{"Path"}) {
22477 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022478 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022479
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022480 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022481
22482 if(not defined $DisableQuickEmptyReport)
22483 {
22484 if(isDump($Descriptor{1}{"Path"})
22485 and isDump($Descriptor{2}{"Path"}))
22486 { # optimization: equal ABI dumps
22487 quickEmptyReports();
22488 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022489 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022490
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022491 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022492
22493 if(isDump($Descriptor{1}{"Path"})) {
22494 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022495 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022496 else {
22497 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
22498 }
22499
22500 if(isDump($Descriptor{2}{"Path"})) {
22501 read_ABI_Dump(2, $Descriptor{2}{"Path"});
22502 }
22503 else {
22504 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022505 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022506
22507 if(not $Descriptor{1}{"Version"})
22508 { # set to default: X
22509 $Descriptor{1}{"Version"} = "X";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022510 print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022511 }
22512
22513 if(not $Descriptor{2}{"Version"})
22514 { # set to default: Y
22515 $Descriptor{2}{"Version"} = "Y";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022516 print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022517 }
22518
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030022519 if(not $UsedDump{1}{"V"}) {
22520 initLogging(1);
22521 }
22522
22523 if(not $UsedDump{2}{"V"}) {
22524 initLogging(2);
22525 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022526
22527 # check input data
22528 if(not $Descriptor{1}{"Headers"}) {
22529 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022530 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022531 if(not $Descriptor{2}{"Headers"}) {
22532 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022533 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022534
22535 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022536 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022537 if(not $Descriptor{1}{"Libs"}) {
22538 exitStatus("Error", "can't find libraries info in descriptor d1");
22539 }
22540 if(not $Descriptor{2}{"Libs"}) {
22541 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022542 }
22543 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022544
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022545 if($UseDumps)
22546 { # --use-dumps
22547 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022548 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
22549 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022550
22551 unlink($DumpPath1);
22552 unlink($DumpPath2);
22553
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022554 my $pid = fork();
22555 if($pid)
22556 { # dump on two CPU cores
22557 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22558 if($RelativeDirectory{1}) {
22559 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22560 }
22561 if($OutputLogPath{1}) {
22562 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22563 }
22564 if($CrossGcc) {
22565 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22566 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022567 if($Quiet)
22568 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022569 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022570 @PARAMS = (@PARAMS, "-logging-mode", "a");
22571 }
22572 elsif($LogMode and $LogMode ne "w")
22573 { # "w" is default
22574 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022575 }
22576 if($ExtendedCheck) {
22577 @PARAMS = (@PARAMS, "-extended");
22578 }
22579 if($UserLang) {
22580 @PARAMS = (@PARAMS, "-lang", $UserLang);
22581 }
22582 if($TargetVersion{1}) {
22583 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22584 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022585 if($BinaryOnly) {
22586 @PARAMS = (@PARAMS, "-binary");
22587 }
22588 if($SourceOnly) {
22589 @PARAMS = (@PARAMS, "-source");
22590 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022591 if($SortDump) {
22592 @PARAMS = (@PARAMS, "-sort");
22593 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022594 if($DumpFormat and $DumpFormat ne "perl") {
22595 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22596 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022597 if($CheckHeadersOnly) {
22598 @PARAMS = (@PARAMS, "-headers-only");
22599 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022600 if($Debug)
22601 {
22602 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022603 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022604 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022605 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022606 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022607 exit(1);
22608 }
22609 }
22610 else
22611 { # child
22612 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22613 if($RelativeDirectory{2}) {
22614 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22615 }
22616 if($OutputLogPath{2}) {
22617 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22618 }
22619 if($CrossGcc) {
22620 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22621 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022622 if($Quiet)
22623 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022624 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022625 @PARAMS = (@PARAMS, "-logging-mode", "a");
22626 }
22627 elsif($LogMode and $LogMode ne "w")
22628 { # "w" is default
22629 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022630 }
22631 if($ExtendedCheck) {
22632 @PARAMS = (@PARAMS, "-extended");
22633 }
22634 if($UserLang) {
22635 @PARAMS = (@PARAMS, "-lang", $UserLang);
22636 }
22637 if($TargetVersion{2}) {
22638 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22639 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022640 if($BinaryOnly) {
22641 @PARAMS = (@PARAMS, "-binary");
22642 }
22643 if($SourceOnly) {
22644 @PARAMS = (@PARAMS, "-source");
22645 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022646 if($SortDump) {
22647 @PARAMS = (@PARAMS, "-sort");
22648 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022649 if($DumpFormat and $DumpFormat ne "perl") {
22650 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22651 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022652 if($CheckHeadersOnly) {
22653 @PARAMS = (@PARAMS, "-headers-only");
22654 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022655 if($Debug)
22656 {
22657 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022658 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022659 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022660 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022661 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022662 exit(1);
22663 }
22664 else {
22665 exit(0);
22666 }
22667 }
22668 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022669
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022670 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022671 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22672 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022673 if($TargetTitle ne $TargetLibraryName) {
22674 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022675 }
22676 if($ShowRetVal) {
22677 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22678 }
22679 if($CrossGcc) {
22680 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22681 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022682 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22683 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022684 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022685 }
22686 if($ReportFormat and $ReportFormat ne "html")
22687 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022688 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22689 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022690 if($OutputReportPath) {
22691 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22692 }
22693 if($BinaryReportPath) {
22694 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22695 }
22696 if($SourceReportPath) {
22697 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22698 }
22699 if($LoggingPath) {
22700 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22701 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022702 if($CheckHeadersOnly) {
22703 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22704 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022705 if($BinaryOnly) {
22706 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22707 }
22708 if($SourceOnly) {
22709 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22710 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022711 if($Debug)
22712 {
22713 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22714 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022715 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022716 system("perl", $0, @CMP_PARAMS);
22717 exit($?>>8);
22718 }
22719 if(not $Descriptor{1}{"Dump"}
22720 or not $Descriptor{2}{"Dump"})
22721 { # need GCC toolchain to analyze
22722 # header files and libraries
22723 detect_default_paths("inc|lib|gcc");
22724 }
22725 if(not $Descriptor{1}{"Dump"})
22726 {
22727 if(not $CheckHeadersOnly) {
22728 readLibs(1);
22729 }
22730 if($CheckHeadersOnly) {
22731 setLanguage(1, "C++");
22732 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022733 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022734 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022735 }
22736 if(not $Descriptor{2}{"Dump"})
22737 {
22738 if(not $CheckHeadersOnly) {
22739 readLibs(2);
22740 }
22741 if($CheckHeadersOnly) {
22742 setLanguage(2, "C++");
22743 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022744 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022745 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022746 }
22747 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22748 { # support for old ABI dumps
22749 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022750 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022751 {
22752 $WORD_SIZE{1} = $WORD_SIZE{2};
22753 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22754 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022755 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022756 {
22757 $WORD_SIZE{2} = $WORD_SIZE{1};
22758 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22759 }
22760 }
22761 elsif(not $WORD_SIZE{1}
22762 and not $WORD_SIZE{2})
22763 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022764 $WORD_SIZE{1} = "4";
22765 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022766 }
22767 if($Descriptor{1}{"Dump"})
22768 { # support for old ABI dumps
22769 prepareTypes(1);
22770 }
22771 if($Descriptor{2}{"Dump"})
22772 { # support for old ABI dumps
22773 prepareTypes(2);
22774 }
22775 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22776 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22777 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022778 # process input data
22779 if($Descriptor{1}{"Headers"}
22780 and not $Descriptor{1}{"Dump"}) {
22781 readHeaders(1);
22782 }
22783 if($Descriptor{2}{"Headers"}
22784 and not $Descriptor{2}{"Dump"}) {
22785 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022786 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022787
22788 # clean memory
22789 %SystemHeaders = ();
22790 %mangled_name_gcc = ();
22791
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022792 prepareSymbols(1);
22793 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022794
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022795 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022796 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022797
22798 # Virtual Tables
22799 registerVTable(1);
22800 registerVTable(2);
22801
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022802 if(not checkDump(1, "1.22")
22803 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022804 { # support for old ABI dumps
22805 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22806 {
22807 if($ClassName=~/</)
22808 { # templates
22809 if(not defined $VirtualTable{1}{$ClassName})
22810 { # synchronize
22811 delete($VirtualTable{2}{$ClassName});
22812 }
22813 }
22814 }
22815 }
22816
22817 registerOverriding(1);
22818 registerOverriding(2);
22819
22820 setVirtFuncPositions(1);
22821 setVirtFuncPositions(2);
22822
22823 # Other
22824 addParamNames(1);
22825 addParamNames(2);
22826
22827 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022828}
22829
22830sub compareAPIs($)
22831{
22832 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022833
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022834 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022835 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022836
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022837 if($Level eq "Binary") {
22838 printMsg("INFO", "comparing ABIs ...");
22839 }
22840 else {
22841 printMsg("INFO", "comparing APIs ...");
22842 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022843
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022844 if($CheckHeadersOnly
22845 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022846 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022847 detectAdded_H($Level);
22848 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022849 }
22850 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022851 { # added/removed in libs
22852 detectAdded($Level);
22853 detectRemoved($Level);
22854 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022855
22856 mergeSymbols($Level);
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030022857
22858 if(not defined $DisableConstantsCheck)
22859 {
22860 if(keys(%{$CheckedSymbols{$Level}})) {
22861 mergeConstants($Level);
22862 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022863 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022864
22865 $Cache{"mergeTypes"} = (); # free memory
22866
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022867 if($CheckHeadersOnly
22868 or $Level eq "Source")
22869 { # added/removed in headers
22870 mergeHeaders($Level);
22871 }
22872 else
22873 { # added/removed in libs
22874 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022875 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022876
22877 foreach my $S (keys(%{$CompatProblems{$Level}}))
22878 {
22879 foreach my $K (keys(%{$CompatProblems{$Level}{$S}}))
22880 {
22881 foreach my $L (keys(%{$CompatProblems{$Level}{$S}{$K}}))
22882 {
22883 if(my $T = $CompatProblems{$Level}{$S}{$K}{$L}{"Type_Name"}) {
22884 $TypeProblemsIndex{$Level}{$T}{$S} = 1;
22885 }
22886 }
22887 }
22888 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022889}
22890
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022891sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022892{
22893 my %Opts = (
22894 "OStarget"=>$OStarget,
22895 "Debug"=>$Debug,
22896 "Quiet"=>$Quiet,
22897 "LogMode"=>$LogMode,
22898 "CheckHeadersOnly"=>$CheckHeadersOnly,
22899
22900 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022901 "GCC_PATH"=>$GCC_PATH,
22902 "TargetSysInfo"=>$TargetSysInfo,
22903 "CrossPrefix"=>$CrossPrefix,
22904 "TargetLibraryName"=>$TargetLibraryName,
22905 "CrossGcc"=>$CrossGcc,
22906 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022907 "NoStdInc"=>$NoStdInc,
Andrey Ponomarenko991da682016-09-07 19:09:50 +030022908 "CxxIncompat"=>$CxxIncompat,
22909 "SkipUnidentified"=>$SkipUnidentified,
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030022910 "DisableConstantsCheck"=>$DisableConstantsCheck,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022911
22912 "BinaryOnly" => $BinaryOnly,
22913 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022914 );
22915 return \%Opts;
22916}
22917
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022918sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022919{
22920 my %CODE_ERROR = reverse(%ERROR_CODE);
22921 return $CODE_ERROR{$_[0]};
22922}
22923
22924sub scenario()
22925{
22926 if($StdOut)
22927 { # enable quiet mode
22928 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022929 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022930 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022931 if(not $LogMode)
22932 { # default
22933 $LogMode = "w";
22934 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022935 if($UserLang)
22936 { # --lang=C++
22937 $UserLang = uc($UserLang);
22938 $COMMON_LANGUAGE{1}=$UserLang;
22939 $COMMON_LANGUAGE{2}=$UserLang;
22940 }
22941 if($LoggingPath)
22942 {
22943 $OutputLogPath{1} = $LoggingPath;
22944 $OutputLogPath{2} = $LoggingPath;
22945 if($Quiet) {
22946 $COMMON_LOG_PATH = $LoggingPath;
22947 }
22948 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022949
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022950 if($Quick) {
22951 $ADD_TMPL_INSTANCES = 0;
22952 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022953 if($OutputDumpPath)
22954 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022955 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022956 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22957 }
22958 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022959 if($BinaryOnly and $SourceOnly)
22960 { # both --binary and --source
22961 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022962 if(not $CmpSystems)
22963 {
22964 $BinaryOnly = 0;
22965 $SourceOnly = 0;
22966 }
22967
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022968 $DoubleReport = 1;
22969 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022970
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022971 if($OutputReportPath)
22972 { # --report-path
22973 $DoubleReport = 0;
22974 $JoinReport = 1;
22975 }
22976 }
22977 elsif($BinaryOnly or $SourceOnly)
22978 { # --binary or --source
22979 $DoubleReport = 0;
22980 $JoinReport = 0;
22981 }
22982 if($UseXML)
22983 { # --xml option
22984 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022985 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022986 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022987 if($ReportFormat)
22988 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022989 $ReportFormat = lc($ReportFormat);
22990 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022991 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022992 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022993 if($ReportFormat eq "htm")
22994 { # HTM == HTML
22995 $ReportFormat = "html";
22996 }
22997 elsif($ReportFormat eq "xml")
22998 { # --report-format=XML equal to --xml
22999 $UseXML = 1;
23000 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023001 }
23002 else
23003 { # default: HTML
23004 $ReportFormat = "html";
23005 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040023006 if($DumpFormat)
23007 { # validate
23008 $DumpFormat = lc($DumpFormat);
23009 if($DumpFormat!~/\A(xml|perl)\Z/) {
23010 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
23011 }
23012 if($DumpFormat eq "xml")
23013 { # --dump-format=XML equal to --xml
23014 $UseXML = 1;
23015 }
23016 }
23017 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040023018 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040023019 $DumpFormat = "perl";
23020 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023021 if($Quiet and $LogMode!~/a|n/)
23022 { # --quiet log
23023 if(-f $COMMON_LOG_PATH) {
23024 unlink($COMMON_LOG_PATH);
23025 }
23026 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040023027 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023028 $CheckUndefined = 1;
23029 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023030 if($TestTool and $UseDumps)
23031 { # --test && --use-dumps == --test-dump
23032 $TestDump = 1;
23033 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040023034 if($Tolerant)
23035 { # enable all
23036 $Tolerance = 1234;
23037 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023038 if($Help)
23039 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023040 HELP_MESSAGE();
23041 exit(0);
23042 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030023043 if($InfoMsg)
23044 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023045 INFO_MESSAGE();
23046 exit(0);
23047 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023048 if($ShowVersion)
23049 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030023050 printMsg("INFO", "ABI Compliance Checker (ABICC) $TOOL_VERSION\nCopyright (C) 2016 Andrey Ponomarenko's ABI 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.");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023051 exit(0);
23052 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023053 if($DumpVersion)
23054 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023055 printMsg("INFO", $TOOL_VERSION);
23056 exit(0);
23057 }
23058 if($ExtendedCheck) {
23059 $CheckHeadersOnly = 1;
23060 }
23061 if($SystemRoot_Opt)
23062 { # user defined root
23063 if(not -e $SystemRoot_Opt) {
23064 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
23065 }
23066 $SystemRoot = $SystemRoot_Opt;
23067 $SystemRoot=~s/[\/]+\Z//g;
23068 if($SystemRoot) {
23069 $SystemRoot = get_abs_path($SystemRoot);
23070 }
23071 }
23072 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040023073
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023074 if($SortDump)
23075 {
23076 $Data::Dumper::Useperl = 1;
23077 $Data::Dumper::Sortkeys = \&dump_sorting;
23078 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040023079
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023080 if($TargetLibsPath)
23081 {
23082 if(not -f $TargetLibsPath) {
23083 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
23084 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030023085 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath)))
23086 {
23087 if($OSgroup eq "windows") {
23088 $TargetLibs{lc($Lib)} = 1;
23089 }
23090 else {
23091 $TargetLibs{$Lib} = 1;
23092 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023093 }
23094 }
23095 if($TargetHeadersPath)
23096 { # --headers-list
23097 if(not -f $TargetHeadersPath) {
23098 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
23099 }
23100 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
23101 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030023102 $TargetHeaders{1}{get_filename($Header)} = 1;
23103 $TargetHeaders{2}{get_filename($Header)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023104 }
23105 }
23106 if($TargetHeader)
23107 { # --header
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030023108 $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
23109 $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023110 }
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030023111 if($TestABIDumper)
23112 {
23113 if($OSgroup ne "linux") {
23114 exitStatus("Error", "-test-abi-dumper option is available on Linux only");
23115 }
23116 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023117 if($TestTool
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030023118 or $TestDump
23119 or $TestABIDumper)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023120 { # --test, --test-dump
23121 detect_default_paths("bin|gcc"); # to compile libs
23122 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040023123 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030023124 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly, $OldStyle, $TestABIDumper);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023125 exit(0);
23126 }
23127 if($DumpSystem)
23128 { # --dump-system
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030023129 if(-d $MODULES_DIR."/Targets/"
23130 and -d $MODULES_DIR."/Targets/".$OStarget) {
23131 $TargetSysInfo = $MODULES_DIR."/Targets/".$OStarget;
23132 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030023133 if(not $TargetSysInfo) {
23134 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
23135 }
23136
23137 if(not -d $TargetSysInfo) {
23138 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
23139 }
23140
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023141 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023142 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023143 { # system XML descriptor
23144 if(not -f $DumpSystem) {
23145 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
23146 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030023147
23148 my $SDesc = readFile($DumpSystem);
23149 if(my $RelDir = $RelativeDirectory{1}) {
23150 $SDesc =~ s/{RELPATH}/$RelDir/g;
23151 }
23152
23153 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023154 foreach (@{$Ret->{"Tools"}})
23155 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023156 push_U($SystemPaths{"bin"}, $_);
23157 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023158 }
23159 if($Ret->{"CrossPrefix"}) {
23160 $CrossPrefix = $Ret->{"CrossPrefix"};
23161 }
23162 }
23163 elsif($SystemRoot_Opt)
23164 { # -sysroot "/" option
23165 # default target: /usr/lib, /usr/include
23166 # search libs: /usr/lib and /lib
23167 if(not -e $SystemRoot."/usr/lib") {
23168 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
23169 }
23170 if(not -e $SystemRoot."/lib") {
23171 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
23172 }
23173 if(not -e $SystemRoot."/usr/include") {
23174 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
23175 }
23176 readSystemDescriptor("
23177 <name>
23178 $DumpSystem
23179 </name>
23180 <headers>
23181 $SystemRoot/usr/include
23182 </headers>
23183 <libs>
23184 $SystemRoot/usr/lib
23185 </libs>
23186 <search_libs>
23187 $SystemRoot/lib
23188 </search_libs>");
23189 }
23190 else {
23191 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
23192 }
23193 detect_default_paths("bin|gcc"); # to check symbols
23194 if($OStarget eq "windows")
23195 { # to run dumpbin.exe
23196 # and undname.exe
23197 check_win32_env();
23198 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023199 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023200 exit(0);
23201 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023202
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023203 if($CmpSystems)
23204 { # --cmp-systems
23205 detect_default_paths("bin"); # to extract dumps
23206 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023207 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023208 exit(0);
23209 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023210
23211 if(not $CountSymbols)
23212 {
23213 if(not $TargetLibraryName) {
23214 exitStatus("Error", "library name is not selected (-l option)");
23215 }
23216 else
23217 { # validate library name
23218 if($TargetLibraryName=~/[\*\/\\]/) {
23219 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
23220 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023221 }
23222 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023223
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030023224 if(not $TargetTitle) {
23225 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023226 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030023227
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023228 if($SymbolsListPath)
23229 {
23230 if(not -f $SymbolsListPath) {
23231 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
23232 }
23233 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
23234 $SymbolsList{$Interface} = 1;
23235 }
23236 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030023237 if($TypesListPath)
23238 {
23239 if(not -f $TypesListPath) {
23240 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
23241 }
23242 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
23243 $TypesList{$Type} = 1;
23244 }
23245 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023246 if($SkipSymbolsListPath)
23247 {
23248 if(not -f $SkipSymbolsListPath) {
23249 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
23250 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030023251 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
23252 {
23253 $SkipSymbols{1}{$Interface} = 1;
23254 $SkipSymbols{2}{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023255 }
23256 }
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030023257 if($SkipTypesListPath)
23258 {
23259 if(not -f $SkipTypesListPath) {
23260 exitStatus("Access_Error", "can't access file \'$SkipTypesListPath\'");
23261 }
23262 foreach my $Type (split(/\s*\n\s*/, readFile($SkipTypesListPath)))
23263 {
23264 $SkipTypes{1}{$Type} = 1;
23265 $SkipTypes{2}{$Type} = 1;
23266 }
23267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023268 if($SkipHeadersPath)
23269 {
23270 if(not -f $SkipHeadersPath) {
23271 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
23272 }
23273 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023274 { # register for both versions
23275 $SkipHeadersList{1}{$Path} = 1;
23276 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030023277
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023278 my ($CPath, $Type) = classifyPath($Path);
23279 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023280 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023281 }
23282 }
23283 if($ParamNamesPath)
23284 {
23285 if(not -f $ParamNamesPath) {
23286 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
23287 }
23288 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
23289 {
23290 if($Line=~s/\A(\w+)\;//)
23291 {
23292 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023293 if($Line=~/;(\d+);/)
23294 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023295 while($Line=~s/(\d+);(\w+)//) {
23296 $AddIntParams{$Interface}{$1}=$2;
23297 }
23298 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023299 else
23300 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023301 my $Num = 0;
23302 foreach my $Name (split(/;/, $Line)) {
23303 $AddIntParams{$Interface}{$Num++}=$Name;
23304 }
23305 }
23306 }
23307 }
23308 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023309
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023310 if($AppPath)
23311 {
23312 if(not -f $AppPath) {
23313 exitStatus("Access_Error", "can't access file \'$AppPath\'");
23314 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030023315
23316 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040023317 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023318 $SymbolsList_App{$Interface} = 1;
23319 }
23320 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023321
23322 if($CountSymbols)
23323 {
23324 if(not -e $CountSymbols) {
23325 exitStatus("Access_Error", "can't access \'$CountSymbols\'");
23326 }
23327
23328 read_ABI_Dump(1, $CountSymbols);
23329
23330 foreach my $Id (keys(%{$SymbolInfo{1}}))
23331 {
23332 my $MnglName = $SymbolInfo{1}{$Id}{"MnglName"};
23333 if(not $MnglName) {
23334 $MnglName = $SymbolInfo{1}{$Id}{"ShortName"}
23335 }
23336
23337 if(my $SV = $SymVer{1}{$MnglName}) {
23338 $CompleteSignature{1}{$SV} = $SymbolInfo{1}{$Id};
23339 }
23340 else {
23341 $CompleteSignature{1}{$MnglName} = $SymbolInfo{1}{$Id};
23342 }
23343
23344 if(my $Alias = $CompleteSignature{1}{$MnglName}{"Alias"}) {
23345 $CompleteSignature{1}{$Alias} = $SymbolInfo{1}{$Id};
23346 }
23347 }
23348
23349 my $Count = 0;
23350 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
23351 {
23352 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
23353 next;
23354 }
23355 if($CompleteSignature{1}{$Symbol}{"Private"}) {
23356 next;
23357 }
23358 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
23359 next;
23360 }
23361
23362 $Count += symbolFilter($Symbol, 1, "Affected + InlineVirt", "Binary");
23363 }
23364
23365 printMsg("INFO", $Count);
23366 exit(0);
23367 }
23368
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023369 if($DumpAPI)
23370 { # --dump-abi
23371 # make an API dump
23372 create_ABI_Dump();
23373 exit($COMPILE_ERRORS);
23374 }
23375 # default: compare APIs
23376 # -d1 <path>
23377 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023378 compareInit();
23379 if($JoinReport or $DoubleReport)
23380 {
23381 compareAPIs("Binary");
23382 compareAPIs("Source");
23383 }
23384 elsif($BinaryOnly) {
23385 compareAPIs("Binary");
23386 }
23387 elsif($SourceOnly) {
23388 compareAPIs("Source");
23389 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023390 exitReport();
23391}
23392
23393scenario();