blob: cf9d9ef25dc720e5d0ea7dcb0e2f8244a4367fa8 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko8580e852016-08-19 19:11:48 +03003# ABI Compliance Checker (ABICC) 1.99.24
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 Ponomarenko85043792012-05-14 16:48:07 +040022# - Perl 5 (5.8 or newer)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040023# - Ctags (5.8 or newer)
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030024# - ABI Dumper (0.99.15 or newer)
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 Ponomarenkof48ec932012-07-19 18:57:20 +040028# - Ctags (5.8 or newer)
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
36# - Exuberant Ctags (5.8 or newer)
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 Ponomarenko8580e852016-08-19 19:11:48 +030063my $TOOL_VERSION = "1.99.24";
64my $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,
96$DisableConstantsCheck, $SkipAddedConstants, $SkipRemovedConstants);
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,
237 "debug!" => \$Debug,
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300238 "cpp-compatible!" => \$CxxCompat,
239 "cxx-incompatible|cpp-incompatible!" => \$CxxIncompat,
240 "mingw-compatible!" => \$MinGWCompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400241 "p|params=s" => \$ParamNamesPath,
242 "relpath1|relpath=s" => \$RelativeDirectory{1},
243 "relpath2=s" => \$RelativeDirectory{2},
244 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400245 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400246 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400247 "bin-report-path=s" => \$BinaryReportPath,
248 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400249 "log-path=s" => \$LoggingPath,
250 "log1-path=s" => \$OutputLogPath{1},
251 "log2-path=s" => \$OutputLogPath{2},
252 "logging-mode=s" => \$LogMode,
253 "list-affected!" => \$ListAffected,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300254 "title|l-full|lib-full=s" => \$TargetTitle,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400255 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400256 "extra-info=s" => \$ExtraInfo,
257 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400258 "force!" => \$Force,
259 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400260 "tolerant!" => \$Tolerant,
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300261 "skip-unidentified!" => \$SkipUnidentified,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400262 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400263 "quick!" => \$Quick,
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300264 "disable-quick-empty-report!" => \$DisableQuickEmptyReport,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400265 "all-affected!" => \$AllAffected,
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300266 "skip-internal-symbols|skip-internal=s" => \$SkipInternalSymbols,
267 "skip-internal-types=s" => \$SkipInternalTypes,
Andrey Ponomarenko8580e852016-08-19 19:11:48 +0300268 "skip-typedef-uncover!" => \$SkipTypedefUncover,
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300269 "check-private-abi!" => \$CheckPrivateABI
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400270) or ERR_MESSAGE();
271
272sub ERR_MESSAGE()
273{
274 printMsg("INFO", "\n".$ShortUsage);
275 exit($ERROR_CODE{"Error"});
276}
277
278my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
279my $SLIB_TYPE = $LIB_TYPE;
280if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
281{ # show as "shared" library
282 $SLIB_TYPE = "shared";
283}
284my $LIB_EXT = getLIB_EXT($OSgroup);
285my $AR_EXT = getAR_EXT($OSgroup);
286my $BYTE_SIZE = 8;
287my $COMMON_LOG_PATH = "logs/run.log";
288
289my $HelpMessage="
290NAME:
291 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400292 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400293
294DESCRIPTION:
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400295 ABI Compliance Checker (ABICC) is a tool for checking backward binary and
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400296 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
297 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
298 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
299 and/or source-level compatibility: changes in calling stack, v-table changes,
300 removed symbols, renamed fields, etc. Binary incompatibility may result in
301 crashing or incorrect behavior of applications built with an old version of
302 a library if they run on a new one. Source incompatibility may result in
303 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400304
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400305 The tool is intended for developers of software libraries and maintainers
306 of operating systems who are interested in ensuring backward compatibility,
307 i.e. allow old applications to run or to be recompiled with newer library
308 versions.
309
310 Also the tool can be used by ISVs for checking applications portability to
311 new library versions. Found issues can be taken into account when adapting
312 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400313
314 This tool is free software: you can redistribute it and/or modify it
315 under the terms of the GNU LGPL or GNU GPL.
316
317USAGE:
318 $CmdName [options]
319
320EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400321 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400322
323 OLD.xml and NEW.xml are XML-descriptors:
324
325 <version>
326 1.0
327 </version>
328
329 <headers>
330 /path1/to/header(s)/
331 /path2/to/header(s)/
332 ...
333 </headers>
334
335 <libs>
336 /path1/to/library(ies)/
337 /path2/to/library(ies)/
338 ...
339 </libs>
340
341INFORMATION OPTIONS:
342 -h|-help
343 Print this help.
344
345 -i|-info
346 Print complete info.
347
348 -v|-version
349 Print version information.
350
351 -dumpversion
352 Print the tool version ($TOOL_VERSION) and don't do anything else.
353
354GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400355 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400356 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400357
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400358 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400359 Descriptor of 1st (old) library version.
360 It may be one of the following:
361
362 1. XML-descriptor (VERSION.xml file):
363
364 <version>
365 1.0
366 </version>
367
368 <headers>
369 /path1/to/header(s)/
370 /path2/to/header(s)/
371 ...
372 </headers>
373
374 <libs>
375 /path1/to/library(ies)/
376 /path2/to/library(ies)/
377 ...
378 </libs>
379
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300380 ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400381
382 2. ABI dump generated by -dump option
383 3. Directory with headers and/or $SLIB_TYPE libraries
384 4. Single header file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400385
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300386 If you are using an 2-4 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400387 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400388
389 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400390 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400391
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400392 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400393 Descriptor of 2nd (new) library version.
394
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400395 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400396 Create library ABI dump for the input XML descriptor. You can
397 transfer it anywhere and pass instead of the descriptor. Also
398 it can be used for debugging the tool.
399
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +0300400 Supported versions of ABI dump: 2.0<=V<=$ABI_DUMP_VERSION\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400401
402sub HELP_MESSAGE() {
403 printMsg("INFO", $HelpMessage."
404MORE INFO:
405 $CmdName --info\n");
406}
407
408sub INFO_MESSAGE()
409{
410 printMsg("INFO", "$HelpMessage
411EXTRA OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400412 -app|-application PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300413 This option allows to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400414 for portability to the new library version.
415
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300416 -static
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400417 Check static libraries instead of the shared ones. The <libs> section
418 of the XML-descriptor should point to static libraries location.
419
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300420 -gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400421 Path to the cross GCC compiler to use instead of the usual (host) GCC.
422
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300423 -gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400424 GCC toolchain prefix.
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300425
426 -gcc-options OPTS
427 Additional compiler options.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400428
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400429 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400430 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400431 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400432
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400433 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400434 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200435 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400436
437 In general case you should specify it in the XML-descriptor:
438 <version>
439 VERSION
440 </version>
441
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400442 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400443 Specify 2nd library version outside the descriptor.
444
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +0400445 -vnum NUM
446 Specify the library version in the generated ABI dump. The <version> section
447 of the input XML descriptor will be overwritten in this case.
448
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400449 -s|-strict
450 Treat all compatibility warnings as problems. Add a number of \"Low\"
451 severity problems to the return value of the tool.
452
453 -headers-only
454 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
455 provide a low quality compatibility report with false positives and
456 without detecting of added/removed symbols.
457
458 Alternatively you can write \"none\" word to the <libs> section
459 in the XML-descriptor:
460 <libs>
461 none
462 </libs>
463
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400464 -show-retval
465 Show the symbol's return type in the report.
466
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400467 -symbols-list PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300468 This option allows to specify a file with a list of symbols (mangled
469 names in C++) that should be checked. Other symbols will not be checked.
470
471 -types-list PATH
472 This option allows to specify a file with a list of types that should
473 be checked. Other types will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400474
475 -skip-symbols PATH
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300476 The list of symbols that should not be checked.
477
478 -skip-types PATH
479 The list of types that should not be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400480
Andrey Ponomarenko26742a82016-09-27 18:27:08 +0300481 -disable-constants-check
482 Do not check for changes in constants.
483
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400484 -headers-list PATH
485 The file with a list of headers, that should be checked/dumped.
486
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400487 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400488 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400489
490 -header NAME
491 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400492
493 -use-dumps
494 Make dumps for two versions of a library and compare dumps. This should
495 increase the performance of the tool and decrease the system memory usage.
496
497 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400498 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400499
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400500 -dump-system NAME -sysroot DIR
501 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400502 create XML descriptors and make ABI dumps for each library. The result
503 set of ABI dumps can be compared (--cmp-systems) with the other one
504 created for other version of operating system in order to check them for
505 compatibility. Do not forget to specify -cross-gcc option if your target
506 system requires some specific version of GCC compiler (different from
507 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400508 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400509
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400510 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400511 The same as the previous option but takes an XML descriptor of the target
512 system as input, where you should describe it:
513
514 /* Primary sections */
515
516 <name>
517 /* Name of the system */
518 </name>
519
520 <headers>
521 /* The list of paths to header files and/or
522 directories with header files, one per line */
523 </headers>
524
525 <libs>
526 /* The list of paths to shared libraries and/or
527 directories with shared libraries, one per line */
528 </libs>
529
530 /* Optional sections */
531
532 <search_headers>
533 /* List of directories to be searched
534 for header files to automatically
535 generate include paths, one per line */
536 </search_headers>
537
538 <search_libs>
539 /* List of directories to be searched
540 for shared libraries to resolve
541 dependencies, one per line */
542 </search_libs>
543
544 <tools>
545 /* List of directories with tools used
546 for analysis (GCC toolchain), one per line */
547 </tools>
548
549 <cross_prefix>
550 /* GCC toolchain prefix.
551 Examples:
552 arm-linux-gnueabi
553 arm-none-symbianelf */
554 </cross_prefix>
555
556 <gcc_options>
557 /* Additional GCC options, one per line */
558 </gcc_options>
559
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400560 -sysinfo DIR
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300561 This option should be used with -dump-system option to dump
562 ABI of operating systems and configure the dumping process.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400563
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400564 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300565 Compare two ABI dumps of a system. Create compatibility reports for
566 each system library and the common HTML report including the summary
567 of test results for all checked libraries.
568
569 Summary report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400570 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400571
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400572 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400573 The file with a list of libraries, that should be dumped by
574 the -dump-system option or should be checked by the -cmp-systems option.
575
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400576 -ext|-extended
577 If your library A is supposed to be used by other library B and you
578 want to control the ABI of B, then you should enable this option. The
579 tool will check for changes in all data types, even if they are not
580 used by any function in the library A. Such data types are not part
581 of the A library ABI, but may be a part of the ABI of the B library.
582
583 The short scheme is:
584 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
585
586 -q|-quiet
587 Print all messages to the file instead of stdout and stderr.
588 Default path (can be changed by -log-path option):
589 $COMMON_LOG_PATH
590
591 -stdout
592 Print analysis results (compatibility reports and ABI dumps) to stdout
593 instead of creating a file. This would allow piping data to other programs.
594
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400595 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400596 Change format of compatibility report.
597 Formats:
598 htm - HTML format (default)
599 xml - XML format
600
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400601 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400602 Change format of ABI dump.
603 Formats:
604 perl - Data::Dumper format (default)
605 xml - XML format
606
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400607 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400608 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400609
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400610 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400611 Set library language (C or C++). You can use this option if the tool
612 cannot auto-detect a language. This option may be useful for checking
613 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400614
615 -arch ARCH
616 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
617 ect.). The option is useful if the tool cannot detect correct architecture
618 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400619
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400620 -binary|-bin|-abi
621 Show \"Binary\" compatibility problems only.
622 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400623 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400624
625 -source|-src|-api
626 Show \"Source\" compatibility problems only.
627 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400628 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400629
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400630 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400631 The maximum number of affected symbols listed under the description
632 of the changed type in the report.
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +0300633
634 -count-symbols PATH
635 Count total public symbols in the ABI dump.
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +0300636
637 -old-style
638 Generate old-style report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400639
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400640OTHER OPTIONS:
641 -test
642 Run internal tests. Create two binary incompatible versions of a sample
643 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300644 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400645
646 -test-dump
647 Test ability to create, read and compare ABI dumps.
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300648
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400649 -debug
650 Debugging mode. Print debug info on the screen. Save intermediate
651 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400652 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400653
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400654 Also consider using --dump option for debugging the tool.
655
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400656 -cpp-compatible
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300657 Do nothing.
658
659 -cxx-incompatible
660 Set this option if input C header files use C++ keywords. The tool
661 will try to replace such keywords at preprocessor stage and replace
662 them back in the final TU dump.
663
664 -mingw-compatible
665 If input header files are compatible with the MinGW GCC compiler,
666 then you can tell the tool about this and speedup the analysis .
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400667
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400668 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400669 Path to file with the function parameter names. It can be used
670 for improving report view if the library header files have no
671 parameter names. File format:
672
673 func1;param1;param2;param3 ...
674 func2;param1;param2;param3 ...
675 ...
676
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400677 -relpath PATH
678 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400679 for dumping the library ABI (see -dump option).
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300680
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400681 -relpath1 PATH
682 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400683
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400684 -relpath2 PATH
685 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400686
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400687 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400688 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400689 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400690 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400691
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400692 -sort
693 Enable sorting of data in ABI dumps.
694
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400695 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400696 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400697 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400698 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400699
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400700 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400701 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400702 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400703 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400704
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400705 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400706 Path to \"Source\" compatibility report.
707 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400708 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400709
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400710 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400711 Log path for all messages.
712 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400713 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400714
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400715 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400716 Log path for 1st version of a library.
717 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400718 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400719
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400720 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400721 Log path for 2nd version of a library.
722 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400723 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400724
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400725 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400726 Change logging mode.
727 Modes:
728 w - overwrite old logs (default)
729 a - append old logs
730 n - do not write any logs
731
732 -list-affected
733 Generate file with the list of incompatible
734 symbols beside the HTML compatibility report.
735 Use 'c++filt \@file' command from GNU binutils
736 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400737 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400738 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400739 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400740
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400741 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400742 The component name in the title and summary of the HTML report.
743 Default:
744 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300745
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300746 -title NAME
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400747 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400748 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400749
750 -extra-info DIR
751 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400752
753 -extra-dump
754 Create extended ABI dump containing all symbols
755 from the translation unit.
756
757 -force
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300758 Try to enable this option if the tool checked zero
759 types and symbols in header files.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400760
761 -tolerance LEVEL
762 Apply a set of heuristics to successfully compile input
763 header files. You can enable several tolerance levels by
764 joining them into one string (e.g. 13, 124, etc.).
765 Levels:
766 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
767 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
Sangwoo Lee159324e2016-06-26 01:55:55 +0900768 3 - skip headers that include non-Linux headers
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400769 4 - skip headers included by others
770
771 -tolerant
772 Enable highest tolerance level [1234].
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300773
774 -skip-unidentified
775 Skip header files in 'headers' and 'include_preamble' sections
776 of the XML descriptor that cannot be found. This is useful if
777 you are trying to use the same descriptor for different targets.
778
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400779 -check
780 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400781
782 -quick
783 Quick analysis. Disable check of some template instances.
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300784
785 -disable-quick-empty-report
786 Do not generate quick empty report if input ABI dumps are equal.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400787
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300788 -skip-internal-symbols PATTERN
789 Do not check symbols matched by the pattern.
790
791 -skip-internal-types PATTERN
792 Do not check types matched by the pattern.
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300793
Andrey Ponomarenko8580e852016-08-19 19:11:48 +0300794 -skip-typedef-uncover
795 Do not report a problem if type is covered or
796 uncovered by typedef (useful for broken debug info).
797
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300798 -check-private-abi
799 Check data types from the private part of the ABI when
800 comparing ABI dumps created by the ABI Dumper tool with
801 use of the -public-headers option.
802
803 Requires ABI Dumper >= 0.99.14
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400804
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400805REPORT:
806 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400807 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400808
809 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400810 logs/LIB_NAME/V1/log.txt
811 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400812
813EXIT CODES:
814 0 - Compatible. The tool has run without any errors.
815 non-zero - Incompatible or the tool has run with errors.
816
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400817MORE INFORMATION:
Andrey Ponomarenko26742a82016-09-27 18:27:08 +0300818 ".$HomePage{"Wiki"}."
Andrey Ponomarenko868b1352016-09-29 14:13:30 +0300819 ".$HomePage{"Dev"}."\n\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400820}
821
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400822my %Operator_Indication = (
823 "not" => "~",
824 "assign" => "=",
825 "andassign" => "&=",
826 "orassign" => "|=",
827 "xorassign" => "^=",
828 "or" => "|",
829 "xor" => "^",
830 "addr" => "&",
831 "and" => "&",
832 "lnot" => "!",
833 "eq" => "==",
834 "ne" => "!=",
835 "lt" => "<",
836 "lshift" => "<<",
837 "lshiftassign" => "<<=",
838 "rshiftassign" => ">>=",
839 "call" => "()",
840 "mod" => "%",
841 "modassign" => "%=",
842 "subs" => "[]",
843 "land" => "&&",
844 "lor" => "||",
845 "rshift" => ">>",
846 "ref" => "->",
847 "le" => "<=",
848 "deref" => "*",
849 "mult" => "*",
850 "preinc" => "++",
851 "delete" => " delete",
852 "vecnew" => " new[]",
853 "vecdelete" => " delete[]",
854 "predec" => "--",
855 "postinc" => "++",
856 "postdec" => "--",
857 "plusassign" => "+=",
858 "plus" => "+",
859 "minus" => "-",
860 "minusassign" => "-=",
861 "gt" => ">",
862 "ge" => ">=",
863 "new" => " new",
864 "multassign" => "*=",
865 "divassign" => "/=",
866 "div" => "/",
867 "neg" => "-",
868 "pos" => "+",
869 "memref" => "->*",
870 "compound" => "," );
871
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400872my %UnknownOperator;
873
874my %NodeType= (
875 "array_type" => "Array",
876 "binfo" => "Other",
877 "boolean_type" => "Intrinsic",
878 "complex_type" => "Intrinsic",
879 "const_decl" => "Other",
880 "enumeral_type" => "Enum",
881 "field_decl" => "Other",
882 "function_decl" => "Other",
883 "function_type" => "FunctionType",
884 "identifier_node" => "Other",
885 "integer_cst" => "Other",
886 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400887 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400888 "method_type" => "MethodType",
889 "namespace_decl" => "Other",
890 "parm_decl" => "Other",
891 "pointer_type" => "Pointer",
892 "real_cst" => "Other",
893 "real_type" => "Intrinsic",
894 "record_type" => "Struct",
895 "reference_type" => "Ref",
896 "string_cst" => "Other",
897 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400898 "template_type_parm" => "TemplateParam",
899 "typename_type" => "TypeName",
900 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400901 "tree_list" => "Other",
902 "tree_vec" => "Other",
903 "type_decl" => "Other",
904 "union_type" => "Union",
905 "var_decl" => "Other",
906 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400907 "nop_expr" => "Other", #
908 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400909 "offset_type" => "Other" );
910
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400911my %CppKeywords_C = map {$_=>1} (
912 # C++ 2003 keywords
913 "public",
914 "protected",
915 "private",
916 "default",
917 "template",
918 "new",
919 #"asm",
920 "dynamic_cast",
921 "auto",
922 "try",
923 "namespace",
924 "typename",
925 "using",
926 "reinterpret_cast",
927 "friend",
928 "class",
929 "virtual",
930 "const_cast",
931 "mutable",
932 "static_cast",
933 "export",
934 # C++0x keywords
935 "noexcept",
936 "nullptr",
937 "constexpr",
938 "static_assert",
939 "explicit",
940 # cannot be used as a macro name
941 # as it is an operator in C++
942 "and",
943 #"and_eq",
944 "not",
945 #"not_eq",
946 "or"
947 #"or_eq",
948 #"bitand",
949 #"bitor",
950 #"xor",
951 #"xor_eq",
952 #"compl"
953);
954
955my %CppKeywords_F = map {$_=>1} (
956 "delete",
957 "catch",
958 "alignof",
959 "thread_local",
960 "decltype",
961 "typeid"
962);
963
964my %CppKeywords_O = map {$_=>1} (
965 "bool",
966 "register",
967 "inline",
968 "operator"
969);
970
971my %CppKeywords_A = map {$_=>1} (
972 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400973 "throw",
974 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400975);
976
977foreach (keys(%CppKeywords_C),
978keys(%CppKeywords_F),
979keys(%CppKeywords_O)) {
980 $CppKeywords_A{$_}=1;
981}
982
983# Header file extensions as described by gcc
984my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
985
986my %IntrinsicMangling = (
987 "void" => "v",
988 "bool" => "b",
989 "wchar_t" => "w",
990 "char" => "c",
991 "signed char" => "a",
992 "unsigned char" => "h",
993 "short" => "s",
994 "unsigned short" => "t",
995 "int" => "i",
996 "unsigned int" => "j",
997 "long" => "l",
998 "unsigned long" => "m",
999 "long long" => "x",
1000 "__int64" => "x",
1001 "unsigned long long" => "y",
1002 "__int128" => "n",
1003 "unsigned __int128" => "o",
1004 "float" => "f",
1005 "double" => "d",
1006 "long double" => "e",
1007 "__float80" => "e",
1008 "__float128" => "g",
1009 "..." => "z"
1010);
1011
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001012my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
1013
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001014my %StdcxxMangling = (
1015 "3std"=>"St",
1016 "3std9allocator"=>"Sa",
1017 "3std12basic_string"=>"Sb",
1018 "3std12basic_stringIcE"=>"Ss",
1019 "3std13basic_istreamIcE"=>"Si",
1020 "3std13basic_ostreamIcE"=>"So",
1021 "3std14basic_iostreamIcE"=>"Sd"
1022);
1023
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04001024my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001025my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
1026
1027my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001028my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001029
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001030my %ConstantSuffix = (
1031 "unsigned int"=>"u",
1032 "long"=>"l",
1033 "unsigned long"=>"ul",
1034 "long long"=>"ll",
1035 "unsigned long long"=>"ull"
1036);
1037
1038my %ConstantSuffixR =
1039reverse(%ConstantSuffix);
1040
1041my %OperatorMangling = (
1042 "~" => "co",
1043 "=" => "aS",
1044 "|" => "or",
1045 "^" => "eo",
1046 "&" => "an",#ad (addr)
1047 "==" => "eq",
1048 "!" => "nt",
1049 "!=" => "ne",
1050 "<" => "lt",
1051 "<=" => "le",
1052 "<<" => "ls",
1053 "<<=" => "lS",
1054 ">" => "gt",
1055 ">=" => "ge",
1056 ">>" => "rs",
1057 ">>=" => "rS",
1058 "()" => "cl",
1059 "%" => "rm",
1060 "[]" => "ix",
1061 "&&" => "aa",
1062 "||" => "oo",
1063 "*" => "ml",#de (deref)
1064 "++" => "pp",#
1065 "--" => "mm",#
1066 "new" => "nw",
1067 "delete" => "dl",
1068 "new[]" => "na",
1069 "delete[]" => "da",
1070 "+=" => "pL",
1071 "+" => "pl",#ps (pos)
1072 "-" => "mi",#ng (neg)
1073 "-=" => "mI",
1074 "*=" => "mL",
1075 "/=" => "dV",
1076 "&=" => "aN",
1077 "|=" => "oR",
1078 "%=" => "rM",
1079 "^=" => "eO",
1080 "/" => "dv",
1081 "->*" => "pm",
1082 "->" => "pt",#rf (ref)
1083 "," => "cm",
1084 "?" => "qu",
1085 "." => "dt",
1086 "sizeof"=> "sz"#st
1087);
1088
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001089my %Intrinsic_Keywords = map {$_=>1} (
1090 "true",
1091 "false",
1092 "_Bool",
1093 "_Complex",
1094 "const",
1095 "int",
1096 "long",
1097 "void",
1098 "short",
1099 "float",
1100 "volatile",
1101 "restrict",
1102 "unsigned",
1103 "signed",
1104 "char",
1105 "double",
1106 "class",
1107 "struct",
1108 "union",
1109 "enum"
1110);
1111
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001112my %GlibcHeader = map {$_=>1} (
1113 "aliases.h",
1114 "argp.h",
1115 "argz.h",
1116 "assert.h",
1117 "cpio.h",
1118 "ctype.h",
1119 "dirent.h",
1120 "envz.h",
1121 "errno.h",
1122 "error.h",
1123 "execinfo.h",
1124 "fcntl.h",
1125 "fstab.h",
1126 "ftw.h",
1127 "glob.h",
1128 "grp.h",
1129 "iconv.h",
1130 "ifaddrs.h",
1131 "inttypes.h",
1132 "langinfo.h",
1133 "limits.h",
1134 "link.h",
1135 "locale.h",
1136 "malloc.h",
1137 "math.h",
1138 "mntent.h",
1139 "monetary.h",
1140 "nl_types.h",
1141 "obstack.h",
1142 "printf.h",
1143 "pwd.h",
1144 "regex.h",
1145 "sched.h",
1146 "search.h",
1147 "setjmp.h",
1148 "shadow.h",
1149 "signal.h",
1150 "spawn.h",
1151 "stdarg.h",
1152 "stdint.h",
1153 "stdio.h",
1154 "stdlib.h",
1155 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001156 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001157 "tar.h",
1158 "termios.h",
1159 "time.h",
1160 "ulimit.h",
1161 "unistd.h",
1162 "utime.h",
1163 "wchar.h",
1164 "wctype.h",
1165 "wordexp.h" );
1166
1167my %GlibcDir = map {$_=>1} (
1168 "arpa",
1169 "bits",
1170 "gnu",
1171 "netinet",
1172 "net",
1173 "nfs",
1174 "rpc",
1175 "sys",
1176 "linux" );
1177
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001178my %WinHeaders = map {$_=>1} (
1179 "dos.h",
1180 "process.h",
1181 "winsock.h",
1182 "config-win.h",
1183 "mem.h",
1184 "windows.h",
1185 "winsock2.h",
1186 "crtdbg.h",
1187 "ws2tcpip.h"
1188);
1189
1190my %ObsoleteHeaders = map {$_=>1} (
1191 "iostream.h",
1192 "fstream.h"
1193);
1194
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001195my %AlienHeaders = map {$_=>1} (
1196 # Solaris
1197 "thread.h",
1198 "sys/atomic.h",
1199 # HPUX
1200 "sys/stream.h",
1201 # Symbian
1202 "AknDoc.h",
1203 # Atari ST
1204 "ext.h",
1205 "tos.h",
1206 # MS-DOS
1207 "alloc.h",
1208 # Sparc
1209 "sys/atomic.h"
1210);
1211
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001212my %ConfHeaders = map {$_=>1} (
1213 "atomic",
1214 "conf.h",
1215 "config.h",
1216 "configure.h",
1217 "build.h",
1218 "setup.h"
1219);
1220
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001221my %LocalIncludes = map {$_=>1} (
1222 "/usr/local/include",
1223 "/usr/local" );
1224
1225my %OS_AddPath=(
1226# These paths are needed if the tool cannot detect them automatically
1227 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001228 "include"=>[
1229 "/Library",
1230 "/Developer/usr/include"
1231 ],
1232 "lib"=>[
1233 "/Library",
1234 "/Developer/usr/lib"
1235 ],
1236 "bin"=>[
1237 "/Developer/usr/bin"
1238 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001239 },
1240 "beos"=>{
1241 # Haiku has GCC 2.95.3 by default
1242 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001243 "include"=>[
1244 "/boot/common",
1245 "/boot/develop"
1246 ],
1247 "lib"=>[
1248 "/boot/common/lib",
1249 "/boot/system/lib",
1250 "/boot/apps"
1251 ],
1252 "bin"=>[
1253 "/boot/common/bin",
1254 "/boot/system/bin",
1255 "/boot/develop/abi"
1256 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001257 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001258);
1259
1260my %Slash_Type=(
1261 "default"=>"/",
1262 "windows"=>"\\"
1263);
1264
1265my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1266
1267# Global Variables
1268my %COMMON_LANGUAGE=(
1269 1 => "C",
1270 2 => "C" );
1271
1272my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001273my $MAX_CPPFILT_FILE_SIZE = 50000;
1274my $CPPFILT_SUPPORT_FILE;
1275
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +03001276my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION, %CLANG_VERSION);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001277
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001278my $STDCXX_TESTING = 0;
1279my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001280my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001281
1282my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001283my $CheckUndefined = 0;
1284
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +03001285my $TargetComponent = undef;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001286if($TargetComponent_Opt) {
1287 $TargetComponent = lc($TargetComponent_Opt);
1288}
1289else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001290{ # default: library
1291 # other components: header, system, ...
1292 $TargetComponent = "library";
1293}
1294
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001295my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001296
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001297my $SystemRoot;
1298
1299my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001300my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001301my %LOG_PATH;
1302my %DEBUG_PATH;
1303my %Cache;
1304my %LibInfo;
1305my $COMPILE_ERRORS = 0;
1306my %CompilerOptions;
1307my %CheckedDyLib;
1308my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1309
1310# Constants (#defines)
1311my %Constants;
1312my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001313my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001314
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001315# Extra Info
1316my %SymbolHeader;
1317my %KnownLibs;
1318
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001319# Templates
1320my %TemplateInstance;
1321my %BasicTemplate;
1322my %TemplateArg;
1323my %TemplateDecl;
1324my %TemplateMap;
1325
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001326# Types
1327my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001328my %SkipTypes = (
1329 "1"=>{},
1330 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001331my %CheckedTypes;
1332my %TName_Tid;
1333my %EnumMembName_Id;
1334my %NestedNameSpaces = (
1335 "1"=>{},
1336 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001337my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001338my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001339my %ClassVTable;
1340my %ClassVTable_Content;
1341my %VTableClass;
1342my %AllocableClass;
1343my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001344my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001345my %Class_SubClasses;
1346my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001347my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001348my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001349
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001350my %CheckedTypeInfo;
1351
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001352# Typedefs
1353my %Typedef_BaseName;
1354my %Typedef_Tr;
1355my %Typedef_Eq;
1356my %StdCxxTypedef;
1357my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001358my %MissedBase;
1359my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001360my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001361
1362# Symbols
1363my %SymbolInfo;
1364my %tr_name;
1365my %mangled_name_gcc;
1366my %mangled_name;
1367my %SkipSymbols = (
1368 "1"=>{},
1369 "2"=>{} );
1370my %SkipNameSpaces = (
1371 "1"=>{},
1372 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001373my %AddNameSpaces = (
1374 "1"=>{},
1375 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001376my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001377my %TypesList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001378my %SymbolsList_App;
1379my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001380my %Symbol_Library = (
1381 "1"=>{},
1382 "2"=>{} );
1383my %Library_Symbol = (
1384 "1"=>{},
1385 "2"=>{} );
1386my %DepSymbol_Library = (
1387 "1"=>{},
1388 "2"=>{} );
1389my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001390 "1"=>{},
1391 "2"=>{} );
1392my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001393my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001394my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001395my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001396my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001397my %Library_Needed= (
1398 "1"=>{},
1399 "2"=>{} );
Andrey Ponomarenko991da682016-09-07 19:09:50 +03001400my $DisabledMSVCUnmangling = undef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001401
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001402# Extra Info
1403my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001404my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001405
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001406# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001407my %Include_Preamble = (
1408 "1"=>[],
1409 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001410my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001411my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001412my %HeaderName_Paths;
1413my %Header_Dependency;
1414my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001415my %Include_Paths = (
1416 "1"=>[],
1417 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001418my %INC_PATH_AUTODETECT = (
1419 "1"=>1,
1420 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001421my %Add_Include_Paths = (
1422 "1"=>[],
1423 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001424my %Skip_Include_Paths;
1425my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001426my %Header_ErrorRedirect;
1427my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001428my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001429my %Header_ShouldNotBeUsed;
1430my %RecursiveIncludes;
1431my %Header_Include_Prefix;
1432my %SkipHeaders;
1433my %SkipHeadersList=(
1434 "1"=>{},
1435 "2"=>{} );
1436my %SkipLibs;
1437my %Include_Order;
1438my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001439my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001440my %TUnit_Funcs;
1441my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001442
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001443my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001444 "1"=>0,
1445 "2"=>0 );
1446my %AutoPreambleMode = (
1447 "1"=>0,
1448 "2"=>0 );
1449my %MinGWMode = (
1450 "1"=>0,
1451 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001452my %Cpp0xMode = (
1453 "1"=>0,
1454 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001455
1456# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001457my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001458my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001459my %RegisteredSONAMEs;
1460my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001461
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001462my %CheckedArch;
1463
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001464# System Objects
1465my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001466my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001467my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001468
1469# System Headers
1470my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001471my @DefaultCppPaths;
1472my @DefaultGccPaths;
1473my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001474my %DefaultCppHeader;
1475my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001476my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001477
1478# Merging
1479my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001480my $Version;
1481my %AddedInt;
1482my %RemovedInt;
1483my %AddedInt_Virt;
1484my %RemovedInt_Virt;
1485my %VirtualReplacement;
1486my %ChangedTypedef;
1487my %CompatRules;
1488my %IncompleteRules;
1489my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001490my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001491my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001492my %ReturnedClass;
1493my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001494my %SourceAlternative;
1495my %SourceAlternative_B;
1496my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001497my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001498
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03001499#Report
1500my %TypeChanges;
1501
1502#Speedup
1503my %TypeProblemsIndex;
1504
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001505# Calling Conventions
1506my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001507 1=>{ "R"=>0, "P"=>0 },
1508 2=>{ "R"=>0, "P"=>0 }
1509);
1510
1511# ABI Dump
1512my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001513
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001514# Filters
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001515my %TargetLibs;
1516my %TargetHeaders;
1517
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001518# Format of objects
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001519my $OStarget = $OSgroup;
1520my %TargetTools;
1521
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001522# Recursion locks
1523my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001524my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001525my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001526my @RecurInclude;
1527my @RecurConstant;
1528
1529# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001530my %SystemPaths = (
1531 "include"=>[],
1532 "lib"=>[],
1533 "bin"=>[]
1534);
1535my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001536my $GCC_PATH;
1537
1538# Symbols versioning
1539my %SymVer = (
1540 "1"=>{},
1541 "2"=>{} );
1542
1543# Problem descriptions
1544my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001545my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001546my %TotalAffected;
1547
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001548# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001549my $ContentID = 1;
1550my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +03001551my $ContentSpanStart_Affected = "<span class=\"sect_aff\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1552my $ContentSpanStart_Info = "<span class=\"sect_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001553my $ContentSpanEnd = "</span>\n";
1554my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1555my $ContentDivEnd = "</div>\n";
1556my $Content_Counter = 0;
1557
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001558# Modes
1559my $JoinReport = 1;
1560my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001561
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001562my %Severity_Val=(
1563 "High"=>3,
1564 "Medium"=>2,
1565 "Low"=>1,
1566 "Safe"=>-1
1567);
1568
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001569sub get_Modules()
1570{
1571 my $TOOL_DIR = get_dirname($0);
1572 if(not $TOOL_DIR)
1573 { # patch for MS Windows
1574 $TOOL_DIR = ".";
1575 }
1576 my @SEARCH_DIRS = (
1577 # tool's directory
1578 abs_path($TOOL_DIR),
1579 # relative path to modules
1580 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001581 # install path
1582 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001583 );
1584 foreach my $DIR (@SEARCH_DIRS)
1585 {
1586 if(not is_abs($DIR))
1587 { # relative path
1588 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1589 }
1590 if(-d $DIR."/modules") {
1591 return $DIR."/modules";
1592 }
1593 }
1594 exitStatus("Module_Error", "can't find modules");
1595}
1596
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001597my %LoadedModules = ();
1598
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001599sub loadModule($)
1600{
1601 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001602 if(defined $LoadedModules{$Name}) {
1603 return;
1604 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001605 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1606 if(not -f $Path) {
1607 exitStatus("Module_Error", "can't access \'$Path\'");
1608 }
1609 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001610 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001611}
1612
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001613sub readModule($$)
1614{
1615 my ($Module, $Name) = @_;
1616 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1617 if(not -f $Path) {
1618 exitStatus("Module_Error", "can't access \'$Path\'");
1619 }
1620 return readFile($Path);
1621}
1622
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001623sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001624{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001625 my $Number = $_[0];
1626 if(not $Number) {
1627 $Number = 1;
1628 }
1629 else {
1630 $Number = int($Number)+1;
1631 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001632 if($Number>3) {
1633 return $Number."th";
1634 }
1635 elsif($Number==1) {
1636 return "1st";
1637 }
1638 elsif($Number==2) {
1639 return "2nd";
1640 }
1641 elsif($Number==3) {
1642 return "3rd";
1643 }
1644 else {
1645 return $Number;
1646 }
1647}
1648
1649sub search_Tools($)
1650{
1651 my $Name = $_[0];
1652 return "" if(not $Name);
1653 if(my @Paths = keys(%TargetTools))
1654 {
1655 foreach my $Path (@Paths)
1656 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001657 if(-f join_P($Path, $Name)) {
1658 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001659 }
1660 if($CrossPrefix)
1661 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001662 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001663 if(-f $Candidate) {
1664 return $Candidate;
1665 }
1666 }
1667 }
1668 }
1669 else {
1670 return "";
1671 }
1672}
1673
1674sub synch_Cmd($)
1675{
1676 my $Name = $_[0];
1677 if(not $GCC_PATH)
1678 { # GCC was not found yet
1679 return "";
1680 }
1681 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001682 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001683 return $Candidate;
1684 }
1685 return "";
1686}
1687
1688sub get_CmdPath($)
1689{
1690 my $Name = $_[0];
1691 return "" if(not $Name);
1692 if(defined $Cache{"get_CmdPath"}{$Name}) {
1693 return $Cache{"get_CmdPath"}{$Name};
1694 }
1695 my %BinUtils = map {$_=>1} (
1696 "c++filt",
1697 "objdump",
1698 "readelf"
1699 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001700 if($BinUtils{$Name} and $GCC_PATH)
1701 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001702 if(my $Dir = get_dirname($GCC_PATH)) {
1703 $TargetTools{$Dir}=1;
1704 }
1705 }
1706 my $Path = search_Tools($Name);
1707 if(not $Path and $OSgroup eq "windows") {
1708 $Path = search_Tools($Name.".exe");
1709 }
1710 if(not $Path and $BinUtils{$Name})
1711 {
1712 if($CrossPrefix)
1713 { # user-defined prefix
1714 $Path = search_Cmd($CrossPrefix."-".$Name);
1715 }
1716 }
1717 if(not $Path and $BinUtils{$Name})
1718 {
1719 if(my $Candidate = synch_Cmd($Name))
1720 { # synch with GCC
1721 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001722 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001723 if(-f $Candidate) {
1724 $Path = $Candidate;
1725 }
1726 }
1727 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001728 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001729 $Path = $Candidate;
1730 }
1731 }
1732 }
1733 if(not $Path) {
1734 $Path = search_Cmd($Name);
1735 }
1736 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001737 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001738 $Path=search_Cmd($Name.".exe");
1739 }
1740 if($Path=~/\s/) {
1741 $Path = "\"".$Path."\"";
1742 }
1743 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1744}
1745
1746sub search_Cmd($)
1747{
1748 my $Name = $_[0];
1749 return "" if(not $Name);
1750 if(defined $Cache{"search_Cmd"}{$Name}) {
1751 return $Cache{"search_Cmd"}{$Name};
1752 }
1753 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1754 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1755 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001756 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001757 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001758 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001759 if(-f $CmdPath)
1760 {
1761 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001762 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001763 }
1764 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1765 }
1766 }
1767 return ($Cache{"search_Cmd"}{$Name} = "");
1768}
1769
1770sub get_CmdPath_Default($)
1771{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001772 return "" if(not $_[0]);
1773 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1774 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001775 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001776 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1777}
1778
1779sub get_CmdPath_Default_I($)
1780{ # search in PATH
1781 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001782 if($Name=~/find/)
1783 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001784 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001785 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001786 }
1787 }
1788 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001789 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001790 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001791 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001792 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001793 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001794 if($OSgroup eq "windows")
1795 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001796 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001797 return $Name;
1798 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001799 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001800 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001801 {
1802 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001803 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001804 }
1805 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001806 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001807}
1808
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001809sub classifyPath($)
1810{
1811 my $Path = $_[0];
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001812 if($Path=~/[\*\+\(\[\|]/)
1813 { # pattern
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001814 return ($Path, "Pattern");
1815 }
1816 elsif($Path=~/[\/\\]/)
1817 { # directory or relative path
1818 return (path_format($Path, $OSgroup), "Path");
1819 }
1820 else {
1821 return ($Path, "Name");
1822 }
1823}
1824
1825sub readDescriptor($$)
1826{
1827 my ($LibVersion, $Content) = @_;
1828 return if(not $LibVersion);
1829 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1830 if(not $Content) {
1831 exitStatus("Error", "$DName is empty");
1832 }
1833 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001834 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001835 }
1836 $Content=~s/\/\*(.|\n)+?\*\///g;
1837 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001838
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001839 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1840 if($TargetVersion{$LibVersion}) {
1841 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1842 }
1843 if(not $Descriptor{$LibVersion}{"Version"}) {
1844 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1845 }
1846 if($Content=~/{RELPATH}/)
1847 {
1848 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1849 $Content =~ s/{RELPATH}/$RelDir/g;
1850 }
1851 else
1852 {
1853 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1854 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1855 }
1856 }
1857
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001858 my $DHeaders = parseTag(\$Content, "headers");
1859 if(not $DHeaders) {
1860 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1861 }
1862 elsif(lc($DHeaders) ne "none")
1863 { # append the descriptor headers list
1864 if($Descriptor{$LibVersion}{"Headers"})
1865 { # multiple descriptors
1866 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001867 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001868 else {
1869 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1870 }
1871 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1872 {
1873 if(not -e $Path) {
1874 exitStatus("Access_Error", "can't access \'$Path\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001875 }
1876 }
1877 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001878
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001879 if(not $CheckHeadersOnly_Opt)
1880 {
1881 my $DObjects = parseTag(\$Content, "libs");
1882 if(not $DObjects) {
1883 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1884 }
1885 elsif(lc($DObjects) ne "none")
1886 { # append the descriptor libraries list
1887 if($Descriptor{$LibVersion}{"Libs"})
1888 { # multiple descriptors
1889 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1890 }
1891 else {
1892 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1893 }
1894 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1895 {
1896 if(not -e $Path) {
1897 exitStatus("Access_Error", "can't access \'$Path\'");
1898 }
1899 }
1900 }
1901 }
1902 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1903 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001904 if(not -d $Path) {
1905 exitStatus("Access_Error", "can't access directory \'$Path\'");
1906 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001907 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001908 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001909 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001910 }
1911 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1912 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001913 if(not -d $Path) {
1914 exitStatus("Access_Error", "can't access directory \'$Path\'");
1915 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001916 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001917 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001918 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001919 }
1920 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1921 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001922 if(not -d $Path) {
1923 exitStatus("Access_Error", "can't access directory \'$Path\'");
1924 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001925 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001926 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001927 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001928 $TargetTools{$Path}=1;
1929 }
1930 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1931 $CrossPrefix = $Prefix;
1932 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001933 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001934 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1935 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001936 if(not -d $Path) {
1937 exitStatus("Access_Error", "can't access directory \'$Path\'");
1938 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001939 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001940 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001941 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001942 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001943 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001944 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_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}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001952 }
1953 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001954 { # skip some auto-generated include paths
1955 if(not is_abs($Path))
1956 {
1957 if(my $P = abs_path($Path)) {
1958 $Path = $P;
1959 }
1960 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001961 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001962 }
1963 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001964 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001965 my ($CPath, $Type) = classifyPath($Path);
1966 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001967 }
1968 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001969 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1970 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001971 if($Option!~/\A\-(Wl|l|L)/)
1972 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001973 $CompilerOptions{$LibVersion} .= " ".$Option;
1974 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001975 }
1976 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1977 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1978 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001979 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001980
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001981 my ($CPath, $Type) = classifyPath($Path);
1982 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001983 }
1984 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1985 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1986 {
1987 my ($CPath, $Type) = classifyPath($Path);
1988 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1989 }
1990 if(my $DDefines = parseTag(\$Content, "defines"))
1991 {
1992 if($Descriptor{$LibVersion}{"Defines"})
1993 { # multiple descriptors
1994 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
1995 }
1996 else {
1997 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
1998 }
1999 }
2000 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
2001 {
2002 if($Order=~/\A(.+):(.+)\Z/) {
2003 $Include_Order{$LibVersion}{$1} = $2;
2004 }
2005 }
2006 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
2007 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002008 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002009 $SkipTypes{$LibVersion}{$Type_Name} = 1;
2010 }
2011 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
2012 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002013 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002014 $SkipSymbols{$LibVersion}{$Symbol} = 1;
2015 }
2016 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
2017 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
2018 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04002019 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
2020 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
2021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002022 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
2023 $SkipConstants{$LibVersion}{$Constant} = 1;
2024 }
2025 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
2026 {
2027 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002028 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002029 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
2030 }
2031 else {
2032 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2033 }
2034 }
2035}
2036
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002037sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002038{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002039 my $CodeRef = shift(@_);
2040 my $Tag = shift(@_);
2041 if(not $Tag or not $CodeRef) {
2042 return undef;
2043 }
2044 my $Sp = 0;
2045 if(@_) {
2046 $Sp = shift(@_);
2047 }
2048 my $Start = index(${$CodeRef}, "<$Tag>");
2049 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002050 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002051 my $End = index(${$CodeRef}, "</$Tag>");
2052 if($End!=-1)
2053 {
2054 my $TS = length($Tag)+3;
2055 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2056 substr($Content, 0, $TS-1, ""); # cut start tag
2057 substr($Content, -$TS, $TS, ""); # cut end tag
2058 if(not $Sp)
2059 {
2060 $Content=~s/\A\s+//g;
2061 $Content=~s/\s+\Z//g;
2062 }
2063 if(substr($Content, 0, 1) ne "<") {
2064 $Content = xmlSpecChars_R($Content);
2065 }
2066 return $Content;
2067 }
2068 }
2069 return undef;
2070}
2071
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002072sub getInfo($)
2073{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002074 my $DumpPath = $_[0];
2075 return if(not $DumpPath or not -f $DumpPath);
2076
2077 readTUDump($DumpPath);
2078
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002079 # processing info
2080 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002081
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002082 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002083 setAnonTypedef_All();
2084 }
2085
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002086 getTypeInfo_All();
2087 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002088 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002089 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002090 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002091
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002092 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002093 %LibInfo = ();
2094 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002095 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002096 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002097 %TemplateDecl = ();
2098 %StdCxxTypedef = ();
2099 %MissedTypedef = ();
2100 %Typedef_Tr = ();
2101 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002102 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002103
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002104 # clean cache
2105 delete($Cache{"getTypeAttr"});
2106 delete($Cache{"getTypeDeclId"});
2107
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002108 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002109 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002110 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002111 }
2112 else
2113 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002114 if($BinaryOnly and not $ExtendedCheck)
2115 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002116 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002117 }
2118 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002119 remove_Unused($Version, "Extended");
2120 }
2121 }
2122
2123 if($CheckInfo)
2124 {
2125 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2126 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2127 }
2128
2129 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2130 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002131 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002132 }
2133
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002134 if($Debug) {
2135 # debugMangling($Version);
2136 }
2137}
2138
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002139sub readTUDump($)
2140{
2141 my $DumpPath = $_[0];
2142
2143 open(TU_DUMP, $DumpPath);
2144 local $/ = undef;
2145 my $Content = <TU_DUMP>;
2146 close(TU_DUMP);
2147
2148 unlink($DumpPath);
2149
2150 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002151 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002152
2153 # clean memory
2154 undef $Content;
2155
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002156 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002157
2158 foreach (0 .. $#Lines)
2159 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002160 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002161 { # get a number and attributes of a node
2162 next if(not $NodeType{$2});
2163 $LibInfo{$Version}{"info_type"}{$1}=$2;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03002164 $LibInfo{$Version}{"info"}{$1}=$3." ";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002165 }
2166
2167 # clean memory
2168 delete($Lines[$_]);
2169 }
2170
2171 # clean memory
2172 undef @Lines;
2173}
2174
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002175sub simplifyConstants()
2176{
2177 foreach my $Constant (keys(%{$Constants{$Version}}))
2178 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002179 if(defined $Constants{$Version}{$Constant}{"Header"})
2180 {
2181 my $Value = $Constants{$Version}{$Constant}{"Value"};
2182 if(defined $EnumConstants{$Version}{$Value}) {
2183 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2184 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002185 }
2186 }
2187}
2188
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002189sub simplifyNames()
2190{
2191 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2192 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002193 if($Typedef_Eq{$Version}{$Base}) {
2194 next;
2195 }
2196 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2197 if($#Translations==0)
2198 {
2199 if(length($Translations[0])<=length($Base)) {
2200 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2201 }
2202 }
2203 else
2204 { # select most appropriate
2205 foreach my $Tr (@Translations)
2206 {
2207 if($Base=~/\A\Q$Tr\E/)
2208 {
2209 $Typedef_Eq{$Version}{$Base} = $Tr;
2210 last;
2211 }
2212 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002213 }
2214 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002215 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002216 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002217 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002218 if(not $TypeName) {
2219 next;
2220 }
2221 next if(index($TypeName,"<")==-1);# template instances only
2222 if($TypeName=~/>(::\w+)+\Z/)
2223 { # skip unused types
2224 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002225 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002226 foreach my $Base (sort {length($b)<=>length($a)}
2227 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002228 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002229 next if(not $Base);
2230 next if(index($TypeName,$Base)==-1);
2231 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002232 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002233 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002234 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2235 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2236 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002237 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002238 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2239 {
2240 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2241 {
2242 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2243 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002244 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002245 }
2246 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002247 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002248 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002249 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002250 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002251 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2252 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002253 }
2254}
2255
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002256sub setAnonTypedef_All()
2257{
2258 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2259 {
2260 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2261 {
2262 if(isAnon(getNameByInfo($InfoId))) {
2263 $TypedefToAnon{getTypeId($InfoId)} = 1;
2264 }
2265 }
2266 }
2267}
2268
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002269sub setTemplateParams_All()
2270{
2271 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2272 {
2273 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2274 setTemplateParams($_);
2275 }
2276 }
2277}
2278
2279sub setTemplateParams($)
2280{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002281 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002282 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002283 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002284 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002285 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002286 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002287 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002288 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002289 setTemplateInstParams($_[0], $TmplInst_Id);
2290 }
2291 }
2292
2293 $BasicTemplate{$Version}{$Tid} = $_[0];
2294
2295 if(my $Prms = getTreeAttr_Prms($_[0]))
2296 {
2297 if(my $Valu = getTreeAttr_Valu($Prms))
2298 {
2299 my $Vector = getTreeVec($Valu);
2300 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2301 {
2302 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2303 {
2304 if(my $Name = getNameByInfo($Val))
2305 {
2306 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2307 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2308 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2309 }
2310 else {
2311 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2312 }
2313 }
2314 }
2315 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002317 }
2318 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002319 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002320 {
2321 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2322 {
2323 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002324 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002325 }
2326 }
2327 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002328}
2329
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002330sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002331{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002332 my ($Tmpl, $Inst) = @_;
2333
2334 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002335 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002336 my ($Params_InfoId, $ElemId) = ();
2337 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2338 $Params_InfoId = $1;
2339 }
2340 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2341 $ElemId = $1;
2342 }
2343 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002344 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002345 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2346 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2347 {
2348 my ($PPos, $PTypeId) = ($1, $2);
2349 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2350 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002351 if($PType eq "template_type_parm") {
2352 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002353 }
2354 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002355 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2356 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002357 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002358 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002359 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002360 else
2361 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002362 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002363 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002364 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002365 }
2366 }
2367 }
2368}
2369
2370sub getTypeDeclId($)
2371{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002372 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002373 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002374 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2375 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2376 }
2377 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2378 {
2379 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2380 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2381 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002382 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002383 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002384 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002385}
2386
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002387sub getTypeInfo_All()
2388{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002389 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002390 { # support for GCC < 4.5
2391 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2392 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2393 # FIXME: check GCC versions
2394 addMissedTypes_Pre();
2395 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002396
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002397 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002398 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002399 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2400 if($IType=~/_type\Z/ and $IType ne "function_type"
2401 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002402 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002403 }
2404 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002405
2406 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002407 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002408 "Name" => "...",
2409 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002410 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002411 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002412 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002413
2414 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002415 { # support for GCC < 4.5
2416 addMissedTypes_Post();
2417 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002418
2419 if($ADD_TMPL_INSTANCES)
2420 {
2421 # templates
2422 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2423 {
2424 if(defined $TemplateMap{$Version}{$Tid}
2425 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2426 {
2427 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2428 {
2429 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2430 {
2431 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2432 {
2433 if(my %MAttr = getTypeAttr($MembTypeId))
2434 {
2435 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2436 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2437 }
2438 }
2439 }
2440 }
2441 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2442 {
2443 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2444 {
2445 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2446
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002447 if($NBid ne $Bid
2448 and $NBid ne $Tid)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002449 {
2450 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2451 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2452 }
2453 }
2454 }
2455 }
2456 }
2457 }
2458}
2459
2460sub createType($$)
2461{
2462 my ($Attr, $LibVersion) = @_;
2463 my $NewId = ++$MAX_ID;
2464
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002465 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002466 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002467 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002468
2469 return "$NewId";
2470}
2471
2472sub instType($$$)
2473{ # create template instances
2474 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002475
2476 if(not $TypeInfo{$LibVersion}{$Tid}) {
2477 return undef;
2478 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002479 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2480
2481 foreach my $Key (sort keys(%{$Map}))
2482 {
2483 if(my $Val = $Map->{$Key})
2484 {
2485 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2486
2487 if(defined $Attr->{"NameSpace"}) {
2488 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2489 }
2490 foreach (keys(%{$Attr->{"TParam"}})) {
2491 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2492 }
2493 }
2494 else
2495 { # remove absent
2496 # _Traits, etc.
2497 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002498 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002499 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2500 }
2501 foreach (keys(%{$Attr->{"TParam"}}))
2502 {
2503 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2504 delete($Attr->{"TParam"}{$_});
2505 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002506 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002507 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2508 }
2509 }
2510 }
2511 }
2512
2513 my $Tmpl = 0;
2514
2515 if(defined $Attr->{"TParam"})
2516 {
2517 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2518 {
2519 my $PName = $Attr->{"TParam"}{$_}{"name"};
2520
2521 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2522 {
2523 my %Base = get_BaseType($PTid, $LibVersion);
2524
2525 if($Base{"Type"} eq "TemplateParam"
2526 or defined $Base{"Template"})
2527 {
2528 $Tmpl = 1;
2529 last
2530 }
2531 }
2532 }
2533 }
2534
2535 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2536 return "$Id";
2537 }
2538 else
2539 {
2540 if(not $Tmpl) {
2541 delete($Attr->{"Template"});
2542 }
2543
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002544 my $New = createType($Attr, $LibVersion);
2545
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002546 my %EMap = ();
2547 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2548 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2549 }
2550 foreach (keys(%{$Map})) {
2551 $EMap{$_} = $Map->{$_};
2552 }
2553
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002554 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2555 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002556 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002557 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002558 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002559 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002560 {
2561 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2562
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002563 if($NBid ne $Bid
2564 and $NBid ne $New)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002565 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002566 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2567 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002568 }
2569 }
2570 }
2571
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002572 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002573 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002574 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2575 {
2576 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2577 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2578 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002579 }
2580 }
2581
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002582 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002583 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002584 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2585 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002586 }
2587 }
2588
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002589 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2590 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002591 }
2592
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002593 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002594 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002595}
2596
2597sub addMissedTypes_Pre()
2598{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002599 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002600 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2601 { # detecting missed typedefs
2602 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2603 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002604 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002605 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002606 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002607 if($TypeType eq "Unknown")
2608 { # template_type_parm
2609 next;
2610 }
2611 my $TypeDeclId = getTypeDeclId($TypeId);
2612 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2613 my $TypedefName = getNameByInfo($MissedTDid);
2614 next if(not $TypedefName);
2615 next if($TypedefName eq "__float80");
2616 next if(isAnon($TypedefName));
2617 if(not $TypeDeclId
2618 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002619 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002620 }
2621 }
2622 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002623 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002624 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002625 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002626 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002627 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002628 next;
2629 }
2630 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002631 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002632 if(not $TypedefName) {
2633 next;
2634 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002635 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002636 my %MissedInfo = ( # typedef info
2637 "Name" => $TypedefName,
2638 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002639 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002640 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002641 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002642 my ($H, $L) = getLocation($MissedTDid);
2643 $MissedInfo{"Header"} = $H;
2644 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002645 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002646 { # other types
2647 next;
2648 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002649 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002650 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002651 next;
2652 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002653 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002654 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002655 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002656 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002657 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002658 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002659 next;
2660 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002661 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002662 next;
2663 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002664 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002665 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002666 next;
2667 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002668 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002669 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002670 next;
2671 }
2672 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002673
2674 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2675
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002676 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002677 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002678 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002679 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002680 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002681
2682 # add missed & remove other
2683 $TypeInfo{$Version} = \%AddTypes;
2684 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002685}
2686
2687sub addMissedTypes_Post()
2688{
2689 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2690 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002691 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2692 {
2693 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2694 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2695 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2696 }
2697 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002698 }
2699}
2700
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002701sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002702{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002703 my $TypeId = $_[0];
2704 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2705 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002706 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002707 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002708 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002709}
2710
2711sub getArraySize($$)
2712{
2713 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002714 if(my $Size = getSize($TypeId))
2715 {
2716 my $Elems = $Size/$BYTE_SIZE;
2717 while($BaseName=~s/\s*\[(\d+)\]//) {
2718 $Elems/=$1;
2719 }
2720 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2721 {
2722 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2723 $Elems/=$BasicSize;
2724 }
2725 }
2726 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002727 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002728 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002729}
2730
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002731sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002732{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002733 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002734 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002735 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2736 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002737 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002738 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2739 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2740 if(not $NodeType)
2741 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002742 return ();
2743 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002744 if($NodeType eq "tree_vec")
2745 {
2746 if($Pos!=$#Positions)
2747 { # select last vector of parameters ( ns<P1>::type<P2> )
2748 next;
2749 }
2750 }
2751 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2752 foreach my $P (@Params)
2753 {
2754 if($P eq "") {
2755 return ();
2756 }
2757 elsif($P ne "\@skip\@") {
2758 @TmplParams = (@TmplParams, $P);
2759 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002760 }
2761 }
2762 return @TmplParams;
2763}
2764
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002765sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002766{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002767 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002768 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002769 if(defined $TypeInfo{$Version}{$TypeId}
2770 and $TypeInfo{$Version}{$TypeId}{"Name"})
2771 { # already created
2772 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002773 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002774 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2775 { # incomplete type
2776 return ();
2777 }
2778 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2779
2780 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002781 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002782
2783 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2784 {
2785 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2786 {
2787 if($Info=~/qual[ ]*:/)
2788 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002789 my $NewId = ++$MAX_ID;
2790
2791 $MissedBase{$Version}{$TypeId} = "$NewId";
2792 $MissedBase_R{$Version}{$NewId} = $TypeId;
2793 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2794 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002795 }
2796 }
2797 $TypeAttr{"Type"} = "Typedef";
2798 }
2799 else {
2800 $TypeAttr{"Type"} = getTypeType($TypeId);
2801 }
2802
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002803 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2804 {
2805 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2806 { # local code
2807 return ();
2808 }
2809 }
2810
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002811 if($TypeAttr{"Type"} eq "Unknown") {
2812 return ();
2813 }
2814 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2815 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002816 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002817 if(my $TName = $TypeAttr{"Name"})
2818 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002819 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002820 $TName_Tid{$Version}{$TName} = $TypeId;
2821 return %TypeAttr;
2822 }
2823 else {
2824 return ();
2825 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002826 }
2827 elsif($TypeAttr{"Type"} eq "Array")
2828 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002829 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2830 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002831 return ();
2832 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002833 if(my $Algn = getAlgn($TypeId)) {
2834 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2835 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002836 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002837 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002838 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002839 if(not $BTAttr{"Name"}) {
2840 return ();
2841 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002842 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002843 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002844 if(my $Size = getSize($TypeId)) {
2845 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2846 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002847 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002848 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2849 }
2850 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002851 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002852 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002853 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002854 else
2855 {
2856 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
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."[]".$2;
2859 }
2860 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002861 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002862 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002863 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002864 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002865 if($BTAttr{"Header"}) {
2866 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002867 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002868 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002869 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2870 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002871 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002872 return ();
2873 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002874 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002875 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002876 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002877 if($TypeAttr{"Name"})
2878 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002879 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002880
2881 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2882 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002883 { # NOTE: register only one int: with built-in decl
2884 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2885 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2886 }
2887 }
2888 return %TypeAttr;
2889 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002890 else {
2891 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002892 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002893 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002894 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2895 {
2896 %TypeAttr = getTrivialTypeAttr($TypeId);
2897 if($TypeAttr{"Name"})
2898 {
2899 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2900 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2901 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2902 }
2903 return %TypeAttr;
2904 }
2905 else {
2906 return ();
2907 }
2908 }
2909 elsif($TypeAttr{"Type"} eq "SizeOf")
2910 {
2911 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2912 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2913 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2914 if($TypeAttr{"Name"})
2915 {
2916 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2917 return %TypeAttr;
2918 }
2919 else {
2920 return ();
2921 }
2922 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002923 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002924 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002925 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2926 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002927 return ();
2928 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002929 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002930 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002931 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002932 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002933 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002934 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002935 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002936 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002937 }
2938 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002939 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002940 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002941 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002942 return ();
2943 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002944 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002945 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002946 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002947 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002948 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002949 }
2950 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002951 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002952 {
2953 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002954 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002955 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002956 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002957 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2958 }
2959 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002960 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002961 }
2962 }
2963 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002964 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002965 }
2966 if($TypeAttr{"Type"} eq "Typedef")
2967 {
2968 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002969
2970 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2971 return ();
2972 }
2973
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002974 if(isAnon($TypeAttr{"Name"}))
2975 { # anon typedef to anon type: ._N
2976 return ();
2977 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002978
2979 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2980 { # artificial typedef of "struct X" to "X"
2981 $TypeAttr{"Artificial"} = 1;
2982 }
2983
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002984 if(my $NS = getNameSpace($TypeDeclId))
2985 {
2986 my $TypeName = $TypeAttr{"Name"};
2987 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2988 { # "some_type" is the typedef to "struct some_type" in C++
2989 if($3) {
2990 $TypeAttr{"Name"} = $3."::".$TypeName;
2991 }
2992 }
2993 else
2994 {
2995 $TypeAttr{"NameSpace"} = $NS;
2996 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002997
2998 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2999 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
3000 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003001 if($BTAttr{"NameSpace"}
3002 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003003 { # types like "std::fpos<__mbstate_t>" are
3004 # not covered by typedefs in the TU dump
3005 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003006 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3007 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003008 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003009 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003010 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003011 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003012 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003013 }
3014 }
3015 }
3016 }
3017 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003018 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003019 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003020 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003021 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
3022 { # typedef int*const TYPEDEF; // first
3023 # int foo(TYPEDEF p); // const is optimized out
3024 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
3025 if($BTAttr{"Name"}=~/</)
3026 {
3027 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
3028 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3029 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003030 }
3031 }
3032 }
3033 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
3034 }
3035 if(not $TypeAttr{"Size"})
3036 {
3037 if($TypeAttr{"Type"} eq "Pointer") {
3038 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3039 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003040 elsif($BTAttr{"Size"}) {
3041 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003042 }
3043 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003044 if(my $Algn = getAlgn($TypeId)) {
3045 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3046 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003047 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003048 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3049 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003050 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003051 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003052 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003053 { # typedef to "class Class"
3054 # should not be registered in TName_Tid
3055 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3056 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3057 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003058 }
3059 return %TypeAttr;
3060 }
3061}
3062
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003063sub getTreeVec($)
3064{
3065 my %Vector = ();
3066 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3067 {
3068 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3069 { # string length is N-1 because of the null terminator
3070 $Vector{$1} = $2;
3071 }
3072 }
3073 return \%Vector;
3074}
3075
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003076sub get_TemplateParam($$)
3077{
3078 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003079 return () if(not $Type_Id);
3080 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3081 return () if(not $NodeType);
3082 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003083 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003084 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003085 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003086 my $Num = getNodeIntCst($Type_Id);
3087 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003088 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003089 }
3090 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003091 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003092 }
3093 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003094 elsif($NodeType eq "string_cst") {
3095 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003096 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003097 elsif($NodeType eq "tree_vec")
3098 {
3099 my $Vector = getTreeVec($Type_Id);
3100 my @Params = ();
3101 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3102 {
3103 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3104 push(@Params, $P2);
3105 }
3106 }
3107 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003108 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003109 elsif($NodeType eq "parm_decl")
3110 {
3111 (getNameByInfo($Type_Id));
3112 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003113 else
3114 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003115 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003116 my $PName = $ParamAttr{"Name"};
3117 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003118 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003119 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003120 if($PName=~/\>/)
3121 {
3122 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003123 $PName = $Cover;
3124 }
3125 }
3126 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003127 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003128 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3129 # template<typename _Key, typename _Compare = std::less<_Key>
3130 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3131 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3132 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3133 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003134 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003135 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003136 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003137 }
3138}
3139
3140sub cover_stdcxx_typedef($)
3141{
3142 my $TypeName = $_[0];
3143 if(my @Covers = sort {length($a)<=>length($b)}
3144 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3145 { # take the shortest typedef
3146 # FIXME: there may be more than
3147 # one typedefs to the same type
3148 return $Covers[0];
3149 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003150 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003151 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3152 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3153 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003154 if(my $Cover = $Covers[0])
3155 {
3156 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3157 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3158 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003159 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003160 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003161}
3162
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003163sub getNodeIntCst($)
3164{
3165 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003166 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003167 if($EnumMembName_Id{$Version}{$CstId}) {
3168 return $EnumMembName_Id{$Version}{$CstId};
3169 }
3170 elsif((my $Value = getTreeValue($CstId)) ne "")
3171 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003172 if($Value eq "0")
3173 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003174 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003175 return "false";
3176 }
3177 else {
3178 return "0";
3179 }
3180 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003181 elsif($Value eq "1")
3182 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003183 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003184 return "true";
3185 }
3186 else {
3187 return "1";
3188 }
3189 }
3190 else {
3191 return $Value;
3192 }
3193 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003194 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003195}
3196
3197sub getNodeStrCst($)
3198{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003199 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3200 {
3201 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003202 {
3203 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3204 { # string length is N-1 because of the null terminator
3205 return substr($1, 0, $2-1);
3206 }
3207 else
3208 { # identifier_node
3209 return substr($1, 0, $2);
3210 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003211 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003212 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003213 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003214}
3215
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003216sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003217{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003218 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003219 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3220 if($Type eq "FieldPtr") {
3221 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3222 }
3223 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3224 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003225 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003226 if($Type eq "MethodPtr")
3227 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003228 if(my $Size = getSize($TypeId))
3229 {
3230 $Size/=$BYTE_SIZE;
3231 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003232 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003233 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003234 if(my $Algn = getAlgn($TypeId)) {
3235 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3236 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003237 # Return
3238 if($Type eq "FieldPtr")
3239 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003240 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003241 if($ReturnAttr{"Name"}) {
3242 $MemPtrName .= $ReturnAttr{"Name"};
3243 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003244 $TypeAttr{"Return"} = $PtrId;
3245 }
3246 else
3247 {
3248 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3249 {
3250 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003251 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3252 if(not $ReturnAttr{"Name"})
3253 { # templates
3254 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003255 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003256 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003257 $TypeAttr{"Return"} = $ReturnTypeId;
3258 }
3259 }
3260 # Class
3261 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3262 {
3263 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003264 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003265 if($Class{"Name"}) {
3266 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3267 }
3268 else {
3269 $MemPtrName .= " (*)";
3270 }
3271 }
3272 else {
3273 $MemPtrName .= " (*)";
3274 }
3275 # Parameters
3276 if($Type eq "FuncPtr"
3277 or $Type eq "MethodPtr")
3278 {
3279 my @ParamTypeName = ();
3280 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3281 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003282 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003283 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003284 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003285 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003286 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3287 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003288 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003289 my $PTypeId = $1;
3290 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003291 if(not $ParamAttr{"Name"})
3292 { # templates (template_type_parm), etc.
3293 return ();
3294 }
3295 if($ParamAttr{"Name"} eq "void") {
3296 last;
3297 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003298 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003299 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003300 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003301 push(@ParamTypeName, $ParamAttr{"Name"});
3302 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003303 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3304 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003305 }
3306 else {
3307 last;
3308 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003309 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003310 else {
3311 last;
3312 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003313 }
3314 }
3315 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3316 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003317 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003318 return %TypeAttr;
3319}
3320
3321sub getTreeTypeName($)
3322{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003323 my $TypeId = $_[0];
3324 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003325 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003326 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003327 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003328 if(my $Name = getNameByInfo($TypeId))
3329 { # bit_size_type
3330 return $Name;
3331 }
3332 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003333 return "unsigned int";
3334 }
3335 else {
3336 return "int";
3337 }
3338 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003339 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003340 return getNameByInfo($1);
3341 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003342 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003343 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003344}
3345
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003346sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003347{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003348 my $Ptd = pointTo($_[0]);
3349 return 0 if(not $Ptd);
3350 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003351 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003352 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3353 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003354 }
3355 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003356 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3357 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003358 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003359 if($InfoT1 eq "pointer_type"
3360 and $InfoT2 eq "function_type") {
3361 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003362 }
3363 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003364 return 0;
3365}
3366
3367sub isMethodPtr($)
3368{
3369 my $Ptd = pointTo($_[0]);
3370 return 0 if(not $Ptd);
3371 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3372 {
3373 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3374 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3375 and $Info=~/ ptrmem /) {
3376 return 1;
3377 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003378 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003379 return 0;
3380}
3381
3382sub isFieldPtr($)
3383{
3384 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3385 {
3386 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3387 and $Info=~/ ptrmem /) {
3388 return 1;
3389 }
3390 }
3391 return 0;
3392}
3393
3394sub pointTo($)
3395{
3396 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3397 {
3398 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3399 return $1;
3400 }
3401 }
3402 return "";
3403}
3404
3405sub getTypeTypeByTypeId($)
3406{
3407 my $TypeId = $_[0];
3408 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3409 {
3410 my $NType = $NodeType{$TType};
3411 if($NType eq "Intrinsic") {
3412 return $NType;
3413 }
3414 elsif(isFuncPtr($TypeId)) {
3415 return "FuncPtr";
3416 }
3417 elsif(isMethodPtr($TypeId)) {
3418 return "MethodPtr";
3419 }
3420 elsif(isFieldPtr($TypeId)) {
3421 return "FieldPtr";
3422 }
3423 elsif($NType ne "Other") {
3424 return $NType;
3425 }
3426 }
3427 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003428}
3429
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003430my %UnQual = (
3431 "r"=>"restrict",
3432 "v"=>"volatile",
3433 "c"=>"const",
3434 "cv"=>"const volatile"
3435);
3436
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003437sub getQual($)
3438{
3439 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003440 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3441 {
3442 my ($Qual, $To) = ();
3443 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3444 $Qual = $UnQual{$1};
3445 }
3446 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3447 $To = $1;
3448 }
3449 if($Qual and $To) {
3450 return ($Qual, $To);
3451 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003452 }
3453 return ();
3454}
3455
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003456sub getQualType($)
3457{
3458 if($_[0] eq "const volatile") {
3459 return "ConstVolatile";
3460 }
3461 return ucfirst($_[0]);
3462}
3463
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003464sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003465{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003466 my $TypeId = $_[0];
3467 my $TypeDeclId = getTypeDeclId($TypeId);
3468 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003469 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003470 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3471 return "Typedef";
3472 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003473 }
3474 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3475 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003476 if(($Qual or $To) and $TypeDeclId
3477 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003478 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003479 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003480 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003481 elsif(not $MissedBase_R{$Version}{$TypeId}
3482 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003483 return "Typedef";
3484 }
3485 elsif($Qual)
3486 { # qualified types
3487 return getQualType($Qual);
3488 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003489
3490 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3491 { # typedef struct { ... } name
3492 $TypeTypedef{$Version}{$TypeId} = $1;
3493 }
3494
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003495 my $TypeType = getTypeTypeByTypeId($TypeId);
3496 if($TypeType eq "Struct")
3497 {
3498 if($TypeDeclId
3499 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3500 return "Template";
3501 }
3502 }
3503 return $TypeType;
3504}
3505
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003506sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003507{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003508 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003509 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003510 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3511 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3512 return 0;
3513 }
3514 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3515 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003516 if(my $TDid = getTypeDeclId($_[0]))
3517 {
3518 if(getTypeId($TDid) eq $_[0]
3519 and getNameByInfo($TDid))
3520 {
3521 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3522 return $1;
3523 }
3524 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003525 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003526 }
3527 }
3528 return 0;
3529}
3530
3531sub selectBaseType($)
3532{
3533 my $TypeId = $_[0];
3534 if(defined $MissedTypedef{$Version}{$TypeId})
3535 { # add missed typedefs
3536 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3537 return ($TypeId, "");
3538 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003539 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003540 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3541 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003542
3543 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3544 my $MB = $MissedBase{$Version}{$TypeId};
3545
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003546 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003547 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003548 and (getTypeId($1) ne $TypeId)
3549 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003550 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003551 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003552 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003553 elsif($MB)
3554 { # add base
3555 return ($MB, "");
3556 }
3557 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003558 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003559 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003560 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003561 elsif($Qual or $To)
3562 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003563 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003564 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003565 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003566 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003567 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003568 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003569 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003570 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003571 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003572 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003573 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003574 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003575 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003576 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003577 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003578 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003579 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003580 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003581 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003582 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003583
3584 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003585}
3586
3587sub getSymbolInfo_All()
3588{
3589 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3590 { # reverse order
3591 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003592 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003593 }
3594 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003595
3596 if($ADD_TMPL_INSTANCES)
3597 {
3598 # templates
3599 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3600 {
3601 my %Map = ();
3602
3603 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3604 {
3605 if(defined $TemplateMap{$Version}{$ClassId})
3606 {
3607 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3608 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3609 }
3610 }
3611 }
3612
3613 if(defined $TemplateMap{$Version}{$Sid})
3614 {
3615 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3616 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3617 }
3618 }
3619
3620 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3621 {
3622 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3623 {
3624 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3625 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3626 }
3627 }
3628 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3629 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3630 }
3631 }
3632 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003633}
3634
3635sub getVarInfo_All()
3636{
3637 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3638 { # reverse order
3639 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003640 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003641 }
3642 }
3643}
3644
3645sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003646 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003647}
3648
3649sub getVarInfo($)
3650{
3651 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003652 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003653 {
3654 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3655 if($NSInfoType and $NSInfoType eq "function_decl") {
3656 return;
3657 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003658 }
3659 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3660 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3661 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3662 delete($SymbolInfo{$Version}{$InfoId});
3663 return;
3664 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003665 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003666 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003667 delete($SymbolInfo{$Version}{$InfoId});
3668 return;
3669 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003670 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3671 delete($SymbolInfo{$Version}{$InfoId});
3672 return;
3673 }
3674 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003675 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3676 {
3677 if($OSgroup eq "windows")
3678 { # cut the offset
3679 $MnglName=~s/\@\d+\Z//g;
3680 }
3681 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3682 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003683 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003684 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003685 { # validate mangled name
3686 delete($SymbolInfo{$Version}{$InfoId});
3687 return;
3688 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003689 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003690 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003691 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003692 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003693 }
3694 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3695 { # non-public global data
3696 delete($SymbolInfo{$Version}{$InfoId});
3697 return;
3698 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003699 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003700 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003701 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003702 if(not defined $TypeInfo{$Version}{$Rid}
3703 or not $TypeInfo{$Version}{$Rid}{"Name"})
3704 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003705 delete($SymbolInfo{$Version}{$InfoId});
3706 return;
3707 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003708 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3709 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003710 if(defined $Val) {
3711 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3712 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003713 }
3714 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003715 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3716 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003717 if(not defined $TypeInfo{$Version}{$ClassId}
3718 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3719 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003720 delete($SymbolInfo{$Version}{$InfoId});
3721 return;
3722 }
3723 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003724 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3725 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003726 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003727 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003728 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003729 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003730 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003731 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003732 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003733 if(not $CheckHeadersOnly)
3734 {
3735 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3736 {
3737 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3738 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3739 {
3740 if(link_symbol($ShortName, $Version, "-Deps"))
3741 { # "const" global data is mangled as _ZL... in the TU dump
3742 # but not mangled when compiling a C shared library
3743 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3744 }
3745 }
3746 }
3747 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003748 if($COMMON_LANGUAGE{$Version} eq "C++")
3749 {
3750 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3751 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003752 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003753 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3754 }
3755 }
3756 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3757 { # try to mangle symbol (link with libraries)
3758 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3759 }
3760 if($OStarget eq "windows")
3761 {
3762 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3763 { # link MS C++ symbols from library with GCC symbols from headers
3764 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3765 }
3766 }
3767 }
3768 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3769 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3770 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003771 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3772 {
3773 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3774 { # non-target symbols
3775 delete($SymbolInfo{$Version}{$InfoId});
3776 return;
3777 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003778 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003779 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3780 {
3781 if(defined $MissedTypedef{$Version}{$Rid})
3782 {
3783 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3784 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3785 }
3786 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003787 }
3788 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003789 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003790 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3791 }
3792 if($ShortName=~/\A(_Z|\?)/) {
3793 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3794 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003795
3796 if($ExtraDump) {
3797 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3798 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003799}
3800
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003801sub isConstType($$)
3802{
3803 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003804 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003805 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003806 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003807 }
3808 return ($Base{"Type"} eq "Const");
3809}
3810
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003811sub getTrivialName($$)
3812{
3813 my ($TypeInfoId, $TypeId) = @_;
3814 my %TypeAttr = ();
3815 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3816 if(not $TypeAttr{"Name"}) {
3817 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3818 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003819 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003820 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003821 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003822 if(isAnon($TypeAttr{"Name"}))
3823 {
3824 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003825 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003826 { # searching for a first not anon scope
3827 if($NSId eq $NameSpaceId) {
3828 last;
3829 }
3830 else
3831 {
3832 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3833 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003834 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003835 last;
3836 }
3837 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003838 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003839 }
3840 }
3841 else
3842 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003843 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003844 {
3845 if($NameSpaceId ne $TypeId) {
3846 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3847 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003848 }
3849 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003850 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003851 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3852 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003853 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003854 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003855 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003856 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003857 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003858 if($TypeAttr{"NameSpace"}) {
3859 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3860 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003861 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003862 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3863 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003864 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003865 if(my @TParams = getTParams($TypeId, "Type")) {
3866 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3867 }
3868 else {
3869 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3870 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003871 }
3872 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3873}
3874
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003875sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003876{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003877 my $TypeId = $_[0];
3878 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003879
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003880 my %TypeAttr = ();
3881
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003882 if($TemplateDecl{$Version}{$TypeId})
3883 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003884 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003885 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003886
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003887 setTypeAccess($TypeId, \%TypeAttr);
3888 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3889 if(isBuiltIn($TypeAttr{"Header"}))
3890 {
3891 delete($TypeAttr{"Header"});
3892 delete($TypeAttr{"Line"});
3893 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003894
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003895 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003896 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3897 if(not $TypeAttr{"Name"}) {
3898 return ();
3899 }
3900 if(not $TypeAttr{"NameSpace"}) {
3901 delete($TypeAttr{"NameSpace"});
3902 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003903
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003904 if($TypeAttr{"Type"} eq "Intrinsic")
3905 {
3906 if(defined $TypeAttr{"Header"})
3907 {
3908 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3909 { # support for SUSE 11.2
3910 # integer_type has srcp dump{1-2}.i
3911 delete($TypeAttr{"Header"});
3912 }
3913 }
3914 }
3915
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003916 my $Tmpl = undef;
3917
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003918 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003919 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003920 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3921
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003922 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003923 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003924 foreach my $Pos (0 .. $#TParams)
3925 {
3926 my $Val = $TParams[$Pos];
3927 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3928
3929 if(not defined $TypeAttr{"Template"})
3930 {
3931 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3932
3933 if($Base{"Type"} eq "TemplateParam"
3934 or defined $Base{"Template"}) {
3935 $TypeAttr{"Template"} = 1;
3936 }
3937 }
3938
3939 if($Tmpl)
3940 {
3941 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3942 {
3943 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3944
3945 if($Val eq $Arg) {
3946 $TypeAttr{"Template"} = 1;
3947 }
3948 }
3949 }
3950 }
3951
3952 if($Tmpl)
3953 {
3954 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3955 {
3956 if($Pos>$#TParams)
3957 {
3958 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3959 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3960 }
3961 }
3962 }
3963 }
3964
3965 if($ADD_TMPL_INSTANCES)
3966 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003967 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003968 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003969 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003970 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003971 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003972 {
3973 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3974 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3975 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003976 }
3977 if(not getTreeAttr_Binf($TypeId))
3978 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003979 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3980 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3981 }
3982 }
3983 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003984 }
3985 }
3986 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003987
3988 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3989
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003990 if(my $Size = getSize($TypeId))
3991 {
3992 $Size = $Size/$BYTE_SIZE;
3993 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003994 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003995 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003996 {
3997 if($ExtraDump)
3998 {
3999 if(not defined $TypeAttr{"Memb"}
4000 and not $Tmpl)
4001 { # declaration only
4002 $TypeAttr{"Forward"} = 1;
4003 }
4004 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004005 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004006
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004007 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004008 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004009 {
4010 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004011 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004012 }
4013 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004014 or $TypeAttr{"Type"} eq "Class")
4015 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004016 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004017 if($Skip) {
4018 return ();
4019 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004020 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004021 if(my $Algn = getAlgn($TypeId)) {
4022 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
4023 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004024 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004025
4026 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
4027 {
4028 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004029 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004030 {
4031 if(not isAnon($TypeAttr{"Name"})) {
4032 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
4033 }
4034 }
4035 }
4036
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004037 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004038 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4039 {
4040 my @Entries = split(/\n/, $VTable);
4041 foreach (1 .. $#Entries)
4042 {
4043 my $Entry = $Entries[$_];
4044 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004045 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004046 }
4047 }
4048 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004049
4050 if($TypeAttr{"Type"} eq "Enum")
4051 {
4052 if(not $TypeAttr{"NameSpace"})
4053 {
4054 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4055 {
4056 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004057 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004058 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004059 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004060 "Header"=>$TypeAttr{"Header"}
4061 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004062 if(isAnon($TypeAttr{"Name"}))
4063 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004064 if($ExtraDump
4065 or is_target_header($TypeAttr{"Header"}, $Version))
4066 {
4067 %{$Constants{$Version}{$MName}} = (
4068 "Value" => $MVal,
4069 "Header" => $TypeAttr{"Header"}
4070 );
4071 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004072 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004073 }
4074 }
4075 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004076 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004077 {
4078 if(defined $TypedefToAnon{$TypeId}) {
4079 $TypeAttr{"AnonTypedef"} = 1;
4080 }
4081 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004082
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004083 return %TypeAttr;
4084}
4085
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004086sub simplifyVTable($)
4087{
4088 my $Content = $_[0];
4089 if($Content=~s/ \[with (.+)]//)
4090 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4091 if(my @Elems = separate_Params($1, 0, 0))
4092 {
4093 foreach my $Elem (@Elems)
4094 {
4095 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4096 {
4097 my ($Arg, $Val) = ($1, $2);
4098
4099 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4100 $Content=~s/,\s*$Arg\b//g;
4101 }
4102 else {
4103 $Content=~s/\b$Arg\b/$Val/g;
4104 }
4105 }
4106 }
4107 }
4108 }
4109
4110 return $Content;
4111}
4112
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004113sub detect_lang($)
4114{
4115 my $TypeId = $_[0];
4116 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004117 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004118 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004119 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4120 }
4121 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004122 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004123 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004124 while($Fncs)
4125 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004126 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004127 return 1;
4128 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004129 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004130 }
4131 }
4132 return 0;
4133}
4134
4135sub setSpec($$)
4136{
4137 my ($TypeId, $TypeAttr) = @_;
4138 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4139 if($Info=~/\s+spec\s+/) {
4140 $TypeAttr->{"Spec"} = 1;
4141 }
4142}
4143
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004144sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004145{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004146 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004147 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004148 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004149 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004150 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004151 my $Pos = 0;
4152 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4153 {
4154 my ($Access, $BInfoId) = ($1, $2);
4155 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004156
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03004157 if($ClassId eq $TypeId)
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004158 { # class A<N>:public A<N-1>
4159 next;
4160 }
4161
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004162 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4163 if(not $CType or $CType eq "template_type_parm"
4164 or $CType eq "typename_type")
4165 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004166 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004167 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004168 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004169 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004170 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4171 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004172 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004173 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4174 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004175 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004176 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004177 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004178 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4179 }
4180 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004181 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004182 }
4183 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004184 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004185}
4186
4187sub getBinfClassId($)
4188{
4189 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03004190 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
4191 return $1;
4192 }
4193
4194 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004195}
4196
4197sub unmangledFormat($$)
4198{
4199 my ($Name, $LibVersion) = @_;
4200 $Name = uncover_typedefs($Name, $LibVersion);
4201 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4202 $Name=~s/\(\w+\)(\d)/$1/;
4203 return $Name;
4204}
4205
4206sub modelUnmangled($$)
4207{
4208 my ($InfoId, $Compiler) = @_;
4209 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4210 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4211 }
4212 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4213 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4214 $PureSignature = "~".$PureSignature;
4215 }
4216 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4217 {
4218 my (@Params, @ParamTypes) = ();
4219 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4220 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4221 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4222 }
4223 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4224 { # checking parameters
4225 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004226 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004227 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004228 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004229
4230 if($PName eq "this"
4231 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4232 {
4233 next;
4234 }
4235
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004236 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004237 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004238 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004239 }
4240 @ParamTypes = (@ParamTypes, $PTName);
4241 }
4242 if(@ParamTypes) {
4243 $PureSignature .= "(".join(", ", @ParamTypes).")";
4244 }
4245 else
4246 {
4247 if($Compiler eq "MSVC")
4248 {
4249 $PureSignature .= "(void)";
4250 }
4251 else
4252 { # GCC
4253 $PureSignature .= "()";
4254 }
4255 }
4256 $PureSignature = delete_keywords($PureSignature);
4257 }
4258 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4259 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004260 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004261 $PureSignature = $ClassName."::".$PureSignature;
4262 }
4263 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4264 $PureSignature = $NS."::".$PureSignature;
4265 }
4266 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4267 $PureSignature .= " const";
4268 }
4269 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4270 $PureSignature .= " volatile";
4271 }
4272 my $ShowReturn = 0;
4273 if($Compiler eq "MSVC"
4274 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4275 {
4276 $ShowReturn=1;
4277 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004278 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4279 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004280 {
4281 $ShowReturn=1;
4282 }
4283 if($ShowReturn)
4284 { # mangled names for template function specializations include return value
4285 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4286 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004287 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004288 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4289 $PureSignature = $ReturnName." ".$PureSignature;
4290 }
4291 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004292 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004293}
4294
4295sub mangle_symbol($$$)
4296{ # mangling for simple methods
4297 # see gcc-4.6.0/gcc/cp/mangle.c
4298 my ($InfoId, $LibVersion, $Compiler) = @_;
4299 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4300 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4301 }
4302 my $Mangled = "";
4303 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004304 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004305 }
4306 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004307 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004308 }
4309 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4310}
4311
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004312sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004313{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004314 my ($InfoId, $LibVersion) = @_;
4315 return "";
4316}
4317
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004318sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004319{ # see gcc-4.6.0/gcc/cp/mangle.c
4320 my ($InfoId, $LibVersion) = @_;
4321 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004322 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004323 my %Repl = ();# SN_ replacements
4324 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4325 {
4326 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4327 if($MangledClass!~/\AN/) {
4328 $MangledClass = "N".$MangledClass;
4329 }
4330 else {
4331 $MangledClass=~s/E\Z//;
4332 }
4333 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4334 $MangledClass=~s/\AN/NV/;
4335 }
4336 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4337 $MangledClass=~s/\AN/NK/;
4338 }
4339 $Mangled .= $MangledClass;
4340 }
4341 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4342 { # mangled by name due to the absence of structured info
4343 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4344 if($MangledNS!~/\AN/) {
4345 $MangledNS = "N".$MangledNS;
4346 }
4347 else {
4348 $MangledNS=~s/E\Z//;
4349 }
4350 $Mangled .= $MangledNS;
4351 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004352 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004353 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004354 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004355 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004356 foreach (@TPos) {
4357 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4358 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004359 }
4360 elsif($TmplParams)
4361 { # remangling mode
4362 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004363 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004364 }
4365 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4366 $Mangled .= "C1";
4367 }
4368 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4369 $Mangled .= "D0";
4370 }
4371 elsif($ShortName)
4372 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004373 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4374 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004375 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004376 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004377 { # "const" global data is mangled as _ZL...
4378 $Mangled .= "L";
4379 }
4380 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004381 if($ShortName=~/\Aoperator(\W.*)\Z/)
4382 {
4383 my $Op = $1;
4384 $Op=~s/\A[ ]+//g;
4385 if(my $OpMngl = $OperatorMangling{$Op}) {
4386 $Mangled .= $OpMngl;
4387 }
4388 else { # conversion operator
4389 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4390 }
4391 }
4392 else {
4393 $Mangled .= length($ShortName).$ShortName;
4394 }
4395 if(@TParams)
4396 { # templates
4397 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004398 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004399 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4400 }
4401 $Mangled .= "E";
4402 }
4403 if(not $ClassId and @TParams) {
4404 add_substitution($ShortName, \%Repl, 0);
4405 }
4406 }
4407 if($ClassId or $NameSpace) {
4408 $Mangled .= "E";
4409 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004410 if(@TParams)
4411 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004412 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004413 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4414 }
4415 }
4416 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4417 {
4418 my @Params = ();
4419 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4420 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4421 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4422 }
4423 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4424 { # checking parameters
4425 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4426 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4427 }
4428 if(not @Params) {
4429 $Mangled .= "v";
4430 }
4431 }
4432 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4433 $Mangled = write_stdcxx_substitution($Mangled);
4434 if($Mangled eq "_Z") {
4435 return "";
4436 }
4437 return $Mangled;
4438}
4439
4440sub correct_incharge($$$)
4441{
4442 my ($InfoId, $LibVersion, $Mangled) = @_;
4443 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4444 {
4445 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004446 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004447 }
4448 }
4449 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4450 {
4451 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004452 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004453 }
4454 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004455 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004456 }
4457 }
4458 return $Mangled;
4459}
4460
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004461sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004462{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004463 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004464 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004465 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004466 return $Name;
4467 }
4468 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004469 while(my $CPos = find_center($TParams, "<"))
4470 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004471 $TParams = substr($TParams, $CPos);
4472 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004473 if($TParams=~s/\A<(.+)>\Z/$1/) {
4474 $Name=~s/<\Q$TParams\E>\Z//;
4475 }
4476 else
4477 { # error
4478 $TParams = "";
4479 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004480 return ($Name, $TParams);
4481}
4482
4483sub get_sub_ns($)
4484{
4485 my $Name = $_[0];
4486 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004487 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004488 {
4489 push(@NS, substr($Name, 0, $CPos));
4490 $Name = substr($Name, $CPos);
4491 $Name=~s/\A:://;
4492 }
4493 return (join("::", @NS), $Name);
4494}
4495
4496sub mangle_ns($$$)
4497{
4498 my ($Name, $LibVersion, $Repl) = @_;
4499 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4500 {
4501 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4502 $Mangled=~s/\AN(.+)E\Z/$1/;
4503 return $Mangled;
4504
4505 }
4506 else
4507 {
4508 my ($MangledNS, $SubNS) = ("", "");
4509 ($SubNS, $Name) = get_sub_ns($Name);
4510 if($SubNS) {
4511 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4512 }
4513 $MangledNS .= length($Name).$Name;
4514 add_substitution($MangledNS, $Repl, 0);
4515 return $MangledNS;
4516 }
4517}
4518
4519sub mangle_param($$$)
4520{
4521 my ($PTid, $LibVersion, $Repl) = @_;
4522 my ($MPrefix, $Mangled) = ("", "");
4523 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004524 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004525 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004526 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004527 if(not $BaseType_Name) {
4528 return "";
4529 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004530 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004531 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004532 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4533 while($Suffix=~/(&|\*|const)\Z/)
4534 {
4535 if($Suffix=~s/[ ]*&\Z//) {
4536 $MPrefix .= "R";
4537 }
4538 if($Suffix=~s/[ ]*\*\Z//) {
4539 $MPrefix .= "P";
4540 }
4541 if($Suffix=~s/[ ]*const\Z//)
4542 {
4543 if($MPrefix=~/R|P/
4544 or $Suffix=~/&|\*/) {
4545 $MPrefix .= "K";
4546 }
4547 }
4548 if($Suffix=~s/[ ]*volatile\Z//) {
4549 $MPrefix .= "V";
4550 }
4551 #if($Suffix=~s/[ ]*restrict\Z//) {
4552 #$MPrefix .= "r";
4553 #}
4554 }
4555 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4556 $Mangled .= $Token;
4557 }
4558 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4559 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004560 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004561 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004562 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004563 foreach (@TPos) {
4564 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4565 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004566 }
4567 elsif($TmplParams)
4568 { # remangling mode
4569 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004570 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004571 }
4572 my $MangledNS = "";
4573 my ($SubNS, $SName) = get_sub_ns($ShortName);
4574 if($SubNS) {
4575 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4576 }
4577 $MangledNS .= length($SName).$SName;
4578 if(@TParams) {
4579 add_substitution($MangledNS, $Repl, 0);
4580 }
4581 $Mangled .= "N".$MangledNS;
4582 if(@TParams)
4583 { # templates
4584 $Mangled .= "I";
4585 foreach my $TParam (@TParams) {
4586 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4587 }
4588 $Mangled .= "E";
4589 }
4590 $Mangled .= "E";
4591 }
4592 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4593 {
4594 if($BaseType{"Type"} eq "MethodPtr") {
4595 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4596 }
4597 else {
4598 $Mangled .= "PF";
4599 }
4600 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4601 my @Params = keys(%{$BaseType{"Param"}});
4602 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4603 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4604 }
4605 if(not @Params) {
4606 $Mangled .= "v";
4607 }
4608 $Mangled .= "E";
4609 }
4610 elsif($BaseType{"Type"} eq "FieldPtr")
4611 {
4612 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4613 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4614 }
4615 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4616 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4617 {
4618 if($Mangled eq $Optimized)
4619 {
4620 if($ShortName!~/::/)
4621 { # remove "N ... E"
4622 if($MPrefix) {
4623 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4624 }
4625 else {
4626 $Mangled=~s/\AN(.+)E\Z/$1/g;
4627 }
4628 }
4629 }
4630 else {
4631 $Mangled = $Optimized;
4632 }
4633 }
4634 add_substitution($Mangled, $Repl, 1);
4635 return $Mangled;
4636}
4637
4638sub mangle_template_param($$$)
4639{ # types + literals
4640 my ($TParam, $LibVersion, $Repl) = @_;
4641 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4642 return mangle_param($TPTid, $LibVersion, $Repl);
4643 }
4644 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4645 { # class_name<1u>::method(...)
4646 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4647 }
4648 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4649 { # class_name<(signed char)1>::method(...)
4650 return "L".$IntrinsicMangling{$1}.$2."E";
4651 }
4652 elsif($TParam eq "true")
4653 { # class_name<true>::method(...)
4654 return "Lb1E";
4655 }
4656 elsif($TParam eq "false")
4657 { # class_name<true>::method(...)
4658 return "Lb0E";
4659 }
4660 else { # internal error
4661 return length($TParam).$TParam;
4662 }
4663}
4664
4665sub add_substitution($$$)
4666{
4667 my ($Value, $Repl, $Rec) = @_;
4668 if($Rec)
4669 { # subtypes
4670 my @Subs = ($Value);
4671 while($Value=~s/\A(R|P|K)//) {
4672 push(@Subs, $Value);
4673 }
4674 foreach (reverse(@Subs)) {
4675 add_substitution($_, $Repl, 0);
4676 }
4677 return;
4678 }
4679 return if($Value=~/\AS(\d*)_\Z/);
4680 $Value=~s/\AN(.+)E\Z/$1/g;
4681 return if(defined $Repl->{$Value});
4682 return if(length($Value)<=1);
4683 return if($StdcxxMangling{$Value});
4684 # check for duplicates
4685 my $Base = $Value;
4686 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4687 {
4688 my $Num = $Repl->{$Type};
4689 my $Replace = macro_mangle($Num);
4690 $Base=~s/\Q$Replace\E/$Type/;
4691 }
4692 if(my $OldNum = $Repl->{$Base})
4693 {
4694 $Repl->{$Value} = $OldNum;
4695 return;
4696 }
4697 my @Repls = sort {$b<=>$a} values(%{$Repl});
4698 if(@Repls) {
4699 $Repl->{$Value} = $Repls[0]+1;
4700 }
4701 else {
4702 $Repl->{$Value} = -1;
4703 }
4704 # register duplicates
4705 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004706 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004707 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4708 {
4709 next if($Base eq $Type);
4710 my $Num = $Repl->{$Type};
4711 my $Replace = macro_mangle($Num);
4712 $Base=~s/\Q$Type\E/$Replace/;
4713 $Repl->{$Base} = $Repl->{$Value};
4714 }
4715}
4716
4717sub macro_mangle($)
4718{
4719 my $Num = $_[0];
4720 if($Num==-1) {
4721 return "S_";
4722 }
4723 else
4724 {
4725 my $Code = "";
4726 if($Num<10)
4727 { # S0_, S1_, S2_, ...
4728 $Code = $Num;
4729 }
4730 elsif($Num>=10 and $Num<=35)
4731 { # SA_, SB_, SC_, ...
4732 $Code = chr(55+$Num);
4733 }
4734 else
4735 { # S10_, S11_, S12_
4736 $Code = $Num-26; # 26 is length of english alphabet
4737 }
4738 return "S".$Code."_";
4739 }
4740}
4741
4742sub write_stdcxx_substitution($)
4743{
4744 my $Mangled = $_[0];
4745 if($StdcxxMangling{$Mangled}) {
4746 return $StdcxxMangling{$Mangled};
4747 }
4748 else
4749 {
4750 my @Repls = keys(%StdcxxMangling);
4751 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4752 foreach my $MangledType (@Repls)
4753 {
4754 my $Replace = $StdcxxMangling{$MangledType};
4755 #if($Mangled!~/$Replace/) {
4756 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4757 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4758 #}
4759 }
4760 }
4761 return $Mangled;
4762}
4763
4764sub write_substitution($$)
4765{
4766 my ($Mangled, $Repl) = @_;
4767 if(defined $Repl->{$Mangled}
4768 and my $MnglNum = $Repl->{$Mangled}) {
4769 $Mangled = macro_mangle($MnglNum);
4770 }
4771 else
4772 {
4773 my @Repls = keys(%{$Repl});
4774 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4775 # FIXME: how to apply replacements? by num or by pos
4776 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4777 foreach my $MangledType (@Repls)
4778 {
4779 my $Replace = macro_mangle($Repl->{$MangledType});
4780 if($Mangled!~/$Replace/) {
4781 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4782 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4783 }
4784 }
4785 }
4786 return $Mangled;
4787}
4788
4789sub delete_keywords($)
4790{
4791 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004792 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004793 return $TypeName;
4794}
4795
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004796sub uncover_typedefs($$)
4797{
4798 my ($TypeName, $LibVersion) = @_;
4799 return "" if(not $TypeName);
4800 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4801 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4802 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004803 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004804 while($TypeName_New ne $TypeName_Pre)
4805 {
4806 $TypeName_Pre = $TypeName_New;
4807 my $TypeName_Copy = $TypeName_New;
4808 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004809 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004810 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004811 if(not $Intrinsic_Keywords{$1}) {
4812 $Words{$1} = 1;
4813 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004814 }
4815 foreach my $Word (keys(%Words))
4816 {
4817 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4818 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004819 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004820 if($BaseType_Name=~/\([\*]+\)/)
4821 { # FuncPtr
4822 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4823 {
4824 my $Type_Suffix = $1;
4825 $TypeName_New = $BaseType_Name;
4826 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004827 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004828 }
4829 }
4830 }
4831 else
4832 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004833 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004834 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004835 }
4836 }
4837 }
4838 }
4839 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4840}
4841
4842sub isInternal($)
4843{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004844 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4845 {
4846 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4847 {
4848 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4849 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4850 return 1;
4851 }
4852 }
4853 }
4854 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004855}
4856
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004857sub getDataVal($$)
4858{
4859 my ($InfoId, $TypeId) = @_;
4860 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4861 {
4862 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4863 {
4864 if(defined $LibInfo{$Version}{"info_type"}{$1}
4865 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004866 {
4867 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004868 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004869 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4870 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004871 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004872 if(my $Addr = getTreeAttr_Op($1)) {
4873 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004874 }
4875 }
4876 }
4877 }
4878 else {
4879 return getInitVal($1, $TypeId);
4880 }
4881 }
4882 }
4883 return undef;
4884}
4885
4886sub getInitVal($$)
4887{
4888 my ($InfoId, $TypeId) = @_;
4889 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4890 {
4891 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4892 {
4893 if($InfoType eq "integer_cst")
4894 {
4895 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004896 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004897 { # characters
4898 $Val = chr($Val);
4899 }
4900 return $Val;
4901 }
4902 elsif($InfoType eq "string_cst") {
4903 return getNodeStrCst($InfoId);
4904 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004905 elsif($InfoType eq "var_decl")
4906 {
4907 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4908 return $Name;
4909 }
4910 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004911 }
4912 }
4913 return undef;
4914}
4915
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004916sub set_Class_And_Namespace($)
4917{
4918 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004919 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004920 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004921 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004922 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004923 my $NSInfoId = $1;
4924 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4925 {
4926 if($InfoType eq "namespace_decl") {
4927 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4928 }
4929 elsif($InfoType eq "record_type") {
4930 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4931 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004932 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004933 }
4934 }
4935 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4936 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004937 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004938 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004939 { # skip
4940 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004941 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004942 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004943
4944 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004945}
4946
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004947sub debugMangling($)
4948{
4949 my $LibVersion = $_[0];
4950 my %Mangled = ();
4951 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4952 {
4953 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4954 {
4955 if($Mngl=~/\A(_Z|\?)/) {
4956 $Mangled{$Mngl}=$InfoId;
4957 }
4958 }
4959 }
4960 translateSymbols(keys(%Mangled), $LibVersion);
4961 foreach my $Mngl (keys(%Mangled))
4962 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004963 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4964 my $U2 = $tr_name{$Mngl};
4965 if($U1 ne $U2) {
4966 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004967 }
4968 }
4969}
4970
4971sub linkSymbol($)
4972{ # link symbols from shared libraries
4973 # with the symbols from header files
4974 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004975 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004976 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004977 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4978 or $EMERGENCY_MODE_48)
4979 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4980 # 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 +03004981 # GCC 4.8.[012] doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004982 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004983 {
4984 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4985 return correct_incharge($InfoId, $Version, $Mangled);
4986 }
4987 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004988 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004989 or not $BinaryOnly
4990 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004991 { # 1. --headers-only mode
4992 # 2. not mangled src-only symbols
4993 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4994 return $Mangled;
4995 }
4996 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004997 }
4998 return "";
4999}
5000
5001sub setLanguage($$)
5002{
5003 my ($LibVersion, $Lang) = @_;
5004 if(not $UserLang) {
5005 $COMMON_LANGUAGE{$LibVersion} = $Lang;
5006 }
5007}
5008
5009sub getSymbolInfo($)
5010{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005011 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005012 if(isInternal($InfoId)) {
5013 return;
5014 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005015 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
5016 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005017 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
5018 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005019 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005020 return;
5021 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005022 setFuncAccess($InfoId);
5023 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005024 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
5025 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005026 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005027 return;
5028 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005029
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005030 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005031 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005032 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005033 if(not defined $TypeInfo{$Version}{$Return}
5034 or not $TypeInfo{$Version}{$Return}{"Name"})
5035 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005036 delete($SymbolInfo{$Version}{$InfoId});
5037 return;
5038 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005039 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005040 }
5041 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5042 {
5043 if(defined $MissedTypedef{$Version}{$Rid})
5044 {
5045 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5046 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5047 }
5048 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005049 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005050 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5051 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005052 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005053 my $Orig = getFuncOrig($InfoId);
5054 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005055 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5056 {
5057 delete($SymbolInfo{$Version}{$InfoId});
5058 return;
5059 }
5060
5061 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005062 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005063 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005064 return;
5065 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005066
5067 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005068 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005069 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5070
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005071 my @TParams = getTParams($Orig, "Func");
5072 if(not @TParams)
5073 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005074 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005075 return;
5076 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005077 foreach my $Pos (0 .. $#TParams)
5078 {
5079 my $Val = $TParams[$Pos];
5080 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5081
5082 if($Tmpl)
5083 {
5084 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5085 {
5086 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5087 }
5088 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005089 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005090
5091 if($Tmpl)
5092 {
5093 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5094 {
5095 if($Pos>$#TParams)
5096 {
5097 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5098 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5099 }
5100 }
5101 }
5102
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005103 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5104 { # operator<< <T>, operator>> <T>
5105 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5106 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005107 if(@TParams) {
5108 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5109 }
5110 else {
5111 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5112 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005113 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005114 }
5115 else
5116 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005117 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005118 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005119 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5120 {
5121 if($OSgroup eq "windows")
5122 { # cut the offset
5123 $MnglName=~s/\@\d+\Z//g;
5124 }
5125 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5126
5127 # NOTE: mangling of some symbols may change depending on GCC version
5128 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5129 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5130 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005131
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005132 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005133 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005134 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005135 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005136 return;
5137 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005138 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005139 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005140 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005141 if($Skip)
5142 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005143 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005144 return;
5145 }
5146 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005147 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5148 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5149 }
5150
5151 if(set_Class_And_Namespace($InfoId))
5152 {
5153 delete($SymbolInfo{$Version}{$InfoId});
5154 return;
5155 }
5156
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005157 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5158 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005159 if(not defined $TypeInfo{$Version}{$ClassId}
5160 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5161 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005162 delete($SymbolInfo{$Version}{$InfoId});
5163 return;
5164 }
5165 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005166 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5167 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005168 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005169 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005170 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005171 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005172 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005173 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005174 }
5175 if($COMMON_LANGUAGE{$Version} eq "C++")
5176 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005177 # C++ or --headers-only mode
5178 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005179 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005180 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5181 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005182 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005183 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005184 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005185 if(my $Mangled = linkSymbol($InfoId)) {
5186 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005187 }
5188 }
5189 if($OStarget eq "windows")
5190 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005191 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005192 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005193 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005194 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005195 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005196 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005197 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005198 }
5199 }
5200 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005201 else
5202 { # not mangled in C
5203 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5204 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005205 if(not $CheckHeadersOnly
5206 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5207 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5208 {
5209 my $Incorrect = 0;
5210
5211 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5212 {
5213 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5214 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5215 { # mangled in the TU dump, but not mangled in the library
5216 $Incorrect = 1;
5217 }
5218 }
5219 else
5220 {
5221 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5222 { # all C++ functions are not mangled in the TU dump
5223 $Incorrect = 1;
5224 }
5225 }
5226 if($Incorrect)
5227 {
5228 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5229 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5230 }
5231 }
5232 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005233 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005234 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005235 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005236 return;
5237 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005238 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005239 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005240 { # identify virtual and pure virtual functions
5241 # NOTE: constructors cannot be virtual
5242 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5243 # in the TU dump, so taking it from the original symbol
5244 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5245 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5246 { # NOTE: D2 destructors are not present in a v-table
5247 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5248 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005249 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005250 if(isInline($InfoId)) {
5251 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005252 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005253 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005254 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5255 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005256 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5257 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005258 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005259 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005260 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005261 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005262 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005263 }
5264 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005265 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5266 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005267 if(not $ExtraDump)
5268 {
5269 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5270 { # non-target symbols
5271 delete($SymbolInfo{$Version}{$InfoId});
5272 return;
5273 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005274 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005275 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005276 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5277 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5278 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5279 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005280 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005281 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5282 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005283 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005284 return;
5285 }
5286 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005287 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005288 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005289 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005290 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005291 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005292 return;
5293 }
5294 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005295 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005296 }
5297 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005298 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5299 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5300 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005301 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005302 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5303 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005304 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005305 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005306 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005307 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005308 }
5309 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005310 if(getFuncLink($InfoId) eq "Static") {
5311 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005312 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005313 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5314 {
5315 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5316 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005317 if($Unmangled=~/\.\_\d/)
5318 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005319 delete($SymbolInfo{$Version}{$InfoId});
5320 return;
5321 }
5322 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005323 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005324
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005325 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5326 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005327 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005328 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5329 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005330 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005331
5332 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5333 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5334 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005335
5336 if($ExtraDump) {
5337 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5338 }
5339}
5340
5341sub guessHeader($)
5342{
5343 my $InfoId = $_[0];
5344 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5345 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5346 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5347 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5348 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5349 {
5350 if(get_filename($HPath) eq $Header)
5351 {
5352 my $HDir = get_filename(get_dirname($HPath));
5353 if($HDir ne "include"
5354 and $HDir=~/\A[a-z]+\Z/i) {
5355 return join_P($HDir, $Header);
5356 }
5357 }
5358 }
5359 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005360}
5361
5362sub isInline($)
5363{ # "body: undefined" in the tree
5364 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005365 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5366 {
5367 if($Info=~/ undefined /i) {
5368 return 0;
5369 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005370 }
5371 return 1;
5372}
5373
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005374sub hasThrow($)
5375{
5376 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5377 {
5378 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5379 return getTreeAttr_Unql($1, "unql");
5380 }
5381 }
5382 return 1;
5383}
5384
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005385sub getTypeId($)
5386{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005387 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5388 {
5389 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5390 return $1;
5391 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005392 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005393 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005394}
5395
5396sub setTypeMemb($$)
5397{
5398 my ($TypeId, $TypeAttr) = @_;
5399 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005400 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005401 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005402 if($TypeType eq "Enum")
5403 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005404 my $MInfoId = getTreeAttr_Csts($TypeId);
5405 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005406 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005407 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5408 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005409 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005410 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5411 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005412 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005413 }
5414 }
5415 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5416 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005417 my $MInfoId = getTreeAttr_Flds($TypeId);
5418 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005419 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005420 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5421 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005422 if(not $IType or $IType ne "field_decl")
5423 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005424
5425 if($IType eq "var_decl")
5426 { # static field
5427 $StaticFields = 1;
5428 }
5429
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005430 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005431 next;
5432 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005433 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005434 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005435 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005436 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005437 }
5438 if(not $StructMembName)
5439 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005440 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005441 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005442 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005443 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5444 if(isAnon($UnnamedTName))
5445 { # rename unnamed fields to unnamed0, unnamed1, ...
5446 $StructMembName = "unnamed".($UnnamedPos++);
5447 }
5448 }
5449 }
5450 if(not $StructMembName)
5451 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005452 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005453 next;
5454 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005455 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005456 if(defined $MissedTypedef{$Version}{$MembTypeId})
5457 {
5458 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5459 $MembTypeId = $AddedTid;
5460 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005461 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005462
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005463 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5464 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005465 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005466 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005467 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5468 }
5469 if($MInfo=~/spec:\s*mutable /)
5470 { # mutable fields
5471 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005472 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005473 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005474 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5475 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005476 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005477 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005478 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005479 }
5480 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005481 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005482 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5483 { # template
5484 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5485 }
5486 else {
5487 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5488 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005489 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005490
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005491 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005492 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005493 }
5494 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005495
5496 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005497}
5498
5499sub setFuncParams($)
5500{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005501 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005502 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005503
5504 my $FType = getFuncType($InfoId);
5505
5506 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005507 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005508 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5509 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005510 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005511 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005512 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5513 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005514 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005515 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5516 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005517 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005518 else
5519 { # skip
5520 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005521 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005522 # skip "this"-parameter
5523 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005524 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005525 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005526 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005527 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005528 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5529 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5530 if(not $ParamName)
5531 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005532 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005533 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005534 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5535 {
5536 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5537 $ParamTypeId = $AddedTid;
5538 }
5539 }
5540 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005541 if(not $PType or $PType eq "Unknown") {
5542 return 1;
5543 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005544 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005545 if(not $PTName) {
5546 return 1;
5547 }
5548 if($PTName eq "void") {
5549 last;
5550 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005551 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005552 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005553 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005554 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005555 $ParamInfoId = getNextElem($ParamInfoId);
5556 next;
5557 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005558 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005559
5560 if(my %Base = get_BaseType($ParamTypeId, $Version))
5561 {
5562 if(defined $Base{"Template"}) {
5563 return 1;
5564 }
5565 }
5566
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005567 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005568 if(my $Algn = getAlgn($ParamInfoId)) {
5569 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5570 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005571 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5572 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005573 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005574 }
5575 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005576 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005577 if($ParamName ne "this" or $FType ne "Method") {
5578 $PPos += 1;
5579 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005580 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005581 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005582 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005583 }
5584 return 0;
5585}
5586
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005587sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005588{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005589 my ($InfoId, $Vtt_Pos) = @_;
5590 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005591 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005592 my $FType = getFuncType($InfoId);
5593
5594 if($FType eq "Method")
5595 {
5596 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005597 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005598 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005599 if(not $ParamListElemId)
5600 { # foo(...)
5601 return 1;
5602 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005603 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005604 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005605 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005606 { # actual params: may differ from formal args
5607 # formal int*const
5608 # actual: int*
5609 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005610 {
5611 $Vtt_Pos=-1;
5612 $ParamListElemId = getNextElem($ParamListElemId);
5613 next;
5614 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005615 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5616 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005617 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005618 $HaveVoid = 1;
5619 last;
5620 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005621 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005622 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005623 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5624 {
5625 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5626 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5627 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005628 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005629 }
5630 }
5631 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5632 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005633 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005634 { # params
5635 if($OldId ne $ParamTypeId)
5636 {
5637 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5638 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5639
5640 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5641 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5642 }
5643 }
5644 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005645 }
5646 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005647 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005648 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005649 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5650 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005651 if($PurpType eq "nop_expr")
5652 { # func ( const char* arg = (const char*)(void*)0 )
5653 $PurpId = getTreeAttr_Op($PurpId);
5654 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005655 my $Val = getInitVal($PurpId, $ParamTypeId);
5656 if(defined $Val) {
5657 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5658 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005659 }
5660 }
5661 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005662 if($Pos!=0 or $FType ne "Method") {
5663 $PPos += 1;
5664 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005665 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005666 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005667 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005668}
5669
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005670sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005671{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005672 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5673 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005674 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5675 return $1;
5676 }
5677 }
5678 return "";
5679}
5680
5681sub getTreeAttr_Chain($)
5682{
5683 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5684 {
5685 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5686 return $1;
5687 }
5688 }
5689 return "";
5690}
5691
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005692sub getTreeAttr_Unql($)
5693{
5694 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5695 {
5696 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5697 return $1;
5698 }
5699 }
5700 return "";
5701}
5702
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005703sub getTreeAttr_Scpe($)
5704{
5705 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5706 {
5707 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5708 return $1;
5709 }
5710 }
5711 return "";
5712}
5713
5714sub getTreeAttr_Type($)
5715{
5716 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5717 {
5718 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5719 return $1;
5720 }
5721 }
5722 return "";
5723}
5724
5725sub getTreeAttr_Name($)
5726{
5727 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5728 {
5729 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5730 return $1;
5731 }
5732 }
5733 return "";
5734}
5735
5736sub getTreeAttr_Mngl($)
5737{
5738 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5739 {
5740 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5741 return $1;
5742 }
5743 }
5744 return "";
5745}
5746
5747sub getTreeAttr_Prms($)
5748{
5749 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5750 {
5751 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5752 return $1;
5753 }
5754 }
5755 return "";
5756}
5757
5758sub getTreeAttr_Fncs($)
5759{
5760 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5761 {
5762 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5763 return $1;
5764 }
5765 }
5766 return "";
5767}
5768
5769sub getTreeAttr_Csts($)
5770{
5771 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5772 {
5773 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5774 return $1;
5775 }
5776 }
5777 return "";
5778}
5779
5780sub getTreeAttr_Purp($)
5781{
5782 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5783 {
5784 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5785 return $1;
5786 }
5787 }
5788 return "";
5789}
5790
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005791sub getTreeAttr_Op($)
5792{
5793 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5794 {
5795 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5796 return $1;
5797 }
5798 }
5799 return "";
5800}
5801
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005802sub getTreeAttr_Valu($)
5803{
5804 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5805 {
5806 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5807 return $1;
5808 }
5809 }
5810 return "";
5811}
5812
5813sub getTreeAttr_Flds($)
5814{
5815 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5816 {
5817 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5818 return $1;
5819 }
5820 }
5821 return "";
5822}
5823
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005824sub getTreeAttr_Binf($)
5825{
5826 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5827 {
5828 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5829 return $1;
5830 }
5831 }
5832 return "";
5833}
5834
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005835sub getTreeAttr_Args($)
5836{
5837 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5838 {
5839 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005840 return $1;
5841 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005842 }
5843 return "";
5844}
5845
5846sub getTreeValue($)
5847{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005848 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5849 {
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03005850 if($Info=~/(low|int)[ ]*:[ ]*([^ ]+) /) {
5851 return $2;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005852 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005853 }
5854 return "";
5855}
5856
5857sub getTreeAccess($)
5858{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005859 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005860 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005861 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5862 {
5863 my $Access = $1;
5864 if($Access eq "prot") {
5865 return "protected";
5866 }
5867 elsif($Access eq "priv") {
5868 return "private";
5869 }
5870 }
5871 elsif($Info=~/ protected /)
5872 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005873 return "protected";
5874 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005875 elsif($Info=~/ private /)
5876 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005877 return "private";
5878 }
5879 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005880 return "public";
5881}
5882
5883sub setFuncAccess($)
5884{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005885 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005886 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005887 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005888 }
5889 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005890 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005891 }
5892}
5893
5894sub setTypeAccess($$)
5895{
5896 my ($TypeId, $TypeAttr) = @_;
5897 my $Access = getTreeAccess($TypeId);
5898 if($Access eq "protected") {
5899 $TypeAttr->{"Protected"} = 1;
5900 }
5901 elsif($Access eq "private") {
5902 $TypeAttr->{"Private"} = 1;
5903 }
5904}
5905
5906sub setFuncKind($)
5907{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005908 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5909 {
5910 if($Info=~/pseudo tmpl/) {
5911 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5912 }
5913 elsif($Info=~/ constructor /) {
5914 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5915 }
5916 elsif($Info=~/ destructor /) {
5917 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5918 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005919 }
5920}
5921
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005922sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005923{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005924 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5925 {
5926 if($Info=~/spec[ ]*:[ ]*pure /) {
5927 return "PureVirt";
5928 }
5929 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5930 return "Virt";
5931 }
5932 elsif($Info=~/ pure\s+virtual /)
5933 { # support for old GCC versions
5934 return "PureVirt";
5935 }
5936 elsif($Info=~/ virtual /)
5937 { # support for old GCC versions
5938 return "Virt";
5939 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005940 }
5941 return "";
5942}
5943
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005944sub getFuncLink($)
5945{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005946 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5947 {
5948 if($Info=~/link[ ]*:[ ]*static /) {
5949 return "Static";
5950 }
5951 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005952 return $1;
5953 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005954 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005955 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005956}
5957
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005958sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005959{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005960 my ($Symbol, $LibVersion) = @_;
5961 return "" if(not $Symbol or not $LibVersion);
5962 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5963 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005964 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005965 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5966 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5967 }
5968 }
5969 if($NS)
5970 {
5971 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5972 return $NS;
5973 }
5974 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005975 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005976 while($NS=~s/::[^:]+\Z//)
5977 {
5978 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5979 return $NS;
5980 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005981 }
5982 }
5983 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005984
5985 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005986}
5987
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005988sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005989{
5990 my ($TypeName, $LibVersion) = @_;
5991 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005992 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005993 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005994 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5995 return $NS;
5996 }
5997 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005998 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005999 while($NS=~s/::[^:]+\Z//)
6000 {
6001 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6002 return $NS;
6003 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006004 }
6005 }
6006 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006007 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006008}
6009
6010sub getNameSpace($)
6011{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006012 my $InfoId = $_[0];
6013 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006014 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006015 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006016 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006017 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006018 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006019 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
6020 {
6021 my $NameSpace = getTreeStr($1);
6022 if($NameSpace eq "::")
6023 { # global namespace
6024 return "";
6025 }
6026 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
6027 $NameSpace = $BaseNameSpace."::".$NameSpace;
6028 }
6029 $NestedNameSpaces{$Version}{$NameSpace} = 1;
6030 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006031 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006032 else {
6033 return "";
6034 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006035 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006036 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006037 { # inside data type
6038 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6039 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006040 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006041 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006042 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006043 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006044}
6045
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006046sub getEnumMembVal($)
6047{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006048 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006049 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006050 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6051 {
6052 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6053 {
6054 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6055 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6056 return getTreeValue($1);
6057 }
6058 else
6059 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6060 return getTreeValue($1);
6061 }
6062 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006063 }
6064 }
6065 return "";
6066}
6067
6068sub getSize($)
6069{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006070 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6071 {
6072 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6073 return getTreeValue($1);
6074 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006075 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006076 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006077}
6078
6079sub getAlgn($)
6080{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006081 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6082 {
6083 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6084 return $1;
6085 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006086 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006087 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006088}
6089
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006090sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006091{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006092 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6093 {
6094 if($Info=~/ bitfield /) {
6095 return getSize($_[0]);
6096 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006097 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006098 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006099}
6100
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006101sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006102{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006103 if(my $Chan = getTreeAttr_Chan($_[0])) {
6104 return $Chan;
6105 }
6106 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6107 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006108 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006109 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006110}
6111
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006112sub registerHeader($$)
6113{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006114 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006115 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006116 return "";
6117 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006118 if(is_abs($Header) and not -f $Header)
6119 { # incorrect absolute path
6120 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006121 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006122 if(skipHeader($Header, $LibVersion))
6123 { # skip
6124 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006125 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006126 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6127 {
6128 detect_header_includes($Header_Path, $LibVersion);
6129
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006130 if(defined $Tolerance and $Tolerance=~/3/)
6131 { # 3 - skip headers that include non-Linux headers
6132 if($OSgroup ne "windows")
6133 {
6134 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6135 {
6136 if(specificHeader($Inc, "windows")) {
6137 return "";
6138 }
6139 }
6140 }
6141 }
6142
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006143 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6144 { # redirect
6145 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6146 or skipHeader($RHeader_Path, $LibVersion))
6147 { # skip
6148 return "";
6149 }
6150 $Header_Path = $RHeader_Path;
6151 }
6152 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6153 { # skip
6154 return "";
6155 }
6156
6157 if(my $HName = get_filename($Header_Path))
6158 { # register
6159 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6160 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6161 }
6162
6163 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6164 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006165 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006166 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006167 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006168 }
6169
6170 if($CheckHeadersOnly
6171 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6172 { # /usr/include/c++/4.6.1/...
6173 $STDCXX_TESTING = 1;
6174 }
6175
6176 return $Header_Path;
6177 }
6178 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006179}
6180
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006181sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006182{
6183 my ($Dir, $WithDeps, $LibVersion) = @_;
6184 $Dir=~s/[\/\\]+\Z//g;
6185 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006186 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006187
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006188 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006189 if($WithDeps)
6190 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006191 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6192 return;
6193 }
6194 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6195 $Mode = "DepsOnly";
6196 }
6197 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006198 else
6199 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006200 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6201 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6202 return;
6203 }
6204 }
6205 $Header_Dependency{$LibVersion}{$Dir} = 1;
6206 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6207 if($Mode eq "DepsOnly")
6208 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006209 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006210 $Header_Dependency{$LibVersion}{$Path} = 1;
6211 }
6212 return;
6213 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006214 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006215 {
6216 if($WithDeps)
6217 {
6218 my $SubDir = $Path;
6219 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6220 { # register all sub directories
6221 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6222 }
6223 }
6224 next if(is_not_header($Path));
6225 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006226 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006227 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006228 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6229 }
6230 }
6231 if(get_filename($Dir) eq "include")
6232 { # search for "lib/include/" directory
6233 my $LibDir = $Dir;
6234 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006235 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006236 }
6237 }
6238}
6239
6240sub parse_redirect($$$)
6241{
6242 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006243 my @Errors = ();
6244 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6245 push(@Errors, $1);
6246 }
6247 my $Redirect = "";
6248 foreach (@Errors)
6249 {
6250 s/\s{2,}/ /g;
6251 if(/(only|must\ include
6252 |update\ to\ include
6253 |replaced\ with
6254 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006255 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006256 {
6257 $Redirect = $2;
6258 last;
6259 }
6260 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6261 {
6262 $Redirect = $2;
6263 last;
6264 }
6265 elsif(/this\ header\ should\ not\ be\ used
6266 |programs\ should\ not\ directly\ include
6267 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6268 |is\ not\ supported\ API\ for\ general\ use
6269 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006270 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006271 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6272 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6273 }
6274 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006275 if($Redirect)
6276 {
6277 $Redirect=~s/\A<//g;
6278 $Redirect=~s/>\Z//g;
6279 }
6280 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006281}
6282
6283sub parse_includes($$)
6284{
6285 my ($Content, $Path) = @_;
6286 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006287 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006288 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006289 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006290 my $Method = substr($Header, 0, 1, "");
6291 substr($Header, length($Header)-1, 1, "");
6292 $Header = path_format($Header, $OSgroup);
6293 if($Method eq "\"" or is_abs($Header))
6294 {
6295 if(-e join_P(get_dirname($Path), $Header))
6296 { # relative path exists
6297 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006298 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006299 else
6300 { # include "..." that doesn't exist is equal to include <...>
6301 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006302 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006303 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006304 else {
6305 $Includes{$Header} = 1;
6306 }
6307 }
6308 if($ExtraInfo)
6309 {
6310 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6311 { # FT_FREETYPE_H
6312 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006313 }
6314 }
6315 return \%Includes;
6316}
6317
6318sub ignore_path($)
6319{
6320 my $Path = $_[0];
6321 if($Path=~/\~\Z/)
6322 {# skipping system backup files
6323 return 1;
6324 }
6325 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6326 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6327 return 1;
6328 }
6329 return 0;
6330}
6331
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006332sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006333{
6334 my ($ArrRef, $W) = @_;
6335 return if(length($W)<2);
6336 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6337}
6338
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006339sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006340{
6341 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006342
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006343 $H1=~s/\.[a-z]+\Z//ig;
6344 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006345
6346 my $Hname1 = get_filename($H1);
6347 my $Hname2 = get_filename($H2);
6348 my $HDir1 = get_dirname($H1);
6349 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006350 my $Dirname1 = get_filename($HDir1);
6351 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006352
6353 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6354 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6355
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006356 if($_[0] eq $_[1]
6357 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006358 return 0;
6359 }
6360 elsif($H1=~/\A\Q$H2\E/) {
6361 return 1;
6362 }
6363 elsif($H2=~/\A\Q$H1\E/) {
6364 return -1;
6365 }
6366 elsif($HDir1=~/\Q$Hname1\E/i
6367 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006368 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006369 return -1;
6370 }
6371 elsif($HDir2=~/\Q$Hname2\E/i
6372 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006373 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006374 return 1;
6375 }
6376 elsif($Hname1=~/\Q$Dirname1\E/i
6377 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006378 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006379 return -1;
6380 }
6381 elsif($Hname2=~/\Q$Dirname2\E/i
6382 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006383 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006384 return 1;
6385 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006386 elsif($Hname1=~/(config|lib|util)/i
6387 and $Hname2!~/(config|lib|util)/i)
6388 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006389 return -1;
6390 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006391 elsif($Hname2=~/(config|lib|util)/i
6392 and $Hname1!~/(config|lib|util)/i)
6393 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006394 return 1;
6395 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006396 else
6397 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006398 my $R1 = checkRelevance($H1);
6399 my $R2 = checkRelevance($H2);
6400 if($R1 and not $R2)
6401 { # libebook/e-book.h
6402 return -1;
6403 }
6404 elsif($R2 and not $R1)
6405 { # libebook/e-book.h
6406 return 1;
6407 }
6408 else
6409 {
6410 return (lc($H1) cmp lc($H2));
6411 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006412 }
6413}
6414
6415sub searchForHeaders($)
6416{
6417 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006418
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006419 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006420 registerGccHeaders();
6421
6422 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6423 { # c++ standard include paths
6424 registerCppHeaders();
6425 }
6426
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006427 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006428 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6429 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006430 {
6431 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006432 if($SystemRoot)
6433 {
6434 if(is_abs($Path)) {
6435 $Path = $SystemRoot.$Path;
6436 }
6437 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006438 if(not -e $Path) {
6439 exitStatus("Access_Error", "can't access \'$Path\'");
6440 }
6441 elsif(-f $Path) {
6442 exitStatus("Access_Error", "\'$Path\' - not a directory");
6443 }
6444 elsif(-d $Path)
6445 {
6446 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006447 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006448 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6449 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006450 }
6451 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006452 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006453 }
6454 }
6455 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006456 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006457 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6458 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006459
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006460 # registering directories
6461 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6462 {
6463 next if(not -e $Path);
6464 $Path = get_abs_path($Path);
6465 $Path = path_format($Path, $OSgroup);
6466 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006467 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006468 }
6469 elsif(-f $Path)
6470 {
6471 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006472 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006473 and not $LocalIncludes{$Dir})
6474 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006475 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006476 # if(my $OutDir = get_dirname($Dir))
6477 # { # registering the outer directory
6478 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6479 # and not $LocalIncludes{$OutDir}) {
6480 # registerDir($OutDir, 0, $LibVersion);
6481 # }
6482 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006483 }
6484 }
6485 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006486
6487 # clean memory
6488 %RegisteredDirs = ();
6489
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006490 # registering headers
6491 my $Position = 0;
6492 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6493 {
6494 if(is_abs($Dest) and not -e $Dest) {
6495 exitStatus("Access_Error", "can't access \'$Dest\'");
6496 }
6497 $Dest = path_format($Dest, $OSgroup);
6498 if(is_header($Dest, 1, $LibVersion))
6499 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006500 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006501 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6502 }
6503 }
6504 elsif(-d $Dest)
6505 {
6506 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006507 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006508 {
6509 next if(ignore_path($Path));
6510 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006511 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006512 push(@Registered, $HPath);
6513 }
6514 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006515 @Registered = sort {sortHeaders($a, $b)} @Registered;
6516 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006517 foreach my $Path (@Registered) {
6518 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6519 }
6520 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03006521 elsif(not defined $SkipUnidentified) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006522 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6523 }
6524 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006525
6526 if(defined $Tolerance and $Tolerance=~/4/)
6527 { # 4 - skip headers included by others
6528 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6529 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006530 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006531 delete($Registered_Headers{$LibVersion}{$Path});
6532 }
6533 }
6534 }
6535
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006536 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6537 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006538 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006539 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006540 if(is_abs($Header) and not -f $Header) {
6541 exitStatus("Access_Error", "can't access file \'$Header\'");
6542 }
6543 $Header = path_format($Header, $OSgroup);
6544 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6545 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006546 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006547 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006548 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03006549 elsif($SkipUnidentified) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006550 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6551 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006552 }
6553 }
6554 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6555 { # set relative paths (for duplicates)
6556 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6557 { # search for duplicates
6558 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6559 my $Prefix = get_dirname($FirstPath);
6560 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6561 { # detect a shortest distinguishing prefix
6562 my $NewPrefix = $1;
6563 my %Identity = ();
6564 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6565 {
6566 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6567 $Identity{$Path} = $1;
6568 }
6569 }
6570 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006571 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006572 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6573 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6574 }
6575 last;
6576 }
6577 $Prefix = $NewPrefix; # increase prefix
6578 }
6579 }
6580 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006581
6582 # clean memory
6583 %HeaderName_Paths = ();
6584
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006585 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6586 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006587 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006588 my ($Pos, $PairPos) = (-1, -1);
6589 my ($Path, $PairPath) = ();
6590 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6591 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6592 foreach my $Header_Path (@Paths)
6593 {
6594 if(get_filename($Header_Path) eq $PairName)
6595 {
6596 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6597 $PairPath = $Header_Path;
6598 }
6599 if(get_filename($Header_Path) eq $HeaderName)
6600 {
6601 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6602 $Path = $Header_Path;
6603 }
6604 }
6605 if($PairPos!=-1 and $Pos!=-1
6606 and int($PairPos)<int($Pos))
6607 {
6608 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6609 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6610 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6611 }
6612 }
6613 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6614 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6615 }
6616}
6617
6618sub detect_real_includes($$)
6619{
6620 my ($AbsPath, $LibVersion) = @_;
6621 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6622 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6623 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6624 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6625 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006626 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6627
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006628 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6629 return () if(not $Path);
6630 open(PREPROC, $Path);
6631 while(<PREPROC>)
6632 {
6633 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6634 {
6635 my $Include = path_format($1, $OSgroup);
6636 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6637 next;
6638 }
6639 if($Include eq $AbsPath) {
6640 next;
6641 }
6642 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6643 }
6644 }
6645 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006646 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6647}
6648
6649sub detect_header_includes($$)
6650{
6651 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006652 return if(not $LibVersion or not $Path);
6653 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6654 return;
6655 }
6656 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6657
6658 if(not -e $Path) {
6659 return;
6660 }
6661
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006662 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006663 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6664 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006665 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006666 {
6667 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006668 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006669 }
6670 if($RedirectPath ne $Path) {
6671 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6672 }
6673 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006674 else
6675 { # can't find
6676 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6677 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006678 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006679 if(my $Inc = parse_includes($Content, $Path))
6680 {
6681 foreach my $Include (keys(%{$Inc}))
6682 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006683 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006684
6685 if(defined $Tolerance and $Tolerance=~/4/)
6686 {
6687 if(my $HPath = identifyHeader($Include, $LibVersion))
6688 {
6689 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6690 }
6691 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006693 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006694}
6695
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006696sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006697{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006698 my $Path = $_[0];
6699 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006700 if($OStarget eq "symbian")
6701 {
6702 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6703 { # epoc32/include/libc/{stdio, ...}.h
6704 return 1;
6705 }
6706 }
6707 else
6708 {
6709 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6710 { # /usr/include/{stdio, ...}.h
6711 return 1;
6712 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006713 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006714 return 0;
6715}
6716
6717sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006718{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006719 my $Dir = $_[0];
6720 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006721 if($OStarget eq "symbian")
6722 {
6723 if(get_filename($OutDir) eq "libc"
6724 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6725 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6726 return 1;
6727 }
6728 }
6729 else
6730 { # linux
6731 if($OutDir eq "/usr/include"
6732 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6733 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6734 return 1;
6735 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006736 }
6737 return 0;
6738}
6739
6740sub detect_recursive_includes($$)
6741{
6742 my ($AbsPath, $LibVersion) = @_;
6743 return () if(not $AbsPath);
6744 if(isCyclical(\@RecurInclude, $AbsPath)) {
6745 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6746 }
6747 my ($AbsDir, $Name) = separate_path($AbsPath);
6748 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006749 { # system GLIBC internals
6750 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006751 }
6752 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6753 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6754 }
6755 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006756
6757 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6758 { # skip /usr/include/c++/*/ headers
6759 return () if(not $ExtraInfo);
6760 }
6761
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006762 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006763 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006764 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006765 { # check "real" (non-"model") include paths
6766 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6767 pop(@RecurInclude);
6768 return @Paths;
6769 }
6770 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6771 detect_header_includes($AbsPath, $LibVersion);
6772 }
6773 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6774 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006775 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006776 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006777 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006778 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006779 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006780 if(-f $Candidate) {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03006781 $HPath = realpath_F($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006782 }
6783 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006784 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006785 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006786 { # search for the nearest header
6787 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006788 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006789 if(-f $Candidate) {
6790 $HPath = $Candidate;
6791 }
6792 }
6793 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006794 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006795 }
6796 next if(not $HPath);
6797 if($HPath eq $AbsPath) {
6798 next;
6799 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006800
6801 if($Debug)
6802 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006803# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6804# {
6805# print STDERR "$AbsPath -> $HPath\n";
6806# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006807 }
6808
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006809 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6810 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006811 { # only include <...>, skip include "..." prefixes
6812 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6813 }
6814 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6815 {
6816 if($IncPath eq $AbsPath) {
6817 next;
6818 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006819 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6820 if($RIncType==-1)
6821 { # include "..."
6822 $RIncType = $IncType;
6823 }
6824 elsif($RIncType==2)
6825 {
6826 if($IncType!=-1) {
6827 $RIncType = $IncType;
6828 }
6829 }
6830 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006831 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6832 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6833 }
6834 }
6835 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6836 {
6837 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6838 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6839 { # distinguish math.h from glibc and math.h from the tested library
6840 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6841 last;
6842 }
6843 }
6844 }
6845 pop(@RecurInclude);
6846 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6847}
6848
6849sub find_in_framework($$$)
6850{
6851 my ($Header, $Framework, $LibVersion) = @_;
6852 return "" if(not $Header or not $Framework or not $LibVersion);
6853 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6854 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6855 }
6856 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6857 {
6858 if(get_filename($Dependency) eq $Framework
6859 and -f get_dirname($Dependency)."/".$Header) {
6860 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6861 }
6862 }
6863 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6864}
6865
6866sub find_in_defaults($)
6867{
6868 my $Header = $_[0];
6869 return "" if(not $Header);
6870 if(defined $Cache{"find_in_defaults"}{$Header}) {
6871 return $Cache{"find_in_defaults"}{$Header};
6872 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006873 foreach my $Dir (@DefaultIncPaths,
6874 @DefaultGccPaths,
6875 @DefaultCppPaths,
6876 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006877 {
6878 next if(not $Dir);
6879 if(-f $Dir."/".$Header) {
6880 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6881 }
6882 }
6883 return ($Cache{"find_in_defaults"}{$Header}="");
6884}
6885
6886sub cmp_paths($$)
6887{
6888 my ($Path1, $Path2) = @_;
6889 my @Parts1 = split(/[\/\\]/, $Path1);
6890 my @Parts2 = split(/[\/\\]/, $Path2);
6891 foreach my $Num (0 .. $#Parts1)
6892 {
6893 my $Part1 = $Parts1[$Num];
6894 my $Part2 = $Parts2[$Num];
6895 if($GlibcDir{$Part1}
6896 and not $GlibcDir{$Part2}) {
6897 return 1;
6898 }
6899 elsif($GlibcDir{$Part2}
6900 and not $GlibcDir{$Part1}) {
6901 return -1;
6902 }
6903 elsif($Part1=~/glib/
6904 and $Part2!~/glib/) {
6905 return 1;
6906 }
6907 elsif($Part1!~/glib/
6908 and $Part2=~/glib/) {
6909 return -1;
6910 }
6911 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6912 return $CmpRes;
6913 }
6914 }
6915 return 0;
6916}
6917
6918sub checkRelevance($)
6919{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006920 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006921 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006922
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006923 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006924 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006925 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006926
6927 my $Name = lc(get_filename($Path));
6928 my $Dir = lc(get_dirname($Path));
6929
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006930 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006931
6932 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006933 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006934 my $Len = length($Token);
6935 next if($Len<=1);
6936 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6937 { # include/evolution-data-server-1.4/libebook/e-book.h
6938 return 1;
6939 }
6940 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006941 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006942 return 1;
6943 }
6944 }
6945 return 0;
6946}
6947
6948sub checkFamily(@)
6949{
6950 my @Paths = @_;
6951 return 1 if($#Paths<=0);
6952 my %Prefix = ();
6953 foreach my $Path (@Paths)
6954 {
6955 if($SystemRoot) {
6956 $Path = cut_path_prefix($Path, $SystemRoot);
6957 }
6958 if(my $Dir = get_dirname($Path))
6959 {
6960 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6961 $Prefix{$Dir} += 1;
6962 $Prefix{get_dirname($Dir)} += 1;
6963 }
6964 }
6965 foreach (sort keys(%Prefix))
6966 {
6967 if(get_depth($_)>=3
6968 and $Prefix{$_}==$#Paths+1) {
6969 return 1;
6970 }
6971 }
6972 return 0;
6973}
6974
6975sub isAcceptable($$$)
6976{
6977 my ($Header, $Candidate, $LibVersion) = @_;
6978 my $HName = get_filename($Header);
6979 if(get_dirname($Header))
6980 { # with prefix
6981 return 1;
6982 }
6983 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6984 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6985 return 1;
6986 }
6987 if(checkRelevance($Candidate))
6988 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6989 return 1;
6990 }
6991 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6992 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6993 # /usr/include/qt4/Qt/qsslconfiguration.h
6994 return 1;
6995 }
6996 if($OStarget eq "symbian")
6997 {
6998 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6999 return 1;
7000 }
7001 }
7002 return 0;
7003}
7004
7005sub isRelevant($$$)
7006{ # disallow to search for "abstract" headers in too deep directories
7007 my ($Header, $Candidate, $LibVersion) = @_;
7008 my $HName = get_filename($Header);
7009 if($OStarget eq "symbian")
7010 {
7011 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
7012 return 0;
7013 }
7014 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007015 if($OStarget ne "bsd")
7016 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007017 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
7018 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
7019 return 0;
7020 }
7021 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007022 if($OStarget ne "windows")
7023 {
7024 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
7025 { # skip /usr/include/wine/msvcrt
7026 return 0;
7027 }
7028 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007029 if(not get_dirname($Header)
7030 and $Candidate=~/[\/\\]wx[\/\\]/)
7031 { # do NOT search in system /wx/ directory
7032 # for headers without a prefix: sstream.h
7033 return 0;
7034 }
7035 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7036 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7037 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7038 return 0;
7039 }
7040 if($Candidate=~/[\/\\]asm-/
7041 and (my $Arch = getArch($LibVersion)) ne "unknown")
7042 { # arch-specific header files
7043 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7044 {# skip ../asm-arm/ if using x86 architecture
7045 return 0;
7046 }
7047 }
7048 my @Candidates = getSystemHeaders($HName, $LibVersion);
7049 if($#Candidates==1)
7050 { # unique header
7051 return 1;
7052 }
7053 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7054 if($#SCandidates==1)
7055 { # unique name
7056 return 1;
7057 }
7058 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7059 if(get_depth($Candidate)-$SystemDepth>=5)
7060 { # abstract headers in too deep directories
7061 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7062 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7063 return 0;
7064 }
7065 }
7066 if($Header eq "parser.h"
7067 and $Candidate!~/\/libxml2\//)
7068 { # select parser.h from xml2 library
7069 return 0;
7070 }
7071 if(not get_dirname($Header)
7072 and keys(%{$SystemHeaders{$HName}})>=3)
7073 { # many headers with the same name
7074 # like thread.h included without a prefix
7075 if(not checkFamily(@Candidates)) {
7076 return 0;
7077 }
7078 }
7079 return 1;
7080}
7081
7082sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007083{ # cache function
7084 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7085 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7086 }
7087 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7088}
7089
7090sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007091{
7092 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007093 if(-f $Header) {
7094 return $Header;
7095 }
7096 if(is_abs($Header) and not -f $Header)
7097 { # incorrect absolute path
7098 return "";
7099 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007100 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007101 { # too abstract configuration headers
7102 return "";
7103 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007104 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007105 if($OSgroup ne "windows")
7106 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007107 if(defined $WinHeaders{lc($HName)}
7108 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007109 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007110 return "";
7111 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007112 }
7113 if($OSgroup ne "macos")
7114 {
7115 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007116 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007117 return "";
7118 }
7119 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007120
7121 if(defined $ObsoleteHeaders{$HName})
7122 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007123 return "";
7124 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007125 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7126 {
7127 if(defined $AlienHeaders{$HName}
7128 or defined $AlienHeaders{$Header})
7129 { # alien headers from other systems
7130 return "";
7131 }
7132 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007133
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007134 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007135 { # search in default paths
7136 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007137 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007138 }
7139 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007140 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007141 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007142 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007143 }
7144 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7145 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7146 {
7147 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007148 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007149 }
7150 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007151 # error
7152 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007153}
7154
7155sub getSystemHeaders($$)
7156{
7157 my ($Header, $LibVersion) = @_;
7158 my @Candidates = ();
7159 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7160 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007161 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007162 next;
7163 }
7164 push(@Candidates, $Candidate);
7165 }
7166 return @Candidates;
7167}
7168
7169sub cut_path_prefix($$)
7170{
7171 my ($Path, $Prefix) = @_;
7172 return $Path if(not $Prefix);
7173 $Prefix=~s/[\/\\]+\Z//;
7174 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7175 return $Path;
7176}
7177
7178sub is_default_include_dir($)
7179{
7180 my $Dir = $_[0];
7181 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007182 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007183}
7184
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007185sub identifyHeader($$)
7186{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007187 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007188 if(not $Header) {
7189 return "";
7190 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007191 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007192 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7193 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007194 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007195 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007196}
7197
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007198sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007199{ # search for header by absolute path, relative path or name
7200 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007201 if(-f $Header)
7202 { # it's relative or absolute path
7203 return get_abs_path($Header);
7204 }
7205 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7206 and my $HeaderDir = find_in_defaults($Header))
7207 { # search for libc headers in the /usr/include
7208 # for non-libc target library before searching
7209 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007210 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007211 }
7212 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7213 { # search in the target library paths
7214 return $Path;
7215 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007216 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007217 { # search in the internal GCC include paths
7218 return $DefaultGccHeader{$Header};
7219 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007220 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007221 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007222 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007223 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007224 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007225 { # search in the default G++ include paths
7226 return $DefaultCppHeader{$Header};
7227 }
7228 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7229 { # search everywhere in the system
7230 return $AnyPath;
7231 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007232 elsif($OSgroup eq "macos")
7233 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7234 if(my $Dir = get_dirname($Header))
7235 {
7236 my $RelPath = "Headers\/".get_filename($Header);
7237 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007238 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007239 }
7240 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007241 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007242 # cannot find anything
7243 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007244}
7245
7246sub getLocation($)
7247{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007248 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7249 {
7250 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007251 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007253 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007254 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007255}
7256
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007257sub getNameByInfo($)
7258{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007259 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007260 {
7261 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7262 {
7263 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7264 {
7265 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7266 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007267 my $Str = $1;
7268 if($CppMode{$Version}
7269 and $Str=~/\Ac99_(.+)\Z/)
7270 {
7271 if($CppKeywords_A{$1}) {
7272 $Str=$1;
7273 }
7274 }
7275 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007276 }
7277 }
7278 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007279 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007280 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007281}
7282
7283sub getTreeStr($)
7284{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007285 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007286 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007287 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7288 {
7289 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007290 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007291 and $Str=~/\Ac99_(.+)\Z/)
7292 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007293 if($CppKeywords_A{$1}) {
7294 $Str=$1;
7295 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007296 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007297 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007298 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007299 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007300 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007301}
7302
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007303sub getFuncShortName($)
7304{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007305 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007306 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007307 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007308 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007309 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007310 {
7311 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7312 {
7313 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7314 return "operator ".$RName;
7315 }
7316 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007317 }
7318 else
7319 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007320 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7321 {
7322 if(my $Ind = $Operator_Indication{$1}) {
7323 return "operator".$Ind;
7324 }
7325 elsif(not $UnknownOperator{$1})
7326 {
7327 printMsg("WARNING", "unknown operator $1");
7328 $UnknownOperator{$1} = 1;
7329 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007330 }
7331 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007332 }
7333 else
7334 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007335 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7336 return getTreeStr($1);
7337 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007338 }
7339 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007340 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007341}
7342
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007343sub getFuncReturn($)
7344{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007345 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7346 {
7347 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7348 {
7349 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7350 return $1;
7351 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007352 }
7353 }
7354 return "";
7355}
7356
7357sub getFuncOrig($)
7358{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007359 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7360 {
7361 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7362 return $1;
7363 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007364 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007365 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007366}
7367
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007368sub unmangleArray(@)
7369{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007370 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007371 { # MSVC mangling
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007372 if(defined $DisabledMSVCUnmangling) {
7373 return @_;
7374 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007375 my $UndNameCmd = get_CmdPath("undname");
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007376 if(not $UndNameCmd)
7377 {
7378 if($OSgroup eq "windows") {
7379 exitStatus("Not_Found", "can't find \"undname\"");
7380 }
7381 elsif(not defined $DisabledMSVCUnmangling)
7382 {
7383 printMsg("WARNING", "can't find \"undname\", disable MSVC unmangling");
7384 $DisabledMSVCUnmangling = 1;
7385 return @_;
7386 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007387 }
7388 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007389 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007390 }
7391 else
7392 { # GCC mangling
7393 my $CppFiltCmd = get_CmdPath("c++filt");
7394 if(not $CppFiltCmd) {
7395 exitStatus("Not_Found", "can't find c++filt in PATH");
7396 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007397 if(not defined $CPPFILT_SUPPORT_FILE)
7398 {
7399 my $Info = `$CppFiltCmd -h 2>&1`;
7400 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7401 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007402 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007403 if($CPPFILT_SUPPORT_FILE)
7404 { # new versions of c++filt can take a file
7405 if($#_>$MAX_CPPFILT_FILE_SIZE)
7406 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7407 # this is fixed in the oncoming version of Binutils
7408 my @Half = splice(@_, 0, ($#_+1)/2);
7409 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007410 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007411 else
7412 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007413 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7414 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7415 if($?==139)
7416 { # segmentation fault
7417 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7418 }
7419 return split(/\n/, $Res);
7420 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007421 }
7422 else
7423 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007424 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7425 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007426 my @Half = splice(@_, 0, ($#_+1)/2);
7427 return (unmangleArray(@Half), unmangleArray(@_))
7428 }
7429 else
7430 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007431 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007432 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7433 if($?==139)
7434 { # segmentation fault
7435 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7436 }
7437 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007438 }
7439 }
7440 }
7441}
7442
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007443sub get_ChargeLevel($$)
7444{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007445 my ($Symbol, $LibVersion) = @_;
7446 return "" if($Symbol!~/\A(_Z|\?)/);
7447 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7448 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007449 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007450 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007451 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007452 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007453 return "[in-charge]";
7454 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007455 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007456 return "[not-in-charge]";
7457 }
7458 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007459 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007460 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007461 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007462 return "[in-charge]";
7463 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007464 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007465 return "[not-in-charge]";
7466 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007467 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007468 return "[in-charge-deleting]";
7469 }
7470 }
7471 }
7472 else
7473 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007474 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007475 return "[in-charge]";
7476 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007477 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007478 return "[not-in-charge]";
7479 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007480 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007481 return "[in-charge]";
7482 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007483 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007484 return "[not-in-charge]";
7485 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007486 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007487 return "[in-charge-deleting]";
7488 }
7489 }
7490 return "";
7491}
7492
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007493sub get_Signature_M($$)
7494{
7495 my ($Symbol, $LibVersion) = @_;
7496 my $Signature_M = $tr_name{$Symbol};
7497 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7498 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007499 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007500 }
7501 return $Signature_M;
7502}
7503
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007504sub get_Signature($$)
7505{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007506 my ($Symbol, $LibVersion) = @_;
7507 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7508 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007509 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007510 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007511 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03007512
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007513 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007514
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007515 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007516 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007517 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7518 {
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007519 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
7520 $ClassName=~s/\bstruct //g;
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007521
7522 if(index($Symbol, "_ZTV")==0) {
7523 return "vtable for $ClassName [data]";
7524 }
7525
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007526 $Signature .= $ClassName."::";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007527 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7528 $Signature .= "~";
7529 }
7530 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007531 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007532 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007533 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007534 }
7535 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007536 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007537 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007538 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7539 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007540 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007541 else
7542 {
7543 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007544 }
7545 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007546 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007547 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007548 if($Pos eq "") {
7549 next;
7550 }
7551
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007552 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007553 if(not $ParamTypeId) {
7554 next;
7555 }
7556
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007557 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007558 if(not $ParamTypeName) {
7559 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7560 }
7561 foreach my $Typedef (keys(%ChangedTypedef))
7562 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007563 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7564 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7565 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007566 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007567 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7568 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007569 if($ParamName eq "this"
7570 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007571 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007572 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007573 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007574 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007575 }
7576 else {
7577 push(@ParamArray, $ParamTypeName);
7578 }
7579 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007580 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7581 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007582 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007583 }
7584 else
7585 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007586 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007587 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007588 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007589 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007590 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007591 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7592 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007593 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007594 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007595 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7596 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007597 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007598 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007599 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7600 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007601 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007602 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007603 }
7604 }
7605 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007606 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007607 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007608 }
7609 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007610 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007611 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007612 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007613}
7614
7615sub create_member_decl($$)
7616{
7617 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007618 if($TName=~/\([\*]+\)/)
7619 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007620 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7621 return $TName;
7622 }
7623 else
7624 {
7625 my @ArraySizes = ();
7626 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7627 push(@ArraySizes, $1);
7628 }
7629 return $TName." ".$Member.join("", @ArraySizes);
7630 }
7631}
7632
7633sub getFuncType($)
7634{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007635 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7636 {
7637 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7638 {
7639 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7640 {
7641 if($Type eq "method_type") {
7642 return "Method";
7643 }
7644 elsif($Type eq "function_type") {
7645 return "Function";
7646 }
7647 else {
7648 return "Other";
7649 }
7650 }
7651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007652 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007653 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007654}
7655
7656sub getFuncTypeId($)
7657{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007658 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7659 {
7660 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7661 return $1;
7662 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007663 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007664 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007665}
7666
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007667sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007668{ # "._N" or "$_N" in older GCC versions
7669 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007670}
7671
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007672sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007673{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007674 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7675 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007676 }
7677
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007678 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007679
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007680 if($_[1] ne "S")
7681 {
7682 $N=~s/\A[ ]+//g;
7683 $N=~s/[ ]+\Z//g;
7684 $N=~s/[ ]{2,}/ /g;
7685 }
7686
7687 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007688
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007689 $N=~s/\b(const|volatile) ([\w\:]+)([\*&,>]|\Z)/$2 $1$3/g; # "const void" to "void const"
7690
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007691 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007692
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007693 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7694 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007695
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007696 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007697
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007698 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007699
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007700 if($_[1] eq "S")
7701 {
7702 if(index($N, "operator")!=-1) {
7703 $N=~s/\b(operator[ ]*)> >/$1>>/;
7704 }
7705 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007706
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +03007707 $N=~s/,([^ ])/, $1/g;
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007708
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007709 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007710}
7711
7712sub get_HeaderDeps($$)
7713{
7714 my ($AbsPath, $LibVersion) = @_;
7715 return () if(not $AbsPath or not $LibVersion);
7716 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7717 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7718 }
7719 my %IncDir = ();
7720 detect_recursive_includes($AbsPath, $LibVersion);
7721 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7722 {
7723 next if(not $HeaderPath);
7724 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7725 my $Dir = get_dirname($HeaderPath);
7726 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7727 {
7728 my $Dep = $Dir;
7729 if($Prefix)
7730 {
7731 if($OSgroup eq "windows")
7732 { # case insensitive seach on windows
7733 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7734 next;
7735 }
7736 }
7737 elsif($OSgroup eq "macos")
7738 { # seach in frameworks
7739 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7740 {
7741 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7742 {# frameworks
7743 my ($HFramework, $HName) = ($1, $2);
7744 $Dep = $HFramework;
7745 }
7746 else
7747 {# mismatch
7748 next;
7749 }
7750 }
7751 }
7752 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7753 { # Linux, FreeBSD
7754 next;
7755 }
7756 }
7757 if(not $Dep)
7758 { # nothing to include
7759 next;
7760 }
7761 if(is_default_include_dir($Dep))
7762 { # included by the compiler
7763 next;
7764 }
7765 if(get_depth($Dep)==1)
7766 { # too short
7767 next;
7768 }
7769 if(isLibcDir($Dep))
7770 { # do NOT include /usr/include/{sys,bits}
7771 next;
7772 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007773 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007774 }
7775 }
7776 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7777 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7778}
7779
7780sub sortIncPaths($$)
7781{
7782 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007783 if(not $ArrRef or $#{$ArrRef}<0) {
7784 return $ArrRef;
7785 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007786 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7787 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007788 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007789 return $ArrRef;
7790}
7791
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007792sub sortDeps($$$)
7793{
7794 if($Header_Dependency{$_[2]}{$_[0]}
7795 and not $Header_Dependency{$_[2]}{$_[1]}) {
7796 return 1;
7797 }
7798 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7799 and $Header_Dependency{$_[2]}{$_[1]}) {
7800 return -1;
7801 }
7802 return 0;
7803}
7804
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007805sub join_P($$)
7806{
7807 my $S = "/";
7808 if($OSgroup eq "windows") {
7809 $S = "\\";
7810 }
7811 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007812}
7813
7814sub get_namespace_additions($)
7815{
7816 my $NameSpaces = $_[0];
7817 my ($Additions, $AddNameSpaceId) = ("", 1);
7818 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7819 {
7820 next if($SkipNameSpaces{$Version}{$NS});
7821 next if(not $NS or $NameSpaces->{$NS}==-1);
7822 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7823 next if($NS=~/\A__/i);
7824 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007825 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007826 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7827 my @NS_Parts = split(/::/, $NS);
7828 next if($#NS_Parts==-1);
7829 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7830 foreach my $NS_Part (@NS_Parts)
7831 {
7832 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7833 $TypeDecl_Suffix .= "}";
7834 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007835 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007836 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7837 $Additions.=" $TypeDecl\n $FuncDecl\n";
7838 $AddNameSpaceId+=1;
7839 }
7840 return $Additions;
7841}
7842
7843sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007844{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007845 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007846 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007847 if($Fmt eq "windows")
7848 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007849 $Path=~s/\//\\/g;
7850 $Path=lc($Path);
7851 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007852 else
7853 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007854 $Path=~s/\\/\//g;
7855 }
7856 return $Path;
7857}
7858
7859sub inc_opt($$)
7860{
7861 my ($Path, $Style) = @_;
7862 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007863 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007864 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007865 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007866 return "-I\"".path_format($Path, "unix")."\"";
7867 }
7868 elsif($OSgroup eq "macos"
7869 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007870 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007871 return "-F".esc(get_dirname($Path));
7872 }
7873 else {
7874 return "-I".esc($Path);
7875 }
7876 }
7877 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007878 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007879 }
7880 return "";
7881}
7882
7883sub platformSpecs($)
7884{
7885 my $LibVersion = $_[0];
7886 my $Arch = getArch($LibVersion);
7887 if($OStarget eq "symbian")
7888 { # options for GCCE compiler
7889 my %Symbian_Opts = map {$_=>1} (
7890 "-D__GCCE__",
7891 "-DUNICODE",
7892 "-fexceptions",
7893 "-D__SYMBIAN32__",
7894 "-D__MARM_INTERWORK__",
7895 "-D_UNICODE",
7896 "-D__S60_50__",
7897 "-D__S60_3X__",
7898 "-D__SERIES60_3X__",
7899 "-D__EPOC32__",
7900 "-D__MARM__",
7901 "-D__EABI__",
7902 "-D__MARM_ARMV5__",
7903 "-D__SUPPORT_CPP_EXCEPTIONS__",
7904 "-march=armv5t",
7905 "-mapcs",
7906 "-mthumb-interwork",
7907 "-DEKA2",
7908 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7909 );
7910 return join(" ", keys(%Symbian_Opts));
7911 }
7912 elsif($OSgroup eq "windows"
7913 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7914 { # add options to MinGW compiler
7915 # to simulate the MSVC compiler
7916 my %MinGW_Opts = map {$_=>1} (
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007917 "-D__unaligned=\" \"",
7918 "-D__nullptr=\"nullptr\"",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007919 "-D_WIN32",
7920 "-D_STDCALL_SUPPORTED",
7921 "-D__int64=\"long long\"",
7922 "-D__int32=int",
7923 "-D__int16=short",
7924 "-D__int8=char",
7925 "-D__possibly_notnullterminated=\" \"",
7926 "-D__nullterminated=\" \"",
7927 "-D__nullnullterminated=\" \"",
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007928 "-D__assume=\" \"",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007929 "-D__w64=\" \"",
7930 "-D__ptr32=\" \"",
7931 "-D__ptr64=\" \"",
7932 "-D__forceinline=inline",
7933 "-D__inline=inline",
7934 "-D__uuidof(x)=IID()",
7935 "-D__try=",
7936 "-D__except(x)=",
7937 "-D__declspec(x)=__attribute__((x))",
7938 "-D__pragma(x)=",
7939 "-D_inline=inline",
7940 "-D__forceinline=__inline",
7941 "-D__stdcall=__attribute__((__stdcall__))",
7942 "-D__cdecl=__attribute__((__cdecl__))",
7943 "-D__fastcall=__attribute__((__fastcall__))",
7944 "-D__thiscall=__attribute__((__thiscall__))",
7945 "-D_stdcall=__attribute__((__stdcall__))",
7946 "-D_cdecl=__attribute__((__cdecl__))",
7947 "-D_fastcall=__attribute__((__fastcall__))",
7948 "-D_thiscall=__attribute__((__thiscall__))",
7949 "-DSHSTDAPI_(x)=x",
7950 "-D_MSC_EXTENSIONS",
7951 "-DSECURITY_WIN32",
7952 "-D_MSC_VER=1500",
7953 "-D_USE_DECLSPECS_FOR_SAL",
7954 "-D__noop=\" \"",
7955 "-DDECLSPEC_DEPRECATED=\" \"",
7956 "-D__builtin_alignof(x)=__alignof__(x)",
7957 "-DSORTPP_PASS");
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007958 if($Arch eq "x86")
7959 {
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007960 $MinGW_Opts{"-D_X86_=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007961 $MinGW_Opts{"-D_M_IX86=300"}=1;
7962 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007963 elsif($Arch eq "x86_64")
7964 {
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007965 $MinGW_Opts{"-D_AMD64_=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007966 $MinGW_Opts{"-D_M_AMD64=300"}=1;
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007967 $MinGW_Opts{"-D_M_X64=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007968 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007969 elsif($Arch eq "ia64")
7970 {
7971 $MinGW_Opts{"-D_IA64_=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007972 $MinGW_Opts{"-D_M_IA64=300"}=1;
7973 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007974 return join(" ", sort keys(%MinGW_Opts));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007975 }
7976 return "";
7977}
7978
7979my %C_Structure = map {$_=>1} (
7980# FIXME: Can't separate union and struct data types before dumping,
7981# so it sometimes cause compilation errors for unknown reason
7982# when trying to declare TYPE* tmp_add_class_N
7983# This is a list of such structures + list of other C structures
7984 "sigval",
7985 "sigevent",
7986 "sigaction",
7987 "sigvec",
7988 "sigstack",
7989 "timeval",
7990 "timezone",
7991 "rusage",
7992 "rlimit",
7993 "wait",
7994 "flock",
7995 "stat",
7996 "_stat",
7997 "stat32",
7998 "_stat32",
7999 "stat64",
8000 "_stat64",
8001 "_stati64",
8002 "if_nameindex",
8003 "usb_device",
8004 "sigaltstack",
8005 "sysinfo",
8006 "timeLocale",
8007 "tcp_debug",
8008 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008009 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008010 "timespec",
8011 "random_data",
8012 "drand48_data",
8013 "_IO_marker",
8014 "_IO_FILE",
8015 "lconv",
8016 "sched_param",
8017 "tm",
8018 "itimerspec",
8019 "_pthread_cleanup_buffer",
8020 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008021 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008022 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008023 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008024 "sigcontext",
8025 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008026 # Mac
8027 "_timex",
8028 "_class_t",
8029 "_category_t",
8030 "_class_ro_t",
8031 "_protocol_t",
8032 "_message_ref_t",
8033 "_super_message_ref_t",
8034 "_ivar_t",
8035 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008036);
8037
8038sub getCompileCmd($$$)
8039{
8040 my ($Path, $Opt, $Inc) = @_;
8041 my $GccCall = $GCC_PATH;
8042 if($Opt) {
8043 $GccCall .= " ".$Opt;
8044 }
8045 $GccCall .= " -x ";
8046 if($OSgroup eq "macos") {
8047 $GccCall .= "objective-";
8048 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04008049
8050 if($EMERGENCY_MODE_48)
8051 { # workaround for GCC 4.8 (C only)
8052 $GccCall .= "c++";
8053 }
8054 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008055 { # compile as "C++" header
8056 # to obtain complete dump using GCC 4.0
8057 $GccCall .= "c++-header";
8058 }
8059 else
8060 { # compile as "C++" source
8061 # GCC 3.3 cannot compile headers
8062 $GccCall .= "c++";
8063 }
8064 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008065 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008066 $GccCall .= " ".$Opts;
8067 }
8068 # allow extra qualifications
8069 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008070 $GccCall .= " -fpermissive";
8071 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008072 if($NoStdInc)
8073 {
8074 $GccCall .= " -nostdinc";
8075 $GccCall .= " -nostdinc++";
8076 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008077 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008078 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008079 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008080 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008081 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008082 if($Inc)
8083 { # include paths
8084 $GccCall .= " ".$Inc;
8085 }
8086 return $GccCall;
8087}
8088
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008089sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008090{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008091 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008092 my %HeaderElems = (
8093 # Types
8094 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008095 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008096 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8097 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008098 "time.h" => ["time_t"],
8099 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008100 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8101 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008102 "stdbool.h" => ["_Bool"],
8103 "rpc/xdr.h" => ["bool_t"],
8104 "in_systm.h" => ["n_long", "n_short"],
8105 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008106 "arpa/inet.h" => ["fw_src", "ip_src"],
8107 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008108 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008109 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008110 );
8111 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008112 foreach (keys(%HeaderElems))
8113 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008114 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008115 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008116 }
8117 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008118 my %Types = ();
8119 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8120 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008121 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008122 }
8123 if(keys(%Types))
8124 {
8125 my %AddHeaders = ();
8126 foreach my $Type (keys(%Types))
8127 {
8128 if(my $Header = $AutoPreamble{$Type})
8129 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008130 if(my $Path = identifyHeader($Header, $LibVersion))
8131 {
8132 if(skipHeader($Path, $LibVersion)) {
8133 next;
8134 }
8135 $Path = path_format($Path, $OSgroup);
8136 $AddHeaders{$Path}{"Type"} = $Type;
8137 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008138 }
8139 }
8140 }
8141 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008142 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008143 }
8144 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008145 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008146}
8147
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008148sub checkCTags($)
8149{
8150 my $Path = $_[0];
8151 if(not $Path) {
8152 return;
8153 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008154 my $CTags = undef;
8155
8156 if($OSgroup eq "bsd")
8157 { # use ectags on BSD
8158 $CTags = get_CmdPath("ectags");
8159 if(not $CTags) {
8160 printMsg("WARNING", "can't find \'ectags\' program");
8161 }
8162 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008163 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008164 $CTags = get_CmdPath("ctags");
8165 }
8166 if(not $CTags)
8167 {
8168 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008169 return;
8170 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008171
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008172 if($OSgroup ne "linux")
8173 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008174 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8175 if($Info!~/exuberant/i)
8176 {
8177 printMsg("WARNING", "incompatible version of \'ctags\' program");
8178 return;
8179 }
8180 }
8181
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008182 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008183 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008184 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008185 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008186 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008187 open(CTAGS, "<", $Out);
8188 while(my $Line = <CTAGS>)
8189 {
8190 chomp($Line);
8191 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008192 if(defined $Intrinsic_Keywords{$Name})
8193 { # noise
8194 next;
8195 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008196 if($Type eq "n")
8197 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008198 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008199 next;
8200 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008201 if(index($Scpe, "struct:")==0) {
8202 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008203 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008204 if(index($Scpe, "namespace:")==0)
8205 {
8206 if($Scpe=~s/\Anamespace://) {
8207 $Name = $Scpe."::".$Name;
8208 }
8209 }
8210 $TUnit_NameSpaces{$Version}{$Name} = 1;
8211 }
8212 elsif($Type eq "p")
8213 {
8214 if(not $Scpe or index($Scpe, "namespace:")==0) {
8215 $TUnit_Funcs{$Version}{$Name} = 1;
8216 }
8217 }
8218 elsif($Type eq "x")
8219 {
8220 if(not $Scpe or index($Scpe, "namespace:")==0) {
8221 $TUnit_Vars{$Version}{$Name} = 1;
8222 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008223 }
8224 }
8225 close(CTAGS);
8226}
8227
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008228sub preChange($$)
8229{
8230 my ($HeaderPath, $IncStr) = @_;
8231
8232 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8233 my $Content = undef;
8234
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008235 if(not defined $MinGWCompat and $OStarget eq "windows"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008236 and get_dumpmachine($GCC_PATH)=~/mingw/i
8237 and $MinGWMode{$Version}!=-1)
8238 { # modify headers to compile by MinGW
8239 if(not $Content)
8240 { # preprocessing
8241 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8242 }
8243 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8244 { # __asm { ... }
8245 $MinGWMode{$Version}=1;
8246 }
8247 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8248 { # comments after preprocessing
8249 $MinGWMode{$Version}=1;
8250 }
8251 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8252 { # 0xffui8
8253 $MinGWMode{$Version}=1;
8254 }
8255
8256 if($MinGWMode{$Version}) {
8257 printMsg("INFO", "Using MinGW compatibility mode");
8258 }
8259 }
8260
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008261 if(defined $CxxIncompat and ($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8262 and $CppMode{$Version}!=-1 and not $CPP_HEADERS)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008263 { # rename C++ keywords in C code
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008264 printMsg("INFO", "Checking the code for C++ keywords");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008265 if(not $Content)
8266 { # preprocessing
8267 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8268 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008269
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008270 my $RegExp_C = join("|", keys(%CppKeywords_C));
8271 my $RegExp_F = join("|", keys(%CppKeywords_F));
8272 my $RegExp_O = join("|", keys(%CppKeywords_O));
8273
8274 my $Detected = undef;
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008275 my $Sentence_O = undef;
8276 my $Sentence_N = undef;
8277 my $Regex = undef;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008278
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008279 $Regex = qr/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*([\,\)\;\.\[]|\-\>|\:\s*\d))/;
8280 while($Content=~/$Regex/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008281 { # MATCH:
8282 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008283 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008284 # unsigned private: 8;
8285 # DO NOT MATCH:
8286 # #pragma GCC visibility push(default)
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008287 $Sentence_O = "$1$2$3$4";
8288 $Sentence_N = "$1$2c99_$3$4";
8289
8290 if($Sentence_O=~/\s+decltype\(/)
8291 { # C++
8292 # decltype(nullptr)
8293 last;
8294 }
8295 else
8296 {
8297 $Content=~s/$Regex/$Sentence_N/g;
8298 $CppMode{$Version} = 1;
8299 if(not defined $Detected) {
8300 $Detected = $Sentence_O;
8301 }
8302 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008303 }
8304 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8305 { # MATCH:
8306 # int delete(...);
8307 # int explicit(...);
8308 # DO NOT MATCH:
8309 # void operator delete(...)
8310 $CppMode{$Version} = 1;
8311 $Detected = "$1$2$3" if(not defined $Detected);
8312 }
8313 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8314 { # MATCH:
8315 # int bool;
8316 # DO NOT MATCH:
8317 # bool X;
8318 # return *this;
8319 # throw;
8320 $CppMode{$Version} = 1;
8321 $Detected = "$1$2$3" if(not defined $Detected);
8322 }
8323 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8324 { # MATCH:
8325 # int operator(...);
8326 # DO NOT MATCH:
8327 # int operator()(...);
8328 $CppMode{$Version} = 1;
8329 $Detected = "$1$2$3" if(not defined $Detected);
8330 }
8331 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8332 { # MATCH:
8333 # int foo(int operator);
8334 # int foo(int operator, int other);
8335 # DO NOT MATCH:
8336 # int operator,(...);
8337 $CppMode{$Version} = 1;
8338 $Detected = "$1$2$3" if(not defined $Detected);
8339 }
8340 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8341 { # MATCH:
8342 # int foo(gboolean *bool);
8343 # DO NOT MATCH:
8344 # void setTabEnabled(int index, bool);
8345 $CppMode{$Version} = 1;
8346 $Detected = "$1$2$3" if(not defined $Detected);
8347 }
8348 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8349 { # MATCH:
8350 # int foo(int* this);
8351 # int bar(int this);
8352 # int baz(int throw);
8353 # DO NOT MATCH:
8354 # foo(X, this);
8355 $CppMode{$Version} = 1;
8356 $Detected = "$1$2$3$4" if(not defined $Detected);
8357 }
8358 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8359 { # MATCH:
8360 # struct template {...};
8361 # extern template foo(...);
8362 $CppMode{$Version} = 1;
8363 $Detected = "$1$2" if(not defined $Detected);
8364 }
8365
8366 if($CppMode{$Version} == 1)
8367 {
8368 if($Debug)
8369 {
8370 $Detected=~s/\A\s+//g;
8371 printMsg("INFO", "Detected code: \"$Detected\"");
8372 }
8373 }
8374
8375 # remove typedef enum NAME NAME;
8376 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8377 my $N = 0;
8378 while($N<=$#FwdTypedefs-1)
8379 {
8380 my $S = $FwdTypedefs[$N];
8381 if($S eq $FwdTypedefs[$N+1])
8382 {
8383 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008384 $CppMode{$Version} = 1;
8385
8386 if($Debug) {
8387 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8388 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008389 }
8390 $N+=2;
8391 }
8392
8393 if($CppMode{$Version}==1) {
8394 printMsg("INFO", "Using C++ compatibility mode");
8395 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008396 else {
8397 printMsg("INFO", "C++ keywords in the C code are not found");
8398 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008399 }
8400
8401 if($CppMode{$Version}==1
8402 or $MinGWMode{$Version}==1)
8403 {
8404 my $IPath = $TMP_DIR."/dump$Version.i";
8405 writeFile($IPath, $Content);
8406 return $IPath;
8407 }
8408
8409 return undef;
8410}
8411
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008412sub getDump()
8413{
8414 if(not $GCC_PATH) {
8415 exitStatus("Error", "internal error - GCC path is not set");
8416 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008417
8418 my @Headers = keys(%{$Registered_Headers{$Version}});
8419 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8420
8421 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8422
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008423 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008424 my $HeaderPath = $TmpHeaderPath;
8425
8426 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008427 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008428 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8429 {
8430 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008431 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008432 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008433 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008434 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8435 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008436 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008437 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008438 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008439 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8440 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8441 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008442 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008443 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008444
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008445 if($ExtraInfo)
8446 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008447 if($IncludeString) {
8448 writeFile($ExtraInfo."/include-string", $IncludeString);
8449 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008450 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8451 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008452
8453 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8454 {
8455 my $REDIR = "";
8456 foreach my $P1 (sort @Redirects) {
8457 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8458 }
8459 writeFile($ExtraInfo."/include-redirect", $REDIR);
8460 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008461 }
8462
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008463 if(not keys(%{$TargetHeaders{$Version}}))
8464 { # Target headers
8465 addTargetHeaders($Version);
8466 }
8467
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008468 # clean memory
8469 %RecursiveIncludes = ();
8470 %Header_Include_Prefix = ();
8471 %Header_Includes = ();
8472
8473 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008474 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008475 delete($Cache{"detect_header_includes"});
8476 delete($Cache{"selectSystemHeader"});
8477
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008478 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008479 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8480 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008481
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008482 if($ExtraInfo)
8483 { # extra information for other tools
8484 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8485 }
8486
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008487 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008488 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008489 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008490
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008491 if($COMMON_LANGUAGE{$Version} eq "C++") {
8492 checkCTags($Pre);
8493 }
8494
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008495 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8496 { # try to correct the preprocessor output
8497 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008498 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008499
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008500 if($COMMON_LANGUAGE{$Version} eq "C++")
8501 { # add classes and namespaces to the dump
8502 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008503 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008504 or $MinGWMode{$Version}==1) {
8505 $CHdump .= " -fpreprocessed";
8506 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008507 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008508 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008509 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008510 chdir($ORIG_DIR);
8511 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8512 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008513 my $Content = readFile($ClassDump);
8514 foreach my $ClassInfo (split(/\n\n/, $Content))
8515 {
8516 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8517 {
8518 my $CName = $1;
8519 next if($CName=~/\A(__|_objc_|_opaque_)/);
8520 $TUnit_NameSpaces{$Version}{$CName} = -1;
8521 if($CName=~/\A[\w:]+\Z/)
8522 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008523 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008524 }
8525 if($CName=~/(\w[\w:]*)::/)
8526 { # namespaces
8527 my $NS = $1;
8528 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8529 $TUnit_NameSpaces{$Version}{$NS} = 1;
8530 }
8531 }
8532 }
8533 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8534 { # read v-tables (advanced approach)
8535 my ($CName, $VTable) = ($1, $2);
8536 $ClassVTable_Content{$Version}{$CName} = $VTable;
8537 }
8538 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008539 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8540 { # add user-defined namespaces
8541 $TUnit_NameSpaces{$Version}{$NS} = 1;
8542 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008543 if($Debug)
8544 { # debug mode
8545 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008546 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008547 }
8548 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008549 }
8550
8551 # add namespaces and classes
8552 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8553 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008554 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008555 }
8556 # some GCC versions don't include class methods to the TU dump by default
8557 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008558 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008559 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8560 {
8561 next if($C_Structure{$CName});
8562 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008563 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008564 if(not $Force and $GCC_44
8565 and $OSgroup eq "linux")
8566 { # optimization for linux with GCC >= 4.4
8567 # disable this code by -force option
8568 if(index($CName, "::")!=-1)
8569 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008570 next;
8571 }
8572 }
8573 else
8574 {
8575 if($CName=~/\A(.+)::[^:]+\Z/
8576 and $TUnit_Classes{$Version}{$1})
8577 { # classes inside other classes
8578 next;
8579 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008580 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008581 if(defined $TUnit_Funcs{$Version}{$CName})
8582 { # the same name for a function and type
8583 next;
8584 }
8585 if(defined $TUnit_Vars{$Version}{$CName})
8586 { # the same name for a variable and type
8587 next;
8588 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008589 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8590 }
8591 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008592 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008593 }
8594 }
8595 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8596 # create TU dump
8597 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008598 if($UserLang eq "C") {
8599 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8600 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008601 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008602 or $MinGWMode{$Version}==1) {
8603 $TUdump .= " -fpreprocessed";
8604 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008605 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008606 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8607 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008608 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008609 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008610 if($?)
8611 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008612 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008613 { # try to recompile
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008614 # FIXME: handle errors and try to recompile
8615 if($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008616 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008617 { # add auto preamble headers and try again
8618 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008619 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008620 foreach my $Num (0 .. $#Headers)
8621 {
8622 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008623 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8624 {
8625 push_U($Include_Preamble{$Version}, $Path);
8626 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008627 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008628 }
8629 resetLogging($Version);
8630 $TMP_DIR = tempdir(CLEANUP=>1);
8631 return getDump();
8632 }
8633 elsif($Cpp0xMode{$Version}!=-1
8634 and ($Errors=~/\Q-std=c++0x\E/
8635 or $Errors=~/is not a class or namespace/))
8636 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008637 if(check_gcc($GCC_PATH, "4.6"))
8638 {
8639 $Cpp0xMode{$Version}=-1;
8640 printMsg("INFO", "Enabling c++0x mode");
8641 resetLogging($Version);
8642 $TMP_DIR = tempdir(CLEANUP=>1);
8643 $CompilerOptions{$Version} .= " -std=c++0x";
8644 return getDump();
8645 }
8646 else {
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008647 printMsg("WARNING", "Probably c++0x element detected");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008648 }
8649
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008650 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008651 #elsif($MinGWMode{$Version}==1)
8652 #{ # disable MinGW mode and try again
8653 # $MinGWMode{$Version}=-1;
8654 # resetLogging($Version);
8655 # $TMP_DIR = tempdir(CLEANUP=>1);
8656 # return getDump();
8657 #}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008658 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008659 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008660 else {
8661 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008662 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008663 printMsg("ERROR", "some errors occurred when compiling headers");
8664 printErrorLog($Version);
8665 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008666 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008667 }
8668 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008669 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008670 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008671
8672 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8673 return $TUs[0];
8674 }
8675 else
8676 {
8677 my $Msg = "can't compile header(s)";
8678 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8679 $Msg .= "\nDid you install G++?";
8680 }
8681 exitStatus("Cannot_Compile", $Msg);
8682 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008683}
8684
8685sub cmd_file($)
8686{
8687 my $Path = $_[0];
8688 return "" if(not $Path or not -e $Path);
8689 if(my $CmdPath = get_CmdPath("file")) {
8690 return `$CmdPath -b \"$Path\"`;
8691 }
8692 return "";
8693}
8694
8695sub getIncString($$)
8696{
8697 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008698 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008699 my $String = "";
8700 foreach (@{$ArrRef}) {
8701 $String .= " ".inc_opt($_, $Style);
8702 }
8703 return $String;
8704}
8705
8706sub getIncPaths(@)
8707{
8708 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008709 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008710 if($INC_PATH_AUTODETECT{$Version})
8711 { # auto-detecting dependencies
8712 my %Includes = ();
8713 foreach my $HPath (@HeaderPaths)
8714 {
8715 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8716 {
8717 if($Skip_Include_Paths{$Version}{$Dir}) {
8718 next;
8719 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008720 if($SystemRoot)
8721 {
8722 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8723 next;
8724 }
8725 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008726 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008727 }
8728 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008729 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008730 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008731 }
8732 }
8733 else
8734 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008735 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008736 }
8737 return \@IncPaths;
8738}
8739
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008740sub push_U($@)
8741{ # push unique
8742 if(my $Array = shift @_)
8743 {
8744 if(@_)
8745 {
8746 my %Exist = map {$_=>1} @{$Array};
8747 foreach my $Elem (@_)
8748 {
8749 if(not defined $Exist{$Elem})
8750 {
8751 push(@{$Array}, $Elem);
8752 $Exist{$Elem} = 1;
8753 }
8754 }
8755 }
8756 }
8757}
8758
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008759sub callPreprocessor($$$)
8760{
8761 my ($Path, $Inc, $LibVersion) = @_;
8762 return "" if(not $Path or not -f $Path);
8763 my $IncludeString=$Inc;
8764 if(not $Inc) {
8765 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8766 }
8767 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008768 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008769 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008770 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008771}
8772
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008773sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008774{ # native "find" is much faster than File::Find (~6x)
8775 # also the File::Find doesn't support --maxdepth N option
8776 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008777 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008778 return () if(not $Path or not -e $Path);
8779 if($OSgroup eq "windows")
8780 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008781 $Path = get_abs_path($Path);
8782 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008783 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008784 if($MaxDepth!=1) {
8785 $Cmd .= " /S";
8786 }
8787 if($Type eq "d") {
8788 $Cmd .= " /AD";
8789 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008790 elsif($Type eq "f") {
8791 $Cmd .= " /A-D";
8792 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008793 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008794 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008795 {
8796 if(not $UseRegex)
8797 { # FIXME: how to search file names in MS shell?
8798 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008799 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008800 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008801 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008802 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008803 }
8804 my @AbsPaths = ();
8805 foreach my $File (@Files)
8806 {
8807 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008808 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008809 }
8810 if($Type eq "f" and not -f $File)
8811 { # skip dirs
8812 next;
8813 }
8814 push(@AbsPaths, path_format($File, $OSgroup));
8815 }
8816 if($Type eq "d") {
8817 push(@AbsPaths, $Path);
8818 }
8819 return @AbsPaths;
8820 }
8821 else
8822 {
8823 my $FindCmd = get_CmdPath("find");
8824 if(not $FindCmd) {
8825 exitStatus("Not_Found", "can't find a \"find\" command");
8826 }
8827 $Path = get_abs_path($Path);
8828 if(-d $Path and -l $Path
8829 and $Path!~/\/\Z/)
8830 { # for directories that are symlinks
8831 $Path.="/";
8832 }
8833 my $Cmd = $FindCmd." \"$Path\"";
8834 if($MaxDepth) {
8835 $Cmd .= " -maxdepth $MaxDepth";
8836 }
8837 if($Type) {
8838 $Cmd .= " -type $Type";
8839 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008840 if($Name and not $UseRegex)
8841 { # wildcards
8842 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008843 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008844 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008845 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008846 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8847 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008848 my @Files = split(/\n/, $Res);
8849 if($Name and $UseRegex)
8850 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008851 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008852 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008853 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008854 }
8855}
8856
8857sub unpackDump($)
8858{
8859 my $Path = $_[0];
8860 return "" if(not $Path or not -e $Path);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008861
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008862 $Path = get_abs_path($Path);
8863 $Path = path_format($Path, $OSgroup);
8864 my ($Dir, $FileName) = separate_path($Path);
8865 my $UnpackDir = $TMP_DIR."/unpack";
8866 rmtree($UnpackDir);
8867 mkpath($UnpackDir);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008868
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008869 if($FileName=~s/\Q.zip\E\Z//g)
8870 { # *.zip
8871 my $UnzipCmd = get_CmdPath("unzip");
8872 if(not $UnzipCmd) {
8873 exitStatus("Not_Found", "can't find \"unzip\" command");
8874 }
8875 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008876 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008877 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008878 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008879 }
8880 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008881 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008882 if(not @Contents) {
8883 exitStatus("Error", "can't extract \'$Path\'");
8884 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008885 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008886 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008887 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008888 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008889 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008890 if($OSgroup eq "windows")
8891 { # -xvzf option is not implemented in tar.exe (2003)
8892 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8893 my $TarCmd = get_CmdPath("tar");
8894 if(not $TarCmd) {
8895 exitStatus("Not_Found", "can't find \"tar\" command");
8896 }
8897 my $GzipCmd = get_CmdPath("gzip");
8898 if(not $GzipCmd) {
8899 exitStatus("Not_Found", "can't find \"gzip\" command");
8900 }
8901 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008902 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008903 if($?) {
8904 exitStatus("Error", "can't extract \'$Path\'");
8905 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008906 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008907 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008908 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008909 }
8910 chdir($ORIG_DIR);
8911 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008912 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008913 if(not @Contents) {
8914 exitStatus("Error", "can't extract \'$Path\'");
8915 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008916 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008917 }
8918 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008919 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008920 my $TarCmd = get_CmdPath("tar");
8921 if(not $TarCmd) {
8922 exitStatus("Not_Found", "can't find \"tar\" command");
8923 }
8924 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008925 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008926 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008927 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008928 }
8929 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008930 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008931 if(not @Contents) {
8932 exitStatus("Error", "can't extract \'$Path\'");
8933 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008934 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008935 }
8936 }
8937}
8938
8939sub createArchive($$)
8940{
8941 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008942 if(not $To) {
8943 $To = ".";
8944 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008945 if(not $Path or not -e $Path
8946 or not -d $To) {
8947 return "";
8948 }
8949 my ($From, $Name) = separate_path($Path);
8950 if($OSgroup eq "windows")
8951 { # *.zip
8952 my $ZipCmd = get_CmdPath("zip");
8953 if(not $ZipCmd) {
8954 exitStatus("Not_Found", "can't find \"zip\"");
8955 }
8956 my $Pkg = $To."/".$Name.".zip";
8957 unlink($Pkg);
8958 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008959 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008960 if($?)
8961 { # cannot allocate memory (or other problems with "zip")
8962 unlink($Path);
8963 exitStatus("Error", "can't pack the ABI dump: ".$!);
8964 }
8965 chdir($ORIG_DIR);
8966 unlink($Path);
8967 return $Pkg;
8968 }
8969 else
8970 { # *.tar.gz
8971 my $TarCmd = get_CmdPath("tar");
8972 if(not $TarCmd) {
8973 exitStatus("Not_Found", "can't find \"tar\"");
8974 }
8975 my $GzipCmd = get_CmdPath("gzip");
8976 if(not $GzipCmd) {
8977 exitStatus("Not_Found", "can't find \"gzip\"");
8978 }
8979 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8980 unlink($Pkg);
8981 chdir($From);
8982 system($TarCmd, "-czf", $Pkg, $Name);
8983 if($?)
8984 { # cannot allocate memory (or other problems with "tar")
8985 unlink($Path);
8986 exitStatus("Error", "can't pack the ABI dump: ".$!);
8987 }
8988 chdir($ORIG_DIR);
8989 unlink($Path);
8990 return $To."/".$Name.".tar.gz";
8991 }
8992}
8993
8994sub is_header_file($)
8995{
8996 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8997 return $_[0];
8998 }
8999 return 0;
9000}
9001
9002sub is_not_header($)
9003{
9004 if($_[0]=~/\.\w+\Z/
9005 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
9006 return 1;
9007 }
9008 return 0;
9009}
9010
9011sub is_header($$$)
9012{
9013 my ($Header, $UserDefined, $LibVersion) = @_;
9014 return 0 if(-d $Header);
9015 if(-f $Header) {
9016 $Header = get_abs_path($Header);
9017 }
9018 else
9019 {
9020 if(is_abs($Header))
9021 { # incorrect absolute path
9022 return 0;
9023 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009024 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009025 $Header = $HPath;
9026 }
9027 else
9028 { # can't find header
9029 return 0;
9030 }
9031 }
9032 if($Header=~/\.\w+\Z/)
9033 { # have an extension
9034 return is_header_file($Header);
9035 }
9036 else
9037 {
9038 if($UserDefined==2)
9039 { # specified on the command line
9040 if(cmd_file($Header)!~/HTML|XML/i) {
9041 return $Header;
9042 }
9043 }
9044 elsif($UserDefined)
9045 { # specified in the XML-descriptor
9046 # header file without an extension
9047 return $Header;
9048 }
9049 else
9050 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04009051 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009052 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009053 { # !~/HTML|XML|shared|dynamic/i
9054 return $Header;
9055 }
9056 }
9057 }
9058 return 0;
9059}
9060
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009061sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009062{
9063 my $LibVersion = $_[0];
9064 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9065 {
9066 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009067 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009068
9069 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9070 detect_recursive_includes($RegHeader, $LibVersion);
9071 }
9072
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009073 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9074 {
9075 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009076
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009077 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009078 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9079 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009080 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009081 }
9082 }
9083 }
9084}
9085
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009086sub familiarDirs($$)
9087{
9088 my ($D1, $D2) = @_;
9089 if($D1 eq $D2) {
9090 return 1;
9091 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009092
9093 my $U1 = index($D1, "/usr/");
9094 my $U2 = index($D2, "/usr/");
9095
9096 if($U1==0 and $U2!=0) {
9097 return 0;
9098 }
9099
9100 if($U2==0 and $U1!=0) {
9101 return 0;
9102 }
9103
9104 if(index($D2, $D1."/")==0) {
9105 return 1;
9106 }
9107
9108 # /usr/include/DIR
9109 # /home/user/DIR
9110
9111 my $DL = get_depth($D1);
9112
9113 my @Dirs1 = ($D1);
9114 while($DL - get_depth($D1)<=2
9115 and get_depth($D1)>=4
9116 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9117 push(@Dirs1, $D1);
9118 }
9119
9120 my @Dirs2 = ($D2);
9121 while(get_depth($D2)>=4
9122 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9123 push(@Dirs2, $D2);
9124 }
9125
9126 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009127 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009128 foreach my $P2 (@Dirs2)
9129 {
9130
9131 if($P1 eq $P2) {
9132 return 1;
9133 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009134 }
9135 }
9136 return 0;
9137}
9138
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009139sub readHeaders($)
9140{
9141 $Version = $_[0];
9142 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9143 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009144 if($Debug)
9145 { # debug mode
9146 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009147 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009148 }
9149 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009150}
9151
9152sub prepareTypes($)
9153{
9154 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009155 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009156 { # support for old ABI dumps
9157 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009158 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009159 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009160 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9161 if($TName=~/\A(\w+)::(\w+)/) {
9162 my ($P1, $P2) = ($1, $2);
9163 if($P1 eq $P2) {
9164 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009165 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009166 else {
9167 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9168 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009169 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009170 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009171 }
9172 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009173 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009174 { # support for old ABI dumps
9175 # V < 2.5: array size == "number of elements"
9176 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009177 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009178 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009179 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009180 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009181 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009182 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009183 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009184 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009185 $Size *= $Base{"Size"};
9186 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009187 }
9188 else
9189 { # array[] is a pointer
9190 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009191 }
9192 }
9193 }
9194 }
9195 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009196 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009197 { # support for old ABI dumps
9198 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009199 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009200 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009201 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009202 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009203 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009204 my %Type = get_Type($TypeId, $LibVersion);
9205 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9206 my %Type2 = get_Type($TypeId_2, $V2);
9207 if($Type{"Size"} ne $Type2{"Size"}) {
9208 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009209 }
9210 }
9211 }
9212 }
9213}
9214
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009215sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009216{
9217 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009218
9219 if(not keys(%{$SymbolInfo{$LibVersion}}))
9220 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009221 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009222 {
9223 if($CheckHeadersOnly) {
9224 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9225 }
9226 else {
9227 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9228 }
9229 }
9230 }
9231
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009232 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009233 if(not checkDump(1, "2.10")
9234 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009235 { # different formats
9236 $Remangle = 1;
9237 }
9238 if($CheckHeadersOnly)
9239 { # different languages
9240 if($UserLang)
9241 { # --lang=LANG for both versions
9242 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9243 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9244 {
9245 if($UserLang eq "C++")
9246 { # remangle symbols
9247 $Remangle = 1;
9248 }
9249 elsif($UserLang eq "C")
9250 { # remove mangling
9251 $Remangle = -1;
9252 }
9253 }
9254 }
9255 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009256
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009257 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009258 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009259 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009260 { # support for old ABI dumps
9261 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9262 {
9263 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9264 {
9265 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9266 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009267 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009268 if(defined $DVal and $DVal ne "")
9269 {
9270 if($TName eq "char") {
9271 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9272 }
9273 elsif($TName eq "bool") {
9274 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9275 }
9276 }
9277 }
9278 }
9279 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009280 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009281 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009282 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9283 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009284 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009285 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9286 # + support for old ABI dumps
9287 next;
9288 }
9289 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009290 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009291 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009292 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009293 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009294
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009295 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009296 if(not checkDump(1, "2.12")
9297 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009298 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009299 if($ShortName eq "operator>>")
9300 {
9301 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9302 { # corrected mangling of operator>>
9303 $SRemangle = 1;
9304 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009305 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009306 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9307 {
9308 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9309 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9310 { # corrected mangling of const global data
9311 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9312 # and incorrectly mangled by old ACC versions
9313 $SRemangle = 1;
9314 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009315 }
9316 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009317 if(not $CheckHeadersOnly)
9318 { # support for old ABI dumps
9319 if(not checkDump(1, "2.17")
9320 or not checkDump(2, "2.17"))
9321 {
9322 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9323 {
9324 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9325 {
9326 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9327 {
9328 $MnglName = $ShortName;
9329 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9330 }
9331 }
9332 }
9333 }
9334 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009335 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009336 { # support for old ABI dumps: some symbols are not mangled in old dumps
9337 # mangle both sets of symbols (old and new)
9338 # NOTE: remangling all symbols by the same mangler
9339 if($MnglName=~/\A_ZN(V|)K/)
9340 { # mangling may be incorrect on old ABI dumps
9341 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009342 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009343 }
9344 if($MnglName=~/\A_ZN(K|)V/)
9345 { # mangling may be incorrect on old ABI dumps
9346 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009347 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009348 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009349 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9350 or (not $ClassID and $CheckHeadersOnly)
9351 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9352 { # support for old ABI dumps, GCC >= 4.0
9353 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009354 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009355 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009356 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009357 $MangledNames{$LibVersion}{$MnglName} = 1;
9358 }
9359 }
9360 }
9361 elsif($Remangle==-1)
9362 { # remove mangling
9363 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009364 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009365 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009366 if(not $MnglName) {
9367 next;
9368 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009369
9370 # NOTE: duplicated entries in the ABI Dump
9371 if(defined $CompleteSignature{$LibVersion}{$MnglName})
9372 {
9373 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9374 {
9375 if($SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} eq "p1")
9376 {
9377 next;
9378 }
9379 }
9380 }
9381
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009382 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9383 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009384 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9385
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009386 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009387 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009388 { # support for old dumps
9389 # add "Volatile" attribute
9390 if($MnglName=~/_Z(K|)V/) {
9391 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9392 }
9393 }
9394 # symbol and its symlink have same signatures
9395 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009396 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009397 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009398
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009399 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9400 {
9401 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009402
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009403 if($SymVer{$LibVersion}{$Alias}) {
9404 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9405 }
9406 }
9407
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009408 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009409 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009410 }
9411 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9412 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9413 }
9414 if($ExtendedCheck)
9415 { # --ext option
9416 addExtension($LibVersion);
9417 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009418
9419 # clean memory
9420 delete($SymbolInfo{$LibVersion});
9421
9422 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009423 { # detect allocable classes with public exported constructors
9424 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009425 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009426 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009427 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009428 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009429 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9430 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009431 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009432 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009433 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009434 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009435 $AllocableClass{$LibVersion}{$ClassName} = 1;
9436 }
9437 }
9438 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009439 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009440 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009441 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009442 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009443 if($CheckHeadersOnly)
9444 {
9445 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9446 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9447 { # all symbols except non-virtual inline
9448 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9449 }
9450 }
9451 else {
9452 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009453 }
9454 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009455 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009456 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009457 }
9458 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009459 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009460 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009461 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009462 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009463 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009464 if(defined $Base{"Type"}
9465 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009466 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009467 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009468 if($Name=~/<([^<>\s]+)>/)
9469 {
9470 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9471 $ReturnedClass{$LibVersion}{$Tid} = 1;
9472 }
9473 }
9474 else {
9475 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9476 }
9477 }
9478 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009479 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009480 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009481 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009482 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009483 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009484 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009485 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009486 if($Base{"Type"}=~/Struct|Class/)
9487 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009488 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009489 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9490 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009491 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009492 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009493 }
9494 }
9495 }
9496 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009497
9498 # mapping {short name => symbols}
9499 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009500 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009501 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009502 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009503 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009504 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009505 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009506 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009507 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9508 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009509 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009510 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009511 }
9512 }
9513 }
9514 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009515
9516 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009517 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009518 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009519 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009520 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009521 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9522 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009523 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009524 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009525 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009526 $ClassNames{$LibVersion}{$TName} = 1;
9527 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009528 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009529 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9530 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009531 }
9532 }
9533 }
9534 }
9535 }
9536}
9537
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009538sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009539{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009540 my ($Tid, $LibVersion) = @_;
9541 if(not $Tid) {
9542 return $Tid;
9543 }
9544
9545 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9546 {
9547 if($TName_Tid{$LibVersion}{$Name}) {
9548 return $TName_Tid{$LibVersion}{$Name};
9549 }
9550 }
9551
9552 return $Tid;
9553}
9554
9555sub register_SymbolUsage($$$)
9556{
9557 my ($InfoId, $UsedType, $LibVersion) = @_;
9558
9559 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9560 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9561 {
9562 register_TypeUsage($RTid, $UsedType, $LibVersion);
9563 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9564 }
9565 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9566 {
9567 register_TypeUsage($FCid, $UsedType, $LibVersion);
9568 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9569
9570 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9571 { # register "this" pointer
9572 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9573 }
9574 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9575 { # register "this" pointer (const method)
9576 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9577 }
9578 }
9579 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9580 {
9581 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9582 {
9583 register_TypeUsage($PTid, $UsedType, $LibVersion);
9584 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9585 }
9586 }
9587 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9588 {
9589 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9590 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9591 register_TypeUsage($TTid, $UsedType, $LibVersion);
9592 }
9593 }
9594}
9595
9596sub register_TypeUsage($$$)
9597{
9598 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009599 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009600 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009601 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009602 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009603 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009604 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009605 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009606
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009607 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009608 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009609 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009610 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009611 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009612 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9613 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9614 }
9615 }
9616
9617 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9618 {
9619 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009620 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009621 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009622 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9623 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009624 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009625 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9626 {
9627 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9628 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009629 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009630 }
9631 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009632 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009633 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009634 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009635 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9636 {
9637 register_TypeUsage($MTid, $UsedType, $LibVersion);
9638 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009639 }
9640 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009641 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009642 or $TInfo{"Type"} eq "MethodPtr"
9643 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009644 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009645 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009646 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009647 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009648 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009649 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009650 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9651 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009652 }
9653 }
9654 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009655 if($TInfo{"Type"} eq "FieldPtr")
9656 {
9657 if(my $RTid = $TInfo{"Return"}) {
9658 register_TypeUsage($RTid, $UsedType, $LibVersion);
9659 }
9660 if(my $CTid = $TInfo{"Class"}) {
9661 register_TypeUsage($CTid, $UsedType, $LibVersion);
9662 }
9663 }
9664 if($TInfo{"Type"} eq "MethodPtr")
9665 {
9666 if(my $CTid = $TInfo{"Class"}) {
9667 register_TypeUsage($CTid, $UsedType, $LibVersion);
9668 }
9669 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009670 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009671 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009672 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009673 $UsedType->{$TypeId} = 1;
9674 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9675 {
9676 register_TypeUsage($BTid, $UsedType, $LibVersion);
9677 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9678 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009679 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009680 else
9681 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9682 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009683 }
9684 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009685}
9686
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009687sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009688{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009689 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9690
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009691 if($Level eq "Dump")
9692 {
9693 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9694 { # TODO: check if this symbol is from
9695 # base classes of other target symbols
9696 return 1;
9697 }
9698 }
9699
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009700 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9701 { # stdc++ interfaces
9702 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009703 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009704
9705 my $Target = 0;
9706 if(my $Header = $SInfo->{"Header"}) {
9707 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9708 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009709 if($ExtendedCheck)
9710 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009711 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009712 $Target = 1;
9713 }
9714 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009715 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009716 {
9717 if($Target)
9718 {
9719 if($Level eq "Dump")
9720 { # dumped
9721 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009722 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009723 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009724 return 1;
9725 }
9726 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009727 else {
9728 return 1;
9729 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009730 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009731 elsif($Level eq "Source")
9732 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009733 return 1;
9734 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009735 elsif($Level eq "Binary")
9736 { # checked
9737 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9738 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9739 return 1;
9740 }
9741 }
9742 }
9743 }
9744 else
9745 { # library is available
9746 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9747 { # exported symbols
9748 return 1;
9749 }
9750 if($Level eq "Dump")
9751 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009752 if($BinaryOnly)
9753 {
9754 if($SInfo->{"Data"})
9755 {
9756 if($Target) {
9757 return 1;
9758 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009759 }
9760 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009761 else
9762 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009763 if($Target) {
9764 return 1;
9765 }
9766 }
9767 }
9768 elsif($Level eq "Source")
9769 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009770 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009771 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009772 { # skip LOCAL symbols
9773 if($Target) {
9774 return 1;
9775 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009776 }
9777 }
9778 elsif($Level eq "Binary")
9779 { # checked
9780 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9781 {
9782 if($Target) {
9783 return 1;
9784 }
9785 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009786 }
9787 }
9788 return 0;
9789}
9790
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009791sub cleanDump($)
9792{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009793 my $LibVersion = $_[0];
9794 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9795 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009796 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9797 {
9798 delete($SymbolInfo{$LibVersion}{$InfoId});
9799 next;
9800 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009801 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009802 if(not $MnglName)
9803 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009804 delete($SymbolInfo{$LibVersion}{$InfoId});
9805 next;
9806 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009807 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009808 if(not $ShortName)
9809 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009810 delete($SymbolInfo{$LibVersion}{$InfoId});
9811 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009812 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009813 if($MnglName eq $ShortName)
9814 { # remove duplicate data
9815 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009816 }
9817 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9818 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9819 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009820 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9821 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9822 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009823 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009824 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009825 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009826 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009827 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9828 {
9829 delete($TypeInfo{$LibVersion}{$Tid});
9830 next;
9831 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009832 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009833 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009834 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009835 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9836 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9837 }
9838 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009839 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9840 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9841 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009842 }
9843}
9844
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009845sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009846{
9847 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009848
9849 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9850 {
9851 if(defined $TypeInfo{$LibVersion}{$Dupl})
9852 {
9853 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9854 { # duplicate
9855 return 0;
9856 }
9857 }
9858 }
9859
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009860 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9861
9862 if(isBuiltIn($THeader)) {
9863 return 0;
9864 }
9865
9866 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9867 return 0;
9868 }
9869
9870 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9871 return 0;
9872 }
9873
9874 if(selfTypedef($Tid, $LibVersion)) {
9875 return 0;
9876 }
9877
9878 if(not isTargetType($Tid, $LibVersion)) {
9879 return 0;
9880 }
9881
9882 return 0;
9883}
9884
9885sub isTargetType($$)
9886{
9887 my ($Tid, $LibVersion) = @_;
9888
9889 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9890 { # derived
9891 return 1;
9892 }
9893
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009894 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009895 { # NOTE: header is defined to source if undefined (DWARF dumps)
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009896 if(not is_target_header($THeader, $LibVersion))
9897 { # from target headers
9898 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009899 }
9900 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009901 else
9902 { # NOTE: if type is defined in source
9903 if($UsedDump{$LibVersion}{"Public"})
9904 {
9905 if(isPrivateABI($Tid, $LibVersion)) {
9906 return 0;
9907 }
9908 else {
9909 return 1;
9910 }
9911 }
9912 else {
9913 return 0;
9914 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +03009915 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009916
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +03009917 if($SkipInternalTypes)
9918 {
9919 if($TypeInfo{$LibVersion}{$Tid}{"Name"}=~/($SkipInternalTypes)/)
9920 {
9921 return 0;
9922 }
9923 }
9924
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009925 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009926}
9927
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009928sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009929{ # remove unused data types from the ABI dump
9930 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009931
9932 my %UsedType = ();
9933
9934 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009935 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009936 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009937 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009938 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009939 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009940 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009941 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009942 next;
9943 }
9944
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009945 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009946 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009947 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009948 {
9949 my %Tree = ();
9950 register_TypeUsage($Tid, \%Tree, $LibVersion);
9951
9952 my $Tmpl = 0;
9953 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9954 {
9955 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9956 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9957 {
9958 $Tmpl = 1;
9959 last;
9960 }
9961 }
9962 if(not $Tmpl)
9963 {
9964 foreach (keys(%Tree)) {
9965 $UsedType{$_} = 1;
9966 }
9967 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009968 }
9969 }
9970 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009971
9972 my %Delete = ();
9973
9974 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009975 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009976 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009977 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009978 next;
9979 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009980
9981 if($Kind eq "Extra")
9982 {
9983 my %Tree = ();
9984 register_TypeUsage($Tid, \%Tree, $LibVersion);
9985
9986 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9987 {
9988 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9989 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9990 {
9991 $Delete{$Tid} = 1;
9992 last;
9993 }
9994 }
9995 }
9996 else
9997 {
9998 # remove type
9999 delete($TypeInfo{$LibVersion}{$Tid});
10000 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010001 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010002
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010003 if($Kind eq "Extra")
10004 { # remove duplicates
10005 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
10006 {
10007 if($UsedType{$Tid})
10008 { # All & Extended
10009 next;
10010 }
10011
10012 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10013
10014 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
10015 delete($TypeInfo{$LibVersion}{$Tid});
10016 }
10017 }
10018 }
10019
10020 foreach my $Tid (keys(%Delete))
10021 {
10022 delete($TypeInfo{$LibVersion}{$Tid});
10023 }
10024}
10025
10026sub check_Completeness($$)
10027{
10028 my ($Info, $LibVersion) = @_;
10029
10030 # data types
10031 if(defined $Info->{"Memb"})
10032 {
10033 foreach my $Pos (keys(%{$Info->{"Memb"}}))
10034 {
10035 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
10036 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
10037 }
10038 }
10039 }
10040 if(defined $Info->{"Base"})
10041 {
10042 foreach my $Bid (keys(%{$Info->{"Base"}})) {
10043 check_TypeInfo($Bid, $LibVersion);
10044 }
10045 }
10046 if(defined $Info->{"BaseType"}) {
10047 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
10048 }
10049 if(defined $Info->{"TParam"})
10050 {
10051 foreach my $Pos (keys(%{$Info->{"TParam"}}))
10052 {
10053 my $TName = $Info->{"TParam"}{$Pos}{"name"};
10054 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
10055 next;
10056 }
10057 if($TName eq "_BoolType") {
10058 next;
10059 }
10060 if($TName=~/\Asizeof\(/) {
10061 next;
10062 }
10063 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
10064 check_TypeInfo($Tid, $LibVersion);
10065 }
10066 else
10067 {
10068 if(defined $Debug) {
10069 printMsg("WARNING", "missed type $TName");
10070 }
10071 }
10072 }
10073 }
10074
10075 # symbols
10076 if(defined $Info->{"Param"})
10077 {
10078 foreach my $Pos (keys(%{$Info->{"Param"}}))
10079 {
10080 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10081 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10082 }
10083 }
10084 }
10085 if(defined $Info->{"Return"}) {
10086 check_TypeInfo($Info->{"Return"}, $LibVersion);
10087 }
10088 if(defined $Info->{"Class"}) {
10089 check_TypeInfo($Info->{"Class"}, $LibVersion);
10090 }
10091}
10092
10093sub check_TypeInfo($$)
10094{
10095 my ($Tid, $LibVersion) = @_;
10096
10097 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10098 return;
10099 }
10100 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10101
10102 if(defined $TypeInfo{$LibVersion}{$Tid})
10103 {
10104 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10105 printMsg("ERROR", "missed type name ($Tid)");
10106 }
10107 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10108 }
10109 else {
10110 printMsg("ERROR", "missed type id $Tid");
10111 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010112}
10113
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010114sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010115{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010116 my ($TypeId, $LibVersion) = @_;
10117 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010118 if($Type{"Type"} eq "Typedef")
10119 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010120 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010121 if($Base{"Type"}=~/Class|Struct/)
10122 {
10123 if($Type{"Name"} eq $Base{"Name"}) {
10124 return 1;
10125 }
10126 elsif($Type{"Name"}=~/::(\w+)\Z/)
10127 {
10128 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10129 { # QPointer<QWidget>::QPointer
10130 return 1;
10131 }
10132 }
10133 }
10134 }
10135 return 0;
10136}
10137
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010138sub addExtension($)
10139{
10140 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010141 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010142 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +030010143 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010144 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010145 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10146 $TName=~s/\A(struct|union|class|enum) //;
10147 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010148
10149 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10150 "Header" => "extended.h",
10151 "ShortName" => $Symbol,
10152 "MnglName" => $Symbol,
10153 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10154 );
10155
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010156 $ExtendedSymbols{$Symbol} = 1;
10157 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10158 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010159 }
10160 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010161 $ExtendedSymbols{"external_func_0"} = 1;
10162 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10163 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010164}
10165
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010166sub findMethod($$$)
10167{
10168 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010169 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010170 {
10171 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10172 return $VirtMethodInClass;
10173 }
10174 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10175 return $VirtMethodInBaseClasses;
10176 }
10177 }
10178 return "";
10179}
10180
10181sub findMethod_Class($$$)
10182{
10183 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010184 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010185 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10186 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10187 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10188 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10189 { # search for interface with the same parameters suffix (overridden)
10190 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10191 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010192 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10193 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010194 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10195 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010196 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10197 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10198 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10199 return $Candidate;
10200 }
10201 }
10202 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010203 else
10204 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010205 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10206 return $Candidate;
10207 }
10208 }
10209 }
10210 }
10211 return "";
10212}
10213
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010214sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010215{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010216 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010217 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010218 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010219 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10220 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010221 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010222 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010223 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010224 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10225 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010226 { # pure virtual D2-destructors are marked as "virt" in the dump
10227 # virtual D2-destructors are NOT marked as "virt" in the dump
10228 # both destructors are not presented in the v-table
10229 next;
10230 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010231 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010232 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10233 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010234 }
10235}
10236
10237sub registerOverriding($)
10238{
10239 my $LibVersion = $_[0];
10240 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010241 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010242 foreach my $ClassName (@Classes)
10243 {
10244 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10245 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010246 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10247 { # pure virtuals
10248 next;
10249 }
10250 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10251 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010252 {
10253 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10254 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10255 { # both overridden virtual methods
10256 # and implemented pure virtual methods
10257 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10258 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10259 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10260 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010261 }
10262 }
10263 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10264 delete($VirtualTable{$LibVersion}{$ClassName});
10265 }
10266 }
10267}
10268
10269sub setVirtFuncPositions($)
10270{
10271 my $LibVersion = $_[0];
10272 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10273 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010274 my ($Num, $Rel) = (1, 0);
10275
10276 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010277 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010278 if($UsedDump{$LibVersion}{"DWARF"}) {
10279 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10280 }
10281 else {
10282 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10283 }
10284 foreach my $VirtFunc (@Funcs)
10285 {
10286 if($UsedDump{$LibVersion}{"DWARF"}) {
10287 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10288 }
10289 else {
10290 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10291 }
10292
10293 # set relative positions
10294 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10295 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10296 { # relative position excluding added and removed virtual functions
10297 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10298 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10299 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10300 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010301 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010302 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010303 }
10304 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010305 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010306 {
10307 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010308 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010309 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010310 }
10311 }
10312}
10313
10314sub get_sub_classes($$$)
10315{
10316 my ($ClassId, $LibVersion, $Recursive) = @_;
10317 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10318 my @Subs = ();
10319 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10320 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010321 if($Recursive)
10322 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010323 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10324 push(@Subs, $SubSubId);
10325 }
10326 }
10327 push(@Subs, $SubId);
10328 }
10329 return @Subs;
10330}
10331
10332sub get_base_classes($$$)
10333{
10334 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010335 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010336 return () if(not defined $ClassType{"Base"});
10337 my @Bases = ();
10338 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10339 keys(%{$ClassType{"Base"}}))
10340 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010341 if($Recursive)
10342 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010343 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10344 push(@Bases, $SubBaseId);
10345 }
10346 }
10347 push(@Bases, $BaseId);
10348 }
10349 return @Bases;
10350}
10351
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010352sub getVTable_Model($$)
10353{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010354 my ($ClassId, $LibVersion) = @_;
10355 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10356 my @Elements = ();
10357 foreach my $BaseId (@Bases, $ClassId)
10358 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010359 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010360 {
10361 if(defined $VirtualTable{$LibVersion}{$BName})
10362 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010363 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10364 if($UsedDump{$LibVersion}{"DWARF"}) {
10365 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10366 }
10367 else {
10368 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10369 }
10370 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010371 push(@Elements, $VFunc);
10372 }
10373 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010374 }
10375 }
10376 return @Elements;
10377}
10378
10379sub getVShift($$)
10380{
10381 my ($ClassId, $LibVersion) = @_;
10382 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10383 my $VShift = 0;
10384 foreach my $BaseId (@Bases)
10385 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010386 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010387 {
10388 if(defined $VirtualTable{$LibVersion}{$BName}) {
10389 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10390 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010391 }
10392 }
10393 return $VShift;
10394}
10395
10396sub getShift($$)
10397{
10398 my ($ClassId, $LibVersion) = @_;
10399 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10400 my $Shift = 0;
10401 foreach my $BaseId (@Bases)
10402 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010403 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010404 {
10405 if($Size!=1)
10406 { # not empty base class
10407 $Shift+=$Size;
10408 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010409 }
10410 }
10411 return $Shift;
10412}
10413
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010414sub getVTable_Size($$)
10415{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010416 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010417 my $Size = 0;
10418 # three approaches
10419 if(not $Size)
10420 { # real size
10421 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10422 $Size = keys(%VTable);
10423 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010424 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010425 if(not $Size)
10426 { # shared library symbol size
10427 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10428 $Size /= $WORD_SIZE{$LibVersion};
10429 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010430 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010431 if(not $Size)
10432 { # model size
10433 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10434 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10435 }
10436 }
10437 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010438}
10439
10440sub isCopyingClass($$)
10441{
10442 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010443 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010444}
10445
10446sub isLeafClass($$)
10447{
10448 my ($ClassId, $LibVersion) = @_;
10449 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10450}
10451
10452sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010453{ # check structured type for public fields
10454 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010455}
10456
10457sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010458{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010459 my ($TypePtr, $Skip, $Start, $End) = @_;
10460 return 0 if(not $TypePtr);
10461 if($End==-1) {
10462 $End = keys(%{$TypePtr->{"Memb"}})-1;
10463 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030010464 foreach my $MemPos (sort {int($a)<=>int($b)} keys(%{$TypePtr->{"Memb"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010465 {
10466 if($Skip and $Skip->{$MemPos})
10467 { # skip removed/added fields
10468 next;
10469 }
10470 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10471 {
10472 if(isPublic($TypePtr, $MemPos)) {
10473 return ($MemPos+1);
10474 }
10475 }
10476 }
10477 return 0;
10478}
10479
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010480sub isReserved($)
10481{ # reserved fields == private
10482 my $MName = $_[0];
10483 if($MName=~/reserved|padding|f_spare/i) {
10484 return 1;
10485 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010486 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010487 return 1;
10488 }
10489 if($MName=~/(pad\d+)/i) {
10490 return 1;
10491 }
10492 return 0;
10493}
10494
10495sub isPublic($$)
10496{
10497 my ($TypePtr, $FieldPos) = @_;
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010498
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010499 return 0 if(not $TypePtr);
10500 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10501 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010502
10503 my $Access = $TypePtr->{"Memb"}{$FieldPos}{"access"};
10504 if($Access eq "private")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010505 { # by access in C++ language
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010506 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010507 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010508
10509 # by name in C language
10510 # TODO: add other methods to detect private members
10511 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030010512 if($MName=~/priv|abidata|parent_object|impl/i)
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010513 { # C-styled private data
10514 return 0;
10515 }
10516 if(lc($MName) eq "abi")
10517 { # ABI information/reserved field
10518 return 0;
10519 }
10520 if(isReserved($MName))
10521 { # reserved fields
10522 return 0;
10523 }
10524
10525 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010526}
10527
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010528sub getVTable_Real($$)
10529{
10530 my ($ClassName, $LibVersion) = @_;
10531 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10532 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010533 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010534 if(defined $Type{"VTable"}) {
10535 return %{$Type{"VTable"}};
10536 }
10537 }
10538 return ();
10539}
10540
10541sub cmpVTables($)
10542{
10543 my $ClassName = $_[0];
10544 my $Res = cmpVTables_Real($ClassName, 1);
10545 if($Res==-1) {
10546 $Res = cmpVTables_Model($ClassName);
10547 }
10548 return $Res;
10549}
10550
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010551sub cmpVTables_Model($)
10552{
10553 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010554 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010555 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010556 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010557 return 1;
10558 }
10559 }
10560 return 0;
10561}
10562
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010563sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010564{
10565 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010566 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10567 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010568 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010569 my %VTable_Old = getVTable_Real($ClassName, 1);
10570 my %VTable_New = getVTable_Real($ClassName, 2);
10571 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010572 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010573 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010574 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010575 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010576 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10577 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010578 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010579 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010580 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010581 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010582 my $Entry1 = $VTable_Old{$Offset};
10583 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010584 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010585 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010586 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010587 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010588
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010589 $Entry1 = simpleVEntry($Entry1);
10590 $Entry2 = simpleVEntry($Entry2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010591
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030010592 if($Entry1=~/ 0x/ or $Entry2=~/ 0x/)
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010593 { # NOTE: problem with vtable-dumper
10594 next;
10595 }
10596
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010597 if($Entry1 ne $Entry2)
10598 { # register as changed
10599 if($Entry1=~/::([^:]+)\Z/)
10600 {
10601 my $M1 = $1;
10602 if($Entry2=~/::([^:]+)\Z/)
10603 {
10604 my $M2 = $1;
10605 if($M1 eq $M2)
10606 { # overridden
10607 next;
10608 }
10609 }
10610 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010611 if(differentDumps("G"))
10612 {
10613 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10614 {
10615 # GCC 4.6.1: -0x00000000000000010
10616 # GCC 4.7.0: -16
10617 next;
10618 }
10619 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010620 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010621 }
10622 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010623 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010624}
10625
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010626sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010627{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010628 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010629 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10630 {
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010631 my $ClassId = $TName_Tid{1}{$ClassName};
10632 if(isPrivateABI($ClassId, 1)) {
10633 next;
10634 }
10635
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010636 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010637 { # already registered
10638 next;
10639 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010640 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010641 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010642 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010643 foreach my $Symbol (@Affected)
10644 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010645 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010646 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010647 "Target"=>$ClassName);
10648 }
10649 }
10650 }
10651}
10652
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010653sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010654{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010655 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010656 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010657 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010658 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010659 next if(not $ClassId);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010660
10661 if(isPrivateABI($ClassId, 1)) {
10662 next;
10663 }
10664
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010665 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010666 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010667 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010668 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010669 if($TName_Tid{1}{$ClassName}
10670 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010671 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010672 if(defined $CompleteSignature{1}{$Symbol}
10673 and $CompleteSignature{1}{$Symbol}{"Virt"})
10674 { # override some method in v.1
10675 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010676 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010677 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010678 }
10679 }
10680 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010681 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010682 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010683 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010684 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010685 if($TName_Tid{2}{$ClassName}
10686 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010687 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010688 if(defined $CompleteSignature{2}{$Symbol}
10689 and $CompleteSignature{2}{$Symbol}{"Virt"})
10690 { # override some method in v.2
10691 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010692 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010693 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010694 }
10695 }
10696 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010697 if($Level eq "Binary")
10698 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010699 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010700 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10701 { # check replacements, including pure virtual methods
10702 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10703 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010704 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010705 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10706 if($AddedPos==$RemovedPos)
10707 {
10708 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10709 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10710 last; # other methods will be reported as "added" or "removed"
10711 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010712 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010713 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10714 {
10715 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10716 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010717 next;
10718 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010719 my $ProblemType = "Virtual_Replacement";
10720 my @Affected = ($RemovedVFunc);
10721 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10722 { # pure methods
10723 if(not isUsedClass($ClassId, 1, $Level))
10724 { # not a parameter of some exported method
10725 next;
10726 }
10727 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010728
10729 # affected all methods (both virtual and non-virtual ones)
10730 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10731 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010732 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010733 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010734 foreach my $AffectedInt (@Affected)
10735 {
10736 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10737 { # affected exported methods only
10738 next;
10739 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010740 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10741 next;
10742 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010743 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10744 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010745 "Target"=>get_Signature($AddedVFunc, 2),
10746 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10747 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010748 }
10749 }
10750 }
10751 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010752 if(not checkDump(1, "2.0")
10753 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010754 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010755 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010756 return;
10757 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010758 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010759 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010760 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010761 next if(not $ClassId_Old);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010762
10763 if(isPrivateABI($ClassId_Old, 1)) {
10764 next;
10765 }
10766
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010767 if(not isCreatable($ClassId_Old, 1))
10768 { # skip classes without public constructors (including auto-generated)
10769 # example: class has only a private exported or private inline constructor
10770 next;
10771 }
10772 if($ClassName=~/>/)
10773 { # skip affected template instances
10774 next;
10775 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010776 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010777 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010778 if(not $ClassId_New) {
10779 next;
10780 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010781 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010782 if($Class_New{"Type"}!~/Class|Struct/)
10783 { # became typedef
10784 if($Level eq "Binary") {
10785 next;
10786 }
10787 if($Level eq "Source")
10788 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010789 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010790 if($Class_New{"Type"}!~/Class|Struct/) {
10791 next;
10792 }
10793 $ClassId_New = $Class_New{"Tid"};
10794 }
10795 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010796
10797 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10798 { # incomplete info in the ABI dump
10799 next;
10800 }
10801
10802
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010803 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10804 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 +040010805
10806 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10807 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10808
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010809 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010810 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10811 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010812 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10813 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010814 my $Shift_Old = getShift($ClassId_Old, 1);
10815 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010816 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010817 my ($Added, $Removed) = (0, 0);
10818 my @StableBases_Old = ();
10819 foreach my $BaseId (@Bases_Old)
10820 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010821 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010822 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010823 push(@StableBases_Old, $BaseId);
10824 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010825 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010826 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010827 { # removed base
10828 # excluding namespace::SomeClass to SomeClass renaming
10829 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010830 if($Level eq "Binary")
10831 { # Binary-level
10832 if($Shift_Old ne $Shift_New)
10833 { # affected fields
10834 if(havePubFields(\%Class_Old)) {
10835 $ProblemKind .= "_And_Shift";
10836 }
10837 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10838 $ProblemKind .= "_And_Size";
10839 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010840 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010841 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10842 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010843 { # affected v-table
10844 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010845 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010846 }
10847 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010848 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010849 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10850 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010851 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10852 {
10853 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10854 if($ProblemKind=~/VTable/) {
10855 $VTableChanged_M{$SubName}=1;
10856 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010857 }
10858 }
10859 foreach my $Interface (@Affected)
10860 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010861 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10862 next;
10863 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010864 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010865 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010866 "Target"=>$BaseName,
10867 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10868 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10869 "Shift"=>abs($Shift_New-$Shift_Old) );
10870 }
10871 $Removed+=1;
10872 }
10873 }
10874 my @StableBases_New = ();
10875 foreach my $BaseId (@Bases_New)
10876 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010877 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010878 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010879 push(@StableBases_New, $BaseId);
10880 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010881 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010882 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010883 { # added base
10884 # excluding namespace::SomeClass to SomeClass renaming
10885 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010886 if($Level eq "Binary")
10887 { # Binary-level
10888 if($Shift_Old ne $Shift_New)
10889 { # affected fields
10890 if(havePubFields(\%Class_Old)) {
10891 $ProblemKind .= "_And_Shift";
10892 }
10893 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10894 $ProblemKind .= "_And_Size";
10895 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010896 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010897 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10898 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010899 { # affected v-table
10900 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010901 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010902 }
10903 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010904 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010905 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10906 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010907 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10908 {
10909 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10910 if($ProblemKind=~/VTable/) {
10911 $VTableChanged_M{$SubName}=1;
10912 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010913 }
10914 }
10915 foreach my $Interface (@Affected)
10916 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010917 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10918 next;
10919 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010920 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010921 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010922 "Target"=>$BaseName,
10923 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10924 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10925 "Shift"=>abs($Shift_New-$Shift_Old) );
10926 }
10927 $Added+=1;
10928 }
10929 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010930 if($Level eq "Binary")
10931 { # Binary-level
10932 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010933 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10934 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010935 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010936 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010937 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010938 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010939 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010940 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10941 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010942 if($NewPos!=$OldPos)
10943 { # changed position of the base class
10944 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010945 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010946 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10947 next;
10948 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010949 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10950 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010951 "Target"=>$BaseName,
10952 "Old_Value"=>$OldPos-1,
10953 "New_Value"=>$NewPos-1 );
10954 }
10955 }
10956 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10957 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10958 { # became non-virtual base
10959 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10960 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010961 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10962 next;
10963 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010964 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10965 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010966 "Target"=>$BaseName );
10967 }
10968 }
10969 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10970 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10971 { # became virtual base
10972 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10973 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010974 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10975 next;
10976 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010977 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10978 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010979 "Target"=>$BaseName );
10980 }
10981 }
10982 }
10983 }
10984 # detect size changes in base classes
10985 if($Shift_Old!=$Shift_New)
10986 { # size of allocable class
10987 foreach my $BaseId (@StableBases_Old)
10988 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010989 my %BaseType = get_Type($BaseId, 1);
10990 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010991 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010992 if($Size_Old ne $Size_New
10993 and $Size_Old and $Size_New)
10994 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010995 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010996 if(isCopyingClass($BaseId, 1)) {
10997 $ProblemType = "Size_Of_Copying_Class";
10998 }
10999 elsif($AllocableClass{1}{$BaseType{"Name"}})
11000 {
11001 if($Size_New>$Size_Old)
11002 { # increased size
11003 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011004 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011005 else
11006 { # decreased size
11007 $ProblemType = "Size_Of_Allocable_Class_Decreased";
11008 if(not havePubFields(\%Class_Old))
11009 { # affected class has no public members
11010 next;
11011 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011012 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011013 }
11014 next if(not $ProblemType);
11015 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
11016 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011017 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
11018 next;
11019 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011020 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
11021 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011022 "Target"=>$BaseType{"Name"},
11023 "Old_Size"=>$Size_Old*$BYTE_SIZE,
11024 "New_Size"=>$Size_New*$BYTE_SIZE );
11025 }
11026 }
11027 }
11028 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011029 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011030 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011031 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011032 { # compare virtual tables size in base classes
11033 my $VShift_Old = getVShift($ClassId_Old, 1);
11034 my $VShift_New = getVShift($ClassId_New, 2);
11035 if($VShift_Old ne $VShift_New)
11036 { # changes in the base class or changes in the list of base classes
11037 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
11038 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
11039 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011040 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011041 foreach my $BaseId (@AllBases_Old)
11042 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011043 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011044 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011045 { # lost base
11046 next;
11047 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011048 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
11049 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011050 if($VSize_Old!=$VSize_New)
11051 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011052 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011053 { # TODO: affected non-virtual methods?
11054 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011055 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
11056 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011057 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011058 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011059 { # skip interfaces that have not changed the absolute virtual position
11060 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011061 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011062 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
11063 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011064 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011065 $VTableChanged_M{$BaseType{"Name"}} = 1;
11066 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011067 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
11068 { # the reason of the layout change: added virtual functions
11069 next if($VirtualReplacement{$VirtFunc});
11070 my $ProblemType = "Added_Virtual_Method";
11071 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
11072 $ProblemType = "Added_Pure_Virtual_Method";
11073 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011074 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011075 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011076 "Target"=>get_Signature($VirtFunc, 2) );
11077 }
11078 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
11079 { # the reason of the layout change: removed virtual functions
11080 next if($VirtualReplacement{$VirtFunc});
11081 my $ProblemType = "Removed_Virtual_Method";
11082 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11083 $ProblemType = "Removed_Pure_Virtual_Method";
11084 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011085 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011086 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011087 "Target"=>get_Signature($VirtFunc, 1) );
11088 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011089 }
11090 }
11091 }
11092 }
11093 }
11094 }
11095 }
11096}
11097
11098sub isCreatable($$)
11099{
11100 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011101 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011102 or isCopyingClass($ClassId, $LibVersion)) {
11103 return 1;
11104 }
11105 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11106 { # Fix for incomplete data: if this class has
11107 # a base class then it should also has a constructor
11108 return 1;
11109 }
11110 if($ReturnedClass{$LibVersion}{$ClassId})
11111 { # returned by some method of this class
11112 # or any other class
11113 return 1;
11114 }
11115 return 0;
11116}
11117
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011118sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011119{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011120 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011121 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11122 { # parameter of some exported method
11123 return 1;
11124 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011125 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11126 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011127 { # method from target class
11128 return 1;
11129 }
11130 return 0;
11131}
11132
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011133sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011134{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011135 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011136 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011137 # - virtual
11138 # - pure-virtual
11139 # - non-virtual
11140 if($CompleteSignature{1}{$Interface}{"Data"})
11141 { # global data is not affected
11142 return;
11143 }
11144 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011145 if(not $Class_Id) {
11146 return;
11147 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011148 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011149 if(cmpVTables_Real($CName, 1)==0)
11150 { # no changes
11151 return;
11152 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011153 $CheckedTypes{$Level}{$CName} = 1;
11154 if($Level eq "Binary")
11155 { # Binary-level
11156 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11157 and not isUsedClass($Class_Id, 1, $Level))
11158 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011159 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011160 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011161 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011162 }
11163 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11164 {
11165 if(defined $VirtualTable{2}{$CName}{$Func}
11166 and defined $CompleteSignature{2}{$Func})
11167 {
11168 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11169 and $CompleteSignature{2}{$Func}{"PureVirt"})
11170 { # became pure virtual
11171 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11172 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011173 "Target"=>get_Signature_M($Func, 1) );
11174 $VTableChanged_M{$CName} = 1;
11175 }
11176 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11177 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11178 { # became non-pure virtual
11179 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11180 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011181 "Target"=>get_Signature_M($Func, 1) );
11182 $VTableChanged_M{$CName} = 1;
11183 }
11184 }
11185 }
11186 if($Level eq "Binary")
11187 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011188 # check virtual table structure
11189 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11190 {
11191 next if($Interface eq $AddedVFunc);
11192 next if($VirtualReplacement{$AddedVFunc});
11193 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11194 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11195 { # pure virtual methods affect all others (virtual and non-virtual)
11196 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011197 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011198 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011199 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011200 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011201 elsif(not defined $VirtualTable{1}{$CName}
11202 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011203 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011204 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011205 { # became polymorphous class, added v-table pointer
11206 %{$CompatProblems{$Level}{$Interface}{"Added_First_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 }
11211 else
11212 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011213 my $VSize_Old = getVTable_Size($CName, 1);
11214 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011215 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011216 if(isCopyingClass($Class_Id, 1))
11217 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11218 my $ProblemType = "Added_Virtual_Method";
11219 if(isLeafClass($Class_Id, 1)) {
11220 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11221 }
11222 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11223 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011224 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011225 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011226 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011227 else
11228 {
11229 my $ProblemType = "Added_Virtual_Method";
11230 if(isLeafClass($Class_Id, 1)) {
11231 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11232 }
11233 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11234 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011235 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011236 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011237 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011238 }
11239 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011240 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11241 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011242 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011243 if(defined $VirtualTable{1}{$CName}
11244 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011245 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011246 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11247 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011248
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011249 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011250 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011251 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11252 foreach my $ASymbol (@Affected)
11253 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011254 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11255 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011256 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011257 next;
11258 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011259 }
11260 $CheckedSymbols{$Level}{$ASymbol} = 1;
11261 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11262 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011263 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011264 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011265 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011266 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011267 }
11268 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011269 else {
11270 # safe
11271 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011272 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011273 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11274 {
11275 next if($VirtualReplacement{$RemovedVFunc});
11276 if($RemovedVFunc eq $Interface
11277 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11278 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011279 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011280 next;
11281 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011282 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011283 { # became non-polymorphous class, removed v-table pointer
11284 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11285 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011286 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011287 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011288 }
11289 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11290 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11291 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011292 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011293 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011294 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11295 next;
11296 }
11297 my $VPos_New = -1;
11298 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011299 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011300 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11301 }
11302 else
11303 {
11304 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011305 next;
11306 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011307 }
11308 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11309 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11310 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11311 {
11312 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11313 foreach my $ASymbol (@Affected)
11314 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011315 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11316 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011317 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011318 next;
11319 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011320 }
11321 my $ProblemType = "Removed_Virtual_Method";
11322 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11323 $ProblemType = "Removed_Pure_Virtual_Method";
11324 }
11325 $CheckedSymbols{$Level}{$ASymbol} = 1;
11326 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11327 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011328 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011329 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011330 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011331 }
11332 }
11333 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011334 }
11335 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011336 else
11337 { # Source-level
11338 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011339 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011340 next if($Interface eq $AddedVFunc);
11341 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011342 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011343 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11344 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011345 "Target"=>get_Signature($AddedVFunc, 2) );
11346 }
11347 }
11348 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11349 {
11350 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11351 {
11352 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11353 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011354 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011355 }
11356 }
11357 }
11358}
11359
11360sub find_MemberPair_Pos_byName($$)
11361{
11362 my ($Member_Name, $Pair_Type) = @_;
11363 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11364 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11365 {
11366 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11367 {
11368 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11369 $Name=~s/\A[_]+|[_]+\Z//g;
11370 if($Name eq $Member_Name) {
11371 return $MemberPair_Pos;
11372 }
11373 }
11374 }
11375 return "lost";
11376}
11377
11378sub find_MemberPair_Pos_byVal($$)
11379{
11380 my ($Member_Value, $Pair_Type) = @_;
11381 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11382 {
11383 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11384 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11385 return $MemberPair_Pos;
11386 }
11387 }
11388 return "lost";
11389}
11390
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011391sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011392{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011393 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011394 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011395 if( $_->{"T1"} eq $_[0]
11396 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011397 {
11398 return 1;
11399 }
11400 }
11401 return 0;
11402}
11403
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011404sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011405{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011406 my %IDs = (
11407 "T1" => $_[0],
11408 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011409 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011410 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011411}
11412
11413sub isRenamed($$$$$)
11414{
11415 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11416 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11417 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011418 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011419 if(not defined $Type2->{"Memb"}{$MemPos}) {
11420 return "";
11421 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011422 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011423 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011424
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011425 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11426 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011427 if($MemberPair_Pos_Rev eq "lost")
11428 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011429 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11430 { # base type match
11431 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011432 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011433 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11434 { # exact type match
11435 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011436 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011437 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11438 { # size match
11439 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011440 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011441 if(isReserved($Pair_Name))
11442 { # reserved fields
11443 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011444 }
11445 }
11446 return "";
11447}
11448
11449sub isLastElem($$)
11450{
11451 my ($Pos, $TypeRef) = @_;
11452 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030011453 if($Name=~/last|count|max|total|num/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011454 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11455 return 1;
11456 }
11457 elsif($Name=~/END|NLIMITS\Z/)
11458 { # __RLIMIT_NLIMITS
11459 return 1;
11460 }
11461 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11462 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11463 { # NImageFormats, NColorRoles
11464 return 1;
11465 }
11466 return 0;
11467}
11468
11469sub nonComparable($$)
11470{
11471 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011472
11473 my $N1 = $T1->{"Name"};
11474 my $N2 = $T2->{"Name"};
11475
11476 $N1=~s/\A(struct|union|enum) //;
11477 $N2=~s/\A(struct|union|enum) //;
11478
11479 if($N1 ne $N2
11480 and not isAnon($N1)
11481 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011482 { # different names
11483 if($T1->{"Type"} ne "Pointer"
11484 or $T2->{"Type"} ne "Pointer")
11485 { # compare base types
11486 return 1;
11487 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011488 if($N1!~/\Avoid\s*\*/
11489 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011490 {
11491 return 1;
11492 }
11493 }
11494 elsif($T1->{"Type"} ne $T2->{"Type"})
11495 { # different types
11496 if($T1->{"Type"} eq "Class"
11497 and $T2->{"Type"} eq "Struct")
11498 { # "class" to "struct"
11499 return 0;
11500 }
11501 elsif($T2->{"Type"} eq "Class"
11502 and $T1->{"Type"} eq "Struct")
11503 { # "struct" to "class"
11504 return 0;
11505 }
11506 else
11507 { # "class" to "enum"
11508 # "union" to "class"
11509 # ...
11510 return 1;
11511 }
11512 }
11513 return 0;
11514}
11515
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011516sub isOpaque($)
11517{
11518 my $T = $_[0];
11519 if(not defined $T->{"Memb"})
11520 {
11521 return 1;
11522 }
11523 return 0;
11524}
11525
11526sub removeVPtr($)
11527{ # support for old ABI dumps
11528 my $TPtr = $_[0];
11529 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11530 if($#Pos>=1)
11531 {
11532 foreach my $Pos (0 .. $#Pos-1)
11533 {
11534 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11535 }
11536 delete($TPtr->{"Memb"}{$#Pos});
11537 }
11538}
11539
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011540sub isPrivateABI($$)
11541{
11542 my ($TypeId, $LibVersion) = @_;
11543
11544 if($CheckPrivateABI) {
11545 return 0;
11546 }
11547
11548 if(defined $TypeInfo{$LibVersion}{$TypeId}{"PrivateABI"}) {
11549 return 1;
11550 }
11551
11552 return 0;
11553}
11554
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011555sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011556{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011557 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011558 return {} if(not $Type1_Id or not $Type2_Id);
11559
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011560 if(defined $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011561 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011562 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011563 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011564
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011565 my %Type1 = get_Type($Type1_Id, 1);
11566 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011567 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011568 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011569 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011570
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011571 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11572 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011573
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011574 if(defined $UsedDump{1}{"DWARF"})
11575 {
11576 if($Type1_Pure{"Name"} eq "__unknown__"
11577 or $Type2_Pure{"Name"} eq "__unknown__")
11578 { # Error ABI dump
11579 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11580 }
11581 }
11582
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011583 if(isPrivateABI($Type1_Id, 1)) {
11584 return {};
11585 }
11586
11587 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
11588 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11589
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011590 my %SubProblems = ();
11591
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011592 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11593 {
11594 if($Type1_Pure{"Type"}=~/Struct|Union/
11595 and $Type2_Pure{"Type"}=~/Struct|Union/)
11596 {
11597 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11598 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011599 if(not defined $UsedDump{1}{"DWARF"}
11600 and not defined $UsedDump{2}{"DWARF"})
11601 {
11602 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11603 "Target"=>$Type1_Pure{"Name"},
11604 "Type_Name"=>$Type1_Pure{"Name"} );
11605 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011606
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011607 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011608 }
11609 }
11610 }
11611
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011612 if(not $Type1_Pure{"Size"}
11613 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011614 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011615 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11616 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11617 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011618 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011619 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011620 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011621 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011622 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011623 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011624 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011625 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11626 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11627 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011628
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011629 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11630 return {};
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011631 }
11632
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011633 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11634 { # support for old ABI dumps
11635 # _vptr field added in 3.0
11636 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11637 {
11638 if(defined $Type2_Pure{"Memb"}
11639 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11640 {
11641 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11642 delete($Type2_Pure{"Memb"}{0});
11643 }
11644 else {
11645 removeVPtr(\%Type2_Pure);
11646 }
11647 }
11648 }
11649 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11650 {
11651 if(defined $Type1_Pure{"Memb"}
11652 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11653 {
11654 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11655 delete($Type1_Pure{"Memb"}{0});
11656 }
11657 else {
11658 removeVPtr(\%Type1_Pure);
11659 }
11660 }
11661 }
11662 }
11663
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011664 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11665 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011666
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011667 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011668 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11669 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011670 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011671 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11672 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011673 if($Base_1{"Name"} ne $Base_2{"Name"})
11674 {
11675 if(differentDumps("G")
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030011676 or differentDumps("V")
11677 or $SkipTypedefUncover)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011678 { # different GCC versions or different dumps
11679 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11680 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11681 # std::__va_list and __va_list
11682 $Base_1{"Name"}=~s/\A(\w+::)+//;
11683 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011684 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11685 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011686 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011687 }
11688 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11689 and $Base_1{"Name"} ne $Base_2{"Name"})
11690 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011691 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011692 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011693 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011694 {
11695 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11696 "Target"=>$Typedef_1{"Name"},
11697 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011698 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11699 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11700 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011701 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11702 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011703
11704 if(defined $UsedDump{1}{"DWARF"})
11705 {
11706 if($Base1_Pure{"Name"}=~/\b__unknown__\b/
11707 or $Base2_Pure{"Name"}=~/\b__unknown__\b/)
11708 { # Error ABI dump
11709 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11710 }
11711 }
11712
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011713 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011714 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011715 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11716 {
11717 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11718 "Target"=>$Typedef_1{"Name"},
11719 "Type_Name"=>$Typedef_1{"Name"},
11720 "Old_Value"=>$Base_1{"Name"},
11721 "New_Value"=>$Base_2{"Name"} );
11722 }
11723 else
11724 {
11725 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11726 "Target"=>$Typedef_1{"Name"},
11727 "Type_Name"=>$Typedef_1{"Name"},
11728 "Old_Value"=>$Base_1{"Name"},
11729 "New_Value"=>$Base_2{"Name"} );
11730 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011731 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011732 }
11733 }
11734 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11735 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011736 my $TT1 = $Type1_Pure{"Type"};
11737 my $TT2 = $Type2_Pure{"Type"};
11738
11739 if($TT1 ne $TT2
11740 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011741 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011742 my $Short1 = $Type1_Pure{"Name"};
11743 my $Short2 = $Type2_Pure{"Name"};
11744
11745 $Short1=~s/\A\Q$TT1\E //ig;
11746 $Short2=~s/\A\Q$TT2\E //ig;
11747
11748 if($Short1 eq $Short2)
11749 {
11750 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11751 "Target"=>$Type1_Pure{"Name"},
11752 "Type_Name"=>$Type1_Pure{"Name"},
11753 "Old_Value"=>lc($Type1_Pure{"Type"}),
11754 "New_Value"=>lc($Type2_Pure{"Type"}) );
11755 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011756 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011757 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011758 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011759
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011760 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011761
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011762 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11763 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11764 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11765 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011766 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011767 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011768 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011769 {
11770 my $ProblemKind = "DataType_Size";
11771 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011772 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011773 {
11774 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11775 $ProblemKind = "Size_Of_Copying_Class";
11776 }
11777 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11778 {
11779 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11780 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11781 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011782 else
11783 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011784 # descreased size of allocable class
11785 # it has no special effects
11786 }
11787 }
11788 }
11789 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11790 "Target"=>$Type1_Pure{"Name"},
11791 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011792 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011793 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011794 }
11795 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011796 if(defined $Type1_Pure{"BaseType"}
11797 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011798 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011799 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11800 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011801 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011802 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11803 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011804 }
11805 }
11806 }
11807 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11808 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11809 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11810 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11811 { # detect removed and renamed fields
11812 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11813 next if(not $Member_Name);
11814 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);
11815 if($MemberPair_Pos eq "lost")
11816 {
11817 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11818 {
11819 if(isUnnamed($Member_Name))
11820 { # support for old-version dumps
11821 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011822 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011823 next;
11824 }
11825 }
11826 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11827 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011828 $RenamedField{$Member_Pos} = $RenamedTo;
11829 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011830 }
11831 else
11832 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011833 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011834 }
11835 }
11836 elsif($Type1_Pure{"Type"} eq "Enum")
11837 {
11838 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11839 next if($Member_Value1 eq "");
11840 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11841 if($MemberPair_Pos ne "lost")
11842 { # renamed
11843 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11844 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11845 if($MemberPair_Pos_Rev eq "lost")
11846 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011847 $RenamedField{$Member_Pos} = $RenamedTo;
11848 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011849 }
11850 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011851 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011852 }
11853 }
11854 else
11855 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011856 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011857 }
11858 }
11859 }
11860 else
11861 { # related
11862 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11863 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11864 }
11865 }
11866 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11867 { # detect added fields
11868 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11869 next if(not $Member_Name);
11870 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);
11871 if($MemberPair_Pos eq "lost")
11872 {
11873 if(isUnnamed($Member_Name))
11874 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011875 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011876 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011877 next;
11878 }
11879 }
11880 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11881 {
11882 if(not $RenamedField_Rev{$Member_Pos})
11883 { # added
11884 $AddedField{$Member_Pos}=1;
11885 }
11886 }
11887 }
11888 }
11889 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11890 { # detect moved fields
11891 my (%RelPos, %RelPosName, %AbsPos) = ();
11892 my $Pos = 0;
11893 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11894 { # relative positions in 1st version
11895 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11896 next if(not $Member_Name);
11897 if(not $RemovedField{$Member_Pos})
11898 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011899 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011900 $RelPosName{1}{$Pos} = $Member_Name;
11901 $AbsPos{1}{$Pos++} = $Member_Pos;
11902 }
11903 }
11904 $Pos = 0;
11905 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11906 { # relative positions in 2nd version
11907 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11908 next if(not $Member_Name);
11909 if(not $AddedField{$Member_Pos})
11910 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011911 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011912 $RelPosName{2}{$Pos} = $Member_Name;
11913 $AbsPos{2}{$Pos++} = $Member_Pos;
11914 }
11915 }
11916 foreach my $Member_Name (keys(%{$RelPos{1}}))
11917 {
11918 my $RPos1 = $RelPos{1}{$Member_Name};
11919 my $AbsPos1 = $NameToPosA{$Member_Name};
11920 my $Member_Name2 = $Member_Name;
11921 if(my $RenamedTo = $RenamedField{$AbsPos1})
11922 { # renamed
11923 $Member_Name2 = $RenamedTo;
11924 }
11925 my $RPos2 = $RelPos{2}{$Member_Name2};
11926 if($RPos2 ne "" and $RPos1 ne $RPos2)
11927 { # different relative positions
11928 my $AbsPos2 = $NameToPosB{$Member_Name2};
11929 if($AbsPos1 ne $AbsPos2)
11930 { # different absolute positions
11931 my $ProblemType = "Moved_Field";
11932 if(not isPublic(\%Type1_Pure, $AbsPos1))
11933 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011934 if($Level eq "Source") {
11935 next;
11936 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011937 $ProblemType = "Moved_Private_Field";
11938 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011939 if($Level eq "Binary"
11940 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011941 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011942 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011943 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011944 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011945 if($MemSize1 ne $MemSize2) {
11946 $ProblemType .= "_And_Size";
11947 }
11948 }
11949 if($ProblemType eq "Moved_Private_Field") {
11950 next;
11951 }
11952 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11953 "Target"=>$Member_Name,
11954 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011955 "Old_Value"=>$RPos1,
11956 "New_Value"=>$RPos2 );
11957 }
11958 }
11959 }
11960 }
11961 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011962 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011963 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11964 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011965 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011966 if(my $RenamedTo = $RenamedField{$Member_Pos})
11967 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011968 if(defined $Constants{2}{$Member_Name})
11969 {
11970 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11971 { # define OLD NEW
11972 next; # Safe
11973 }
11974 }
11975
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011976 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11977 {
11978 if(isPublic(\%Type1_Pure, $Member_Pos))
11979 {
11980 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11981 "Target"=>$Member_Name,
11982 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011983 "Old_Value"=>$Member_Name,
11984 "New_Value"=>$RenamedTo );
11985 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011986 elsif(isReserved($Member_Name))
11987 {
11988 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11989 "Target"=>$Member_Name,
11990 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011991 "Old_Value"=>$Member_Name,
11992 "New_Value"=>$RenamedTo );
11993 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011994 }
11995 elsif($Type1_Pure{"Type"} eq "Enum")
11996 {
11997 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11998 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11999 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012000 "Old_Value"=>$Member_Name,
12001 "New_Value"=>$RenamedTo );
12002 }
12003 }
12004 elsif($RemovedField{$Member_Pos})
12005 { # removed
12006 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12007 {
12008 my $ProblemType = "Removed_Field";
12009 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012010 or isUnnamed($Member_Name))
12011 {
12012 if($Level eq "Source") {
12013 next;
12014 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012015 $ProblemType = "Removed_Private_Field";
12016 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012017 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012018 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012019 {
12020 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
12021 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012022 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 +040012023 { # changed offset
12024 $ProblemType .= "_And_Layout";
12025 }
12026 }
12027 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
12028 { # affected size
12029 $ProblemType .= "_And_Size";
12030 }
12031 }
12032 if($ProblemType eq "Removed_Private_Field") {
12033 next;
12034 }
12035 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12036 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012037 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012038 }
12039 elsif($Type2_Pure{"Type"} eq "Union")
12040 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012041 if($Level eq "Binary"
12042 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012043 {
12044 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
12045 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012046 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012047 }
12048 else
12049 {
12050 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
12051 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012052 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012053 }
12054 }
12055 elsif($Type1_Pure{"Type"} eq "Enum")
12056 {
12057 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
12058 "Target"=>$Member_Name,
12059 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012060 "Old_Value"=>$Member_Name );
12061 }
12062 }
12063 else
12064 { # changed
12065 my $MemberPair_Pos = $RelatedField{$Member_Pos};
12066 if($Type1_Pure{"Type"} eq "Enum")
12067 {
12068 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
12069 next if($Member_Value1 eq "");
12070 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
12071 next if($Member_Value2 eq "");
12072 if($Member_Value1 ne $Member_Value2)
12073 {
12074 my $ProblemType = "Enum_Member_Value";
12075 if(isLastElem($Member_Pos, \%Type1_Pure)) {
12076 $ProblemType = "Enum_Last_Member_Value";
12077 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012078 if($SkipConstants{1}{$Member_Name}) {
12079 $ProblemType = "Enum_Private_Member_Value";
12080 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012081 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12082 "Target"=>$Member_Name,
12083 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012084 "Old_Value"=>$Member_Value1,
12085 "New_Value"=>$Member_Value2 );
12086 }
12087 }
12088 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
12089 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012090 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
12091 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
12092
12093 if($Access1 ne "private"
12094 and $Access2 eq "private")
12095 {
12096 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12097 "Target"=>$Member_Name,
12098 "Type_Name"=>$Type1_Pure{"Name"});
12099 }
12100 elsif($Access1 ne "protected"
12101 and $Access1 ne "private"
12102 and $Access2 eq "protected")
12103 {
12104 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12105 "Target"=>$Member_Name,
12106 "Type_Name"=>$Type1_Pure{"Name"});
12107 }
12108
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012109 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12110 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012111 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012112 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12113 $SizeV1 = $BSize1;
12114 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012115 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012116 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12117 $SizeV2 = $BSize2;
12118 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012119 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12120 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012121 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012122 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012123 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012124 {
12125 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12126 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12127 { # field size change (including anon-structures and unions)
12128 # - same types
12129 # - unnamed types
12130 # - bitfields
12131 my $ProblemType = "Field_Size";
12132 if(not isPublic(\%Type1_Pure, $Member_Pos)
12133 or isUnnamed($Member_Name))
12134 { # should not be accessed by applications, goes to "Low Severity"
12135 # example: "abidata" members in GStreamer types
12136 $ProblemType = "Private_".$ProblemType;
12137 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012138 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 +040012139 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012140 if($Type2_Pure{"Type"} ne "Union"
12141 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012142 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012143 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 +040012144 { # changed offset
12145 $ProblemType .= "_And_Layout";
12146 }
12147 }
12148 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12149 $ProblemType .= "_And_Type_Size";
12150 }
12151 }
12152 if($ProblemType eq "Private_Field_Size")
12153 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012154 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012155 if($ProblemType eq "Field_Size")
12156 {
12157 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12158 { # Low severity
12159 $ProblemType = "Struct_Field_Size_Increased";
12160 }
12161 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012162 if($ProblemType)
12163 { # register a problem
12164 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12165 "Target"=>$Member_Name,
12166 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012167 "Old_Size"=>$SizeV1,
12168 "New_Size"=>$SizeV2);
12169 }
12170 }
12171 }
12172 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12173 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12174 { # do NOT check bitfield type changes
12175 next;
12176 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012177 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012178 {
12179 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12180 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12181 {
12182 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12183 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012184 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012185 }
12186 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12187 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12188 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012189 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012190 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012191 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012192 }
12193 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012194 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12195 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012196 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012197 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12198 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012199
12200 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012201 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012202 or $ProblemType eq "Field_Type_And_Size"
12203 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012204 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012205 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012206 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012207 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012208 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012209 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012210 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012211 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012212 }
12213 }
12214 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12215 {
12216 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012217 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012218 }
12219 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012220 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012221 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012222 }
12223 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12224 {
12225 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012226 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012227 }
12228 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012229 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012230 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012231 }
12232 }
12233 }
12234
12235 if($Level eq "Source")
12236 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012237 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012238 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012239 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12240 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012241
12242 if($ProblemType eq "Field_Type")
12243 {
12244 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012245 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012246 }
12247 }
12248 }
12249 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012250
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012251 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012252 {
12253 my $ProblemType_Init = $ProblemType;
12254 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012255 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012256 if(not isPublic(\%Type1_Pure, $Member_Pos)
12257 or isUnnamed($Member_Name)) {
12258 $ProblemType = "Private_".$ProblemType;
12259 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012260 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 +040012261 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012262 if($Type2_Pure{"Type"} ne "Union"
12263 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012264 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012265 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 +040012266 { # changed offset
12267 $ProblemType .= "_And_Layout";
12268 }
12269 }
12270 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12271 $ProblemType .= "_And_Type_Size";
12272 }
12273 }
12274 }
12275 else
12276 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012277 # TODO: Private_Field_Type rule?
12278
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012279 if(not isPublic(\%Type1_Pure, $Member_Pos)
12280 or isUnnamed($Member_Name)) {
12281 next;
12282 }
12283 }
12284 if($ProblemType eq "Private_Field_Type_And_Size")
12285 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012286 }
12287 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12288 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012289 "Type_Name"=>$Type1_Pure{"Name"});
12290
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012291 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012292 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012293 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012294 }
12295 }
12296 if(not isPublic(\%Type1_Pure, $Member_Pos))
12297 { # do NOT check internal type changes
12298 next;
12299 }
12300 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012301 { # checking member type changes
12302 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12303
12304 my %DupProblems = ();
12305
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012306 foreach my $Sub_SubProblemType (sort keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012307 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012308 foreach my $Sub_SubLocation (sort {length($a)<=>length($b)} sort keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012309 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012310 if(not defined $AllAffected)
12311 {
12312 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12313 next;
12314 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012315 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012316
12317 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12318 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12319
12320 if(not defined $AllAffected)
12321 {
12322 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012323 }
12324 }
12325 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012326
12327 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012328 }
12329 }
12330 }
12331 }
12332 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12333 { # checking added members, public and private
12334 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12335 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012336 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012337 if($AddedField{$Member_Pos})
12338 { # added
12339 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12340 {
12341 my $ProblemType = "Added_Field";
12342 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012343 or isUnnamed($Member_Name))
12344 {
12345 if($Level eq "Source") {
12346 next;
12347 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012348 $ProblemType = "Added_Private_Field";
12349 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012350 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012351 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012352 {
12353 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12354 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012355 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 +040012356 { # changed offset
12357 $ProblemType .= "_And_Layout";
12358 }
12359 }
12360 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12361 $ProblemType .= "_And_Size";
12362 }
12363 }
12364 if($ProblemType eq "Added_Private_Field")
12365 { # skip added private fields
12366 next;
12367 }
12368 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12369 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012370 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012371 }
12372 elsif($Type2_Pure{"Type"} eq "Union")
12373 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012374 if($Level eq "Binary"
12375 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012376 {
12377 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12378 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012379 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012380 }
12381 else
12382 {
12383 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12384 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012385 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012386 }
12387 }
12388 elsif($Type2_Pure{"Type"} eq "Enum")
12389 {
12390 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12391 next if($Member_Value eq "");
12392 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12393 "Target"=>$Member_Name,
12394 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012395 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012396 }
12397 }
12398 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012399
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012400 if($Type1_Pure{"Type"} eq "FuncPtr")
12401 {
12402 foreach my $PPos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Param"}}))
12403 {
12404 if(not defined $Type2_Pure{"Param"}{$PPos}) {
12405 next;
12406 }
12407
12408 my $PT1 = $Type1_Pure{"Param"}{$PPos}{"type"};
12409 my $PT2 = $Type2_Pure{"Param"}{$PPos}{"type"};
12410
12411 my $PName = "p".$PPos;
12412
12413 my $FP_SubProblems = mergeTypes($PT1, $PT2, $Level);
12414 my %DupProblems = ();
12415
12416 foreach my $FP_SubProblemType (keys(%{$FP_SubProblems}))
12417 {
12418 foreach my $FP_SubLocation (keys(%{$FP_SubProblems->{$FP_SubProblemType}}))
12419 {
12420 if(not defined $AllAffected)
12421 {
12422 if(defined $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}}) {
12423 next;
12424 }
12425 }
12426
12427 my $NewLocation = ($FP_SubLocation)?$PName."->".$FP_SubLocation:$PName;
12428 $SubProblems{$FP_SubProblemType}{$NewLocation} = $FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation};
12429
12430 if(not defined $AllAffected)
12431 {
12432 $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}} = 1;
12433 }
12434 }
12435 }
12436
12437 %DupProblems = ();
12438 }
12439 }
12440
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012441 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012442 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012443}
12444
12445sub isUnnamed($) {
12446 return $_[0]=~/\Aunnamed\d+\Z/;
12447}
12448
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012449sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012450{
12451 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012452 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12453 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12454 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12455 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012456 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012457 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012458 }
12459 return $TypeName;
12460}
12461
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012462sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012463{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012464 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012465 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012466 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12467 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012468 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012469 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12470 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012471 return () if(not $Type{"Type"});
12472 if($Type{"Type"} ne $Type_Type)
12473 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012474 return () if(not $Type{"BaseType"});
12475 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012476 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012477 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012478 return %Type;
12479}
12480
12481my %TypeSpecAttributes = (
12482 "Const" => 1,
12483 "Volatile" => 1,
12484 "ConstVolatile" => 1,
12485 "Restrict" => 1,
12486 "Typedef" => 1
12487);
12488
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012489sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012490{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012491 my ($TypeId, $Info) = @_;
12492 if(not $TypeId or not $Info
12493 or not $Info->{$TypeId}) {
12494 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012495 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012496 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12497 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12498 }
12499 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012500 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012501 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012502 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012503 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012504 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012505 return %Type;
12506}
12507
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012508sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012509{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012510 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012511 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012512 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12513 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012514 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012515 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12516 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012517 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12518 my $PLevel = 0;
12519 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12520 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012521 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012522 return $PLevel if(not $Type{"BaseType"});
12523 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12524 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12525 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012526}
12527
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012528sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012529{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012530 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012531 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012532 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12533 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012534 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012535 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12536 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012537 return %Type if(not $Type{"BaseType"});
12538 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012539 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012540 return %Type;
12541}
12542
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012543sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012544{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012545 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012546 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012547 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12548 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012549 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012550 my $Qual = "";
12551 if($Type{"Type"} eq "Pointer") {
12552 $Qual .= "*";
12553 }
12554 elsif($Type{"Type"} eq "Ref") {
12555 $Qual .= "&";
12556 }
12557 elsif($Type{"Type"} eq "ConstVolatile") {
12558 $Qual .= "const volatile";
12559 }
12560 elsif($Type{"Type"} eq "Const"
12561 or $Type{"Type"} eq "Volatile"
12562 or $Type{"Type"} eq "Restrict") {
12563 $Qual .= lc($Type{"Type"});
12564 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012565 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012566 return $BQual.$Qual;
12567}
12568
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012569sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012570{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012571 my ($TypeId, $Info) = @_;
12572 if(not $TypeId or not $Info
12573 or not $Info->{$TypeId}) {
12574 return ();
12575 }
12576 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012577 return %Type if(not $Type{"BaseType"});
12578 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012579 {
12580 if($Info->{$BTid}) {
12581 return %{$Info->{$BTid}};
12582 }
12583 else { # something is going wrong
12584 return ();
12585 }
12586 }
12587 else {
12588 return %Type;
12589 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012590}
12591
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012592sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012593{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012594 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012595 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012596 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12597 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012598}
12599
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012600sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012601{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012602 my $Symbol = $_[0];
12603 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12604}
12605
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012606sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012607 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12608}
12609
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012610sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012611{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012612 my ($SInfo, $LibVersion) = @_;
12613
12614 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012615 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012616 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012617 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012618 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012619 return 1;
12620 }
12621 }
12622 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012623 if(my $ShortName = $SInfo->{"ShortName"})
12624 {
12625 if(index($ShortName,"<")!=-1
12626 and index($ShortName,">")!=-1) {
12627 return 1;
12628 }
12629 }
12630
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012631 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012632}
12633
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012634sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012635{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012636 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012637 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012638 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012639 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012640 { # class specialization
12641 return 1;
12642 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012643 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012644 { # method specialization
12645 return 1;
12646 }
12647 }
12648 return 0;
12649}
12650
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012651sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012652{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012653 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012654
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012655 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012656 { # non-public global data
12657 return 0;
12658 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012659
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012660 if(defined $SkipInternalSymbols)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012661 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012662 return 0 if($Symbol=~/($SkipInternalSymbols)/);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012663 }
12664
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012665 if($Symbol=~/\A_Z/)
12666 {
12667 if($Symbol=~/[CD][3-4]E/) {
12668 return 0;
12669 }
12670 }
12671
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012672 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012673 { # support for old ABI dumps in --headers-only mode
12674 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12675 {
12676 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12677 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012678 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012679 if(not $PType or $PType eq "Unknown") {
12680 return 0;
12681 }
12682 }
12683 }
12684 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012685 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012686 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012687 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12688
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012689 if($SkipSymbols{$LibVersion}{$Symbol})
12690 { # user defined symbols to ignore
12691 return 0;
12692 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012693
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012694 if($SymbolsListPath and not $SymbolsList{$Symbol})
12695 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012696 if(not $TargetHeadersPath or not $Header
12697 or not is_target_header($Header, 1))
12698 { # -symbols-list | -headers-list
12699 return 0;
12700 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012701 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012702
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012703 if($AppPath and not $SymbolsList_App{$Symbol})
12704 { # user defined symbols (in application)
12705 return 0;
12706 }
12707
12708 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12709
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012710 if($ClassId)
12711 {
12712 if(not isTargetType($ClassId, $LibVersion)) {
12713 return 0;
12714 }
12715 }
12716
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012717 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12718 if(not $NameSpace and $ClassId)
12719 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012720 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012721 }
12722 if($NameSpace)
12723 { # user defined namespaces to ignore
12724 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12725 return 0;
12726 }
12727 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12728 { # nested namespaces
12729 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12730 return 0;
12731 }
12732 }
12733 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012734 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012735 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012736 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012737 { # --skip-headers or <skip_headers> (not <skip_including>)
12738 if($Skip==1) {
12739 return 0;
12740 }
12741 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012742 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012743 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012744 { # user defined types
12745 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12746
12747 if(not $TypesList{$CName})
12748 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012749 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12750 {
12751 $CName=~s/\A\Q$NS\E\:\://g;
12752 }
12753
12754 if(not $TypesList{$CName})
12755 {
12756 my $Found = 0;
12757
12758 while($CName=~s/\:\:.+?\Z//)
12759 {
12760 if($TypesList{$CName})
12761 {
12762 $Found = 1;
12763 last;
12764 }
12765 }
12766
12767 if(not $Found) {
12768 return 0;
12769 }
12770 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012771 }
12772 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012773
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012774 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12775 { # non-target symbols
12776 return 0;
12777 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012778 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012779 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012780 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12781 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012782 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012783 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12784 { # inline virtual methods
12785 if($Type=~/InlineVirt/) {
12786 return 1;
12787 }
12788 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12789 if(not $Allocable)
12790 { # check bases
12791 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12792 {
12793 if(not isCopyingClass($DCId, $LibVersion))
12794 { # exists a derived class without default c-tor
12795 $Allocable=1;
12796 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012797 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012798 }
12799 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012800 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012801 return 0;
12802 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012803 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012804 else
12805 { # inline non-virtual methods
12806 return 0;
12807 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012808 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012809 }
12810 }
12811 return 1;
12812}
12813
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012814sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012815{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012816 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012817 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12818 {
12819 if(link_symbol($Symbol, 1, "+Deps"))
12820 { # linker can find a new symbol
12821 # in the old-version library
12822 # So, it's not a new symbol
12823 next;
12824 }
12825 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012826 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012827 next;
12828 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012829 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012830 }
12831}
12832
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012833sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012834{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012835 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012836 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12837 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012838 if(link_symbol($Symbol, 2, "+Deps"))
12839 { # linker can find an old symbol
12840 # in the new-version library
12841 next;
12842 }
12843 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012844 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012845 next;
12846 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012847 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012848 }
12849}
12850
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012851sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012852{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012853 my $Level = $_[0];
12854 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012855 { # checking added symbols
12856 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012857 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012858 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012859 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012860 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012861 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012862 { # checking removed symbols
12863 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012864 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012865 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012866 { # skip v-tables for templates, that should not be imported by applications
12867 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012868 if(my $CName = $VTableClass{$Symbol})
12869 {
12870 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12871 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012872 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012873 next;
12874 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012875 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012876
12877 if($SkipSymbols{1}{$Symbol})
12878 { # user defined symbols to ignore
12879 next;
12880 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012881 }
12882 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012883 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012884 }
12885 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12886 { # symbols for pure virtual methods cannot be called by clients
12887 next;
12888 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012889 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012890 }
12891}
12892
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012893sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012894{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012895 my ($LibVersion, $V) = @_;
12896 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12897 return $Cache{"checkDump"}{$LibVersion}{$V};
12898 }
12899 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012900}
12901
12902sub detectAdded_H($)
12903{
12904 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012905 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12906 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012907 if($Level eq "Source")
12908 { # remove symbol version
12909 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12910 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012911
12912 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12913 { # skip artificial constructors
12914 next;
12915 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012916 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012917 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12918 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012919 next;
12920 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012921 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012922 next;
12923 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012924 if(not defined $CompleteSignature{1}{$Symbol}
12925 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12926 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012927 if($UsedDump{2}{"SrcBin"})
12928 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012929 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012930 { # support for old and different (!) ABI dumps
12931 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12932 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012933 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012934 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012935 {
12936 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12937 {
12938 if($Lang eq "C")
12939 { # support for old ABI dumps: missed extern "C" functions
12940 next;
12941 }
12942 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012943 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012944 else
12945 {
12946 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012947 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012948 next;
12949 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012950 }
12951 }
12952 }
12953 }
12954 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012955 }
12956 }
12957}
12958
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012959sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012960{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012961 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012962 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12963 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012964 if($Level eq "Source")
12965 { # remove symbol version
12966 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12967 $Symbol=$SN;
12968 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012969 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12970 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012971 next;
12972 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012973 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012974 next;
12975 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012976 if(not defined $CompleteSignature{2}{$Symbol}
12977 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012978 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012979 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012980 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012981 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012982 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012983 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12984 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012985 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012986 if($CheckHeadersOnly)
12987 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012988 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12989 {
12990 if($Lang eq "C")
12991 { # support for old ABI dumps: missed extern "C" functions
12992 next;
12993 }
12994 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012995 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012996 else
12997 {
12998 if(not link_symbol($Symbol, 1, "-Deps"))
12999 { # skip removed inline symbols
13000 next;
13001 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013002 }
13003 }
13004 }
13005 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040013006 if(not checkDump(1, "2.15"))
13007 {
13008 if($Symbol=~/_IT_E\Z/)
13009 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
13010 next;
13011 }
13012 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013013 if(not $CompleteSignature{1}{$Symbol}{"Class"})
13014 {
13015 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
13016 {
13017 if(defined $Constants{2}{$Short})
13018 {
13019 my $Val = $Constants{2}{$Short}{"Value"};
13020 if(defined $Func_ShortName{2}{$Val})
13021 { # old name defined to new
13022 next;
13023 }
13024 }
13025 }
13026
13027 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013028 $RemovedInt{$Level}{$Symbol} = 1;
13029 if($Level eq "Source")
13030 { # search for a source-compatible equivalent
13031 setAlternative($Symbol, $Level);
13032 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013033 }
13034 }
13035}
13036
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013037sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013038{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013039 my $Level = $_[0];
13040 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013041 { # checking added symbols
13042 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013043 next if($CompleteSignature{2}{$Symbol}{"Private"});
13044 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013045 if($Level eq "Binary")
13046 {
13047 if($CompleteSignature{2}{$Symbol}{"InLine"})
13048 {
13049 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
13050 { # skip inline non-virtual functions
13051 next;
13052 }
13053 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013054 }
13055 else
13056 { # Source
13057 if($SourceAlternative_B{$Symbol}) {
13058 next;
13059 }
13060 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013061 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013062 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013063 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013064 { # checking removed symbols
13065 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013066 next if($CompleteSignature{1}{$Symbol}{"Private"});
13067 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013068 if($Level eq "Binary")
13069 {
13070 if($CompleteSignature{1}{$Symbol}{"InLine"})
13071 {
13072 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
13073 { # skip inline non-virtual functions
13074 next;
13075 }
13076 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013077 }
13078 else
13079 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013080 if(my $Alt = $SourceAlternative{$Symbol})
13081 {
13082 if(defined $CompleteSignature{1}{$Alt}
13083 and $CompleteSignature{1}{$Symbol}{"Const"})
13084 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013085 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013086 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013087 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013088 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013089 }
13090 else
13091 { # do NOT show removed symbol
13092 next;
13093 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013094 }
13095 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013096 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013097 }
13098}
13099
13100sub addParamNames($)
13101{
13102 my $LibraryVersion = $_[0];
13103 return if(not keys(%AddIntParams));
13104 my $SecondVersion = $LibraryVersion==1?2:1;
13105 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13106 {
13107 next if(not keys(%{$AddIntParams{$Interface}}));
13108 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013109 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013110 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13111 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013112 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013113 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13114 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13115 {
13116 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13117 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13118 }
13119 }
13120 else {
13121 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13122 }
13123 }
13124 }
13125 }
13126}
13127
13128sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013129{ # detect changed typedefs to show
13130 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013131 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13132 {
13133 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013134 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13135 if(not $BName1 or isAnon($BName1)) {
13136 next;
13137 }
13138 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13139 if(not $BName2 or isAnon($BName2)) {
13140 next;
13141 }
13142 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013143 $ChangedTypedef{$Typedef} = 1;
13144 }
13145 }
13146}
13147
13148sub get_symbol_suffix($$)
13149{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013150 my ($Symbol, $Full) = @_;
13151 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013152 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013153 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013154 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013155 if(not $Full) {
13156 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13157 }
13158 return $Suffix;
13159}
13160
13161sub get_symbol_prefix($$)
13162{
13163 my ($Symbol, $LibVersion) = @_;
13164 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13165 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13166 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013167 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013168 }
13169 return $ShortName;
13170}
13171
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013172sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013173{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013174 my $Symbol = $_[0];
13175 my $PSymbol = $Symbol;
13176 if(not defined $CompleteSignature{2}{$PSymbol}
13177 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13178 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13179 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013180 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013181 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013182 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013183 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013184 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13185 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013186 {
13187 if(defined $CompleteSignature{2}{$PSymbol}
13188 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13189 {
13190 $SourceAlternative{$Symbol} = $PSymbol;
13191 $SourceAlternative_B{$PSymbol} = $Symbol;
13192 if(not defined $CompleteSignature{1}{$PSymbol}
13193 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13194 $SourceReplacement{$Symbol} = $PSymbol;
13195 }
13196 }
13197 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013198 }
13199 else
13200 {
13201 foreach my $Sp ("KV", "VK", "K", "V")
13202 {
13203 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13204 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13205 {
13206 if(defined $CompleteSignature{2}{$PSymbol}
13207 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13208 {
13209 $SourceAlternative{$Symbol} = $PSymbol;
13210 $SourceAlternative_B{$PSymbol} = $Symbol;
13211 if(not defined $CompleteSignature{1}{$PSymbol}
13212 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13213 $SourceReplacement{$Symbol} = $PSymbol;
13214 }
13215 }
13216 }
13217 $PSymbol = $Symbol;
13218 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013219 }
13220 }
13221 }
13222 return "";
13223}
13224
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013225sub getSymKind($$)
13226{
13227 my ($Symbol, $LibVersion) = @_;
13228 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13229 {
13230 return "Global_Data";
13231 }
13232 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13233 {
13234 return "Method";
13235 }
13236 return "Function";
13237}
13238
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013239sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013240{
13241 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013242 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013243
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013244 mergeBases($Level);
13245
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013246 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013247 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013248 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013249 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013250 next;
13251 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013252 if(defined $CompleteSignature{1}{$Symbol}
13253 and $CompleteSignature{1}{$Symbol}{"Header"})
13254 { # double-check added symbol
13255 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013256 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013257 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013258 next;
13259 }
13260 if($Symbol=~/\A(_Z|\?)/)
13261 { # C++
13262 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13263 }
13264 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13265 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013266 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13267 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013268 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013269 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013270 {
13271 if($TName_Tid{1}{$AffectedClass_Name})
13272 { # class should exist in previous version
13273 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13274 { # old v-table is NOT copied by old applications
13275 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13276 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013277 "Target"=>get_Signature($Symbol, 2),
13278 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013279 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013280 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013281 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013282 }
13283 }
13284 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013285 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13286 { # check all removed exported symbols
13287 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013288 next;
13289 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013290 if(defined $CompleteSignature{2}{$Symbol}
13291 and $CompleteSignature{2}{$Symbol}{"Header"})
13292 { # double-check removed symbol
13293 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013294 }
13295 if($CompleteSignature{1}{$Symbol}{"Private"})
13296 { # skip private methods
13297 next;
13298 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013299 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013300 next;
13301 }
13302 $CheckedSymbols{$Level}{$Symbol} = 1;
13303 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13304 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013305 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13306 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013307 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013308 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13309 {
13310 if($TName_Tid{2}{$AffectedClass_Name})
13311 { # class should exist in newer version
13312 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13313 { # old v-table is NOT copied by old applications
13314 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13315 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013316 "Target"=>get_Signature($OverriddenMethod, 1),
13317 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013318 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013319 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013320 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013321 }
13322 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013323 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013324 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013325 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013326 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013327 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013328 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013329 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013330 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013331 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013332 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013333 {
13334 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13335 "Target"=>$tr_name{$Symbol},
13336 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013337 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013338 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013339 else
13340 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013341 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013342 "Target"=>$tr_name{$Symbol},
13343 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013344 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013345 }
13346 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013347 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013348 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013349 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013350 {
13351 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13352 "Target"=>$tr_name{$Symbol},
13353 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013354 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013355 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013356 else
13357 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013358 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013359 "Target"=>$tr_name{$Symbol},
13360 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013361 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013362 }
13363 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013364 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13365 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13366 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13367 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13368 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013369 {
13370 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013371 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013372 $ProblemType = "Global_Data_Symbol_Changed_Type";
13373 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013374 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13375 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013376 "Old_Type"=>$RTName1,
13377 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013378 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013379 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013380 }
13381 }
13382 }
13383 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013384 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013385 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013386 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013387 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013388 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013389 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013390 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013391 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13392 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013393 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013394 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013395 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013396 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013397 }
13398 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013399 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13400 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013401 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013402 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013403 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013404 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013405 }
13406 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013407 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013408 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013409 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013410 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013411 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013412 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013413 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013414 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013415 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013416 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013417 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013418 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013419 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013420 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013421 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013422 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013423 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013424 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013425 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013426 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013427 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013428 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013429 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013430 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013431 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013432 { # "volatile" to non-"volatile"
13433
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013434 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013435 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013436 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013437 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013438 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013439 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013440 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013441 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013442 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013443 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013444 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013445 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013446 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013447 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013448 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013449 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013450 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013451 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13452 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013453 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013454 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013455 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013456 }
13457 }
13458 }
13459 }
13460 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013461 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13462 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013463 $CurrentSymbol = $Symbol;
13464
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013465 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13466 if($Level eq "Source")
13467 { # remove symbol version
13468 $Symbol=$SN;
13469 }
13470 else
13471 { # Binary
13472 if(not $SV)
13473 { # symbol without version
13474 if(my $VSym = $SymVer{1}{$Symbol})
13475 { # the symbol is linked with versioned symbol
13476 if($CompleteSignature{2}{$VSym}{"MnglName"})
13477 { # show report for symbol@ver only
13478 next;
13479 }
13480 elsif(not link_symbol($VSym, 2, "-Deps"))
13481 { # changed version: sym@v1 to sym@v2
13482 # do NOT show report for symbol
13483 next;
13484 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013485 }
13486 }
13487 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013488 my $PSymbol = $Symbol;
13489 if($Level eq "Source"
13490 and my $S = $SourceReplacement{$Symbol})
13491 { # take a source-compatible replacement function
13492 $PSymbol = $S;
13493 }
13494 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013495 { # private symbols
13496 next;
13497 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013498 if(not defined $CompleteSignature{1}{$Symbol}
13499 or not defined $CompleteSignature{2}{$PSymbol})
13500 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013501 next;
13502 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013503 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13504 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13505 { # no mangled name
13506 next;
13507 }
13508 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13509 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013510 { # without a header
13511 next;
13512 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013513
13514 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13515 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13516 { # became pure
13517 next;
13518 }
13519 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13520 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13521 { # became non-pure
13522 next;
13523 }
13524
13525 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13526 { # exported, target, inline virtual and pure virtual
13527 next;
13528 }
13529 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13530 { # exported, target, inline virtual and pure virtual
13531 next;
13532 }
13533
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013534 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013535 {
13536 if($CompleteSignature{1}{$Symbol}{"Data"}
13537 and $CompleteSignature{2}{$PSymbol}{"Data"})
13538 {
13539 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13540 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13541 if(defined $Value1)
13542 {
13543 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13544 if(defined $Value2)
13545 {
13546 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13547 if($Value1 ne $Value2)
13548 {
13549 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13550 "Old_Value"=>$Value1,
13551 "New_Value"=>$Value2,
13552 "Target"=>get_Signature($Symbol, 1) );
13553 }
13554 }
13555 }
13556 }
13557 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013558
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013559 if($CompleteSignature{2}{$PSymbol}{"Private"})
13560 {
13561 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13562 "Target"=>get_Signature_M($PSymbol, 2) );
13563 }
13564 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13565 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13566 {
13567 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13568 "Target"=>get_Signature_M($PSymbol, 2) );
13569 }
13570 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13571 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13572 {
13573 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13574 "Target"=>get_Signature_M($PSymbol, 2) );
13575 }
13576
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013577 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013578 mergeVirtualTables($Symbol, $Level);
13579
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013580 if($COMPILE_ERRORS)
13581 { # if some errors occurred at the compiling stage
13582 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013583 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013584 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013585 { # missed information about parameters in newer version
13586 next;
13587 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013588 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013589 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013590 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013591 next;
13592 }
13593 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013594 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013595 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013596 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013597 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13598 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013599 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13600 "Target"=>get_Signature($Symbol, 1)
13601 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013602 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013603 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013604 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13605 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013606 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013607 "Target"=>get_Signature($Symbol, 1)
13608 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013609 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013610 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13611 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013612 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013613 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013614 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013615 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13616 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13617 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013618 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013619 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013620 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13621 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013622 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013623 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013624 my $ProblemType = "Virtual_Method_Position";
13625 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13626 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013627 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013628 if(isUsedClass($Class_Id, 1, $Level))
13629 {
13630 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013631 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013632 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013633 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13634 next;
13635 }
13636 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013637 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013638 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13639 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013640 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013641 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013642 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013643 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013644 }
13645 }
13646 }
13647 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013648 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13649 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013650 { # do NOT check type changes in pure virtuals
13651 next;
13652 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013653 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013654 if($Symbol=~/\A(_Z|\?)/
13655 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013656 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013657 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013658 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013659 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013660 }
13661 }
13662 else
13663 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013664 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013665 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013666 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013667 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13668 last if($PType2_Name eq "...");
13669 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13670 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013671 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013672 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013673 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013674 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13675 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013676 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13677 $ParamPos_Prev = "lost";
13678 }
13679 }
13680 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013681 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013682 }
13683 if($ParamPos_Prev eq "lost")
13684 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013685 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013686 {
13687 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013688 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013689 $ProblemType = "Added_Unnamed_Parameter";
13690 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013691 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013692 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013693 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013694 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013695 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013696 }
13697 else
13698 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013699 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013700 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013701 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013702 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13703 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013704 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013705 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013706 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013707 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013708 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013709 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013710 "Param_Type"=>$PType2_Name,
13711 "Old_Value"=>$PName_Old,
13712 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013713 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013714 }
13715 }
13716 else
13717 {
13718 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013719 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013720 $ProblemType = "Added_Middle_Unnamed_Parameter";
13721 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013722 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013723 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013724 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013725 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013726 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013727 }
13728 }
13729 }
13730 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013731 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013732 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013733 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013734 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013735 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013736 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013737 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013738 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013739 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013740 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13741 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013742 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013743 }
13744 }
13745 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013746 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013747 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013748 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013749 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13750 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013751 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13752 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013753 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013754 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013755 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013756 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13757 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013758 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13759 $ParamPos_New = "lost";
13760 }
13761 }
13762 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013763 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013764 }
13765 if($ParamPos_New eq "lost")
13766 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013767 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013768 {
13769 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013770 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013771 $ProblemType = "Removed_Unnamed_Parameter";
13772 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013773 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013774 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013775 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013776 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013777 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013778 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013779 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013780 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013781 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013782 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013783 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013784 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013785 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013786 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013787 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013788 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013789 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013790 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013791 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013792 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013793 "Old_Value"=>$PName,
13794 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013795 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013796 }
13797 }
13798 else
13799 {
13800 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013801 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013802 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13803 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013804 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013805 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013806 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013807 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013808 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013809 }
13810 }
13811 }
13812 }
13813 }
13814 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013815 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13816 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013817 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013818
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013819 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013820 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013821 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13822 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013823 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013824
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013825 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013826 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013827 if($SubProblemType eq "Return_Type_And_Size") {
13828 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13829 }
13830 elsif($SubProblemType eq "Return_Type_Format") {
13831 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13832 }
13833 else {
13834 $ProblemTypes{"Global_Data_Type"} = 1;
13835 }
13836
13837 # quals
13838 if($SubProblemType eq "Return_Type"
13839 or $SubProblemType eq "Return_Type_And_Size"
13840 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013841 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013842 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13843 { # const to non-const
13844 if($RR==2) {
13845 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13846 }
13847 else {
13848 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13849 }
13850 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013851 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013852 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13853 { # non-const to const
13854 if($RA==2) {
13855 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13856 }
13857 else {
13858 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13859 }
13860 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013861 }
13862 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013863 }
13864 else
13865 {
13866 # quals
13867 if($SubProblemType eq "Return_Type"
13868 or $SubProblemType eq "Return_Type_And_Size"
13869 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013870 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013871 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013872 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013873 if(addedQual($Old_Value, $New_Value, "volatile"))
13874 {
13875 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13876 if($Level ne "Source"
13877 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13878 $ProblemTypes{"Return_Type"} = 1;
13879 }
13880 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013881 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013882 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13883 {
13884 if($RA==2) {
13885 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13886 }
13887 else {
13888 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13889 }
13890 if($Level ne "Source"
13891 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13892 $ProblemTypes{"Return_Type"} = 1;
13893 }
13894 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013895 }
13896 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013897 if($Level eq "Binary"
13898 and not $CompleteSignature{1}{$Symbol}{"Data"})
13899 {
13900 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13901 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13902 { # if one of the architectures is unknown
13903 # then set other arhitecture to unknown too
13904 ($Arch1, $Arch2) = ("unknown", "unknown");
13905 }
13906 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013907 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013908 {
13909 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13910 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13911 }
13912 else
13913 {
13914 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13915 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13916 }
13917
13918 if($SubProblemType eq "Return_Type_Became_Void")
13919 {
13920 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13921 { # parameters stack has been affected
13922 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013923 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013924 }
13925 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013926 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013927 }
13928 }
13929 }
13930 elsif($SubProblemType eq "Return_Type_From_Void")
13931 {
13932 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13933 { # parameters stack has been affected
13934 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013935 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013936 }
13937 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013938 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013939 }
13940 }
13941 }
13942 elsif($SubProblemType eq "Return_Type"
13943 or $SubProblemType eq "Return_Type_And_Size"
13944 or $SubProblemType eq "Return_Type_Format")
13945 {
13946 if($Conv1{"Method"} ne $Conv2{"Method"})
13947 {
13948 if($Conv1{"Method"} eq "stack")
13949 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013950 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013951 }
13952 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013953 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013954 }
13955 }
13956 else
13957 {
13958 if($Conv1{"Method"} eq "reg")
13959 {
13960 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13961 {
13962 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013963 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013964 }
13965 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013966 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013967 }
13968 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013969 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013970 }
13971 }
13972 }
13973 }
13974 }
13975 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013976
13977 if(not keys(%ProblemTypes))
13978 { # default
13979 $ProblemTypes{$SubProblemType} = 1;
13980 }
13981
13982 foreach my $ProblemType (keys(%ProblemTypes))
13983 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013984 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013985 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013986 }
13987 if($ReturnType1_Id and $ReturnType2_Id)
13988 {
13989 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013990 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13991
13992 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013993
13994 if($CompleteSignature{1}{$Symbol}{"Data"})
13995 {
13996 if($Level eq "Binary")
13997 {
13998 if(get_PLevel($ReturnType1_Id, 1)==0)
13999 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014000 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014001 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014002
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014003 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
14004 {
14005 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014006 {
14007 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
14008 {
14009 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
14010 last;
14011 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014012 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014013 }
14014 }
14015 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014016 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014017 {
14018 if(defined $GlobalDataObject{1}{$Symbol}
14019 and defined $GlobalDataObject{2}{$Symbol})
14020 {
14021 my $Old_Size = $GlobalDataObject{1}{$Symbol};
14022 my $New_Size = $GlobalDataObject{2}{$Symbol};
14023 if($Old_Size!=$New_Size)
14024 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014025 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014026 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014027 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014028 }
14029 }
14030 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014031 }
14032 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014033
14034 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014035 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014036 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014037 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014038 my $NewLocation = "retval";
14039 if($SubLocation and $SubLocation ne "retval") {
14040 $NewLocation = "retval->".$SubLocation;
14041 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014042 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
14043 }
14044 }
14045
14046 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
14047 {
14048 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
14049 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014050 my $NewLocation = "retval";
14051 if($SubLocation and $SubLocation ne "retval") {
14052 $NewLocation = "retval->".$SubLocation;
14053 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014054 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014055 }
14056 }
14057 }
14058
14059 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014060 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
14061 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
14062 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014063 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014064 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014065 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
14066 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014067 if($ThisPtr1_Id and $ThisPtr2_Id)
14068 {
14069 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014070 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
14071 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014072 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014073 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014074 {
14075 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014076 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014077 }
14078 }
14079 }
14080 }
14081 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014082 if($Level eq "Binary") {
14083 mergeVTables($Level);
14084 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014085 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14086 $CheckedSymbols{$Level}{$Symbol} = 1;
14087 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014088}
14089
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014090sub rmQuals($$)
14091{
14092 my ($Value, $Qual) = @_;
14093 if(not $Qual) {
14094 return $Value;
14095 }
14096 if($Qual eq "all")
14097 { # all quals
14098 $Qual = "const|volatile|restrict";
14099 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014100 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014101 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014102 }
14103 return $Value;
14104}
14105
14106sub cmpBTypes($$$$)
14107{
14108 my ($T1, $T2, $V1, $V2) = @_;
14109 $T1 = uncover_typedefs($T1, $V1);
14110 $T2 = uncover_typedefs($T2, $V2);
14111 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14112}
14113
14114sub addedQual($$$)
14115{
14116 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014117 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014118}
14119
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014120sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014121{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014122 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014123 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014124}
14125
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014126sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014127{
14128 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14129 $Old_Value = uncover_typedefs($Old_Value, $V1);
14130 $New_Value = uncover_typedefs($New_Value, $V2);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014131
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014132 if($Old_Value eq $New_Value)
14133 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014134 return 0;
14135 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014136 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014137 { # without a qual
14138 return 0;
14139 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014140 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014141 { # became non-qual
14142 return 1;
14143 }
14144 else
14145 {
14146 my @BQ1 = getQualModel($Old_Value, $Qual);
14147 my @BQ2 = getQualModel($New_Value, $Qual);
14148 foreach (0 .. $#BQ1)
14149 { # removed qual
14150 if($BQ1[$_]==1
14151 and $BQ2[$_]!=1)
14152 {
14153 return 2;
14154 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014155 }
14156 }
14157 return 0;
14158}
14159
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014160sub getQualModel($$)
14161{
14162 my ($Value, $Qual) = @_;
14163 if(not $Qual) {
14164 return $Value;
14165 }
14166
14167 # cleaning
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014168 while($Value=~/(\w+)/)
14169 {
14170 my $W = $1;
14171
14172 if($W eq $Qual) {
14173 $Value=~s/\b$W\b/\@/g;
14174 }
14175 else {
14176 $Value=~s/\b$W\b//g;
14177 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014178 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014179
14180 $Value=~s/\@/$Qual/g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014181 $Value=~s/[^\*\&\w]+//g;
14182
14183 # modeling
14184 # int*const*const == 011
14185 # int**const == 001
14186 my @Model = ();
14187 my @Elems = split(/[\*\&]/, $Value);
14188 if(not @Elems) {
14189 return (0);
14190 }
14191 foreach (@Elems)
14192 {
14193 if($_ eq $Qual) {
14194 push(@Model, 1);
14195 }
14196 else {
14197 push(@Model, 0);
14198 }
14199 }
14200
14201 return @Model;
14202}
14203
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014204my %StringTypes = map {$_=>1} (
14205 "char*",
14206 "char const*"
14207);
14208
14209my %CharTypes = map {$_=>1} (
14210 "char",
14211 "char const"
14212);
14213
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014214sub showVal($$$)
14215{
14216 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014217 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014218 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014219 if(substr($Value, 0, 2) eq "_Z")
14220 {
14221 if(my $Unmangled = $tr_name{$Value}) {
14222 return $Unmangled;
14223 }
14224 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014225 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014226 { # strings
14227 return "\"$Value\"";
14228 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014229 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014230 { # characters
14231 return "\'$Value\'";
14232 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014233 if($Value eq "")
14234 { # other
14235 return "\'\'";
14236 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014237 return $Value;
14238}
14239
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014240sub getRegs($$$)
14241{
14242 my ($LibVersion, $Symbol, $Pos) = @_;
14243
14244 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14245 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014246 my %Regs = ();
14247 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14248 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014249 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014250 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14251 }
14252 }
14253
14254 return join(", ", sort keys(%Regs));
14255 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014256 elsif(defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}
14257 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}
14258 and not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}{"offset"})
14259 {
14260 return "unknown";
14261 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014262
14263 return undef;
14264}
14265
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014266sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014267{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014268 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014269 if(not $Symbol) {
14270 return;
14271 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014272 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14273 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14274 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14275 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014276 if(not $PType1_Id
14277 or not $PType2_Id) {
14278 return;
14279 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014280
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014281 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014282 { # do not merge "this"
14283 if($PName1 eq "this" or $PName2 eq "this") {
14284 return;
14285 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014286 }
14287
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014288 my %Type1 = get_Type($PType1_Id, 1);
14289 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014290
14291 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14292
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014293 my %BaseType1 = get_BaseType($PType1_Id, 1);
14294 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014295
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014296 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014297
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014298 if($Level eq "Binary")
14299 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014300 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014301 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14302 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14303 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14304 {
14305 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014306 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014307 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014308 }
14309 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14310 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14311 {
14312 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014313 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014314 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014315 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014316 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014317
14318 if(defined $UsedDump{1}{"DWARF"}
14319 and defined $UsedDump{2}{"DWARF"})
14320 {
14321 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14322 {
14323 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14324 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014325
14326 if($Old_Regs ne "unknown"
14327 and $New_Regs ne "unknown")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014328 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014329 if($Old_Regs and $New_Regs)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014330 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014331 if($Old_Regs ne $New_Regs)
14332 {
14333 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14334 "Target"=>$PName1,
14335 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14336 "Old_Value"=>$Old_Regs,
14337 "New_Value"=>$New_Regs );
14338 }
14339 }
14340 elsif($Old_Regs and not $New_Regs)
14341 {
14342 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014343 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014344 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014345 "Old_Value"=>$Old_Regs );
14346 }
14347 elsif(not $Old_Regs and $New_Regs)
14348 {
14349 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14350 "Target"=>$PName1,
14351 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014352 "New_Value"=>$New_Regs );
14353 }
14354 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014355
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014356 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14357 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14358 {
14359 if($Old_Offset ne $New_Offset)
14360 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014361 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14362 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14363
14364 $Old_Offset = $Old_Offset - $Start1;
14365 $New_Offset = $New_Offset - $Start2;
14366
14367 if($Old_Offset ne $New_Offset)
14368 {
14369 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14370 "Target"=>$PName1,
14371 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14372 "Old_Value"=>$Old_Offset,
14373 "New_Value"=>$New_Offset );
14374 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014375 }
14376 }
14377 }
14378 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014379 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014380 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14381 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014382 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014383 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014384 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14385 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014386 if(not checkDump(1, "2.13")
14387 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014388 { # support for old ABI dumps
14389 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014390 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014391 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014392 and $Value_Old eq "false" and $Value_New eq "0")
14393 { # int class::method ( bool p = 0 );
14394 # old ABI dumps: "false"
14395 # new ABI dumps: "0"
14396 $Value_Old = "0";
14397 }
14398 }
14399 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014400 if(not checkDump(1, "2.18")
14401 and checkDump(2, "2.18"))
14402 { # support for old ABI dumps
14403 if(not defined $Value_Old
14404 and substr($Value_New, 0, 2) eq "_Z") {
14405 $Value_Old = $Value_New;
14406 }
14407 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014408 if(defined $Value_Old)
14409 {
14410 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14411 if(defined $Value_New)
14412 {
14413 $Value_New = showVal($Value_New, $PType2_Id, 2);
14414 if($Value_Old ne $Value_New)
14415 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014416 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014417 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014418 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014419 "Old_Value"=>$Value_Old,
14420 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014421 }
14422 }
14423 else
14424 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014425 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014426 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014427 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014428 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014429 }
14430 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014431 elsif(defined $Value_New)
14432 {
14433 $Value_New = showVal($Value_New, $PType2_Id, 2);
14434 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14435 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014436 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014437 "New_Value"=>$Value_New );
14438 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014439 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014440
14441 if($ChkRnmd)
14442 {
14443 if($PName1 and $PName2 and $PName1 ne $PName2
14444 and $PType1_Id!=-1 and $PType2_Id!=-1
14445 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14446 { # except unnamed "..." value list (Id=-1)
14447 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14448 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014449 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014450 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14451 "Old_Value"=>$PName1,
14452 "New_Value"=>$PName2,
14453 "New_Signature"=>get_Signature($Symbol, 2) );
14454 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014455 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014456
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014457 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014458 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014459
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014460 foreach my $SubProblemType (keys(%SubProblems))
14461 { # add new problems, remove false alarms
14462 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14463 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014464
14465 # quals
14466 if($SubProblemType eq "Parameter_Type"
14467 or $SubProblemType eq "Parameter_Type_And_Size"
14468 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014469 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014470 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014471 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014472 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014473 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014474 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014475 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14476 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14477 }
14478 }
14479 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14480 {
14481 if(removedQual($Old_Value, $New_Value, "volatile")) {
14482 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014483 }
14484 }
14485 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14486 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14487 { # int to "int const"
14488 delete($SubProblems{$SubProblemType});
14489 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014490 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014491 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14492 { # "int const" to int
14493 delete($SubProblems{$SubProblemType});
14494 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014495 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14496 { # "const" to non-"const"
14497 if($RR==2) {
14498 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14499 }
14500 else {
14501 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14502 }
14503 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014504 }
14505 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014506
14507 if($Level eq "Source")
14508 {
14509 foreach my $SubProblemType (keys(%SubProblems))
14510 {
14511 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14512 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14513
14514 if($SubProblemType eq "Parameter_Type")
14515 {
14516 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14517 delete($SubProblems{$SubProblemType});
14518 }
14519 }
14520 }
14521 }
14522
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014523 foreach my $SubProblemType (keys(%SubProblems))
14524 { # modify/register problems
14525 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14526 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014527 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14528 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014529
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014530 my $NewProblemType = $SubProblemType;
14531 if($Old_Value eq "..." and $New_Value ne "...")
14532 { # change from "..." to "int"
14533 if($ParamPos1==0)
14534 { # ISO C requires a named argument before "..."
14535 next;
14536 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014537 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014538 }
14539 elsif($New_Value eq "..." and $Old_Value ne "...")
14540 { # change from "int" to "..."
14541 if($ParamPos2==0)
14542 { # ISO C requires a named argument before "..."
14543 next;
14544 }
14545 $NewProblemType = "Parameter_Became_VaList";
14546 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014547 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014548 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014549 {
14550 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014551 if($Arch1 eq "unknown"
14552 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014553 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014554 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014555 ($Arch1, $Arch2) = ("unknown", "unknown");
14556 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014557 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014558 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014559 { # real
14560 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14561 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14562 }
14563 else
14564 { # model
14565 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14566 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14567 }
14568 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014569 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014570 if($Conv1{"Method"} eq "stack")
14571 {
14572 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14573 $NewProblemType = "Parameter_Type_And_Stack";
14574 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014575 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014576 elsif($Conv1{"Method"} eq "reg")
14577 {
14578 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14579 $NewProblemType = "Parameter_Type_And_Register";
14580 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014581 }
14582 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014583 elsif($Conv1{"Method"} ne "unknown"
14584 and $Conv2{"Method"} ne "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014585 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014586 if($Conv1{"Method"} eq "stack") {
14587 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014588 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014589 elsif($Conv1{"Method"} eq "register") {
14590 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014591 }
14592 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014593 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14594 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014595 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014596 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014597 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014598 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014599 "New_Signature"=>get_Signature($Symbol, 2) );
14600 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014601 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014602
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014603 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014604
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014605 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014606 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14607 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014608 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014609 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014610 {
14611 my $NewProblemType = $SubProblemType;
14612 if($SubProblemType eq "DataType_Size")
14613 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014614 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014615 { # stack has been affected
14616 $NewProblemType = "DataType_Size_And_Stack";
14617 }
14618 }
14619 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014620 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014621 }
14622 }
14623}
14624
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014625sub find_ParamPair_Pos_byName($$$)
14626{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014627 my ($Name, $Symbol, $LibVersion) = @_;
14628 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014629 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014630 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14631 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014632 {
14633 return $ParamPos;
14634 }
14635 }
14636 return "lost";
14637}
14638
14639sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14640{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014641 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014642 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014643 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014644 {
14645 next if($Order eq "backward" and $ParamPos>$MediumPos);
14646 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014647 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14648 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014649 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014650 push(@Positions, $ParamPos);
14651 }
14652 }
14653 return @Positions;
14654}
14655
14656sub getTypeIdByName($$)
14657{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014658 my ($TypeName, $LibVersion) = @_;
14659 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014660}
14661
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014662sub diffTypes($$$)
14663{
14664 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14665 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14666 }
14667 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14668 { # skip recursive declarations
14669 return 0;
14670 }
14671
14672 pushType($_[0], $_[1], \@RecurTypes_Diff);
14673 my $Diff = diffTypes_I(@_);
14674 pop(@RecurTypes_Diff);
14675
14676 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14677}
14678
14679sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014680{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014681 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014682
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014683 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14684 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014685
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014686 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14687 { # equal types
14688 return 0;
14689 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014690 if($Type1_Pure{"Name"} eq "void")
14691 { # from void* to something
14692 return 0;
14693 }
Andrey Ponomarenkof9f25c92016-07-26 17:20:17 +030014694 if($Type2_Pure{"Name"} eq "void")
14695 { # from something to void*
14696 return 0;
14697 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014698 if($Type1_Pure{"Name"}=~/\*/
14699 or $Type2_Pure{"Name"}=~/\*/)
14700 { # compared in detectTypeChange()
14701 return 0;
14702 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014703
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014704 my %FloatType = map {$_=>1} (
14705 "float",
14706 "double",
14707 "long double"
14708 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014709
14710 my $T1 = $Type1_Pure{"Type"};
14711 my $T2 = $Type2_Pure{"Type"};
14712
14713 if($T1 eq "Struct"
14714 and $T2 eq "Class")
14715 { # compare as data structures
14716 $T2 = "Struct";
14717 }
14718
14719 if($T1 eq "Class"
14720 and $T2 eq "Struct")
14721 { # compare as data structures
14722 $T1 = "Struct";
14723 }
14724
14725 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014726 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014727 if($T1 eq "Intrinsic"
14728 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014729 { # "int" to "enum"
14730 return 0;
14731 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014732 elsif($T2 eq "Intrinsic"
14733 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014734 { # "enum" to "int"
14735 return 0;
14736 }
14737 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014738 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014739 # ...
14740 return 1;
14741 }
14742 }
14743 else
14744 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014745 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014746 {
14747 if($FloatType{$Type1_Pure{"Name"}}
14748 or $FloatType{$Type2_Pure{"Name"}})
14749 { # "float" to "double"
14750 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014751 if($Level eq "Source")
14752 { # Safe
14753 return 0;
14754 }
14755 else {
14756 return 1;
14757 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014758 }
14759 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014760 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014761 {
14762 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14763 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014764 if(not @Membs1
14765 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014766 { # private
14767 return 0;
14768 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014769 if($#Membs1!=$#Membs2)
14770 { # different number of elements
14771 return 1;
14772 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014773 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014774 {
14775 foreach my $Pos (@Membs1)
14776 { # compare elements by name and value
14777 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14778 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14779 { # different names
14780 return 1;
14781 }
14782 }
14783 }
14784 else
14785 {
14786 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014787 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014788 if($Level eq "Source")
14789 {
14790 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14791 { # different names
14792 return 1;
14793 }
14794 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014795
14796 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14797 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14798
14799 if($MT1{"Name"} ne $MT2{"Name"}
14800 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14801 {
14802 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14803 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14804
14805 if($PL1 ne $PL2)
14806 { # different pointer level
14807 return 1;
14808 }
14809
14810 # compare base types
14811 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14812 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14813
14814 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14815 { # different types
14816 return 1;
14817 }
14818 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014819 }
14820 }
14821 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014822 else
14823 {
14824 # TODO: arrays, etc.
14825 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014826 }
14827 return 0;
14828}
14829
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014830sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014831{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014832 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014833 if(not $Type1_Id or not $Type2_Id) {
14834 return ();
14835 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014836 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014837 my %Type1 = get_Type($Type1_Id, 1);
14838 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014839 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14840 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014841
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030014842 if(defined $SkipTypedefUncover)
14843 {
14844 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}) {
14845 return ();
14846 }
14847
14848 if(cmpBTypes($Type1_Pure{"Name"}, $Type2_Pure{"Name"}, 1, 2)) {
14849 return ();
14850 }
14851 }
14852
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014853 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14854 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 +040014855
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014856 if(defined $UsedDump{1}{"DWARF"})
14857 {
14858 if($Type1_Pure{"Name"} eq "__unknown__"
14859 or $Type2_Pure{"Name"} eq "__unknown__"
14860 or $Type1_Base{"Name"} eq "__unknown__"
14861 or $Type2_Base{"Name"} eq "__unknown__")
14862 { # Error ABI dump
14863 return ();
14864 }
14865 }
14866
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014867 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14868 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014869 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14870 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14871 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14872 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14873 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14874 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14875 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014876 if($Type1{"Name"} eq $Type2{"Name"})
14877 {
14878 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14879 { # will be reported in mergeTypes() as typedef problem
14880 return ();
14881 }
14882 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14883 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14884 if(%Typedef_1 and %Typedef_2)
14885 {
14886 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14887 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14888 { # const Typedef
14889 return ();
14890 }
14891 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014892 }
14893 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14894 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014895 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014896 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14897 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014898 {
14899 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14900 "Old_Value"=>$Type1_Base{"Name"},
14901 "New_Value"=>$Type2_Base{"Name"},
14902 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014903 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014904 }
14905 else
14906 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014907 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014908 { # format change
14909 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14910 "Old_Value"=>$Type1_Base{"Name"},
14911 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014912 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014913 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014914 }
14915 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14916 {
14917 %{$LocalProblems{$Prefix."_BaseType"}}=(
14918 "Old_Value"=>$Type1_Base{"Name"},
14919 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014920 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014921 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014922 }
14923 }
14924 }
14925 }
14926 elsif($Type1{"Name"} ne $Type2{"Name"})
14927 { # type change
14928 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14929 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014930 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014931 and $Type1_Pure{"Name"} eq "void")
14932 {
14933 %{$LocalProblems{"Return_Type_From_Void"}}=(
14934 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014935 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014936 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014937 elsif($Prefix eq "Return"
14938 and $Type2_Pure{"Name"} eq "void")
14939 {
14940 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14941 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014942 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014943 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014944 else
14945 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014946 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014947 and $Type1{"Size"} and $Type2{"Size"}
14948 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014949 {
14950 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14951 "Old_Value"=>$Type1{"Name"},
14952 "New_Value"=>$Type2{"Name"},
14953 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014954 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014955 }
14956 else
14957 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014958 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014959 { # format change
14960 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14961 "Old_Value"=>$Type1{"Name"},
14962 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014963 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014964 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014965 }
14966 elsif(tNameLock($Type1_Id, $Type2_Id))
14967 { # FIXME: correct this condition
14968 %{$LocalProblems{$Prefix."_Type"}}=(
14969 "Old_Value"=>$Type1{"Name"},
14970 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014971 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014972 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014973 }
14974 }
14975 }
14976 }
14977 }
14978 if($Type1_PLevel!=$Type2_PLevel)
14979 {
14980 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14981 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14982 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014983 if($Level eq "Source")
14984 {
14985 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014986 "Old_Value"=>$Type1_PLevel,
14987 "New_Value"=>$Type2_PLevel);
14988 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014989 else
14990 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014991 if($Type2_PLevel>$Type1_PLevel)
14992 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014993 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14994 "Old_Value"=>$Type1_PLevel,
14995 "New_Value"=>$Type2_PLevel);
14996 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014997 else
14998 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014999 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
15000 "Old_Value"=>$Type1_PLevel,
15001 "New_Value"=>$Type2_PLevel);
15002 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015003 }
15004 }
15005 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040015006 if($Type1_Pure{"Type"} eq "Array"
15007 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015008 { # base_type[N] -> base_type[N]
15009 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015010 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015011 foreach my $SubProblemType (keys(%SubProblems))
15012 {
15013 $SubProblemType=~s/_Type/_BaseType/g;
15014 next if(defined $LocalProblems{$SubProblemType});
15015 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
15016 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
15017 }
15018 }
15019 }
15020 return %LocalProblems;
15021}
15022
15023sub tNameLock($$)
15024{
15025 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015026 my $Changed = 0;
15027 if(differentDumps("G"))
15028 { # different GCC versions
15029 $Changed = 1;
15030 }
15031 elsif(differentDumps("V"))
15032 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015033 if(not checkDump(1, "2.20")
15034 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015035 { # latest names update
15036 # 2.6: added restrict qualifier
15037 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015038 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015039 $Changed = 1;
15040 }
15041 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015042
15043 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
15044 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
15045
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015046 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
15047 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
15048
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015049 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015050 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015051 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015052 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015053 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015054 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015055 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015056 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015057 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015058 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015059 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
15060 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
15061 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015062 { # equal base types
15063 return 0;
15064 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015065
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015066 if(not checkDump(1, "2.13")
15067 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015068 { # broken array names in ABI dumps < 2.13
15069 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015070 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015071 return 0;
15072 }
15073 }
15074
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015075 if(not checkDump(1, "2.6")
15076 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015077 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015078 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015079 and $TN2=~/\brestrict\b/) {
15080 return 0;
15081 }
15082 }
15083
15084 if(not checkDump(1, "2.20")
15085 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015086 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015087 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
15088 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015089 return 0;
15090 }
15091 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015092 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015093 else
15094 {
15095 # typedef struct {...} type_t
15096 # typedef struct type_t {...} type_t
15097 if(index($TN1, " ".$TN2)!=-1)
15098 {
15099 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
15100 return 0;
15101 }
15102 }
15103 if(index($TN2, " ".$TN1)!=-1)
15104 {
15105 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
15106 return 0;
15107 }
15108 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015109
15110 if($TT1 eq "FuncPtr"
15111 and $TT2 eq "FuncPtr")
15112 {
15113 my $TN1_C = $TN1;
15114 my $TN2_C = $TN2;
15115
15116 $TN1_C=~s/\b(struct|union) //g;
15117 $TN2_C=~s/\b(struct|union) //g;
15118
15119 if($TN1_C eq $TN2_C) {
15120 return 0;
15121 }
15122 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015123 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015124
15125 my ($N1, $N2) = ($TN1, $TN2);
15126 $N1=~s/\b(struct|union) //g;
15127 $N2=~s/\b(struct|union) //g;
15128
15129 if($N1 eq $N2)
15130 { # QList<struct QUrl> and QList<QUrl>
15131 return 0;
15132 }
15133
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015134 return 1;
15135}
15136
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015137sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015138{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015139 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015140 if(defined $Cache{"differentDumps"}{$Check}) {
15141 return $Cache{"differentDumps"}{$Check};
15142 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015143 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015144 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015145 if($Check eq "G")
15146 {
15147 if(getGccVersion(1) ne getGccVersion(2))
15148 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015149 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015150 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015151 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015152 if($Check eq "V")
15153 {
15154 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15155 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15156 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015157 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015158 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015159 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015160 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015161 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015162}
15163
15164sub formatVersion($$)
15165{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015166 my ($V, $Digits) = @_;
15167 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015168 return join(".", splice(@Elems, 0, $Digits));
15169}
15170
15171sub htmlSpecChars($)
15172{
15173 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015174 if(not $Str) {
15175 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015176 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015177 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15178 $Str=~s/</&lt;/g;
15179 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15180 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015181 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15182 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015183 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015184 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015185 $Str=~s/\n/<br\/>/g;
15186 $Str=~s/\"/&quot;/g;
15187 $Str=~s/\'/&#39;/g;
15188 return $Str;
15189}
15190
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015191sub xmlSpecChars($)
15192{
15193 my $Str = $_[0];
15194 if(not $Str) {
15195 return $Str;
15196 }
15197
15198 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15199 $Str=~s/</&lt;/g;
15200 $Str=~s/>/&gt;/g;
15201
15202 $Str=~s/\"/&quot;/g;
15203 $Str=~s/\'/&#39;/g;
15204
15205 return $Str;
15206}
15207
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015208sub xmlSpecChars_R($)
15209{
15210 my $Str = $_[0];
15211 if(not $Str) {
15212 return $Str;
15213 }
15214
15215 $Str=~s/&amp;/&/g;
15216 $Str=~s/&lt;/</g;
15217 $Str=~s/&gt;/>/g;
15218
15219 $Str=~s/&quot;/"/g;
15220 $Str=~s/&#39;/'/g;
15221
15222 return $Str;
15223}
15224
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015225sub black_name($)
15226{
15227 my $Name = $_[0];
15228 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15229}
15230
15231sub highLight_Signature($)
15232{
15233 my $Signature = $_[0];
15234 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15235}
15236
15237sub highLight_Signature_Italic_Color($)
15238{
15239 my $Signature = $_[0];
15240 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15241}
15242
15243sub separate_symbol($)
15244{
15245 my $Symbol = $_[0];
15246 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15247 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15248 ($Name, $Spec, $Ver) = ($1, $2, $3);
15249 }
15250 return ($Name, $Spec, $Ver);
15251}
15252
15253sub cut_f_attrs($)
15254{
15255 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15256 return $2;
15257 }
15258 return "";
15259}
15260
15261sub highLight_Signature_PPos_Italic($$$$$)
15262{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015263 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15264 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015265 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15266 my $Return = "";
15267 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15268 $Return = $2;
15269 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015270 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015271 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015272 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015273 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015274 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015275 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015276 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015277 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015278 }
15279 return $Signature;
15280 }
15281 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15282 $Begin.=" " if($Begin!~/ \Z/);
15283 $End = cut_f_attrs($Signature);
15284 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015285 my ($Short, $Params) = split_Signature($Signature);
15286 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015287 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015288 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015289 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015290 $Part=~s/\A\s+|\s+\Z//g;
15291 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15292 if($Part=~/\([\*]+(\w+)\)/i) {
15293 $ParamName = $1;#func-ptr
15294 }
15295 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15296 $ParamName = $1;
15297 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015298 if(not $ParamName)
15299 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015300 push(@Parts, $Part_Styled);
15301 next;
15302 }
15303 if($ItalicParams and not $TName_Tid{1}{$Part}
15304 and not $TName_Tid{2}{$Part})
15305 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015306 my $Style = "<i>$ParamName</i>";
15307
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015308 if($Param_Pos ne ""
15309 and $Pos==$Param_Pos) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015310 $Style = "<span class=\'fp\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015311 }
15312 elsif($ColorParams) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015313 $Style = "<span class=\'color_p\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015314 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015315
15316 $Part_Styled=~s!(\W)$ParamName([\,\)]|\Z)!$1$Style$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015317 }
15318 $Part_Styled=~s/,(\w)/, $1/g;
15319 push(@Parts, $Part_Styled);
15320 }
15321 if(@Parts)
15322 {
15323 foreach my $Num (0 .. $#Parts)
15324 {
15325 if($Num==$#Parts)
15326 { # add ")" to the last parameter
15327 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15328 }
15329 elsif(length($Parts[$Num])<=45) {
15330 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15331 }
15332 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015333 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015334 }
15335 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015336 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015337 }
15338 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015339 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015340 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015341 $Signature=~s!\[\]![&#160;]!g;
15342 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015343 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15344 if($SymbolVersion) {
15345 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15346 }
15347 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015348}
15349
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015350sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015351{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015352 my $Signature = $_[0];
15353 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15354 {
15355 $Signature=~s/\A\Q$ShortName\E\(//g;
15356 cut_f_attrs($Signature);
15357 $Signature=~s/\)\Z//;
15358 return ($ShortName, $Signature);
15359 }
15360
15361 # error
15362 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015363}
15364
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015365sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015366{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015367 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015368 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015369 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15370 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015371 foreach my $Pos (0 .. length($Params) - 1)
15372 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015373 my $S = substr($Params, $Pos, 1);
15374 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015375 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015376 }
15377 if($S eq "," and
15378 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015379 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015380 if($Comma)
15381 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015382 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015383 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015384 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015385 }
15386 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015387 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015388 }
15389 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015390 if(not $Sp)
15391 { # remove spaces
15392 foreach (@Parts)
15393 {
15394 s/\A //g;
15395 s/ \Z//g;
15396 }
15397 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015398 return @Parts;
15399}
15400
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015401sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015402{
15403 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015404 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015405 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015406 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15407 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015408 $Center+=length($1);
15409 }
15410 foreach my $Pos (0 .. length($Sign)-1)
15411 {
15412 my $S = substr($Sign, $Pos, 1);
15413 if($S eq $Target)
15414 {
15415 if($B{"("}==$B{")"}
15416 and $B{"<"}==$B{">"}) {
15417 return $Center;
15418 }
15419 }
15420 if(defined $B{$S}) {
15421 $B{$S}+=1;
15422 }
15423 $Center+=1;
15424 }
15425 return 0;
15426}
15427
15428sub appendFile($$)
15429{
15430 my ($Path, $Content) = @_;
15431 return if(not $Path);
15432 if(my $Dir = get_dirname($Path)) {
15433 mkpath($Dir);
15434 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015435 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015436 print FILE $Content;
15437 close(FILE);
15438}
15439
15440sub writeFile($$)
15441{
15442 my ($Path, $Content) = @_;
15443 return if(not $Path);
15444 if(my $Dir = get_dirname($Path)) {
15445 mkpath($Dir);
15446 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015447 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015448 print FILE $Content;
15449 close(FILE);
15450}
15451
15452sub readFile($)
15453{
15454 my $Path = $_[0];
15455 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015456 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015457 local $/ = undef;
15458 my $Content = <FILE>;
15459 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015460 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015461 $Content=~s/\r/\n/g;
15462 }
15463 return $Content;
15464}
15465
15466sub get_filename($)
15467{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015468 if(defined $Cache{"get_filename"}{$_[0]}) {
15469 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015470 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015471 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15472 return ($Cache{"get_filename"}{$_[0]}=$1);
15473 }
15474 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015475}
15476
15477sub get_dirname($)
15478{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015479 if(defined $Cache{"get_dirname"}{$_[0]}) {
15480 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015481 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015482 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15483 return ($Cache{"get_dirname"}{$_[0]}=$1);
15484 }
15485 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015486}
15487
15488sub separate_path($) {
15489 return (get_dirname($_[0]), get_filename($_[0]));
15490}
15491
15492sub esc($)
15493{
15494 my $Str = $_[0];
15495 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15496 return $Str;
15497}
15498
15499sub readLineNum($$)
15500{
15501 my ($Path, $Num) = @_;
15502 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015503 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015504 foreach (1 ... $Num) {
15505 <FILE>;
15506 }
15507 my $Line = <FILE>;
15508 close(FILE);
15509 return $Line;
15510}
15511
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015512sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015513{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015514 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015515 return () if(not $Path or not -f $Path);
15516 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015517 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15518 {
15519 foreach my $AttrVal (split(/;/, $1))
15520 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015521 if($AttrVal=~/(.+):(.+)/)
15522 {
15523 my ($Name, $Value) = ($1, $2);
15524 $Attributes{$Name} = $Value;
15525 }
15526 }
15527 }
15528 return \%Attributes;
15529}
15530
15531sub is_abs($) {
15532 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15533}
15534
15535sub get_abs_path($)
15536{ # abs_path() should NOT be called for absolute inputs
15537 # because it can change them
15538 my $Path = $_[0];
15539 if(not is_abs($Path)) {
15540 $Path = abs_path($Path);
15541 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030015542 return path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015543}
15544
15545sub get_OSgroup()
15546{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015547 my $N = $Config{"osname"};
15548 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015549 return "macos";
15550 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015551 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015552 return "bsd";
15553 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015554 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015555 return "beos";
15556 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015557 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015558 return "symbian";
15559 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015560 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015561 return "windows";
15562 }
15563 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015564 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015565 }
15566}
15567
15568sub getGccVersion($)
15569{
15570 my $LibVersion = $_[0];
15571 if($GCC_VERSION{$LibVersion})
15572 { # dump version
15573 return $GCC_VERSION{$LibVersion};
15574 }
15575 elsif($UsedDump{$LibVersion}{"V"})
15576 { # old-version dumps
15577 return "unknown";
15578 }
15579 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15580 if(not $GccVersion) {
15581 return "unknown";
15582 }
15583 return $GccVersion;
15584}
15585
15586sub showArch($)
15587{
15588 my $Arch = $_[0];
15589 if($Arch eq "arm"
15590 or $Arch eq "mips") {
15591 return uc($Arch);
15592 }
15593 return $Arch;
15594}
15595
15596sub getArch($)
15597{
15598 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015599
15600 if($TargetArch) {
15601 return $TargetArch;
15602 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015603 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015604 { # dump
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015605 return $CPU_ARCH{$LibVersion};
15606 }
15607 elsif($UsedDump{$LibVersion}{"V"})
15608 { # old-version dumps
15609 return "unknown";
15610 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015611
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015612 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015613}
15614
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015615sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015616{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015617 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015618
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015619 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015620 if(getArch(1) ne getArch(2)
15621 or getArch(1) eq "unknown"
15622 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015623 { # don't show architecture in the header
15624 $ArchInfo="";
15625 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015626 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015627 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015628 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015629 }
15630 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015631 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015632 }
15633 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015634 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015635 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015636
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015637 my $V1 = $Descriptor{1}{"Version"};
15638 my $V2 = $Descriptor{2}{"Version"};
15639
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015640 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15641 {
15642 my $M1 = $UsedDump{1}{"M"};
15643 my $M2 = $UsedDump{2}{"M"};
15644
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015645 my $M1S = $M1;
15646 my $M2S = $M2;
15647
15648 $M1S=~s/(\.so|\.ko)\..+/$1/ig;
15649 $M2S=~s/(\.so|\.ko)\..+/$1/ig;
15650
15651 if($M1S eq $M2S
15652 and $V1 ne "X" and $V2 ne "Y")
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015653 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015654 $Title .= " report for the <span style='color:Blue;'>$M1S</span> $TargetComponent";
15655 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015656 }
15657 else
15658 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015659 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$V1."</span>)";
15660 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$V2."</span>) objects";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015661 }
15662 }
15663 else
15664 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015665 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015666 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015667 }
15668
15669 $Title .= $ArchInfo;
15670
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015671 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015672 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015673 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015674 $Title = "<h1>".$Title."</h1>\n";
15675 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015676}
15677
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015678sub get_CheckedHeaders($)
15679{
15680 my $LibVersion = $_[0];
15681
15682 my @Headers = ();
15683
15684 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15685 {
15686 my $File = get_filename($Path);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015687
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015688 if(not is_target_header($File, $LibVersion)) {
15689 next;
15690 }
15691
15692 if(skipHeader($File, $LibVersion)) {
15693 next;
15694 }
15695
15696 push(@Headers, $Path);
15697 }
15698
15699 return @Headers;
15700}
15701
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015702sub get_SourceInfo()
15703{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015704 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015705
15706 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015707 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015708 $CheckedHeaders = "<a name='Headers'></a>";
15709 if($OldStyle) {
15710 $CheckedHeaders .= "<h2>Header Files (".($#Headers+1).")</h2>";
15711 }
15712 else {
15713 $CheckedHeaders .= "<h2>Header Files <span class='gray'>&nbsp;".($#Headers+1)."&nbsp;</span></h2>";
15714 }
15715 $CheckedHeaders .= "<hr/>\n<div class='h_list'>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015716 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 +040015717 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015718 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15719 my $Name = get_filename($Identity);
15720 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15721 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015722 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015723 $CheckedHeaders .= "</div>\n";
15724 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015725 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015726
15727 if(my @Sources = keys(%{$Registered_Sources{1}}))
15728 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015729 $CheckedSources = "<a name='Sources'></a>";
15730 if($OldStyle) {
15731 $CheckedSources .= "<h2>Source Files (".($#Sources+1).")</h2>";
15732 }
15733 else {
15734 $CheckedSources .= "<h2>Source Files <span class='gray'>&nbsp;".($#Sources+1)."&nbsp;</span></h2>";
15735 }
15736 $CheckedSources .= "<hr/>\n<div class='h_list'>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015737 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15738 {
15739 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15740 my $Name = get_filename($Identity);
15741 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15742 $CheckedSources .= $Name.$Comment."<br/>\n";
15743 }
15744 $CheckedSources .= "</div>\n";
15745 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15746 }
15747
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015748 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015749 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015750 $CheckedLibs = "<a name='Libs'></a>";
15751 if($OldStyle) {
15752 $CheckedLibs .= "<h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2>";
15753 }
15754 else {
15755 $CheckedLibs .= "<h2>".get_ObjTitle()." <span class='gray'>&nbsp;".keys(%{$Library_Symbol{1}})."&nbsp;</span></h2>";
15756 }
15757 $CheckedLibs .= "<hr/>\n<div class='lib_list'>\n";
15758 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}})) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015759 $CheckedLibs .= $Library."<br/>\n";
15760 }
15761 $CheckedLibs .= "</div>\n";
15762 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015763 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015764
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015765 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15766}
15767
15768sub get_ObjTitle()
15769{
15770 if(defined $UsedDump{1}{"DWARF"}) {
15771 return "Objects";
15772 }
15773 else {
15774 return ucfirst($SLIB_TYPE)." Libraries";
15775 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015776}
15777
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015778sub get_TypeProblems_Count($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015779{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015780 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015781 my $Type_Problems_Count = 0;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015782
15783 foreach my $Type_Name (sort keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015784 {
15785 my %Kinds_Target = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015786 foreach my $Kind (keys(%{$TypeChanges{$Level}{$Type_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015787 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015788 foreach my $Location (keys(%{$TypeChanges{$Level}{$Type_Name}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015789 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015790 my $Target = $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015791 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015792
15793 if($Severity ne $TargetSeverity) {
15794 next;
15795 }
15796
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015797 if($Kinds_Target{$Kind}{$Target}) {
15798 next;
15799 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015800
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015801 $Kinds_Target{$Kind}{$Target} = 1;
15802 $Type_Problems_Count += 1;
15803 }
15804 }
15805 }
15806 return $Type_Problems_Count;
15807}
15808
15809sub get_Summary($)
15810{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015811 my $Level = $_[0];
15812 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015813 $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 +040015814 %{$RESULT{$Level}} = (
15815 "Problems"=>0,
15816 "Warnings"=>0,
15817 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015818 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015819 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015820 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015821 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015822 {
15823 if(not defined $CompatRules{$Level}{$Kind})
15824 { # unknown rule
15825 if(not $UnknownRules{$Level}{$Kind})
15826 { # only one warning
15827 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15828 $UnknownRules{$Level}{$Kind}=1;
15829 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015830 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015831 }
15832 }
15833 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015834 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15835 {
15836 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15837 {
15838 if(not defined $CompatRules{$Level}{$Kind})
15839 { # unknown rule
15840 if(not $UnknownRules{$Level}{$Kind})
15841 { # only one warning
15842 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15843 $UnknownRules{$Level}{$Kind}=1;
15844 }
15845 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15846 }
15847 }
15848 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015849 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015850 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015851 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015852 {
15853 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15854 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015855 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015856 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015857 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015858 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015859 $Added += 1;
15860 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015861 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015862 {
15863 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015864 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015865 }
15866 else
15867 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015868 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015869 $I_Other += 1;
15870 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015871 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015872 $I_Problems_High += 1;
15873 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015874 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015875 $I_Problems_Medium += 1;
15876 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015877 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015878 $I_Problems_Low += 1;
15879 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015880 if(($Severity ne "Low" or $StrictCompat)
15881 and $Severity ne "Safe") {
15882 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015883 }
15884 }
15885 }
15886 }
15887 }
15888 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015889
15890 my %MethodTypeIndex = ();
15891
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015892 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015893 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015894 my @Kinds = sort keys(%{$CompatProblems{$Level}{$Interface}});
15895 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015896 {
15897 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15898 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015899 my @Locs = sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}});
15900 foreach my $Location (@Locs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015901 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015902 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15903 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015904
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015905 if(defined $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target})
15906 { # one location for one type and target
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015907 next;
15908 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015909 $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target} = 1;
15910 $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15911
15912 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015913
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015914 if(($Severity ne "Low" or $StrictCompat)
15915 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015916 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015917 if(my $Sev = $TotalAffected{$Level}{$Interface})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015918 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015919 if($Severity_Val{$Severity}>$Severity_Val{$Sev}) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015920 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015921 }
15922 }
15923 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015924 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015925 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015926 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015927 }
15928 }
15929 }
15930 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015931
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015932 $T_Problems_High = get_TypeProblems_Count("High", $Level);
15933 $T_Problems_Medium = get_TypeProblems_Count("Medium", $Level);
15934 $T_Problems_Low = get_TypeProblems_Count("Low", $Level);
15935 $T_Other = get_TypeProblems_Count("Safe", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015936
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015937 # changed and removed public symbols
15938 my $SCount = keys(%{$CheckedSymbols{$Level}});
15939 if($ExtendedCheck)
15940 { # don't count external_func_0 for constants
15941 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015942 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015943 if($SCount)
15944 {
15945 my %Weight = (
15946 "High" => 100,
15947 "Medium" => 50,
15948 "Low" => 25
15949 );
15950 foreach (keys(%{$TotalAffected{$Level}})) {
15951 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015952 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015953 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015954 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015955 else {
15956 $RESULT{$Level}{"Affected"} = 0;
15957 }
15958
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015959 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15960 if($RESULT{$Level}{"Affected"}>=100) {
15961 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015962 }
15963
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015964 $RESULT{$Level}{"Problems"} += $Removed;
15965 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015966 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015967 if($StrictCompat) {
15968 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15969 }
15970 else {
15971 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15972 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015973
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015974 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015975 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015976 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015977 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015978 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015979 if($Severity eq "Safe")
15980 {
15981 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015982 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015983 elsif($Severity eq "Low")
15984 {
15985 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015986 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015987 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015988 }
15989
15990 if($C_Problems_Low)
15991 {
15992 if($StrictCompat) {
15993 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15994 }
15995 else {
15996 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015997 }
15998 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015999 if($RESULT{$Level}{"Problems"}
16000 and $RESULT{$Level}{"Affected"}) {
16001 $RESULT{$Level}{"Verdict"} = "incompatible";
16002 }
16003 else {
16004 $RESULT{$Level}{"Verdict"} = "compatible";
16005 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016006
16007 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
16008 if(not $TotalTypes)
16009 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016010 $TotalTypes = keys(%{$TName_Tid{1}});
16011 }
16012
16013 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
16014 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016015 my ($ClangV1, $ClangV2) = ($CLANG_VERSION{1}, $CLANG_VERSION{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016016
16017 my ($TestInfo, $TestResults, $Problem_Summary) = ();
16018
16019 if($ReportFormat eq "xml")
16020 { # XML
16021 # test info
16022 $TestInfo .= " <library>$TargetLibraryName</library>\n";
16023 $TestInfo .= " <version1>\n";
16024 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016025 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016026 if($GccV1) {
16027 $TestInfo .= " <gcc>$GccV1</gcc>\n";
16028 }
16029 elsif($ClangV1) {
16030 $TestInfo .= " <clang>$ClangV1</clang>\n";
16031 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016032 $TestInfo .= " </version1>\n";
16033
16034 $TestInfo .= " <version2>\n";
16035 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016036 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016037 if($GccV2) {
16038 $TestInfo .= " <gcc>$GccV2</gcc>\n";
16039 }
16040 elsif($ClangV2) {
16041 $TestInfo .= " <clang>$ClangV2</clang>\n";
16042 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016043 $TestInfo .= " </version2>\n";
16044 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
16045
16046 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016047 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016048 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016049 $TestResults .= " <headers>\n";
16050 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
16051 {
16052 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
16053 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
16054 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
16055 }
16056 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016057 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016058
16059 if(my @Sources = keys(%{$Registered_Sources{1}}))
16060 {
16061 $TestResults .= " <sources>\n";
16062 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
16063 {
16064 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
16065 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
16066 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
16067 }
16068 $TestResults .= " </sources>\n";
16069 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016070
16071 $TestResults .= " <libs>\n";
16072 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
16073 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016074 # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016075 $TestResults .= " <name>$Library</name>\n";
16076 }
16077 $TestResults .= " </libs>\n";
16078
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016079 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016080 $TestResults .= " <types>".$TotalTypes."</types>\n";
16081
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016082 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
16083 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016084 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
16085
16086 # problem summary
16087 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
16088 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
16089
16090 $Problem_Summary .= " <problems_with_types>\n";
16091 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
16092 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
16093 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
16094 $Problem_Summary .= " <safe>$T_Other</safe>\n";
16095 $Problem_Summary .= " </problems_with_types>\n";
16096
16097 $Problem_Summary .= " <problems_with_symbols>\n";
16098 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
16099 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
16100 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016101 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016102 $Problem_Summary .= " </problems_with_symbols>\n";
16103
16104 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016105 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016106 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016107
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016108 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
16109
16110 return ($TestInfo.$TestResults.$Problem_Summary, "");
16111 }
16112 else
16113 { # HTML
16114 # test info
16115 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016116 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016117
16118 if($TargetComponent eq "library") {
16119 $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
16120 }
16121 else {
16122 $TestInfo .= "<tr><th>Module Name</th><td>$TargetTitle</td></tr>\n";
16123 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016124
16125 my (@VInf1, @VInf2, $AddTestInfo) = ();
16126 if($Arch1 ne "unknown"
16127 and $Arch2 ne "unknown")
16128 { # CPU arch
16129 if($Arch1 eq $Arch2)
16130 { # go to the separate section
Andrey Ponomarenko19b61de2016-08-31 19:45:06 +030016131 $AddTestInfo .= "<tr><th>Arch</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016132 }
16133 else
16134 { # go to the version number
16135 push(@VInf1, showArch($Arch1));
16136 push(@VInf2, showArch($Arch2));
16137 }
16138 }
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030016139 if($Level eq "Binary"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016140 and $OStarget ne "windows")
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016141 {
16142 if($GccV1 ne "unknown"
16143 and $GccV2 ne "unknown")
16144 { # GCC version
16145 if($GccV1 eq $GccV2)
16146 { # go to the separate section
16147 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
16148 }
16149 else
16150 { # go to the version number
16151 push(@VInf1, "gcc ".$GccV1);
16152 push(@VInf2, "gcc ".$GccV2);
16153 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016154 }
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016155 elsif($ClangV1
16156 and $ClangV2)
16157 { # Clang version
16158 if($ClangV1 eq $ClangV2)
16159 { # go to the separate section
16160 $AddTestInfo .= "<tr><th>Clang Version</th><td>$ClangV1</td></tr>\n";
16161 }
16162 else
16163 { # go to the version number
16164 push(@VInf1, "clang ".$ClangV1);
16165 push(@VInf2, "clang ".$ClangV2);
16166 }
16167 }
16168 elsif($GccV1 ne "unknown" and $ClangV2)
16169 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016170 push(@VInf1, "gcc ".$GccV1);
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016171 push(@VInf2, "clang ".$ClangV2);
16172 }
16173 elsif($ClangV1 and $GccV2 ne "unknown")
16174 {
16175 push(@VInf1, "clang ".$ClangV1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016176 push(@VInf2, "gcc ".$GccV2);
16177 }
16178 }
16179 # show long version names with GCC version and CPU architecture name (if different)
16180 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
16181 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
16182 $TestInfo .= $AddTestInfo;
16183 #if($COMMON_LANGUAGE{1}) {
16184 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
16185 #}
16186 if($ExtendedCheck) {
16187 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
16188 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016189 if($JoinReport)
16190 {
16191 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016192 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016193 }
16194 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016195 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016196 }
16197 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016198 $TestInfo .= "</table>\n";
16199
16200 # test results
16201 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016202 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016203
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030016204 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016205 {
16206 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
16207 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
16208 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016209
16210 if(my @Sources = keys(%{$Registered_Sources{1}}))
16211 {
16212 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16213 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16214 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016215
16216 if(not $ExtendedCheck)
16217 {
16218 my $Libs_Link = "0";
16219 $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 +040016220 $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 +040016221 }
16222
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016223 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016224
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016225 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016226 if($JoinReport) {
16227 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16228 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016229
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030016230 my $BC_Rate = show_number(100 - $RESULT{$Level}{"Affected"});
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016231
16232 $TestResults .= "<tr><th>Compatibility</th>\n";
16233 if($RESULT{$Level}{"Verdict"} eq "incompatible")
16234 {
16235 my $Cl = "incompatible";
16236 if($BC_Rate>=90) {
16237 $Cl = "warning";
16238 }
16239 elsif($BC_Rate>=80) {
16240 $Cl = "almost_compatible";
16241 }
16242
16243 $TestResults .= "<td class=\'$Cl\'>".$BC_Rate."%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016244 }
16245 else {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016246 $TestResults .= "<td class=\'compatible\'>100%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016247 }
16248 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016249 $TestResults .= "</table>\n";
16250
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016251 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016252 # problem summary
16253 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016254 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016255 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16256
16257 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016258 if($Added>0)
16259 {
16260 if($JoinReport) {
16261 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16262 }
16263 else {
16264 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16265 }
16266 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016267 $META_DATA .= "added:$Added;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016268 $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 +040016269
16270 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016271 if($Removed>0)
16272 {
16273 if($JoinReport) {
16274 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16275 }
16276 else {
16277 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16278 }
16279 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016280 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016281 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016282 $Problem_Summary .= "<td>High</td><td".getStyle("I", "Removed", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016283
16284 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016285 $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 +040016286 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016287 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016288 $Problem_Summary .= "<td>High</td><td".getStyle("T", "High", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016289
16290 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016291 $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 +040016292 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016293 $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 +040016294
16295 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016296 $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 +040016297 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016298 $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 +040016299
16300 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016301 $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 +040016302 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016303 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016304 $Problem_Summary .= "<td>High</td><td".getStyle("I", "High", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016305
16306 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016307 $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 +040016308 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016309 $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 +040016310
16311 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016312 $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 +040016313 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016314 $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 +040016315
16316 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016317 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16318 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016319 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016320 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016321 $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 +040016322
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016323 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016324 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016325 {
16326 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016327 $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 +030016328 $META_DATA .= "type_changes_other:$T_Other;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016329 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016330
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016331 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016332 {
16333 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016334 $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 +030016335 $META_DATA .= "interface_changes_other:$I_Other;";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016337
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016338 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016339 {
16340 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016341 $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 +030016342 $META_DATA .= "constant_changes_other:$C_Other;";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016343 }
16344
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016345 $META_DATA .= "tool_version:$TOOL_VERSION";
16346 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016347
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016348 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16349 }
16350}
16351
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016352sub getStyle($$$)
16353{
16354 my ($Subj, $Act, $Num) = @_;
16355 my %Style = (
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016356 "Added"=>"new",
16357 "Removed"=>"failed",
16358 "Safe"=>"passed",
16359 "Low"=>"warning",
16360 "Medium"=>"failed",
16361 "High"=>"failed"
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016362 );
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016363
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016364 if($Num>0) {
16365 return " class='".$Style{$Act}."'";
16366 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016367
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016368 return "";
16369}
16370
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016371sub show_number($)
16372{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016373 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016374 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016375 my $Num = cut_off_number($_[0], 2, 0);
16376 if($Num eq "0")
16377 {
16378 foreach my $P (3 .. 7)
16379 {
16380 $Num = cut_off_number($_[0], $P, 1);
16381 if($Num ne "0") {
16382 last;
16383 }
16384 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016385 }
16386 if($Num eq "0") {
16387 $Num = $_[0];
16388 }
16389 return $Num;
16390 }
16391 return $_[0];
16392}
16393
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016394sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016395{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016396 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016397 if($num!~/\./)
16398 {
16399 $num .= ".";
16400 foreach (1 .. $digs_to_cut-1) {
16401 $num .= "0";
16402 }
16403 }
16404 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16405 {
16406 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16407 $num .= "0";
16408 }
16409 }
16410 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16411 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16412 }
16413 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016414 if($z) {
16415 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16416 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016417 return $num;
16418}
16419
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016420sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016421{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016422 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016423 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016424
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016425 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016426 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16427 {
16428 my $Header = $Constants{1}{$Constant}{"Header"};
16429 if(not $Header)
16430 { # added
16431 $Header = $Constants{2}{$Constant}{"Header"}
16432 }
16433
16434 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16435 {
16436 if(not defined $CompatRules{$Level}{$Kind}) {
16437 next;
16438 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016439 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016440 next;
16441 }
16442 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16443 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016444 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016445
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016446 if($ReportFormat eq "xml")
16447 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016448 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016449 {
16450 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016451 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016452 {
16453 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016454 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16455 {
16456 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16457 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16458 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016459
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016460 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16461 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16462 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016463 if($Overcome) {
16464 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16465 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016466 $CHANGED_CONSTANTS .= " </problem>\n";
16467 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016468 $CHANGED_CONSTANTS .= " </constant>\n";
16469 }
16470 $CHANGED_CONSTANTS .= " </header>\n";
16471 }
16472 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16473 }
16474 else
16475 { # HTML
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016476 my $ProblemsNum = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016477 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016478 {
16479 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016480 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016481 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016482 my $Report = "";
16483
16484 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16485 {
16486 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16487 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016488 $Report .= "<tr>\n<th>1</th>\n<td>".$Change."</td>\n<td>$Effect</td>\n</tr>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016489 $ProblemsNum += 1;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016490 }
16491 if($Report)
16492 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016493 $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 +030016494 $Report = $ContentSpanStart."<span class='ext'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016495 $Report = insertIDs($Report);
16496 }
16497 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016498 }
16499 $CHANGED_CONSTANTS .= "<br/>\n";
16500 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016501 if($CHANGED_CONSTANTS)
16502 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016503 my $Title = "Problems with Constants, $TargetSeverity Severity";
16504 if($TargetSeverity eq "Safe")
16505 { # Safe Changes
16506 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016507 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016508 if($OldStyle) {
16509 $CHANGED_CONSTANTS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$CHANGED_CONSTANTS;
16510 }
16511 else {
16512 $CHANGED_CONSTANTS = "<h2>$Title <span".getStyle("C", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$CHANGED_CONSTANTS;
16513 }
16514 $CHANGED_CONSTANTS = "<a name='".get_Anchor("Constant", $Level, $TargetSeverity)."'></a>\n".$CHANGED_CONSTANTS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016515 }
16516 }
16517 return $CHANGED_CONSTANTS;
16518}
16519
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016520sub getTitle($$$)
16521{
16522 my ($Header, $Library, $NameSpace) = @_;
16523 my $Title = "";
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016524
16525 # if($Library and $Library!~/\.\w+\Z/) {
16526 # $Library .= " (.$LIB_EXT)";
16527 # }
16528
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016529 if($Header and $Library)
16530 {
16531 $Title .= "<span class='h_name'>$Header</span>";
16532 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16533 }
16534 elsif($Library) {
16535 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16536 }
16537 elsif($Header) {
16538 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16539 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016540
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016541 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016542 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016543 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016544
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016545 return $Title;
16546}
16547
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016548sub get_Report_Added($)
16549{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016550 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016551 my $ADDED_INTERFACES = "";
16552 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016553 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016554 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016555 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016556 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016557 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016558 {
16559 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16560 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016561 if($Level eq "Source" and $ReportFormat eq "html")
16562 { # do not show library name in HTML report
16563 $DyLib = "";
16564 }
16565 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016566 }
16567 }
16568 }
16569 if($ReportFormat eq "xml")
16570 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016571 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016572 {
16573 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016574 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016575 {
16576 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016577 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016578 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16579 }
16580 $ADDED_INTERFACES .= " </library>\n";
16581 }
16582 $ADDED_INTERFACES .= " </header>\n";
16583 }
16584 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16585 }
16586 else
16587 { # HTML
16588 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016589 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016590 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016591 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016592 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016593 my %NameSpaceSymbols = ();
16594 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016595 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016596 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016597 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016598 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016599 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16600 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016601 foreach my $Interface (@SortedInterfaces)
16602 {
16603 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016604 my $Signature = get_Signature($Interface, 2);
16605 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016606 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016607 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016608 if($Interface=~/\A(_Z|\?)/)
16609 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016610 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016611 $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 +040016612 }
16613 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016614 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016615 }
16616 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016617 else
16618 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016619 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016620 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016621 }
16622 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016623 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016624 }
16625 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016626 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016627 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016628 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016629 }
16630 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016631 if($ADDED_INTERFACES)
16632 {
16633 my $Anchor = "<a name='Added'></a>";
16634 if($JoinReport) {
16635 $Anchor = "<a name='".$Level."_Added'></a>";
16636 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016637 if($OldStyle) {
16638 $ADDED_INTERFACES = "<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES;
16639 }
16640 else {
16641 $ADDED_INTERFACES = "<h2>Added Symbols <span".getStyle("I", "Added", $Added_Number).">&nbsp;$Added_Number&nbsp;</span></h2><hr/>\n".$ADDED_INTERFACES;
16642 }
16643 $ADDED_INTERFACES = $Anchor.$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016644 }
16645 }
16646 return $ADDED_INTERFACES;
16647}
16648
16649sub get_Report_Removed($)
16650{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016651 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016652 my $REMOVED_INTERFACES = "";
16653 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016654 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016655 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016656 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016657 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016658 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016659 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016660 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16661 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016662 if($Level eq "Source" and $ReportFormat eq "html")
16663 { # do not show library name in HTML report
16664 $DyLib = "";
16665 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016666 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016667 }
16668 }
16669 }
16670 if($ReportFormat eq "xml")
16671 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016672 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016673 {
16674 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016675 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016676 {
16677 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016678 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16679 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016680 }
16681 $REMOVED_INTERFACES .= " </library>\n";
16682 }
16683 $REMOVED_INTERFACES .= " </header>\n";
16684 }
16685 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16686 }
16687 else
16688 { # HTML
16689 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016690 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016691 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016692 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016693 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016694 my %NameSpaceSymbols = ();
16695 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016696 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016697 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016698 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016699 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016700 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16701 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016702 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016703 {
16704 $Removed_Number += 1;
16705 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016706 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016707 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016708 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016709 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016710 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016711 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016712 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016713 $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 +040016714 }
16715 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016716 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016717 }
16718 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016719 else
16720 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016721 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016722 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016723 }
16724 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016725 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016726 }
16727 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016728 }
16729 }
16730 $REMOVED_INTERFACES .= "<br/>\n";
16731 }
16732 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016733 if($REMOVED_INTERFACES)
16734 {
16735 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16736 if($JoinReport) {
16737 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16738 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016739 if($OldStyle) {
16740 $REMOVED_INTERFACES = "<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES;
16741 }
16742 else {
16743 $REMOVED_INTERFACES = "<h2>Removed Symbols <span".getStyle("I", "Removed", $Removed_Number).">&nbsp;$Removed_Number&nbsp;</span></h2><hr/>\n".$REMOVED_INTERFACES;
16744 }
16745
16746 $REMOVED_INTERFACES = $Anchor.$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016747 }
16748 }
16749 return $REMOVED_INTERFACES;
16750}
16751
16752sub getXmlParams($$)
16753{
16754 my ($Content, $Problem) = @_;
16755 return "" if(not $Content or not $Problem);
16756 my %XMLparams = ();
16757 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16758 {
16759 my $Macro = "\@".lc($Attr);
16760 if($Content=~/\Q$Macro\E/) {
16761 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16762 }
16763 }
16764 my @PString = ();
16765 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016766 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016767 }
16768 if(@PString) {
16769 return " ".join(" ", @PString);
16770 }
16771 else {
16772 return "";
16773 }
16774}
16775
16776sub addMarkup($)
16777{
16778 my $Content = $_[0];
16779 # auto-markup
16780 $Content=~s/\n[ ]*//; # spaces
16781 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16782 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016783 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016784 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16785 if($Content=~/\ANOTE:/)
16786 { # notes
16787 $Content=~s!(NOTE):!<b>$1</b>:!g;
16788 }
16789 else {
16790 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16791 }
16792 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16793 my @Keywords = (
16794 "void",
16795 "const",
16796 "static",
16797 "restrict",
16798 "volatile",
16799 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016800 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016801 );
16802 my $MKeys = join("|", @Keywords);
16803 foreach (@Keywords) {
16804 $MKeys .= "|non-".$_;
16805 }
16806 $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 +040016807
16808 # Markdown
16809 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16810 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016811 return $Content;
16812}
16813
16814sub applyMacroses($$$$)
16815{
16816 my ($Level, $Kind, $Content, $Problem) = @_;
16817 return "" if(not $Content or not $Problem);
16818 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16819 $Content = addMarkup($Content);
16820 # macros
16821 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16822 {
16823 my $Macro = "\@".lc($Attr);
16824 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016825 if(not defined $Value
16826 or $Value eq "") {
16827 next;
16828 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016829
16830 if(index($Content, $Macro)==-1) {
16831 next;
16832 }
16833
16834 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16835 and $Kind!~/_Type_/
16836 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016837 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016838 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016839 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016840 $Value = black_name($Value);
16841 }
16842 elsif($Value=~/\s/) {
16843 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16844 }
16845 elsif($Value=~/\A\d+\Z/
16846 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16847 { # bits to bytes
16848 if($Value % $BYTE_SIZE)
16849 { # bits
16850 if($Value==1) {
16851 $Value = "<b>".$Value."</b> bit";
16852 }
16853 else {
16854 $Value = "<b>".$Value."</b> bits";
16855 }
16856 }
16857 else
16858 { # bytes
16859 $Value /= $BYTE_SIZE;
16860 if($Value==1) {
16861 $Value = "<b>".$Value."</b> byte";
16862 }
16863 else {
16864 $Value = "<b>".$Value."</b> bytes";
16865 }
16866 }
16867 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016868 else
16869 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016870 $Value = "<b>".htmlSpecChars($Value)."</b>";
16871 }
16872 $Content=~s/\Q$Macro\E/$Value/g;
16873 }
16874
16875 if($Content=~/(\A|[^\@\w])\@\w/)
16876 {
16877 if(not $IncompleteRules{$Level}{$Kind})
16878 { # only one warning
16879 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16880 $IncompleteRules{$Level}{$Kind} = 1;
16881 }
16882 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016883 return $Content;
16884}
16885
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016886sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016887{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016888 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016889 my $INTERFACE_PROBLEMS = "";
16890 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016891
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016892 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016893 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016894 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16895 if($SV and defined $CompatProblems{$Level}{$SN}) {
16896 next;
16897 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016898 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16899 my $DyLib = $Symbol_Library{1}{$Symbol};
16900 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
16901 { # Symbol with Version
16902 $DyLib = $Symbol_Library{1}{$VSym};
16903 }
16904 if(not $DyLib)
16905 { # const global data
16906 $DyLib = "";
16907 }
16908 if($Level eq "Source" and $ReportFormat eq "html")
16909 { # do not show library name in HTML report
16910 $DyLib = "";
16911 }
16912
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016913 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016914 {
16915 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016916 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016917 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016918 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16919 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016920 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016921 if($Severity eq $TargetSeverity)
16922 {
16923 $SymbolChanges{$Symbol}{$Kind} = $CompatProblems{$Level}{$Symbol}{$Kind};
16924 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016925 }
16926 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016927 }
16928 }
16929 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016930
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016931 if($ReportFormat eq "xml")
16932 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016933 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016934 {
16935 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016936 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016937 {
16938 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016939 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16940 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016941 {
16942 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016943 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016944 {
16945 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16946 {
16947 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016948 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016949
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016950 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16951 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16952 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16953 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16954 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016955 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16956 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16957 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016958 $INTERFACE_PROBLEMS .= " </problem>\n";
16959 }
16960 }
16961 $INTERFACE_PROBLEMS .= " </symbol>\n";
16962 }
16963 $INTERFACE_PROBLEMS .= " </library>\n";
16964 }
16965 $INTERFACE_PROBLEMS .= " </header>\n";
16966 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016967 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016968 }
16969 else
16970 { # HTML
16971 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016972 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016973 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016974 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016975 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016976 my (%NameSpaceSymbols, %NewSignature) = ();
16977 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016978 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016979 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016980 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016981 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016982 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016983 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 +040016984 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016985 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016986 my $Signature = get_Signature($Symbol, 1);
16987 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016988 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016989 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016990 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016991 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016992 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016993 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016994 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016995 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016996 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016997 }
16998 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16999 {
17000 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017001 $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 +040017002 $ProblemNum += 1;
17003 $ProblemsNum += 1;
17004 }
17005 }
17006 }
17007 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017008 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017009 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017010 my $ShowSymbol = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017011 if($Signature) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017012 $ShowSymbol = highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017013 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017014
17015 if($NameSpace)
17016 {
17017 $SYMBOL_REPORT = cut_Namespace($SYMBOL_REPORT, $NameSpace);
17018 $ShowSymbol = cut_Namespace($ShowSymbol, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017019 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017020
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017021 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowSymbol;
17022 if($OldStyle) {
17023 $INTERFACE_PROBLEMS .= " ($ProblemNum)";
17024 }
17025 else {
17026 $INTERFACE_PROBLEMS .= " <span".getStyle("I", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>";
17027 }
17028 $INTERFACE_PROBLEMS .= $ContentSpanEnd."<br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017029 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017030
17031 if(my $NSign = $NewSignature{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017032 { # argument list changed to
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017033 if($NameSpace) {
17034 $NSign = cut_Namespace($NSign, $NameSpace);
17035 }
17036 $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 +040017037 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017038
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017039 if($Symbol=~/\A(_Z|\?)/) {
17040 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
17041 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017042
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017043 $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 +040017044 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017045 }
17046 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017047 $INTERFACE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017048 }
17049 }
17050 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017051
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017052 if($INTERFACE_PROBLEMS)
17053 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017054 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
17055 my $Title = "Problems with Symbols, $TargetSeverity Severity";
17056 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017057 { # Safe Changes
17058 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017059 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017060 if($OldStyle) {
17061 $INTERFACE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$INTERFACE_PROBLEMS;
17062 }
17063 else {
17064 $INTERFACE_PROBLEMS = "<h2>$Title <span".getStyle("I", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$INTERFACE_PROBLEMS;
17065 }
17066 $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 +040017067 }
17068 }
17069 return $INTERFACE_PROBLEMS;
17070}
17071
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017072sub cut_Namespace($$)
17073{
17074 my ($N, $Ns) = @_;
17075 $N=~s/\b\Q$Ns\E:://g;
17076 return $N;
17077}
17078
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017079sub get_Report_TypeProblems($$)
17080{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017081 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017082 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017083
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017084 my %ReportMap = ();
17085 my %TypeChanges_Sev = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017086
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017087 foreach my $TypeName (keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017088 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017089 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
17090
17091 foreach my $Kind (keys(%{$TypeChanges{$Level}{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017092 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017093 foreach my $Location (keys(%{$TypeChanges{$Level}{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017094 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017095 my $Target = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017096 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017097
17098 if($Severity eq $TargetSeverity)
17099 {
17100 $ReportMap{$HeaderName}{$TypeName} = 1;
17101 $TypeChanges_Sev{$TypeName}{$Kind}{$Location} = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017102 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017103 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017104 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017105 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017106
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017107 if($ReportFormat eq "xml")
17108 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017109 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017110 {
17111 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017112 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017113 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017114 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017115 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017116 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017117 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017118 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017119 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017120 $Kinds_Locations{$Kind}{$Location} = 1;
17121
17122 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17123 if($Kinds_Target{$Kind}{$Target}) {
17124 next;
17125 }
17126 $Kinds_Target{$Kind}{$Target} = 1;
17127
17128 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017129 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
17130 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
17131 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
17132 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
17133 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017134 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
17135 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
17136 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017137 $TYPE_PROBLEMS .= " </problem>\n";
17138 }
17139 }
Andrey Ponomarenkof9f25c92016-07-26 17:20:17 +030017140 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
17141 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017142 $TYPE_PROBLEMS .= showVTables($TypeName);
17143 }
17144 $TYPE_PROBLEMS .= " </type>\n";
17145 }
17146 $TYPE_PROBLEMS .= " </header>\n";
17147 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017148 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017149 }
17150 else
17151 { # HTML
17152 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017153 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017154 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017155 my (%NameSpace_Type) = ();
17156 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017157 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017158 }
17159 foreach my $NameSpace (sort keys(%NameSpace_Type))
17160 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017161 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017162 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 +040017163 foreach my $TypeName (@SortedTypes)
17164 {
17165 my $ProblemNum = 1;
17166 my $TYPE_REPORT = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017167 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017168
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017169 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017170 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017171 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017172 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017173 $Kinds_Locations{$Kind}{$Location} = 1;
17174
17175 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17176 if($Kinds_Target{$Kind}{$Target}) {
17177 next;
17178 }
17179 $Kinds_Target{$Kind}{$Target} = 1;
17180
17181 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017182 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17183 {
17184 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017185 $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 +040017186 $ProblemNum += 1;
17187 $ProblemsNum += 1;
17188 }
17189 }
17190 }
17191 $ProblemNum -= 1;
17192 if($TYPE_REPORT)
17193 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017194 my $Affected = getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017195 my $ShowVTables = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017196 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017197 $ShowVTables = showVTables($TypeName);
17198 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017199
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017200 my $ShowType = show_Type($TypeName, 1, 1);
17201
17202 if($NameSpace)
17203 {
17204 $TYPE_REPORT = cut_Namespace($TYPE_REPORT, $NameSpace);
17205 $ShowType = cut_Namespace($ShowType, $NameSpace);
17206 $Affected = cut_Namespace($Affected, $NameSpace);
17207 $ShowVTables = cut_Namespace($ShowVTables, $NameSpace);
17208 }
17209
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017210 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowType;
17211 if($OldStyle) {
17212 $TYPE_PROBLEMS .= " ($ProblemNum)";
17213 }
17214 else {
17215 $TYPE_PROBLEMS .= " <span".getStyle("T", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>";
17216 }
17217 $TYPE_PROBLEMS .= $ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017218 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
17219 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
17220 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
17221 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017222 }
17223 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017224 $TYPE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017225 }
17226 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017227
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017228 if($TYPE_PROBLEMS)
17229 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017230 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
17231 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017232 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017233 { # Safe Changes
17234 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017235 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017236 if($OldStyle) {
17237 $TYPE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$TYPE_PROBLEMS;
17238 }
17239 else {
17240 $TYPE_PROBLEMS = "<h2>$Title <span".getStyle("T", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$TYPE_PROBLEMS;
17241 }
17242 $TYPE_PROBLEMS = "<a name=\'".get_Anchor("Type", $Level, $TargetSeverity)."\'></a>\n".$TYPE_PROBLEMS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017243 }
17244 }
17245 return $TYPE_PROBLEMS;
17246}
17247
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017248sub show_Type($$$)
17249{
17250 my ($Name, $Html, $LibVersion) = @_;
17251 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
17252 $TType = lc($TType);
17253 if($TType=~/struct|union|enum/) {
17254 $Name=~s/\A\Q$TType\E //g;
17255 }
17256 if($Html) {
17257 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
17258 }
17259 else {
17260 $Name = $TType." ".$Name;
17261 }
17262 return $Name;
17263}
17264
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017265sub get_Anchor($$$)
17266{
17267 my ($Kind, $Level, $Severity) = @_;
17268 if($JoinReport)
17269 {
17270 if($Severity eq "Safe") {
17271 return "Other_".$Level."_Changes_In_".$Kind."s";
17272 }
17273 else {
17274 return $Kind."_".$Level."_Problems_".$Severity;
17275 }
17276 }
17277 else
17278 {
17279 if($Severity eq "Safe") {
17280 return "Other_Changes_In_".$Kind."s";
17281 }
17282 else {
17283 return $Kind."_Problems_".$Severity;
17284 }
17285 }
17286}
17287
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017288sub showVTables($)
17289{
17290 my $TypeName = $_[0];
17291 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017292 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017293 if(defined $Type1{"VTable"}
17294 and keys(%{$Type1{"VTable"}}))
17295 {
17296 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017297 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017298 if(defined $Type2{"VTable"}
17299 and keys(%{$Type2{"VTable"}}))
17300 {
17301 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17302 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017303 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017304 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017305 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17306 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017307 }
17308 my $VTABLES = "";
17309 if($ReportFormat eq "xml")
17310 { # XML
17311 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017312 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017313 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017314 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017315 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17316 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017317 $VTABLES .= " </entry>\n";
17318 }
17319 $VTABLES .= " </vtable>\n\n";
17320 }
17321 else
17322 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017323 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017324 $VTABLES .= "<tr><th>Offset</th>";
17325 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017326 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017327 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017328 {
17329 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017330
17331 my $E1 = $Entries{$Index}{"E1"};
17332 my $E2 = $Entries{$Index}{"E2"};
17333
17334 if($E1 ne $E2
17335 and $E1!~/ 0x/
17336 and $E2!~/ 0x/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017337 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017338 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017339 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017340 $Color1 = " class='failed'";
17341 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017342 }
17343 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017344 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017345 }
17346 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017347 $VTABLES .= "<tr><th>".$Index."</th>\n";
17348 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17349 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017350 }
17351 $VTABLES .= "</table><br/>\n";
17352 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017353 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017354 }
17355 return $VTABLES;
17356 }
17357 }
17358 return "";
17359}
17360
17361sub simpleVEntry($)
17362{
17363 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017364 if(not defined $VEntry
17365 or $VEntry eq "") {
17366 return "";
17367 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017368
17369 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017370 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17371 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17372 if($VEntry=~/\A_ZThn.+\Z/) {
17373 $VEntry = "non-virtual thunk";
17374 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017375 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017376 # support for old GCC versions
17377 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17378 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17379 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017380 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17381 return $VEntry;
17382}
17383
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017384sub adjustParamPos($$$)
17385{
17386 my ($Pos, $Symbol, $LibVersion) = @_;
17387 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17388 {
17389 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17390 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17391 {
17392 return $Pos-1;
17393 }
17394
17395 return $Pos;
17396 }
17397
17398 return undef;
17399}
17400
17401sub getParamPos($$$)
17402{
17403 my ($Name, $Symbol, $LibVersion) = @_;
17404
17405 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17406 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17407 {
17408 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17409 foreach (keys(%{$Info->{"Param"}}))
17410 {
17411 if($Info->{"Param"}{$_}{"name"} eq $Name)
17412 {
17413 return $_;
17414 }
17415 }
17416 }
17417
17418 return undef;
17419}
17420
17421sub getParamName($)
17422{
17423 my $Loc = $_[0];
17424 $Loc=~s/\->.*//g;
17425 return $Loc;
17426}
17427
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017428sub getAffectedSymbols($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017429{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017430 my ($Level, $Target_TypeName, $Kinds_Locations) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017431
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017432 my $LIMIT = 10;
17433 if(defined $AffectLimit) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017434 $LIMIT = $AffectLimit;
17435 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017436
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017437 my @Kinds = sort keys(%{$Kinds_Locations});
17438 my %KLocs = ();
17439 foreach my $Kind (@Kinds)
17440 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017441 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 +030017442 $KLocs{$Kind} = \@Locs;
17443 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017444
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017445 my %SymLocKind = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017446 foreach my $Symbol (sort keys(%{$TypeProblemsIndex{$Level}{$Target_TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017447 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017448 if(index($Symbol, "_Z")==0
17449 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017450 { # duplicated problems for C2 constructors, D2 and D0 destructors
17451 next;
17452 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017453
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017454 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017455 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017456 foreach my $Loc (@{$KLocs{$Kind}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017457 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017458 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017459 next;
17460 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017461
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017462 if(index($Symbol, "\@")!=-1
17463 or index($Symbol, "\$")!=-1)
17464 {
17465 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17466
17467 if($Level eq "Source")
17468 { # remove symbol version
17469 $Symbol = $SN;
17470 }
17471
17472 if($SV and defined $CompatProblems{$Level}{$SN}
17473 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
17474 { # duplicated problems for versioned symbols
17475 next;
17476 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017477 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017478
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017479 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017480 if($Type_Name ne $Target_TypeName) {
17481 next;
17482 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017483
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017484 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017485 last;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017486 }
17487 }
17488 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017489
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017490 %KLocs = (); # clear
17491
17492 my %SymSel = ();
17493 my $Num = 0;
17494 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymLocKind))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017495 {
17496 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17497 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017498 foreach my $Kind (sort keys(%{$SymLocKind{$Symbol}{$Loc}}))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017499 {
17500 $SymSel{$Symbol}{"Loc"} = $Loc;
17501 $SymSel{$Symbol}{"Kind"} = $Kind;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017502 last LOOP;
17503 }
17504 }
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017505
17506 $Num += 1;
17507
17508 if($Num>=$LIMIT) {
17509 last;
17510 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017511 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017512
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017513 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017514
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017515 if($ReportFormat eq "xml")
17516 { # XML
17517 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017518
17519 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017520 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017521 my $Kind = $SymSel{$Symbol}{"Kind"};
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017522 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017523
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017524 my $PName = getParamName($Loc);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017525 my $Desc = getAffectDesc($Level, $Symbol, $Kind, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017526
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017527 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017528 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017529 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017530 $Target .= " param=\"$PName\"";
17531 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017532 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017533 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017534 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017535 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017536 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017537 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017538 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017539
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017540 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017541 $Target .= " field=\"$1\"";
17542 }
17543
17544 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017545 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017546 $Affected .= " </symbol>\n";
17547 }
17548 $Affected .= " </affected>\n";
17549 }
17550 else
17551 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017552 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017553 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017554 my $Kind = $SymSel{$Symbol}{"Kind"};
17555 my $Loc = $SymSel{$Symbol}{"Loc"};
17556
17557 my $Desc = getAffectDesc($Level, $Symbol, $Kind, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017558 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017559 my $PName = getParamName($Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017560 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17561
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017562 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017563 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017564 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017565
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017566 if(keys(%SymLocKind)>$LIMIT) {
17567 $Affected .= " <b>...</b>\n<br/>\n"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017568 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017569
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017570 $Affected = "<div class='affected'>".$Affected."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017571 if($Affected)
17572 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017573 my $Num = keys(%SymLocKind);
17574 my $Per = show_number($Num*100/keys(%{$CheckedSymbols{$Level}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017575 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017576 $Affected = $ContentSpanStart_Affected."[+] affected symbols: $Num ($Per\%)".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017577 }
17578 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017579
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017580 return $Affected;
17581}
17582
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017583sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017584{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017585 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017586 if($L2=~/\A(retval|this)\b/
17587 and $L1!~/\A(retval|this)\b/)
17588 {
17589 if($L1!~/\-\>/) {
17590 return 1;
17591 }
17592 elsif($L2=~/\-\>/) {
17593 return 1;
17594 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017595 }
17596 return 0;
17597}
17598
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017599sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017600{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017601 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017602
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017603 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017604
17605 my $Location_I = $Location;
17606 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17607
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017608 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017609
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017610 if($Kind eq "Overridden_Virtual_Method"
17611 or $Kind eq "Overridden_Virtual_Method_B") {
17612 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17613 }
17614 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17615 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017616 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17617
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017618 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17619 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017620 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17621 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17622
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017623 if($ClassName eq $Problem{"Type_Name"}) {
17624 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17625 }
17626 else {
17627 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17628 }
17629 }
17630 else
17631 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017632 my $TypeID = undef;
17633
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017634 if($Location=~/retval/)
17635 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017636 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017637 push(@Sentence, "Field \'".$Location."\' in return value");
17638 }
17639 else {
17640 push(@Sentence, "Return value");
17641 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017642
17643 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017644 }
17645 elsif($Location=~/this/)
17646 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017647 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017648 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17649 }
17650 else {
17651 push(@Sentence, "\'this\' pointer");
17652 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017653
17654 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017655 }
17656 else
17657 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017658
17659 my $PName = getParamName($Location);
17660 my $PPos = getParamPos($PName, $Symbol, 1);
17661
17662 if(index($Location, "->")!=-1) {
17663 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017664 }
17665 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017666 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017667 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017668 if($PName) {
17669 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017670 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017671
17672 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17673 }
17674
17675 if($Location!~/this/)
17676 {
17677 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017678 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017679 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017680 push(@Sentence, "(pointer)");
17681 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017682 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017683 push(@Sentence, "(reference)");
17684 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017685 }
17686 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017687
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017688 if($Location eq "this") {
17689 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17690 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017691 else
17692 {
17693 my $Location_T = $Location;
17694 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17695
17696 my $TypeID_Problem = $TypeID;
17697 if($Location_T) {
17698 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17699 }
17700
17701 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17702 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17703 }
17704 else {
17705 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17706 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017707 }
17708 }
17709 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017710 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017711 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 +040017712 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017713
17714 my $Sent = join(" ", @Sentence);
17715
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017716 $Sent=~s/->/./g;
17717
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017718 if($ReportFormat eq "xml")
17719 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017720 $Sent=~s/'//g;
17721 }
17722
17723 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017724}
17725
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017726sub getFieldType($$$)
17727{
17728 my ($Location, $TypeId, $LibVersion) = @_;
17729
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017730 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017731
17732 foreach my $Name (@Fields)
17733 {
17734 my %Info = get_BaseType($TypeId, $LibVersion);
17735
17736 foreach my $Pos (keys(%{$Info{"Memb"}}))
17737 {
17738 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17739 {
17740 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17741 last;
17742 }
17743 }
17744 }
17745
17746 return $TypeId;
17747}
17748
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017749sub get_XmlSign($$)
17750{
17751 my ($Symbol, $LibVersion) = @_;
17752 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17753 my $Report = "";
17754 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17755 {
17756 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017757 my $Type = $Info->{"Param"}{$Pos}{"type"};
17758 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017759 foreach my $Typedef (keys(%ChangedTypedef))
17760 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017761 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17762 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17763 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017764 }
17765 $Report .= " <param pos=\"$Pos\">\n";
17766 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017767 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017768 $Report .= " </param>\n";
17769 }
17770 if(my $Return = $Info->{"Return"})
17771 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017772 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017773 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017774 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017775 $Report .= " </retval>\n";
17776 }
17777 return $Report;
17778}
17779
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017780sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017781{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017782 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017783 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017784 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017785 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017786 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17787 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017788 next;
17789 }
17790 $Report .= " <symbol name=\"$Symbol\">\n";
17791 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017792 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017793 {
17794 if(defined $CompleteSignature{1}{$Symbol}
17795 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17796 {
17797 $P1 = get_XmlSign($Symbol, 1);
17798 $S1 = get_Signature($Symbol, 1);
17799 }
17800 elsif($Symbol=~/\A(_Z|\?)/) {
17801 $S1 = $tr_name{$Symbol};
17802 }
17803 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017804 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017805 {
17806 if(defined $CompleteSignature{2}{$Symbol}
17807 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17808 {
17809 $P2 = get_XmlSign($Symbol, 2);
17810 $S2 = get_Signature($Symbol, 2);
17811 }
17812 elsif($Symbol=~/\A(_Z|\?)/) {
17813 $S2 = $tr_name{$Symbol};
17814 }
17815 }
17816 if($S1)
17817 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017818 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017819 $Report .= $P1;
17820 $Report .= " </old>\n";
17821 }
17822 if($S2 and $S2 ne $S1)
17823 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017824 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017825 $Report .= $P2;
17826 $Report .= " </new>\n";
17827 }
17828 $Report .= " </symbol>\n";
17829 }
17830 $Report .= "</symbols_info>\n";
17831 return $Report;
17832}
17833
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017834sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017835{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017836 my ($Level, $Report) = @_;
17837 if($ReportFormat eq "xml") {
17838 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017839 }
17840 if($StdOut)
17841 { # --stdout option
17842 print STDOUT $Report;
17843 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017844 else
17845 {
17846 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017847 mkpath(get_dirname($RPath));
17848
17849 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17850 print REPORT $Report;
17851 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017852 }
17853}
17854
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017855sub getReport($)
17856{
17857 my $Level = $_[0];
17858 if($ReportFormat eq "xml")
17859 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017860 if($Level eq "Join")
17861 {
17862 my $Report = "<reports>\n";
17863 $Report .= getReport("Binary");
17864 $Report .= getReport("Source");
17865 $Report .= "</reports>\n";
17866 return $Report;
17867 }
17868 else
17869 {
17870 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17871 my ($Summary, $MetaData) = get_Summary($Level);
17872 $Report .= $Summary."\n";
17873 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17874 $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 +040017875
17876 # additional symbols info (if needed)
17877 # $Report .= get_Report_SymbolsInfo($Level);
17878
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017879 $Report .= "</report>\n";
17880 return $Report;
17881 }
17882 }
17883 else
17884 { # HTML
17885 my $CssStyles = readModule("Styles", "Report.css");
17886 my $JScripts = readModule("Scripts", "Sections.js");
17887 if($Level eq "Join")
17888 {
17889 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17890 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017891 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017892 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17893 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 +040017894 my ($BSummary, $BMetaData) = get_Summary("Binary");
17895 my ($SSummary, $SMetaData) = get_Summary("Source");
17896 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 +030017897 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017898 <br/>
17899 <div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017900 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17901 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017902 </div>";
17903 $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>";
17904 $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 +030017905 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017906 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017907 return $Report;
17908 }
17909 else
17910 {
17911 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017912 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17913 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17914 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 +040017915 if($Level eq "Binary")
17916 {
17917 if(getArch(1) eq getArch(2)
17918 and getArch(1) ne "unknown") {
17919 $Description .= " on ".showArch(getArch(1));
17920 }
17921 }
17922 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 +030017923 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017924 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17925 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17926 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017927 $Report .= "</div>\n<br/><br/><br/>\n";
17928 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017929 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017930 return $Report;
17931 }
17932 }
17933}
17934
17935sub createReport()
17936{
17937 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017938 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017939 writeReport("Join", getReport("Join"));
17940 }
17941 elsif($DoubleReport)
17942 { # default
17943 writeReport("Binary", getReport("Binary"));
17944 writeReport("Source", getReport("Source"));
17945 }
17946 elsif($BinaryOnly)
17947 { # --binary
17948 writeReport("Binary", getReport("Binary"));
17949 }
17950 elsif($SourceOnly)
17951 { # --source
17952 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017953 }
17954}
17955
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017956sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017957{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017958 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017959
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017960 $Footer .= "<hr/>\n";
17961 $Footer .= "<div class='footer' align='right'>";
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030017962 $Footer .= "<i>Generated by <a href='".$HomePage{"Dev"}."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;</i>\n";
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017963 $Footer .= "</div>\n";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017964 $Footer .= "<br/>\n";
17965
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017966 return $Footer;
17967}
17968
17969sub get_Report_Problems($$)
17970{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017971 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017972
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017973 my $Report = get_Report_TypeProblems($Severity, $Level);
17974 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017975 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017976 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017977
17978 if($Severity eq "Low" or $Severity eq "Safe") {
17979 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017980 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017981
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017982 if($ReportFormat eq "html")
17983 {
17984 if($Report)
17985 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017986 if($JoinReport)
17987 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017988 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017989 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17990 }
17991 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017992 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017993 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017994 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017995 else
17996 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017997 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017998 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17999 }
18000 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040018001 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018002 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018003 }
18004 }
18005 }
18006 return $Report;
18007}
18008
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018009sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018010{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018011 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +030018012
18013 my $Head = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
18014 $Head .= "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n";
18015 $Head .= "<head>\n";
18016 $Head .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
18017 $Head .= "<meta name=\"keywords\" content=\"$Keywords\" />\n";
18018 $Head .= "<meta name=\"description\" content=\"$Description\" />\n";
18019 $Head .= "<title>$Title</title>\n";
18020 $Head .= "<style type=\"text/css\">\n$Styles</style>\n";
18021 $Head .= "<script type=\"text/javascript\" language=\"JavaScript\">\n<!--\n$Scripts\n-->\n</script>\n";
18022 $Head .= "</head>\n";
18023
18024 return $Head;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018025}
18026
18027sub insertIDs($)
18028{
18029 my $Text = $_[0];
18030 while($Text=~/CONTENT_ID/)
18031 {
18032 if(int($Content_Counter)%2) {
18033 $ContentID -= 1;
18034 }
18035 $Text=~s/CONTENT_ID/c_$ContentID/;
18036 $ContentID += 1;
18037 $Content_Counter += 1;
18038 }
18039 return $Text;
18040}
18041
18042sub checkPreprocessedUnit($)
18043{
18044 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018045 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018046 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018047 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018048
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018049 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018050 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018051 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018052 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018053 chomp($Line);
18054 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018055 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018056 $CurHeader = path_format($1, $OSgroup);
18057 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018058 $CurClass = "";
18059
18060 if(index($CurHeader, $TMP_DIR)==0) {
18061 next;
18062 }
18063
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018064 if(substr($CurHeaderName, 0, 1) eq "<")
18065 { # <built-in>, <command-line>, etc.
18066 $CurHeaderName = "";
18067 $CurHeader = "";
18068 }
18069
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018070 if($ExtraInfo)
18071 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018072 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018073 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
18074 }
18075 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018076 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018077 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018078 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018079 if($CurHeaderName)
18080 {
18081 if(not $Include_Neighbors{$Version}{$CurHeaderName}
18082 and not $Registered_Headers{$Version}{$CurHeader})
18083 { # not a target
18084 next;
18085 }
18086 if(not is_target_header($CurHeaderName, 1)
18087 and not is_target_header($CurHeaderName, 2))
18088 { # user-defined header
18089 next;
18090 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018091 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018092 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018093
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018094 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018095 {
18096 my ($Name, $Value) = ($1, $2);
18097 if(not $Constants{$Version}{$Name}{"Access"})
18098 {
18099 $Constants{$Version}{$Name}{"Access"} = "public";
18100 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018101 if($CurHeaderName) {
18102 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
18103 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018104 }
18105 }
18106 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
18107 $Constants{$Version}{$1}{"Access"} = "private";
18108 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018109 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018110 else
18111 {
18112 if(defined $ExtraDump)
18113 {
18114 if($Line=~/(\w+)\s*\(/)
18115 { # functions
18116 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18117 }
18118 #elsif($Line=~/(\w+)\s*;/)
18119 #{ # data
18120 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18121 #}
18122 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
18123 $CurClass = $2;
18124 }
18125 }
18126 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018127 }
18128 close(PREPROC);
18129 foreach my $Constant (keys(%{$Constants{$Version}}))
18130 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018131 if($Constants{$Version}{$Constant}{"Access"} eq "private")
18132 {
18133 delete($Constants{$Version}{$Constant});
18134 next;
18135 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040018136 if(not $ExtraDump and ($Constant=~/_h\Z/i
18137 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018138 { # skip
18139 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018140 }
18141 else {
18142 delete($Constants{$Version}{$Constant}{"Access"});
18143 }
18144 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018145 if($Debug)
18146 {
18147 mkpath($DEBUG_PATH{$Version});
18148 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
18149 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018150}
18151
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018152sub uncoverConstant($$)
18153{
18154 my ($LibVersion, $Constant) = @_;
18155 return "" if(not $LibVersion or not $Constant);
18156 return $Constant if(isCyclical(\@RecurConstant, $Constant));
18157 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
18158 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
18159 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018160
18161 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018162 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018163 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
18164 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018165 {
18166 push(@RecurConstant, $Constant);
18167 my $Uncovered = uncoverConstant($LibVersion, $Value);
18168 if($Uncovered ne "") {
18169 $Value = $Uncovered;
18170 }
18171 pop(@RecurConstant);
18172 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018173
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018174 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018175 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018176 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
18177 }
18178 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
18179}
18180
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018181sub simpleConstant($$)
18182{
18183 my ($LibVersion, $Value) = @_;
18184 if($Value=~/\W/)
18185 {
18186 my $Value_Copy = $Value;
18187 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
18188 {
18189 my $Word = $1;
18190 if($Value!~/$Word\s*\(/)
18191 {
18192 my $Val = uncoverConstant($LibVersion, $Word);
18193 if($Val ne "")
18194 {
18195 $Value=~s/\b$Word\b/$Val/g;
18196 }
18197 }
18198 }
18199 }
18200 return $Value;
18201}
18202
18203sub computeValue($)
18204{
18205 my $Value = $_[0];
18206
18207 if($Value=~/\A\((-?[\d]+)\)\Z/) {
18208 return $1;
18209 }
18210
18211 if($Value=~/\A[\d\-\+()]+\Z/) {
18212 return eval($Value);
18213 }
18214
18215 return $Value;
18216}
18217
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018218my %IgnoreConstant = map {$_=>1} (
18219 "VERSION",
18220 "VERSIONCODE",
18221 "VERNUM",
18222 "VERS_INFO",
18223 "PATCHLEVEL",
18224 "INSTALLPREFIX",
18225 "VBUILD",
18226 "VPATCH",
18227 "VMINOR",
18228 "BUILD_STRING",
18229 "BUILD_TIME",
18230 "PACKAGE_STRING",
18231 "PRODUCTION",
18232 "CONFIGURE_COMMAND",
18233 "INSTALLDIR",
18234 "BINDIR",
18235 "CONFIG_FILE_PATH",
18236 "DATADIR",
18237 "EXTENSION_DIR",
18238 "INCLUDE_PATH",
18239 "LIBDIR",
18240 "LOCALSTATEDIR",
18241 "SBINDIR",
18242 "SYSCONFDIR",
18243 "RELEASE",
18244 "SOURCE_ID",
18245 "SUBMINOR",
18246 "MINOR",
18247 "MINNOR",
18248 "MINORVERSION",
18249 "MAJOR",
18250 "MAJORVERSION",
18251 "MICRO",
18252 "MICROVERSION",
18253 "BINARY_AGE",
18254 "INTERFACE_AGE",
18255 "CORE_ABI",
18256 "PATCH",
18257 "COPYRIGHT",
18258 "TIMESTAMP",
18259 "REVISION",
18260 "PACKAGE_TAG",
18261 "PACKAGEDATE",
18262 "NUMVERSION",
18263 "Release",
18264 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018265);
18266
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018267sub constantFilter($$$)
18268{
18269 my ($Name, $Value, $Level) = @_;
18270
18271 if($Level eq "Binary")
18272 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018273 if($Name=~/_t\Z/)
18274 { # __malloc_ptr_t
18275 return 1;
18276 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018277 foreach (keys(%IgnoreConstant))
18278 {
18279 if($Name=~/(\A|_)$_(_|\Z)/)
18280 { # version
18281 return 1;
18282 }
18283 if(/\A[A-Z].*[a-z]\Z/)
18284 {
18285 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18286 { # version
18287 return 1;
18288 }
18289 }
18290 }
18291 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18292 { # version
18293 return 1;
18294 }
18295 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18296 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18297 return 1;
18298 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018299
18300 if($Value=~/\A["'].*['"]/i)
18301 { # string
18302 return 0;
18303 }
18304
18305 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18306 { # static int gcry_pth_init
18307 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018308 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018309 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018310 return 1;
18311 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018312 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018313 { # foo(p)
18314 return 1;
18315 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018316 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018317 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018318 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018319 return 1;
18320 }
18321 }
18322
18323 return 0;
18324}
18325
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018326sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018327{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018328 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018329 foreach my $Constant (keys(%{$Constants{1}}))
18330 {
18331 if($SkipConstants{1}{$Constant})
18332 { # skipped by the user
18333 next;
18334 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018335
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018336 if(my $Header = $Constants{1}{$Constant}{"Header"})
18337 {
18338 if(not is_target_header($Header, 1)
18339 and not is_target_header($Header, 2))
18340 { # user-defined header
18341 next;
18342 }
18343 }
18344 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018345 next;
18346 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018347
18348 my $Old_Value = uncoverConstant(1, $Constant);
18349
18350 if(constantFilter($Constant, $Old_Value, $Level))
18351 { # separate binary and source problems
18352 next;
18353 }
18354
18355 if(not defined $Constants{2}{$Constant}{"Value"})
18356 { # removed
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030018357 if(not defined $SkipRemovedConstants)
18358 {
18359 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18360 "Target"=>$Constant,
18361 "Old_Value"=>$Old_Value );
18362 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018363 next;
18364 }
18365
18366 if($Constants{2}{$Constant}{"Value"} eq "")
18367 { # empty value
18368 # TODO: implement a rule
18369 next;
18370 }
18371
18372 my $New_Value = uncoverConstant(2, $Constant);
18373
18374 my $Old_Value_Pure = $Old_Value;
18375 my $New_Value_Pure = $New_Value;
18376
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018377 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18378 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18379 $New_Value_Pure=~s/(\W)\s+/$1/g;
18380 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018381
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018382 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018383
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018384 if($New_Value_Pure ne $Old_Value_Pure)
18385 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018386 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18387 { # complex values
18388 next;
18389 }
18390 if(computeValue($Old_Value) eq computeValue($New_Value))
18391 { # expressions
18392 next;
18393 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018394 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18395 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18396 next;
18397 }
18398 if($Old_Value eq "0" and $New_Value eq "NULL")
18399 { # 0 => NULL
18400 next;
18401 }
18402 if($Old_Value eq "NULL" and $New_Value eq "0")
18403 { # NULL => 0
18404 next;
18405 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018406 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018407 "Target"=>$Constant,
18408 "Old_Value"=>$Old_Value,
18409 "New_Value"=>$New_Value );
18410 }
18411 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018412
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030018413 if(defined $SkipAddedConstants) {
18414 return;
18415 }
18416
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018417 foreach my $Constant (keys(%{$Constants{2}}))
18418 {
18419 if(not defined $Constants{1}{$Constant}{"Value"})
18420 {
18421 if($SkipConstants{2}{$Constant})
18422 { # skipped by the user
18423 next;
18424 }
18425
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018426 if(my $Header = $Constants{2}{$Constant}{"Header"})
18427 {
18428 if(not is_target_header($Header, 1)
18429 and not is_target_header($Header, 2))
18430 { # user-defined header
18431 next;
18432 }
18433 }
18434 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018435 next;
18436 }
18437
18438 my $New_Value = uncoverConstant(2, $Constant);
18439 if(not defined $New_Value or $New_Value eq "") {
18440 next;
18441 }
18442
18443 if(constantFilter($Constant, $New_Value, $Level))
18444 { # separate binary and source problems
18445 next;
18446 }
18447
18448 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18449 "Target"=>$Constant,
18450 "New_Value"=>$New_Value );
18451 }
18452 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018453}
18454
18455sub convert_integer($)
18456{
18457 my $Value = $_[0];
18458 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018459 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018460 return hex($Value);
18461 }
18462 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018463 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018464 return oct($Value);
18465 }
18466 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018467 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018468 return oct($Value);
18469 }
18470 else {
18471 return $Value;
18472 }
18473}
18474
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018475sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018476{
18477 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018478 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018479 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018480 {
18481 if($LibVersion==1)
18482 {
18483 printMsg("WARNING", "checking headers only");
18484 $CheckHeadersOnly = 1;
18485 }
18486 else {
18487 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18488 }
18489 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018490
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018491 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018492 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018493 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018494
18495 if($CheckUndefined)
18496 {
18497 my %UndefinedLibs = ();
18498
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018499 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18500
18501 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018502 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018503 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018504 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018505 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018506 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018507 if($Symbol_Library{$LibVersion}{$Symbol}
18508 or $DepSymbol_Library{$LibVersion}{$Symbol})
18509 { # exported by target library
18510 next;
18511 }
18512 if(index($Symbol, '@')!=-1)
18513 { # exported default symbol version (@@)
18514 $Symbol=~s/\@/\@\@/;
18515 if($Symbol_Library{$LibVersion}{$Symbol}
18516 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18517 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018518 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018519 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018520 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18521 $UndefinedLibs{$Path} = 1;
18522 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018523 }
18524 }
18525 }
18526 if($ExtraInfo)
18527 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018528 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018529 {
18530 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018531 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018532 foreach (@Paths)
18533 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018534 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018535 my ($Dir, $Name) = separate_path($_);
18536
18537 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018538 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018539 }
18540
18541 $Name = parse_libname($Name, "name", $OStarget);
18542 $Name=~s/\Alib//;
18543
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018544 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018545 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018546
18547 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18548 {
18549 $LibString = " -L".esc($Dir).$LibString;
18550 }
18551
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018552 writeFile($ExtraInfo."/libs-string", $LibString);
18553 }
18554 }
18555 }
18556
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018557 if($ExtraInfo) {
18558 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18559 }
18560
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018561 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018562 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018563 if($#LibPaths!=-1)
18564 {
18565 if(not keys(%{$Symbol_Library{$LibVersion}}))
18566 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018567 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018568 printMsg("WARNING", "checking headers only");
18569 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018570 }
18571 }
18572 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018573
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018574 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018575 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018576}
18577
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018578my %Prefix_Lib_Map=(
18579 # symbols for autodetecting library dependencies (by prefix)
18580 "pthread_" => ["libpthread"],
18581 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18582 "cairo_" => ["libcairo"],
18583 "gtk_" => ["libgtk-x11-2.0"],
18584 "atk_" => ["libatk-1.0"],
18585 "gdk_" => ["libgdk-x11-2.0"],
18586 "gl" => ["libGL"],
18587 "glu" => ["libGLU"],
18588 "popt" => ["libpopt"],
18589 "Py" => ["libpython"],
18590 "jpeg_" => ["libjpeg"],
18591 "BZ2_" => ["libbz2"],
18592 "Fc" => ["libfontconfig"],
18593 "Xft" => ["libXft"],
18594 "SSL_" => ["libssl"],
18595 "sem_" => ["libpthread"],
18596 "snd_" => ["libasound"],
18597 "art_" => ["libart_lgpl_2"],
18598 "dbus_g" => ["libdbus-glib-1"],
18599 "GOMP_" => ["libgomp"],
18600 "omp_" => ["libgomp"],
18601 "cms" => ["liblcms"]
18602);
18603
18604my %Pattern_Lib_Map=(
18605 "SL[a-z]" => ["libslang"]
18606);
18607
18608my %Symbol_Lib_Map=(
18609 # symbols for autodetecting library dependencies (by name)
18610 "pow" => "libm",
18611 "fmod" => "libm",
18612 "sin" => "libm",
18613 "floor" => "libm",
18614 "cos" => "libm",
18615 "dlopen" => "libdl",
18616 "deflate" => "libz",
18617 "inflate" => "libz",
18618 "move_panel" => "libpanel",
18619 "XOpenDisplay" => "libX11",
18620 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018621 "clock_gettime" => "librt",
18622 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018623);
18624
18625sub find_SymbolLibs($$)
18626{
18627 my ($LibVersion, $Symbol) = @_;
18628
18629 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18630 { # debug symbols
18631 return ();
18632 }
18633
18634 my %Paths = ();
18635
18636 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18637 {
18638 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18639 $Paths{$Path} = 1;
18640 }
18641 }
18642
18643 if(my $SymbolPrefix = getPrefix($Symbol))
18644 {
18645 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18646 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18647 }
18648
18649 if(not keys(%Paths))
18650 {
18651 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18652 {
18653 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18654 {
18655 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18656 $Paths{$Path} = 1;
18657 }
18658 }
18659 }
18660 }
18661
18662 if(not keys(%Paths))
18663 {
18664 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18665 {
18666 if($Symbol=~/\A$Prefix/)
18667 {
18668 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18669 {
18670 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18671 $Paths{$Path} = 1;
18672 }
18673 }
18674 }
18675 }
18676 }
18677
18678 if(not keys(%Paths))
18679 {
18680 if($SymbolPrefix)
18681 { # try to find a library by symbol prefix
18682 if($SymbolPrefix eq "inotify" and
18683 index($Symbol, "\@GLIBC")!=-1)
18684 {
18685 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18686 $Paths{$Path} = 1;
18687 }
18688 }
18689 else
18690 {
18691 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18692 $Paths{$Path} = 1;
18693 }
18694 }
18695 }
18696 }
18697
18698 if(my @Paths = keys(%Paths)) {
18699 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18700 }
18701 }
18702 return keys(%Paths);
18703}
18704
18705sub get_LibPath_Prefix($$)
18706{
18707 my ($LibVersion, $Prefix) = @_;
18708
18709 $Prefix = lc($Prefix);
18710 $Prefix=~s/[_]+\Z//g;
18711
18712 foreach ("-2", "2", "-1", "1", "")
18713 { # libgnome-2.so
18714 # libxml2.so
18715 # libdbus-1.so
18716 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18717 return $Path;
18718 }
18719 }
18720 return "";
18721}
18722
18723sub getPrefix($)
18724{
18725 my $Str = $_[0];
18726 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18727 { # XmuValidArea: Xmu
18728 return $1;
18729 }
18730 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18731 { # snfReadFont: snf
18732 return $1;
18733 }
18734 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18735 { # XRRTimes: XRR
18736 return $1;
18737 }
18738 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18739 { # H5HF_delete: H5
18740 return $1;
18741 }
18742 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18743 { # alarm_event_add: alarm_
18744 return $1;
18745 }
18746 elsif($Str=~/\A(([a-z])\2{1,})/i)
18747 { # ffopen
18748 return $1;
18749 }
18750 return "";
18751}
18752
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018753sub getSymbolSize($$)
18754{ # size from the shared library
18755 my ($Symbol, $LibVersion) = @_;
18756 return 0 if(not $Symbol);
18757 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18758 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18759 {
18760 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18761 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18762 {
18763 if($Size<0) {
18764 return -$Size;
18765 }
18766 }
18767 }
18768 return 0;
18769}
18770
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018771sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018772{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18773 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018774 my ($Name, $Type) = @_;
18775
18776 # single
18777 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018778 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018779 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018780 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018781 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018782
18783 # double
18784 if($Name=~/$DEFAULT_STD_PARMS/)
18785 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018786 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018787 {
18788 my ($ShortName, $FuncParams) = split_Signature($Name);
18789
18790 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18791 {
18792 if(index($FParam, "<")!=-1)
18793 {
18794 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18795 my $FParam_N = canonifyName($FParam, "T");
18796 if($FParam_N ne $FParam) {
18797 $Name=~s/\Q$FParam\E/$FParam_N/g;
18798 }
18799 }
18800 }
18801 }
18802 elsif($Type eq "T")
18803 {
18804 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18805
18806 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018807 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018808 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018809 my $FParam = $TParams[0];
18810 foreach my $Pos (1 .. $#TParams)
18811 {
18812 my $TParam = $TParams[$Pos];
18813 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18814 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18815 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018816 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018817 }
18818 }
18819 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018820 if($Type eq "S") {
18821 return formatName($Name, "S");
18822 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018823 return $Name;
18824}
18825
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018826sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018827{
18828 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018829 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018830 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018831 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018832 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018833 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018834 next if($tr_name{$Symbol});
18835 $Symbol=~s/[\@\$]+(.*)\Z//;
18836 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018837 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018838 elsif(index($Symbol, "?")==0)
18839 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018840 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018841 }
18842 else
18843 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018844 $tr_name{$Symbol} = $Symbol;
18845 $mangled_name_gcc{$Symbol} = $Symbol;
18846 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018847 }
18848 }
18849 if($#MnglNames1 > -1)
18850 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018851 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018852 foreach my $MnglName (@MnglNames1)
18853 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018854 if(my $Unmangled = pop(@UnmangledNames))
18855 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018856 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018857 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18858 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18859 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018860 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018861 and $tr_name{$MnglName}=~/vtable for (.+)/)
18862 { # bind class name and v-table symbol
18863 my $ClassName = $1;
18864 $ClassVTable{$ClassName} = $MnglName;
18865 $VTableClass{$MnglName} = $ClassName;
18866 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018867 }
18868 }
18869 }
18870 if($#MnglNames2 > -1)
18871 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018872 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018873 foreach my $MnglName (@MnglNames2)
18874 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018875 if(my $Unmangled = pop(@UnmangledNames))
18876 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018877 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018878 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18879 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018880 }
18881 }
18882 return \%tr_name;
18883}
18884
18885sub link_symbol($$$)
18886{
18887 my ($Symbol, $RunWith, $Deps) = @_;
18888 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18889 return 1;
18890 }
18891 if($Deps eq "+Deps")
18892 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018893 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018894 return 1;
18895 }
18896 }
18897 return 0;
18898}
18899
18900sub link_symbol_internal($$$)
18901{
18902 my ($Symbol, $RunWith, $Where) = @_;
18903 return 0 if(not $Where or not $Symbol);
18904 if($Where->{$RunWith}{$Symbol})
18905 { # the exact match by symbol name
18906 return 1;
18907 }
18908 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18909 { # indirect symbol version, i.e.
18910 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018911 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018912 if($Where->{$RunWith}{$VSym}) {
18913 return 1;
18914 }
18915 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018916 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018917 if($Sym and $Ver)
18918 { # search for the symbol with the same version
18919 # or without version
18920 if($Where->{$RunWith}{$Sym})
18921 { # old: foo@v|foo@@v
18922 # new: foo
18923 return 1;
18924 }
18925 if($Where->{$RunWith}{$Sym."\@".$Ver})
18926 { # old: foo|foo@@v
18927 # new: foo@v
18928 return 1;
18929 }
18930 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18931 { # old: foo|foo@v
18932 # new: foo@@v
18933 return 1;
18934 }
18935 }
18936 return 0;
18937}
18938
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018939sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018940{
18941 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018942 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018943 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018944 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018945 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018946 my $NM = get_CmdPath("nm");
18947 if(not $NM) {
18948 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018949 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018950 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018951 while(<APP>)
18952 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018953 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018954 push(@Imported, $1);
18955 }
18956 }
18957 close(APP);
18958 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018959 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018960 {
18961 my $DumpBinCmd = get_CmdPath("dumpbin");
18962 if(not $DumpBinCmd) {
18963 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18964 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018965 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018966 while(<APP>)
18967 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018968 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18969 push(@Imported, $1);
18970 }
18971 }
18972 close(APP);
18973 }
18974 else
18975 {
18976 my $ReadelfCmd = get_CmdPath("readelf");
18977 if(not $ReadelfCmd) {
18978 exitStatus("Not_Found", "can't find \"readelf\"");
18979 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018980 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018981 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018982 while(<APP>)
18983 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018984 if(defined $symtab)
18985 { # do nothing with symtab
18986 if(index($_, "'.dynsym'")!=-1)
18987 { # dynamic table
18988 $symtab = undef;
18989 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018990 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018991 elsif(index($_, "'.symtab'")!=-1)
18992 { # symbol table
18993 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018994 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018995 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018996 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018997 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18998 if($Ndx eq "UND")
18999 { # only imported symbols
19000 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019001 }
19002 }
19003 }
19004 close(APP);
19005 }
19006 return @Imported;
19007}
19008
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019009my %ELF_BIND = map {$_=>1} (
19010 "WEAK",
19011 "GLOBAL"
19012);
19013
19014my %ELF_TYPE = map {$_=>1} (
19015 "FUNC",
19016 "IFUNC",
19017 "OBJECT",
19018 "COMMON"
19019);
19020
19021my %ELF_VIS = map {$_=>1} (
19022 "DEFAULT",
19023 "PROTECTED"
19024);
19025
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019026sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019027{ # read the line of 'readelf' output corresponding to the symbol
19028 my @Info = split(/\s+/, $_[0]);
19029 # Num: Value Size Type Bind Vis Ndx Name
19030 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019031 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019032 shift(@Info); # spaces
19033 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019034
19035 if($#Info==7)
19036 { # UND SYMBOL (N)
19037 if($Info[7]=~/\(\d+\)/) {
19038 pop(@Info);
19039 }
19040 }
19041
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019042 if($#Info!=6)
19043 { # other lines
19044 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019045 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019046 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019047 return () if(not defined $ELF_BIND{$Info[3]});
19048 return () if(not defined $ELF_VIS{$Info[4]});
19049 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
19050 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
19051 return ();
19052 }
19053 if($OStarget eq "symbian")
19054 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
19055 if(index($Info[6], "_._.absent_export_")!=-1)
19056 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
19057 return ();
19058 }
19059 $Info[6]=~s/\@.+//g; # remove version
19060 }
19061 if(index($Info[2], "0x") == 0)
19062 { # size == 0x3d158
19063 $Info[2] = hex($Info[2]);
19064 }
19065 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019066}
19067
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019068sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019069{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019070 my ($LibVersion, $Name) = @_;
19071 return "" if(not $LibVersion or not $Name);
19072 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
19073 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019074 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019075 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
19076}
19077
19078sub get_LibPath_I($$)
19079{
19080 my ($LibVersion, $Name) = @_;
19081 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019082 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019083 if(-f $Name)
19084 { # absolute path
19085 return $Name;
19086 }
19087 else
19088 { # broken
19089 return "";
19090 }
19091 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019092 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019093 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019094 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019095 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019096 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019097 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019098 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019099 }
19100 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
19101 { # ldconfig default paths
19102 return $DefaultPath;
19103 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019104 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019105 { # search in default linker directories
19106 # and then in all system paths
19107 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019108 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019109 }
19110 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019111 if(not defined $Cache{"checkSystemFiles"}) {
19112 checkSystemFiles();
19113 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019114 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
19115 return $AllObjects[0];
19116 }
19117 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
19118 {
19119 if($ShortName ne $Name)
19120 { # FIXME: check this case
19121 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
19122 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019123 }
19124 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019125 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019126 # can't find
19127 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019128}
19129
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019130sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019131{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019132 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
19133 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019134
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019135 my $Real_Path = realpath_F($Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019136
19137 if(not $Real_Path)
19138 { # broken link
19139 return ();
19140 }
19141
19142 my $Lib_Name = get_filename($Real_Path);
19143
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019144 if($ExtraInfo)
19145 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019146 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019147 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019148 }
19149
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019150 if($IsNeededLib)
19151 {
19152 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
19153 return ();
19154 }
19155 }
19156 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019157 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019158
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019159 push(@RecurLib, $Lib_Name);
19160 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019161 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
19162
19163 if(not $IsNeededLib)
19164 { # special cases: libstdc++ and libc
19165 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
19166 {
19167 if($ShortName eq "libstdc++")
19168 { # libstdc++.so.6
19169 $STDCXX_TESTING = 1;
19170 }
19171 elsif($ShortName eq "libc")
19172 { # libc-2.11.3.so
19173 $GLIBC_TESTING = 1;
19174 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019175 }
19176 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019177 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019178 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019179 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019180 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019181 mkpath(get_dirname($DebugPath));
19182 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019183 if($OStarget eq "macos")
19184 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019185 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019186 if(not $NM) {
19187 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019188 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019189 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019190 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019191 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019192 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019193 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019194 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019195 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019196 else
19197 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019198 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019199 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019200 while(<LIB>)
19201 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019202 if($CheckUndefined)
19203 {
19204 if(not $IsNeededLib)
19205 {
19206 if(/ U _([\w\$]+)\s*\Z/)
19207 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019208 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019209 next;
19210 }
19211 }
19212 }
19213
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019214 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019215 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019216 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019217 if($IsNeededLib)
19218 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019219 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019220 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019221 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19222 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019223 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019224 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019225 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019226 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019227 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19228 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019229 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19230 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019231 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019232 setLanguage($LibVersion, "C++");
19233 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019234 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019235 }
19236 }
19237 }
19238 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019239
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019240 if($Deps)
19241 {
19242 if($LIB_TYPE eq "dynamic")
19243 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019244
19245 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019246 if(not $OtoolCmd) {
19247 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019248 }
19249
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019250 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19251 while(<LIB>)
19252 {
19253 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
19254 and $1 ne $Lib_Path) {
19255 $NeededLib{$1} = 1;
19256 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019257 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019258 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019259 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019260 }
19261 }
19262 elsif($OStarget eq "windows")
19263 { # Windows *.dll, *.lib
19264 my $DumpBinCmd = get_CmdPath("dumpbin");
19265 if(not $DumpBinCmd) {
19266 exitStatus("Not_Found", "can't find \"dumpbin\"");
19267 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019268 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019269 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019270 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019271 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019272 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019273 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019274 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019275 else
19276 { # write to pipe
19277 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019278 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019279 while(<LIB>)
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019280 {
19281 my $realname = undef;
19282 if($LIB_TYPE eq "dynamic")
19283 {
19284 # 1197 4AC 0000A620 SetThreadStackGuarantee
19285 # 1198 4AD SetThreadToken (forwarded to ...)
19286 # 3368 _o2i_ECPublicKey
19287 # 1 0 00005B30 ??0?N = ... (with pdb)
19288 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
19289 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
19290 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
19291 { # dynamic, static and forwarded symbols
19292 $realname = $1;
19293 }
19294 }
19295 else
19296 { # static
19297 if(/\A\s{10,}\d*\s+([\w\?\@]+)\s*\Z/i)
19298 {
19299 # 16 IID_ISecurityInformation
19300 $realname = $1;
19301 }
19302 }
19303
19304 if($realname)
19305 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019306 if($IsNeededLib)
19307 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019308 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019309 {
19310 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19311 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19312 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019313 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019314 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019315 {
19316 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19317 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019318 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19319 {
19320 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19321 setLanguage($LibVersion, "C++");
19322 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019323 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019324 }
19325 }
19326 }
19327 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019328
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019329 if($Deps)
19330 {
19331 if($LIB_TYPE eq "dynamic")
19332 { # dependencies
19333 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19334 while(<LIB>)
19335 {
19336 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19337 and $1 ne $Lib_Path) {
19338 $NeededLib{path_format($1, $OSgroup)} = 1;
19339 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019340 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019341 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019342 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019343 }
19344 }
19345 else
19346 { # Unix; *.so, *.a
19347 # Symbian: *.dso, *.lib
19348 my $ReadelfCmd = get_CmdPath("readelf");
19349 if(not $ReadelfCmd) {
19350 exitStatus("Not_Found", "can't find \"readelf\"");
19351 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019352 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019353 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019354 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019355 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019356 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019357 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019358 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019359 else
19360 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019361 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019362 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019363 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019364 while(<LIB>)
19365 {
19366 if($LIB_TYPE eq "dynamic")
19367 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019368 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019369 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019370 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019371 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019372 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019373 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019374 # do nothing with symtab
19375 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019376 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019377 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019378 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019379 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019380 next;
19381 }
19382 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019383 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019384 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019385 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019386 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019387 if($CheckUndefined)
19388 {
19389 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019390 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019391 }
19392 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019393 next;
19394 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019395 if($Bind eq "WEAK")
19396 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019397 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019398 if($Weak eq "-Weak")
19399 { # skip WEAK symbols
19400 next;
19401 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019402 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019403 my $Short = $Symbol;
19404 $Short=~s/\@.+//g;
19405 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019406 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019407 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19408 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019409 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019410 if($IsNeededLib)
19411 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019412 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019413 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019414 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19415 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019416 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019417 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019418 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019419 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019420 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19421 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19422 if($Vers)
19423 {
19424 if($LIB_EXT eq "so")
19425 { # value
19426 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19427 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19428 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019429 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019430 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19431 {
19432 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19433 setLanguage($LibVersion, "C++");
19434 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019435 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019436 }
19437 }
19438 }
19439 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019440
19441 if($Deps and $LIB_TYPE eq "dynamic")
19442 { # dynamic library specifics
19443 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19444 open(LIB, $Cmd." |");
19445
19446 while(<LIB>)
19447 {
19448 if(/NEEDED.+\[([^\[\]]+)\]/)
19449 { # dependencies:
19450 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19451 $NeededLib{$1} = 1;
19452 }
19453 }
19454
19455 close(LIB);
19456 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019457 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019458 if($Vers)
19459 {
19460 if(not $IsNeededLib and $LIB_EXT eq "so")
19461 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019462 my %Found = ();
19463
19464 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019465 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019466 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019467 next if(index($Symbol,"\@")==-1);
19468 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019469 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019470 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019471 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019472 if($Symbol_SameValue ne $Symbol
19473 and index($Symbol_SameValue,"\@")==-1)
19474 {
19475 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019476 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019477 last;
19478 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019479 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019480 }
19481 }
19482
19483 # default
19484 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19485 {
19486 next if(defined $Found{$Symbol});
19487 next if(index($Symbol,"\@\@")==-1);
19488
19489 if($Symbol=~/\A([^\@]*)\@\@/
19490 and not $SymVer{$LibVersion}{$1})
19491 {
19492 $SymVer{$LibVersion}{$1} = $Symbol;
19493 $Found{$Symbol} = 1;
19494 }
19495 }
19496
19497 # non-default
19498 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19499 {
19500 next if(defined $Found{$Symbol});
19501 next if(index($Symbol,"\@")==-1);
19502
19503 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19504 and not $SymVer{$LibVersion}{$1})
19505 {
19506 $SymVer{$LibVersion}{$1} = $Symbol;
19507 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019508 }
19509 }
19510 }
19511 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019512 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019513 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019514 foreach my $DyLib (sort keys(%NeededLib))
19515 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019516 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19517
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019518 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19519 {
19520 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19521 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19522 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019523 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019524 }
19525 }
19526 pop(@RecurLib);
19527 return $Library_Symbol{$LibVersion};
19528}
19529
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019530sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019531{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019532 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019533 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019534 return keys(%Prefixes);
19535}
19536
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019537sub get_prefixes_I($$)
19538{
19539 foreach my $P (@{$_[0]})
19540 {
19541 my @Parts = reverse(split(/[\/\\]+/, $P));
19542 my $Name = $Parts[0];
19543 foreach (1 .. $#Parts)
19544 {
19545 $_[1]->{$Name}{$P} = 1;
19546 last if($_>4 or $Parts[$_] eq "include");
19547 $Name = $Parts[$_].$SLASH.$Name;
19548 }
19549 }
19550}
19551
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019552sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019553{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019554 $Cache{"checkSystemFiles"} = 1;
19555
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019556 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019557
19558 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019559 {
19560 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019561
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019562 my @Files = cmd_find($DevelPath,"f");
19563 foreach my $Link (cmd_find($DevelPath,"l"))
19564 { # add symbolic links
19565 if(-f $Link) {
19566 push(@Files, $Link);
19567 }
19568 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019569
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019570 # search for headers in /usr/lib
19571 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19572 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19573 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019574
19575 # search for libraries in /usr/lib (including symbolic links)
19576 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19577 foreach my $Path (@Libs)
19578 {
19579 my $N = get_filename($Path);
19580 $SystemObjects{$N}{$Path} = 1;
19581 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019582 }
19583 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019584
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019585 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019586 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019587 next if(not -d $DevelPath);
19588 # search for all header files in the /usr/include
19589 # with or without extension (ncurses.h, QtCore, ...)
19590 push(@SysHeaders, cmd_find($DevelPath,"f"));
19591 foreach my $Link (cmd_find($DevelPath,"l"))
19592 { # add symbolic links
19593 if(-f $Link) {
19594 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019595 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019596 }
19597 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019598 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019599}
19600
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019601sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019602{
19603 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019604 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019605 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19606 {
19607 if(not -e $Dest) {
19608 exitStatus("Access_Error", "can't access \'$Dest\'");
19609 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019610 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019611 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19612 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019613 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019614 }
19615 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019616 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019617}
19618
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019619sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019620{
19621 my ($Path, $LibVersion) = @_;
19622 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019623 my $Name = get_filename($Path);
19624 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019625 return 1;
19626 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019627 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019628 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19629 return 1;
19630 }
19631 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19632 {
19633 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19634 return 1;
19635 }
19636 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019637 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019638 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019639 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019640 return 1;
19641 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019642 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019643 return 1;
19644 }
19645 }
19646 return 0;
19647}
19648
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019649sub specificHeader($$)
19650{
19651 my ($Header, $Spec) = @_;
19652 my $Name = get_filename($Header);
19653
19654 if($Spec eq "windows")
19655 {# MS Windows
19656 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19657 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19658 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19659 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19660 my @Dirs = (
19661 "win32",
19662 "win64",
19663 "win",
19664 "windows",
19665 "msvcrt"
19666 ); # /gsf-win32/
19667 if(my $DIRs = join("|", @Dirs)) {
19668 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19669 }
19670 }
19671 elsif($Spec eq "macos")
19672 { # Mac OS
19673 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19674 }
19675
19676 return 0;
19677}
19678
19679sub skipAlienHeader($)
19680{
19681 my $Path = $_[0];
19682 my $Name = get_filename($Path);
19683 my $Dir = get_dirname($Path);
19684
19685 if($Tolerance=~/2/)
19686 { # 2 - skip internal headers
19687 my @Terms = (
19688 "p",
19689 "priv",
19690 "int",
19691 "impl",
19692 "implementation",
19693 "internal",
19694 "private",
19695 "old",
19696 "compat",
19697 "debug",
19698 "test",
19699 "gen"
19700 );
19701
19702 my @Dirs = (
19703 "private",
19704 "priv",
19705 "port",
19706 "impl",
19707 "internal",
19708 "detail",
19709 "details",
19710 "old",
19711 "compat",
19712 "debug",
19713 "config",
19714 "compiler",
19715 "platform",
19716 "test"
19717 );
19718
19719 if(my $TERMs = join("|", @Terms)) {
19720 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19721 }
19722 if(my $DIRs = join("|", @Dirs)) {
19723 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19724 }
19725
19726 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19727 }
19728
19729 if($Tolerance=~/1/)
19730 { # 1 - skip non-Linux headers
19731 if($OSgroup ne "windows")
19732 {
19733 if(specificHeader($Path, "windows")) {
19734 return 1;
19735 }
19736 }
19737 if($OSgroup ne "macos")
19738 {
19739 if(specificHeader($Path, "macos")) {
19740 return 1;
19741 }
19742 }
19743 }
19744
19745 # valid
19746 return 0;
19747}
19748
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019749sub skipHeader($$)
19750{
19751 my ($Path, $LibVersion) = @_;
19752 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019753 if(defined $Cache{"skipHeader"}{$Path}) {
19754 return $Cache{"skipHeader"}{$Path};
19755 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019756 if(defined $Tolerance and $Tolerance=~/1|2/)
19757 { # --tolerant
19758 if(skipAlienHeader($Path)) {
19759 return ($Cache{"skipHeader"}{$Path} = 1);
19760 }
19761 }
19762 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19763 return 0;
19764 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019765 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19766}
19767
19768sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019769{ # returns:
19770 # 1 - if header should NOT be included and checked
19771 # 2 - if header should NOT be included, but should be checked
19772 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019773 my $Name = get_filename($Path);
19774 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019775 return $Kind;
19776 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019777 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19778 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019779 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019780 if(index($Path, $D)!=-1)
19781 {
19782 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19783 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19784 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019785 }
19786 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019787 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19788 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019789 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019790 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19791 {
19792 if($Name=~/$P/) {
19793 return $Kind;
19794 }
19795 if($P=~/[\/\\]/ and $Path=~/$P/) {
19796 return $Kind;
19797 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019798 }
19799 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019800
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019801 return 0;
19802}
19803
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019804sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019805{
19806 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019807 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019808 { # system directory
19809 return;
19810 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019811 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019812 { # already registered
19813 return;
19814 }
19815 foreach my $Path (find_libs($Dir,"",1))
19816 {
19817 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019818 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019819 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019820 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019821 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19822}
19823
19824sub registerObject($$)
19825{
19826 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019827
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019828 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019829 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Mattias Ellert01e41222015-12-19 23:34:57 +010019830 if($OStarget=~/linux|bsd|gnu/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019831 {
19832 if(my $SONAME = getSONAME($Path)) {
19833 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19834 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019835 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019836 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19837 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019838 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019839
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019840 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019841 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019842 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019843 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019844 if($ObjArch ne getArch_GCC($LibVersion))
19845 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19846 $CheckedArch{$LibVersion} = 1;
19847 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 +040019848 }
19849 }
19850 }
19851}
19852
19853sub getArch_Object($)
19854{
19855 my $Path = $_[0];
19856
19857 my %MachineType = (
19858 "14C" => "x86",
19859 "8664" => "x86_64",
19860 "1C0" => "arm",
19861 "200" => "ia64"
19862 );
19863
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019864 my %ArchName = (
19865 "s390:31-bit" => "s390",
19866 "s390:64-bit" => "s390x",
19867 "powerpc:common" => "ppc32",
19868 "powerpc:common64" => "ppc64",
19869 "i386:x86-64" => "x86_64",
19870 "mips:3000" => "mips",
19871 "sparc:v8plus" => "sparcv9"
19872 );
19873
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019874 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019875 {
19876 my $DumpbinCmd = get_CmdPath("dumpbin");
19877 if(not $DumpbinCmd) {
19878 exitStatus("Not_Found", "can't find \"dumpbin\"");
19879 }
19880
19881 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19882 my $Out = `$Cmd`;
19883
19884 if($Out=~/(\w+)\smachine/)
19885 {
19886 if(my $Type = $MachineType{uc($1)})
19887 {
19888 return $Type;
19889 }
19890 }
19891 }
Mattias Ellert01e41222015-12-19 23:34:57 +010019892 elsif($OStarget=~/linux|bsd|gnu/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019893 {
19894 my $ObjdumpCmd = get_CmdPath("objdump");
19895 if(not $ObjdumpCmd) {
19896 exitStatus("Not_Found", "can't find \"objdump\"");
19897 }
19898
19899 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019900
19901 if($OSgroup eq "windows") {
19902 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19903 }
19904 else {
19905 $Cmd = "LANG=$LOCALE ".$Cmd;
19906 }
19907 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019908
19909 if($Out=~/architecture:\s+([\w\-\:]+)/)
19910 {
19911 my $Arch = $1;
19912 if($Arch=~s/\:(.+)//)
19913 {
19914 my $Suffix = $1;
19915
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019916 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019917 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019918 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019919 }
19920 }
19921
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019922 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019923 $Arch = "x86";
19924 }
19925
19926 if($Arch eq "x86-64") {
19927 $Arch = "x86_64";
19928 }
19929
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019930 if($Arch eq "ia64-elf64") {
19931 $Arch = "ia64";
19932 }
19933
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019934 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019935 }
19936 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019937 elsif($OStarget=~/macos/)
19938 {
19939 my $OtoolCmd = get_CmdPath("otool");
19940 if(not $OtoolCmd) {
19941 exitStatus("Not_Found", "can't find \"otool\"");
19942 }
19943
19944 my $Cmd = $OtoolCmd." -hv -arch all \"$Path\"";
19945 my $Out = qx/$Cmd/;
19946
19947 if($Out=~/X86_64/i) {
19948 return "x86_64";
19949 }
19950 elsif($Out=~/X86/i) {
19951 return "x86";
19952 }
19953 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019954 else
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019955 {
19956 exitStatus("Error", "Not implemented yet");
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019957 # TODO
19958 }
19959
19960 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019961}
19962
19963sub getSONAME($)
19964{
19965 my $Path = $_[0];
19966 return if(not $Path);
19967 if(defined $Cache{"getSONAME"}{$Path}) {
19968 return $Cache{"getSONAME"}{$Path};
19969 }
19970 my $ObjdumpCmd = get_CmdPath("objdump");
19971 if(not $ObjdumpCmd) {
19972 exitStatus("Not_Found", "can't find \"objdump\"");
19973 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019974 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019975 if($OSgroup eq "windows") {
19976 $SonameCmd .= " | find \"SONAME\"";
19977 }
19978 else {
19979 $SonameCmd .= " | grep SONAME";
19980 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019981 if(my $SonameInfo = `$SonameCmd`)
19982 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019983 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19984 return ($Cache{"getSONAME"}{$Path} = $1);
19985 }
19986 }
19987 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019988}
19989
19990sub getSOPaths_Dest($$)
19991{
19992 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019993 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019994 return ();
19995 }
19996 if(-f $Dest)
19997 {
19998 if(not parse_libname($Dest, "name", $OStarget)) {
19999 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
20000 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020001 registerObject($Dest, $LibVersion);
20002 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020003 return ($Dest);
20004 }
20005 elsif(-d $Dest)
20006 {
20007 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020008 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020009 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020010 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
20011 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020012 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020013 { # all files and symlinks that match the name of a library
20014 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
20015 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020016 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020017 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020018 }
20019 }
20020 }
20021 else
20022 { # search for all files and symlinks
20023 foreach my $Path (find_libs($Dest,"",""))
20024 {
20025 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020026 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020027 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020028 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020029 }
20030 if($OSgroup eq "macos")
20031 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020032 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020033 {
20034 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020035 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020036 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020037 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
20038 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020039 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020040 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020041 }
20042 }
20043 }
20044 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020045 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020046 }
20047 else {
20048 return ();
20049 }
20050}
20051
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020052sub realpath_F($)
20053{
20054 my $Path = $_[0];
20055 return path_format(realpath($Path), $OSgroup);
20056}
20057
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020058sub isCyclical($$)
20059{
20060 my ($Stack, $Value) = @_;
20061 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020062}
20063
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020064sub getGCC_Opts($)
20065{ # to use in module
20066 my $LibVersion = $_[0];
20067
20068 my @Opts = ();
20069
20070 if($CompilerOptions{$LibVersion})
20071 { # user-defined options
20072 push(@Opts, $CompilerOptions{$LibVersion});
20073 }
20074 if($GccOptions)
20075 { # additional
20076 push(@Opts, $GccOptions);
20077 }
20078
20079 if(@Opts) {
20080 return join(" ", @Opts);
20081 }
20082
20083 return undef;
20084}
20085
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040020086sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020087{
20088 my $LibVersion = $_[0];
20089
20090 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
20091 return $Cache{"getArch_GCC"}{$LibVersion};
20092 }
20093
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030020094 if(not $GCC_PATH) {
20095 return undef;
20096 }
20097
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020098 my $Arch = undef;
20099
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030020100 if(my $Target = get_dumpmachine($GCC_PATH))
20101 {
20102 if($Target=~/x86_64/) {
20103 $Arch = "x86_64";
20104 }
20105 elsif($Target=~/i[3-6]86/) {
20106 $Arch = "x86";
20107 }
20108 elsif($Target=~/\Aarm/i) {
20109 $Arch = "arm";
20110 }
20111 }
20112
20113 if(not $Arch)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020114 {
20115 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
20116
20117 my $Cmd = $GCC_PATH." test.c -o test";
20118 if(my $Opts = getGCC_Opts($LibVersion))
20119 { # user-defined options
20120 $Cmd .= " ".$Opts;
20121 }
20122
20123 chdir($TMP_DIR);
20124 system($Cmd);
20125 chdir($ORIG_DIR);
20126
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020127 my $EX = join_P($TMP_DIR, "test");
20128
20129 if($OSgroup eq "windows") {
20130 $EX = join_P($TMP_DIR, "test.exe");
20131 }
20132
20133 $Arch = getArch_Object($EX);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020134
20135 unlink("$TMP_DIR/test.c");
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020136 unlink($EX);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020137 }
20138
20139 if(not $Arch) {
20140 exitStatus("Error", "can't check ARCH type");
20141 }
20142
20143 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
20144}
20145
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020146sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020147{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020148 my $LibVersion = $_[0];
20149
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020150 my $Size = undef;
20151
20152 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020153 if(my $Arch = getArch($LibVersion))
20154 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040020155 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020156 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020157 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020158 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
20159 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020160 }
20161 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020162
20163 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020164 {
20165 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020166
20167 my $Cmd = $GCC_PATH." -E -dD empty.h";
20168 if(my $Opts = getGCC_Opts($LibVersion))
20169 { # user-defined options
20170 $Cmd .= " ".$Opts;
20171 }
20172
20173 chdir($TMP_DIR);
20174 my $Defines = `$Cmd`;
20175 chdir($ORIG_DIR);
20176
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020177 unlink("$TMP_DIR/empty.h");
20178
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020179 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
20180 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020181 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020182 }
20183 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
20184 { # GCC 3
20185 my $PTRDIFF = $1;
20186 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020187 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020188 }
20189 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020190 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020191 }
20192 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020193 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020194
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020195 if(not $Size) {
20196 exitStatus("Error", "can't check WORD size");
20197 }
20198
20199 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020200}
20201
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020202sub getWordSize($)
20203{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020204 return $WORD_SIZE{$_[0]};
20205}
20206
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020207sub majorVersion($)
20208{
20209 my $V = $_[0];
20210 return 0 if(not $V);
20211 my @VParts = split(/\./, $V);
20212 return $VParts[0];
20213}
20214
20215sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020216{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020217 my ($V1, $V2) = @_;
20218 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020219 my @V1Parts = split(/\./, $V1);
20220 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020221 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
20222 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020223 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
20224 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
20225 }
20226 return -1 if($#V1Parts < $#V2Parts);
20227 return 1 if($#V1Parts > $#V2Parts);
20228 return 0;
20229}
20230
20231sub read_ABI_Dump($$)
20232{
20233 my ($LibVersion, $Path) = @_;
20234 return if(not $LibVersion or not -e $Path);
20235 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020236 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020237 { # input *.abi
20238 $FilePath = $Path;
20239 }
20240 else
20241 { # input *.abi.tar.gz
20242 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020243 if(not isDump_U($FilePath)) {
20244 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20245 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020246 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020247
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020248 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020249
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020250 my $Line = readLineNum($FilePath, 0);
20251 if($Line=~/xml/)
20252 { # XML format
20253 loadModule("XmlDump");
20254 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020255 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020256 else
20257 { # Perl Data::Dumper format (default)
20258 open(DUMP, $FilePath);
20259 local $/ = undef;
20260 my $Content = <DUMP>;
20261 close(DUMP);
20262
20263 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
20264 { # remove temp file
20265 unlink($FilePath);
20266 }
20267 if($Content!~/};\s*\Z/) {
20268 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20269 }
20270 $ABI = eval($Content);
20271 if(not $ABI) {
20272 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
20273 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020274 }
20275 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020276 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020277 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020278 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020279 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020280 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020281 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020282 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030020283 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020284
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020285 if($ABI->{"PublicABI"}) {
20286 $UsedDump{$LibVersion}{"Public"} = 1;
20287 }
20288
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020289 if($ABI->{"ABI_DUMP_VERSION"})
20290 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020291 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020292 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020293 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020294 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020295 }
20296 else
20297 { # support for old ABI dumps
20298 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020299 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020300 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020301 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020302 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020303
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020304 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020305 {
20306 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 +040020307 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020308
20309 if(defined $ABI->{"ABI_DUMPER_VERSION"})
20310 { # DWARF ABI Dump
20311 $UseConv_Real{$LibVersion}{"P"} = 1;
20312 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
20313
20314 $UsedDump{$LibVersion}{"DWARF"} = 1;
20315
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030020316 if(not $TargetComponent_Opt)
20317 {
20318 if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
20319 $TargetComponent = "module";
20320 }
20321 else {
20322 $TargetComponent = "object";
20323 }
20324 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020325 }
20326
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020327 if(not checkDump($LibVersion, "2.11"))
20328 { # old ABI dumps
20329 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020330 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020331 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020332 { # ABI dump created with --binary option
20333 $UsedDump{$LibVersion}{"BinOnly"} = 1;
20334 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020335 else
20336 { # default
20337 $UsedDump{$LibVersion}{"SrcBin"} = 1;
20338 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020339
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020340 if(defined $ABI->{"Mode"}
20341 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020342 { # --ext option
20343 $ExtendedCheck = 1;
20344 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020345 if($ABI->{"Extra"}) {
20346 $ExtraDump = 1;
20347 }
20348
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020349 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020350 {
20351 $UsedDump{$LibVersion}{"L"} = $Lang;
20352 setLanguage($LibVersion, $Lang);
20353 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020354 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020355 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020356 }
20357 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020358 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020359 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020360 if(not $TInfo)
20361 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020362 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020363 }
20364 my %Tid_TDid = ();
20365 foreach my $TDid (keys(%{$TInfo}))
20366 {
20367 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
20368 {
20369 $MAX_ID = $Tid if($Tid>$MAX_ID);
20370 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020371 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020372 }
20373 }
20374 my %NewID = ();
20375 foreach my $Tid (keys(%Tid_TDid))
20376 {
20377 my @TDids = keys(%{$Tid_TDid{$Tid}});
20378 if($#TDids>=1)
20379 {
20380 foreach my $TDid (@TDids)
20381 {
20382 if($TDid) {
20383 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20384 }
20385 else
20386 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020387 my $ID = ++$MAX_ID;
20388
20389 $NewID{$TDid}{$Tid} = $ID;
20390 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20391 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020392 }
20393 }
20394 }
20395 else
20396 {
20397 my $TDid = $TDids[0];
20398 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20399 }
20400 }
20401 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20402 {
20403 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20404 if(defined $Info{"BaseType"})
20405 {
20406 my $Bid = $Info{"BaseType"}{"Tid"};
20407 my $BDid = $Info{"BaseType"}{"TDid"};
20408 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020409 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020410 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20411 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20412 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020413 }
20414 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20415 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020416 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020417 read_Machine_DumpInfo($ABI, $LibVersion);
20418 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020419 if(not $SymbolInfo{$LibVersion})
20420 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020421 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020422 }
20423 if(not keys(%{$SymbolInfo{$LibVersion}}))
20424 { # validation of old-version dumps
20425 if(not $ExtendedCheck) {
20426 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20427 }
20428 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020429 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020430 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020431 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020432 else
20433 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020434 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020435 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020436 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020437 }
20438 if(not $DepSymbols)
20439 { # Cannot reconstruct DepSymbols. This may result in false
20440 # positives if the old dump is for library 2. Not a problem if
20441 # old dumps are only from old libraries.
20442 $DepSymbols = {};
20443 }
20444 foreach my $Symbol (keys(%{$DepSymbols})) {
20445 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20446 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020447 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020448 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020449
20450 if(my $V = $TargetVersion{$LibVersion}) {
20451 $Descriptor{$LibVersion}{"Version"} = $V;
20452 }
20453 else {
20454 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20455 }
20456
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020457 if(not keys(%{$SkipTypes{$LibVersion}}))
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020458 { # if not defined by -skip-types option
20459 if(defined $ABI->{"SkipTypes"})
20460 {
20461 foreach my $TName (keys(%{$ABI->{"SkipTypes"}}))
20462 {
20463 $SkipTypes{$LibVersion}{$TName} = 1;
20464 }
20465 }
20466 if(defined $ABI->{"OpaqueTypes"})
20467 { # support for old dumps
20468 foreach my $TName (keys(%{$ABI->{"OpaqueTypes"}}))
20469 {
20470 $SkipTypes{$LibVersion}{$TName} = 1;
20471 }
20472 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020473 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020474
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020475 if(not keys(%{$SkipSymbols{$LibVersion}}))
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020476 { # if not defined by -skip-symbols option
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020477 if(defined $ABI->{"SkipSymbols"}) {
20478 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20479 }
20480 if(defined $ABI->{"SkipInterfaces"})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020481 { # support for old dumps
20482 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20483 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020484 if(defined $ABI->{"InternalInterfaces"})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020485 { # support for old dumps
20486 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20487 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020488 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020489 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020490
20491 if(not $TargetHeaders{$LibVersion})
20492 { # if not defined by -headers-list option
20493 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20494 }
20495
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020496 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020497 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020498 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030020499
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020500 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020501 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020502 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020503
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020504 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020505 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020506
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020507 if(not checkDump($LibVersion, "2.10.1")
20508 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020509 { # support for old ABI dumps: added target headers
20510 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020511 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020512 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020513
20514 if(not $ABI->{"PublicABI"})
20515 {
20516 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20517 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20518 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020519 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020520 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020521 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020522 if(defined $ABI->{"GccConstants"})
20523 { # 3.0
20524 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20525 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20526 }
20527 }
20528
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020529 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020530 if(not $NestedNameSpaces{$LibVersion})
20531 { # support for old dumps
20532 # Cannot reconstruct NameSpaces. This may affect design
20533 # of the compatibility report.
20534 $NestedNameSpaces{$LibVersion} = {};
20535 }
20536 # target system type
20537 # needed to adopt HTML report
20538 if(not $DumpSystem)
20539 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020540 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020541 }
20542 # recreate environment
20543 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20544 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020545 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020546 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020547 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20548 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020549 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020550 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020551 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020552 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20553 {
20554 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20555 setLanguage($LibVersion, "C++");
20556 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020557 }
20558 }
20559 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020560 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20561 {
20562 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20563 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20564 }
20565 }
20566
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020567 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020568 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020569 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020570 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020571 {
20572 if(not $Symbol_Library{$LibVersion}{$MnglName}
20573 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20574 push(@VFunc, $MnglName);
20575 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020576 }
20577 }
20578 translateSymbols(@VFunc, $LibVersion);
20579 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020580 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20581
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020582 if(not checkDump($LibVersion, "3.0"))
20583 { # support for old ABI dumps
20584 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20585 {
20586 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20587 {
20588 if(ref($BaseType) eq "HASH") {
20589 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20590 }
20591 }
20592 }
20593 }
20594
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020595 if(not checkDump($LibVersion, "3.2"))
20596 { # support for old ABI dumps
20597 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20598 {
20599 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20600 {
20601 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20602 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20603 }
20604 }
20605 }
20606
20607 # repair target headers list
20608 delete($TargetHeaders{$LibVersion});
20609 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020610 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20611 }
20612 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20613 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020614 }
20615
20616 # non-target constants from anon enums
20617 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20618 {
20619 if(not $ExtraDump
20620 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20621 {
20622 delete($Constants{$LibVersion}{$Name});
20623 }
20624 }
20625 }
20626
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020627 if(not checkDump($LibVersion, "2.20"))
20628 { # support for old ABI dumps
20629 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20630 {
20631 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20632
20633 if($TType=~/Struct|Union|Enum|Typedef/)
20634 { # repair complex types first
20635 next;
20636 }
20637
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020638 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020639 {
20640 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20641 if($BType=~/Struct|Union|Enum/i)
20642 {
20643 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20644 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20645 }
20646 }
20647 }
20648 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20649 {
20650 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20651 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20652 if($TType=~/Struct|Union|Enum/) {
20653 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20654 }
20655 }
20656 }
20657
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020658 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020659 { # NOTE: order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020660 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20661 { # support for old ABI dumps < 2.0 (ACC 1.22)
20662 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20663 {
20664 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20665 {
20666 if($Access ne "public") {
20667 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20668 }
20669 }
20670 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20671 }
20672 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20673 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020674 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20675 { # support for old ABI dumps
20676 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20677 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020678 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20679 { # DWARF ABI Dumps
20680 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20681 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020682 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20683 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20684 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020685
20686 # support for old formatting of type names
20687 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = formatName($TypeInfo{$LibVersion}{$TypeId}{"Name"}, "T");
20688
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020689 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20690 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020691 {
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +030020692 foreach my $SubId (keys(%{$TInfo{"Base"}}))
20693 {
20694 if($SubId eq $TypeId)
20695 { # Fix erroneus ABI dump
20696 delete($TypeInfo{$LibVersion}{$TypeId}{"Base"}{$SubId});
20697 next;
20698 }
20699
20700 $Class_SubClasses{$LibVersion}{$SubId}{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020701 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020702 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020703 if($TInfo{"Type"} eq "MethodPtr")
20704 {
20705 if(defined $TInfo{"Param"})
20706 { # support for old ABI dumps <= 1.17
20707 if(not defined $TInfo{"Param"}{"0"})
20708 {
20709 my $Max = keys(%{$TInfo{"Param"}});
20710 foreach my $Pos (1 .. $Max) {
20711 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20712 }
20713 delete($TInfo{"Param"}{$Max});
20714 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20715 }
20716 }
20717 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020718 if($TInfo{"BaseType"} eq $TypeId)
20719 { # fix ABI dump
20720 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20721 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020722
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020723 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020724 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020725 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020726 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020727 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20728 if(not $BName)
20729 { # broken type
20730 next;
20731 }
20732 if($TInfo{"Name"} eq $BName)
20733 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020734 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020735 next;
20736 }
20737 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20738 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020739 }
20740 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020741 }
20742 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20743 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020744 $TName_Tid{$LibVersion}{$TInfo{"Name"}} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020745 }
20746 }
20747
20748 if(not checkDump($LibVersion, "2.15"))
20749 { # support for old ABI dumps
20750 my %Dups = ();
20751 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20752 {
20753 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020754 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020755 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20756 { # remove template decls
20757 delete($SymbolInfo{$LibVersion}{$InfoId});
20758 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020759 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020760 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020761 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20762 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020763 { # templates
20764 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020765 }
20766 }
20767 }
20768
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020769 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20770 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020771 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20772 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20773 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20774 { # support for old ABI dumps (< 3.1)
20775 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20776 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20777 { # add "this" first parameter
20778 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20779 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20780
20781 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20782 {
20783 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20784 foreach my $Pos (reverse(0 .. $#Pos)) {
20785 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20786 }
20787 }
20788 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20789 }
20790 }
20791
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020792 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20793 { # ABI dumps have no mangled names for C-functions
20794 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20795 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020796 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20797 { # support for old ABI dumps
20798 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20799 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020800 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20801 { # DWARF ABI Dumps
20802 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20803 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020804 }
20805
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020806 $Descriptor{$LibVersion}{"Dump"} = 1;
20807}
20808
20809sub read_Machine_DumpInfo($$)
20810{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020811 my ($ABI, $LibVersion) = @_;
20812 if($ABI->{"Arch"}) {
20813 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020814 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020815 if($ABI->{"WordSize"}) {
20816 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020817 }
20818 else
20819 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020820 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020821 }
20822 if(not $WORD_SIZE{$LibVersion})
20823 { # support for old dumps (<1.23)
20824 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20825 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020826 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020827 }
20828 else
20829 {
20830 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020831 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020832 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020833 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20834 { # any "pointer"-type
20835 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020836 last;
20837 }
20838 }
20839 if($PSize)
20840 { # a pointer type size
20841 $WORD_SIZE{$LibVersion} = $PSize;
20842 }
20843 else {
20844 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20845 }
20846 }
20847 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020848 if($ABI->{"GccVersion"}) {
20849 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020850 }
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030020851 elsif($ABI->{"ClangVersion"}) {
20852 $CLANG_VERSION{$LibVersion} = $ABI->{"ClangVersion"};
20853 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020854}
20855
20856sub read_Libs_DumpInfo($$)
20857{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020858 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020859 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20860 if(not $Library_Symbol{$LibVersion})
20861 { # support for old dumps
20862 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20863 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020864 if(keys(%{$Library_Symbol{$LibVersion}})
20865 and not $DumpAPI) {
20866 $Descriptor{$LibVersion}{"Libs"} = "OK";
20867 }
20868}
20869
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020870sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020871{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020872 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020873
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020874 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020875 and not $DumpAPI) {
20876 $Descriptor{$LibVersion}{"Headers"} = "OK";
20877 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020878 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020879 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020880 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020881 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020882 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020883
20884 if(keys(%{$ABI->{"Sources"}})
20885 and not $DumpAPI) {
20886 $Descriptor{$LibVersion}{"Sources"} = "OK";
20887 }
20888 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020889 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020890 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20891 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20892 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020893}
20894
20895sub find_libs($$$)
20896{
20897 my ($Path, $Type, $MaxDepth) = @_;
20898 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020899 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020900}
20901
20902sub createDescriptor($$)
20903{
20904 my ($LibVersion, $Path) = @_;
20905 if(not $LibVersion or not $Path
20906 or not -e $Path) {
20907 return "";
20908 }
20909 if(-d $Path)
20910 { # directory with headers files and shared objects
20911 return "
20912 <version>
20913 ".$TargetVersion{$LibVersion}."
20914 </version>
20915
20916 <headers>
20917 $Path
20918 </headers>
20919
20920 <libs>
20921 $Path
20922 </libs>";
20923 }
20924 else
20925 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020926 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020927 { # standard XML-descriptor
20928 return readFile($Path);
20929 }
20930 elsif(is_header($Path, 2, $LibVersion))
20931 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020932 $CheckHeadersOnly = 1;
20933
20934 if($LibVersion==1) {
20935 $TargetVersion{$LibVersion} = "X";
20936 }
20937
20938 if($LibVersion==2) {
20939 $TargetVersion{$LibVersion} = "Y";
20940 }
20941
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020942 return "
20943 <version>
20944 ".$TargetVersion{$LibVersion}."
20945 </version>
20946
20947 <headers>
20948 $Path
20949 </headers>
20950
20951 <libs>
20952 none
20953 </libs>";
20954 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020955 else
20956 { # standard XML-descriptor
20957 return readFile($Path);
20958 }
20959 }
20960}
20961
20962sub detect_lib_default_paths()
20963{
20964 my %LPaths = ();
20965 if($OSgroup eq "bsd")
20966 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020967 if(my $LdConfig = get_CmdPath("ldconfig"))
20968 {
20969 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20970 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020971 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20972 {
20973 my $Name = "lib".$1;
20974 if(not defined $LPaths{$Name}) {
20975 $LPaths{$Name} = $2;
20976 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020977 }
20978 }
20979 }
20980 else {
20981 printMsg("WARNING", "can't find ldconfig");
20982 }
20983 }
20984 else
20985 {
20986 if(my $LdConfig = get_CmdPath("ldconfig"))
20987 {
20988 if($SystemRoot and $OSgroup eq "linux")
20989 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20990 if(-e $SystemRoot."/etc/ld.so.conf") {
20991 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20992 }
20993 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020994 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20995 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020996 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20997 {
20998 my ($Name, $Path) = ($1, $2);
20999 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021000 if(not defined $LPaths{$Name})
21001 { # get first element from the list of available paths
21002
21003 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
21004 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
21005 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
21006
21007 $LPaths{$Name} = $Path;
21008 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021009 }
21010 }
21011 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040021012 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021013 printMsg("WARNING", "can't find ldconfig");
21014 }
21015 }
21016 return \%LPaths;
21017}
21018
21019sub detect_bin_default_paths()
21020{
21021 my $EnvPaths = $ENV{"PATH"};
21022 if($OSgroup eq "beos") {
21023 $EnvPaths.=":".$ENV{"BETOOLS"};
21024 }
21025 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021026 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021027 {
21028 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021029 next if(not $Path);
21030 if($SystemRoot
21031 and $Path=~/\A\Q$SystemRoot\E\//)
21032 { # do NOT use binaries from target system
21033 next;
21034 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021035 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021036 }
21037}
21038
21039sub detect_inc_default_paths()
21040{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021041 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021042 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021043 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021044 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021045 next if(index($Line, "/cc1plus ")!=-1);
21046
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021047 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
21048 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030021049 my $Path = realpath_F($1);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021050 if(index($Path, "c++")!=-1
21051 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021052 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021053 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021054 if(not defined $MAIN_CPP_DIR
21055 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
21056 $MAIN_CPP_DIR = $Path;
21057 }
21058 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021059 elsif(index($Path, "gcc")!=-1) {
21060 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021061 }
21062 else
21063 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021064 if($Path=~/local[\/\\]+include/)
21065 { # local paths
21066 next;
21067 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021068 if($SystemRoot
21069 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
21070 { # The GCC include path for user headers is not a part of the system root
21071 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
21072 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
21073 next;
21074 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021075 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021076 }
21077 }
21078 }
21079 unlink("$TMP_DIR/empty.h");
21080 return %DPaths;
21081}
21082
21083sub detect_default_paths($)
21084{
21085 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
21086 my $Search = $_[0];
21087 if($Search!~/inc/) {
21088 $HSearch = 0;
21089 }
21090 if($Search!~/lib/) {
21091 $LSearch = 0;
21092 }
21093 if($Search!~/bin/) {
21094 $BSearch = 0;
21095 }
21096 if($Search!~/gcc/) {
21097 $GSearch = 0;
21098 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021099 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021100 { # <search_headers> section of the XML descriptor
21101 # do NOT search for systems headers
21102 $HSearch = 0;
21103 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021104 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030021105 { # <search_libs> section of the XML descriptor
21106 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021107 $LSearch = 0;
21108 }
21109 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
21110 { # additional search paths
21111 next if($Type eq "include" and not $HSearch);
21112 next if($Type eq "lib" and not $LSearch);
21113 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021114 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021115 }
21116 if($OSgroup ne "windows")
21117 { # unix-like
21118 foreach my $Type ("include", "lib", "bin")
21119 { # automatic detection of system "devel" directories
21120 next if($Type eq "include" and not $HSearch);
21121 next if($Type eq "lib" and not $LSearch);
21122 next if($Type eq "bin" and not $BSearch);
21123 my ($UsrDir, $RootDir) = ("/usr", "/");
21124 if($SystemRoot and $Type ne "bin")
21125 { # 1. search for target headers and libraries
21126 # 2. use host commands: ldconfig, readelf, etc.
21127 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
21128 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021129 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021130 if(-d $RootDir."/".$Type)
21131 { # if "/lib" is symbolic link
21132 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021133 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021134 }
21135 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021136 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021137 }
21138 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021139 if(-d $UsrDir)
21140 {
21141 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021142 if(-d $UsrDir."/".$Type)
21143 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021144 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021145 }
21146 }
21147 }
21148 }
21149 if($BSearch)
21150 {
21151 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021152 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021153 }
21154 # check environment variables
21155 if($OSgroup eq "beos")
21156 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021157 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021158 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021159 if($_ eq ".") {
21160 next;
21161 }
21162 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
21163 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
21164 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021165 }
21166 }
21167 if($HSearch)
21168 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021169 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
21170 split(/:|;/, $ENV{"BEINCLUDES"})
21171 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021172 }
21173 if($LSearch)
21174 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021175 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
21176 split(/:|;/, $ENV{"BELIBRARIES"}),
21177 split(/:|;/, $ENV{"LIBRARY_PATH"})
21178 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021179 }
21180 }
21181 if($LSearch)
21182 { # using linker to get system paths
21183 if(my $LPaths = detect_lib_default_paths())
21184 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021185 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021186 foreach my $Name (keys(%{$LPaths}))
21187 {
21188 if($SystemRoot
21189 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
21190 { # wrong ldconfig configuration
21191 # check your <sysroot>/etc/ld.so.conf
21192 next;
21193 }
21194 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021195 if(my $Dir = get_dirname($LPaths->{$Name})) {
21196 $Dirs{$Dir} = 1;
21197 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021198 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021199 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021200 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021201 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021202 }
21203 if($BSearch)
21204 {
21205 if($CrossGcc)
21206 { # --cross-gcc=arm-linux-gcc
21207 if(-e $CrossGcc)
21208 { # absolute or relative path
21209 $GCC_PATH = get_abs_path($CrossGcc);
21210 }
21211 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
21212 { # command name
21213 $GCC_PATH = $CrossGcc;
21214 }
21215 else {
21216 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
21217 }
21218 if($GCC_PATH=~/\s/) {
21219 $GCC_PATH = "\"".$GCC_PATH."\"";
21220 }
21221 }
21222 }
21223 if($GSearch)
21224 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021225 if(not $CrossGcc)
21226 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021227 $GCC_PATH = get_CmdPath("gcc");
21228 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021229 if(not $GCC_PATH)
21230 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021231 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021232 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021233 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021234 { # select the latest version
21235 @GCCs = sort {$b cmp $a} @GCCs;
21236 if(check_gcc($GCCs[0], "3"))
21237 {
21238 $GCC_PATH = $GCCs[0];
21239 last;
21240 }
21241 }
21242 }
21243 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021244 if(not $GCC_PATH) {
21245 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
21246 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021247
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021248 my $GCC_Ver = get_dumpversion($GCC_PATH);
21249 if($GCC_Ver eq "4.8")
21250 { # on Ubuntu -dumpversion returns 4.8 for gcc 4.8.4
21251 my $Info = `$GCC_PATH --version`;
21252
21253 if($Info=~/gcc\s+(|\([^()]+\)\s+)(\d+\.\d+\.\d+)/)
21254 { # gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
21255 # gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)
21256 $GCC_Ver = $2;
21257 }
21258 }
21259
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030021260 if($OStarget=~/macos/)
21261 {
21262 my $Info = `$GCC_PATH --version`;
21263
21264 if($Info=~/clang/i) {
21265 printMsg("WARNING", "doesn't work with clang, please install GCC instead (and select it by -gcc-path option)");
21266 }
21267 }
21268
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021269 if($GCC_Ver)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021270 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021271 my $GccTarget = get_dumpmachine($GCC_PATH);
21272
21273 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021274 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021275 $OStarget = "linux";
21276 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021277 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021278 elsif($GccTarget=~/symbian/)
21279 {
21280 $OStarget = "symbian";
21281 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
21282 }
21283
21284 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
21285
21286 # check GCC version
21287 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
21288 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021289 # introduced in 4.8 and fixed in 4.8.3
21290 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.");
21291
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021292 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021293 }
21294 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021295 else {
21296 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021297 }
21298 }
21299 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021300 {
21301 # GCC standard paths
21302 if($GCC_PATH and not $NoStdInc)
21303 {
21304 my %DPaths = detect_inc_default_paths();
21305 @DefaultCppPaths = @{$DPaths{"Cpp"}};
21306 @DefaultGccPaths = @{$DPaths{"Gcc"}};
21307 @DefaultIncPaths = @{$DPaths{"Inc"}};
21308 push_U($SystemPaths{"include"}, @DefaultIncPaths);
21309 }
21310
21311 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021312 my $IncPath = "/usr/include";
21313 if($SystemRoot) {
21314 $IncPath = $SystemRoot.$IncPath;
21315 }
21316 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021317 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021318 }
21319 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021320
21321 if($ExtraInfo)
21322 {
21323 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
21324 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
21325 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021326}
21327
21328sub getLIB_EXT($)
21329{
21330 my $Target = $_[0];
21331 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
21332 return $Ext;
21333 }
21334 return $OS_LibExt{$LIB_TYPE}{"default"};
21335}
21336
21337sub getAR_EXT($)
21338{
21339 my $Target = $_[0];
21340 if(my $Ext = $OS_Archive{$Target}) {
21341 return $Ext;
21342 }
21343 return $OS_Archive{"default"};
21344}
21345
21346sub get_dumpversion($)
21347{
21348 my $Cmd = $_[0];
21349 return "" if(not $Cmd);
21350 if($Cache{"get_dumpversion"}{$Cmd}) {
21351 return $Cache{"get_dumpversion"}{$Cmd};
21352 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021353 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021354 chomp($V);
21355 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
21356}
21357
21358sub get_dumpmachine($)
21359{
21360 my $Cmd = $_[0];
21361 return "" if(not $Cmd);
21362 if($Cache{"get_dumpmachine"}{$Cmd}) {
21363 return $Cache{"get_dumpmachine"}{$Cmd};
21364 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021365 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021366 chomp($Machine);
21367 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
21368}
21369
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021370sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021371{
21372 my $Cmd = $_[0];
21373 return "" if(not $Cmd);
21374 my @Options = (
21375 "--version",
21376 "-help"
21377 );
21378 foreach my $Opt (@Options)
21379 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021380 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021381 if($Info) {
21382 return 1;
21383 }
21384 }
21385 return 0;
21386}
21387
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021388sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021389{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021390 my ($Cmd, $ReqVer) = @_;
21391 return 0 if(not $Cmd or not $ReqVer);
21392 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
21393 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021394 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021395 if(my $GccVer = get_dumpversion($Cmd))
21396 {
21397 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
21398 if(cmpVersions($GccVer, $ReqVer)>=0) {
21399 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
21400 }
21401 }
21402 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021403}
21404
21405sub get_depth($)
21406{
21407 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021408 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021409 }
21410 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
21411}
21412
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021413sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021414{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021415 return if($Cache{"registerGccHeaders"}); # this function should be called once
21416
21417 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021418 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021419 my @Headers = cmd_find($Path,"f");
21420 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21421 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021422 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021423 my $FileName = get_filename($HPath);
21424 if(not defined $DefaultGccHeader{$FileName})
21425 { # skip duplicated
21426 $DefaultGccHeader{$FileName} = $HPath;
21427 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021428 }
21429 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021430 $Cache{"registerGccHeaders"} = 1;
21431}
21432
21433sub registerCppHeaders()
21434{
21435 return if($Cache{"registerCppHeaders"}); # this function should be called once
21436
21437 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021438 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021439 my @Headers = cmd_find($CppDir,"f");
21440 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21441 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021442 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021443 my $FileName = get_filename($Path);
21444 if(not defined $DefaultCppHeader{$FileName})
21445 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021446 $DefaultCppHeader{$FileName} = $Path;
21447 }
21448 }
21449 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021450 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021451}
21452
21453sub parse_libname($$$)
21454{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021455 return "" if(not $_[0]);
21456 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21457 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021458 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021459 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21460}
21461
21462sub parse_libname_I($$$)
21463{
21464 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021465
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021466 if($Target eq "symbian") {
21467 return parse_libname_symbian($Name, $Type);
21468 }
21469 elsif($Target eq "windows") {
21470 return parse_libname_windows($Name, $Type);
21471 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021472
21473 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021474 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021475 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021476 { # libSDL-1.2.so.0.7.1
21477 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021478 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021479 if($Type eq "name")
21480 { # libSDL-1.2
21481 # libwbxml2
21482 return $2;
21483 }
21484 elsif($Type eq "name+ext")
21485 { # libSDL-1.2.so
21486 # libwbxml2.so
21487 return $1;
21488 }
21489 elsif($Type eq "version")
21490 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021491 if(defined $7
21492 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021493 { # 0.7.1
21494 return $7;
21495 }
21496 else
21497 { # libc-2.5.so (=>2.5 version)
21498 my $MV = $5;
21499 $MV=~s/\A[\-\_]+//g;
21500 return $MV;
21501 }
21502 }
21503 elsif($Type eq "short")
21504 { # libSDL
21505 # libwbxml2
21506 return $3;
21507 }
21508 elsif($Type eq "shortest")
21509 { # SDL
21510 # wbxml
21511 return shortest_name($3);
21512 }
21513 }
21514 return "";# error
21515}
21516
21517sub parse_libname_symbian($$)
21518{
21519 my ($Name, $Type) = @_;
21520 my $Ext = getLIB_EXT("symbian");
21521 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21522 { # libpthread{00010001}.dso
21523 if($Type eq "name")
21524 { # libpthread{00010001}
21525 return $2;
21526 }
21527 elsif($Type eq "name+ext")
21528 { # libpthread{00010001}.dso
21529 return $1;
21530 }
21531 elsif($Type eq "version")
21532 { # 00010001
21533 my $V = $4;
21534 $V=~s/\{(.+)\}/$1/;
21535 return $V;
21536 }
21537 elsif($Type eq "short")
21538 { # libpthread
21539 return $3;
21540 }
21541 elsif($Type eq "shortest")
21542 { # pthread
21543 return shortest_name($3);
21544 }
21545 }
21546 return "";# error
21547}
21548
21549sub parse_libname_windows($$)
21550{
21551 my ($Name, $Type) = @_;
21552 my $Ext = getLIB_EXT("windows");
21553 if($Name=~/((.+?)\.$Ext)\Z/)
21554 { # netapi32.dll
21555 if($Type eq "name")
21556 { # netapi32
21557 return $2;
21558 }
21559 elsif($Type eq "name+ext")
21560 { # netapi32.dll
21561 return $1;
21562 }
21563 elsif($Type eq "version")
21564 { # DLL version embedded
21565 # at binary-level
21566 return "";
21567 }
21568 elsif($Type eq "short")
21569 { # netapi32
21570 return $2;
21571 }
21572 elsif($Type eq "shortest")
21573 { # netapi
21574 return shortest_name($2);
21575 }
21576 }
21577 return "";# error
21578}
21579
21580sub shortest_name($)
21581{
21582 my $Name = $_[0];
21583 # remove prefix
21584 $Name=~s/\A(lib|open)//;
21585 # remove suffix
21586 $Name=~s/[\W\d_]+\Z//i;
21587 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21588 return $Name;
21589}
21590
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021591sub createSymbolsList($$$$$)
21592{
21593 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021594
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021595 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021596 prepareSymbols(1);
21597
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021598 my %SymbolHeaderLib = ();
21599 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021600
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021601 # Get List
21602 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21603 {
21604 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021605 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021606 next;
21607 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021608 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021609 { # skip other symbols
21610 next;
21611 }
21612 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21613 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021614 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021615 next;
21616 }
21617 my $DyLib = $Symbol_Library{1}{$Symbol};
21618 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021619 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021620 next;
21621 }
21622 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21623 $Total+=1;
21624 }
21625 # Draw List
21626 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21627 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21628 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21629 {
21630 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21631 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021632 my %NS_Symbol = ();
21633 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021634 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021635 }
21636 foreach my $NameSpace (sort keys(%NS_Symbol))
21637 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021638 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021639 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21640 foreach my $Symbol (@SortedInterfaces)
21641 {
21642 my $SubReport = "";
21643 my $Signature = get_Signature($Symbol, 1);
21644 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021645 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021646 }
21647 if($Symbol=~/\A(_Z|\?)/)
21648 {
21649 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021650 $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 +040021651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021652 else {
21653 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21654 }
21655 }
21656 else
21657 {
21658 if($Signature) {
21659 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21660 }
21661 else {
21662 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21663 }
21664 }
21665 $SYMBOLS_LIST .= $SubReport;
21666 }
21667 }
21668 $SYMBOLS_LIST .= "<br/>\n";
21669 }
21670 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021671 # clear info
21672 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21673 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21674 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21675 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021676 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021677 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021678 my $CssStyles = readModule("Styles", "SymbolsList.css");
21679 my $JScripts = readModule("Scripts", "Sections.js");
21680 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021681 my $Title = "$LName: public symbols";
21682 my $Keywords = "$LName, API, symbols";
21683 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021684 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021685 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021686 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021687 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021688 writeFile($SaveTo, $SYMBOLS_LIST);
21689}
21690
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021691sub add_target_libs($)
21692{
21693 foreach (@{$_[0]}) {
21694 $TargetLibs{$_} = 1;
21695 }
21696}
21697
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021698sub is_target_lib($)
21699{
21700 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021701 if(not $LName) {
21702 return 0;
21703 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030021704 if($OSgroup eq "windows") {
21705 $LName = lc($LName);
21706 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021707 if($TargetLibraryName
21708 and $LName!~/\Q$TargetLibraryName\E/) {
21709 return 0;
21710 }
21711 if(keys(%TargetLibs)
21712 and not $TargetLibs{$LName}
21713 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21714 return 0;
21715 }
21716 return 1;
21717}
21718
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021719sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021720{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021721 my ($H, $V) = @_;
21722 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021723 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021724 if($TargetHeaders{$V}{$H}) {
21725 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021726 }
21727 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021728 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021729}
21730
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021731sub readLibs($)
21732{
21733 my $LibVersion = $_[0];
21734 if($OStarget eq "windows")
21735 { # dumpbin.exe will crash
21736 # without VS Environment
21737 check_win32_env();
21738 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021739 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021740 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021741 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021742}
21743
21744sub dump_sorting($)
21745{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021746 my $Hash = $_[0];
21747 return [] if(not $Hash);
21748 my @Keys = keys(%{$Hash});
21749 return [] if($#Keys<0);
21750 if($Keys[0]=~/\A\d+\Z/)
21751 { # numbers
21752 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021753 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021754 else
21755 { # strings
21756 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021757 }
21758}
21759
21760sub printMsg($$)
21761{
21762 my ($Type, $Msg) = @_;
21763 if($Type!~/\AINFO/) {
21764 $Msg = $Type.": ".$Msg;
21765 }
21766 if($Type!~/_C\Z/) {
21767 $Msg .= "\n";
21768 }
21769 if($Quiet)
21770 { # --quiet option
21771 appendFile($COMMON_LOG_PATH, $Msg);
21772 }
21773 else
21774 {
21775 if($Type eq "ERROR") {
21776 print STDERR $Msg;
21777 }
21778 else {
21779 print $Msg;
21780 }
21781 }
21782}
21783
21784sub exitStatus($$)
21785{
21786 my ($Code, $Msg) = @_;
21787 printMsg("ERROR", $Msg);
21788 exit($ERROR_CODE{$Code});
21789}
21790
21791sub exitReport()
21792{ # the tool has run without any errors
21793 printReport();
21794 if($COMPILE_ERRORS)
21795 { # errors in headers may add false positives/negatives
21796 exit($ERROR_CODE{"Compile_Error"});
21797 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021798 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21799 { # --binary
21800 exit($ERROR_CODE{"Incompatible"});
21801 }
21802 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21803 { # --source
21804 exit($ERROR_CODE{"Incompatible"});
21805 }
21806 elsif($RESULT{"Source"}{"Problems"}
21807 or $RESULT{"Binary"}{"Problems"})
21808 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021809 exit($ERROR_CODE{"Incompatible"});
21810 }
21811 else {
21812 exit($ERROR_CODE{"Compatible"});
21813 }
21814}
21815
21816sub readRules($)
21817{
21818 my $Kind = $_[0];
21819 if(not -f $RULES_PATH{$Kind}) {
21820 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21821 }
21822 my $Content = readFile($RULES_PATH{$Kind});
21823 while(my $Rule = parseTag(\$Content, "rule"))
21824 {
21825 my $RId = parseTag(\$Rule, "id");
21826 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21827 foreach my $Prop (@Properties) {
21828 if(my $Value = parseTag(\$Rule, lc($Prop)))
21829 {
21830 $Value=~s/\n[ ]*//;
21831 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21832 }
21833 }
21834 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21835 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21836 }
21837 else {
21838 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21839 }
21840 }
21841}
21842
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021843sub getReportPath($)
21844{
21845 my $Level = $_[0];
21846 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21847 if($Level eq "Binary")
21848 {
21849 if($BinaryReportPath)
21850 { # --bin-report-path
21851 return $BinaryReportPath;
21852 }
21853 elsif($OutputReportPath)
21854 { # --report-path
21855 return $OutputReportPath;
21856 }
21857 else
21858 { # default
21859 return $Dir."/abi_compat_report.$ReportFormat";
21860 }
21861 }
21862 elsif($Level eq "Source")
21863 {
21864 if($SourceReportPath)
21865 { # --src-report-path
21866 return $SourceReportPath;
21867 }
21868 elsif($OutputReportPath)
21869 { # --report-path
21870 return $OutputReportPath;
21871 }
21872 else
21873 { # default
21874 return $Dir."/src_compat_report.$ReportFormat";
21875 }
21876 }
21877 else
21878 {
21879 if($OutputReportPath)
21880 { # --report-path
21881 return $OutputReportPath;
21882 }
21883 else
21884 { # default
21885 return $Dir."/compat_report.$ReportFormat";
21886 }
21887 }
21888}
21889
21890sub printStatMsg($)
21891{
21892 my $Level = $_[0];
21893 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21894}
21895
21896sub listAffected($)
21897{
21898 my $Level = $_[0];
21899 my $List = "";
21900 foreach (keys(%{$TotalAffected{$Level}}))
21901 {
21902 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21903 { # skip "Low"-severity problems
21904 next;
21905 }
21906 $List .= "$_\n";
21907 }
21908 my $Dir = get_dirname(getReportPath($Level));
21909 if($Level eq "Binary") {
21910 writeFile($Dir."/abi_affected.txt", $List);
21911 }
21912 elsif($Level eq "Source") {
21913 writeFile($Dir."/src_affected.txt", $List);
21914 }
21915}
21916
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021917sub printReport()
21918{
21919 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021920 createReport();
21921 if($JoinReport or $DoubleReport)
21922 {
21923 if($RESULT{"Binary"}{"Problems"}
21924 or $RESULT{"Source"}{"Problems"}) {
21925 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021926 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021927 else {
21928 printMsg("INFO", "result: COMPATIBLE");
21929 }
21930 printStatMsg("Binary");
21931 printStatMsg("Source");
21932 if($ListAffected)
21933 { # --list-affected
21934 listAffected("Binary");
21935 listAffected("Source");
21936 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021937 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021938 elsif($BinaryOnly)
21939 {
21940 if($RESULT{"Binary"}{"Problems"}) {
21941 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21942 }
21943 else {
21944 printMsg("INFO", "result: COMPATIBLE");
21945 }
21946 printStatMsg("Binary");
21947 if($ListAffected)
21948 { # --list-affected
21949 listAffected("Binary");
21950 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021951 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021952 elsif($SourceOnly)
21953 {
21954 if($RESULT{"Source"}{"Problems"}) {
21955 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21956 }
21957 else {
21958 printMsg("INFO", "result: COMPATIBLE");
21959 }
21960 printStatMsg("Source");
21961 if($ListAffected)
21962 { # --list-affected
21963 listAffected("Source");
21964 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021965 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021966 if($StdOut)
21967 {
21968 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021969 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021970 printMsg("INFO", "compatibility report has been generated to stdout");
21971 }
21972 else
21973 { # default
21974 printMsg("INFO", "compatibility reports have been generated to stdout");
21975 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021976 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021977 else
21978 {
21979 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021980 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021981 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21982 }
21983 elsif($DoubleReport)
21984 { # default
21985 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21986 }
21987 elsif($BinaryOnly)
21988 { # --binary
21989 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21990 }
21991 elsif($SourceOnly)
21992 { # --source
21993 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21994 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021995 }
21996}
21997
21998sub check_win32_env()
21999{
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022000 if(not $ENV{"VCINSTALLDIR"}
22001 or not $ENV{"INCLUDE"}) {
22002 exitStatus("Error", "can't start without VC environment (vcvars64.bat)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022003 }
22004}
22005
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022006sub diffSets($$)
22007{
22008 my ($S1, $S2) = @_;
22009 my @SK1 = keys(%{$S1});
22010 my @SK2 = keys(%{$S2});
22011 if($#SK1!=$#SK2) {
22012 return 1;
22013 }
22014 foreach my $K1 (@SK1)
22015 {
22016 if(not defined $S2->{$K1}) {
22017 return 1;
22018 }
22019 }
22020 return 0;
22021}
22022
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022023sub defaultDumpPath($$)
22024{
22025 my ($N, $V) = @_;
22026 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
22027}
22028
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022029sub create_ABI_Dump()
22030{
22031 if(not -e $DumpAPI) {
22032 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
22033 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022034
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022035 if(isDump($DumpAPI)) {
22036 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022037 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022038 else {
22039 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022040 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022041
22042 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022043 { # set to default: N
22044 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022045 }
22046
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022047 initLogging(1);
22048 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022049
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022050 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022051 if($OutputDumpPath)
22052 { # user defined path
22053 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022054 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022055 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
22056
22057 if(not $Archive and not $StdOut)
22058 { # check archive utilities
22059 if($OSgroup eq "windows")
22060 { # using zip
22061 my $ZipCmd = get_CmdPath("zip");
22062 if(not $ZipCmd) {
22063 exitStatus("Not_Found", "can't find \"zip\"");
22064 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022065 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022066 else
22067 { # using tar and gzip
22068 my $TarCmd = get_CmdPath("tar");
22069 if(not $TarCmd) {
22070 exitStatus("Not_Found", "can't find \"tar\"");
22071 }
22072 my $GzipCmd = get_CmdPath("gzip");
22073 if(not $GzipCmd) {
22074 exitStatus("Not_Found", "can't find \"gzip\"");
22075 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022076 }
22077 }
22078
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022079 if(not $Descriptor{1}{"Dump"})
22080 {
22081 if(not $CheckHeadersOnly) {
22082 readLibs(1);
22083 }
22084 if($CheckHeadersOnly) {
22085 setLanguage(1, "C++");
22086 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022087 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022088 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022089 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022090 if(not $Descriptor{1}{"Dump"})
22091 {
22092 if($Descriptor{1}{"Headers"}) {
22093 readHeaders(1);
22094 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022095 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022096 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022097 if(not keys(%{$SymbolInfo{1}}))
22098 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022099 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022100 {
22101 if($CheckHeadersOnly) {
22102 exitStatus("Empty_Set", "the set of public symbols is empty");
22103 }
22104 else {
22105 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
22106 }
22107 }
22108 }
22109 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022110 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022111 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
22112 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022113 if($ExtraDump)
22114 { # add unmangled names to the ABI dump
22115 my @Names = ();
22116 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
22117 {
22118 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
22119 push(@Names, $MnglName);
22120 }
22121 }
22122 translateSymbols(@Names, 1);
22123 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
22124 {
22125 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
22126 {
22127 if(my $Unmangled = $tr_name{$MnglName})
22128 {
22129 if($MnglName ne $Unmangled) {
22130 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
22131 }
22132 }
22133 }
22134 }
22135 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022136
22137 my %GccConstants = (); # built-in GCC constants
22138 foreach my $Name (keys(%{$Constants{1}}))
22139 {
22140 if(not defined $Constants{1}{$Name}{"Header"})
22141 {
22142 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
22143 delete($Constants{1}{$Name});
22144 }
22145 }
22146
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022147 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022148 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022149 "TypeInfo" => $TypeInfo{1},
22150 "SymbolInfo" => $SymbolInfo{1},
22151 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022152 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022153 "SymbolVersion" => $SymVer{1},
22154 "LibraryVersion" => $Descriptor{1}{"Version"},
22155 "LibraryName" => $TargetLibraryName,
22156 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022157 "SkipTypes" => $SkipTypes{1},
22158 "SkipSymbols" => $SkipSymbols{1},
22159 "SkipNameSpaces" => $SkipNameSpaces{1},
22160 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022161 "Headers" => \%HeadersInfo,
22162 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022163 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022164 "NameSpaces" => $NestedNameSpaces{1},
22165 "Target" => $OStarget,
22166 "Arch" => getArch(1),
22167 "WordSize" => $WORD_SIZE{1},
22168 "GccVersion" => get_dumpversion($GCC_PATH),
22169 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
22170 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
22171 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022172 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022173 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022174 }
22175 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022176 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022177 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022178 if($ExtendedCheck)
22179 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022180 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022181 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022182 if($BinaryOnly)
22183 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022184 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022185 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022186 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022187 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022188 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022189 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
22190 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022191 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022192
22193 my $ABI_DUMP = "";
22194 if($UseXML)
22195 {
22196 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022197 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022198 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022199 else
22200 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022201 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022202 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022203 if($StdOut)
22204 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022205 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022206 printMsg("INFO", "ABI dump has been generated to stdout");
22207 return;
22208 }
22209 else
22210 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022211 my ($DDir, $DName) = separate_path($DumpPath);
22212 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022213 if(not $Archive) {
22214 $DPath = $DumpPath;
22215 }
22216
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022217 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022218
22219 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022220 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022221 close(DUMP);
22222
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022223 if(not -s $DPath) {
22224 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
22225 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022226 if($Archive) {
22227 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022228 }
22229
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022230 if($OutputDumpPath) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022231 printMsg("INFO", "dump path: $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022232 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022233 else {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022234 printMsg("INFO", "dump path: $DumpPath");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022235 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022236 # 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 +040022237 }
22238}
22239
22240sub quickEmptyReports()
22241{ # Quick "empty" reports
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022242 # ~4 times faster than merging equal dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022243 # NOTE: the dump contains the "LibraryVersion" attribute
22244 # if you change the version, then your dump will be different
22245 # OVERCOME: use -v1 and v2 options for comparing dumps
22246 # and don't change version in the XML descriptor (and dumps)
22247 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022248 if($Descriptor{1}{"Path"} eq $Descriptor{2}{"Path"}
22249 or -s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022250 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022251 my $FilePath1 = $Descriptor{1}{"Path"};
22252 my $FilePath2 = $Descriptor{2}{"Path"};
22253
22254 if(not isDump_U($FilePath1)) {
22255 $FilePath1 = unpackDump($FilePath1);
22256 }
22257
22258 if(not isDump_U($FilePath2)) {
22259 $FilePath2 = unpackDump($FilePath2);
22260 }
22261
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022262 if($FilePath1 and $FilePath2)
22263 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022264 my $Line = readLineNum($FilePath1, 0);
22265 if($Line=~/xml/)
22266 { # XML format
22267 # is not supported yet
22268 return;
22269 }
22270
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022271 local $/ = undef;
22272
22273 open(DUMP1, $FilePath1);
22274 my $Content1 = <DUMP1>;
22275 close(DUMP1);
22276
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022277 my $Eq = 0;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022278
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022279 if($FilePath1 eq $FilePath2) {
22280 $Eq = 1;
22281 }
22282
22283 if(not $Eq)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022284 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022285 open(DUMP2, $FilePath2);
22286 my $Content2 = <DUMP2>;
22287 close(DUMP2);
22288
22289 if($Content1 eq $Content2) {
22290 $Eq = 1;
22291 }
22292
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022293 # clean memory
22294 undef $Content2;
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022295 }
22296
22297 if($Eq)
22298 {
22299 printMsg("INFO", "Input ABI dumps are equal, so generating quick empty report");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022300 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022301 my $ABIdump = eval($Content1);
22302
22303 # clean memory
22304 undef $Content1;
22305
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022306 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022307 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 +040022308 }
22309 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022310 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022311 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
22312 }
22313 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022314 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022315 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
22316 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022317 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022318
22319 foreach (keys(%{$Registered_Headers{1}})) {
22320 $TargetHeaders{1}{$_} = 1;
22321 }
22322
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022323 read_Libs_DumpInfo($ABIdump, 1);
22324 read_Machine_DumpInfo($ABIdump, 1);
22325 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022326
22327 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
22328 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
22329
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022330 foreach my $S (keys(%{$ABIdump->{"SymbolInfo"}}))
22331 {
22332 if(my $Class = $ABIdump->{"SymbolInfo"}{$S}{"Class"})
22333 {
22334 if(defined $ABIdump->{"TypeInfo"}{$Class}{"PrivateABI"}) {
22335 next;
22336 }
22337 }
22338
22339 my $Access = $ABIdump->{"SymbolInfo"}{$S}{"Access"};
22340 if($Access ne "private")
22341 {
22342 $CheckedSymbols{"Binary"}{$S} = 1;
22343 $CheckedSymbols{"Source"}{$S} = 1;
22344 }
22345 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022346
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022347 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
22348 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022349
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030022350 if(not defined $Descriptor{1}{"Version"}) {
22351 $Descriptor{1}{"Version"} = "X";
22352 }
22353
22354 if(not defined $Descriptor{2}{"Version"}) {
22355 $Descriptor{2}{"Version"} = "Y";
22356 }
22357
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022358 if(defined $ABIdump->{"ABI_DUMPER_VERSION"})
22359 {
22360 $UsedDump{1}{"DWARF"} = 1;
22361 $UsedDump{2}{"DWARF"} = 1;
22362
22363 $UsedDump{1}{"M"} = $ABIdump->{"LibraryName"};
22364 $UsedDump{2}{"M"} = $ABIdump->{"LibraryName"};
22365 }
22366
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022367 exitReport();
22368 }
22369 }
22370 }
22371}
22372
22373sub initLogging($)
22374{
22375 my $LibVersion = $_[0];
22376 # create log directory
22377 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
22378 if($OutputLogPath{$LibVersion})
22379 { # user-defined by -log-path option
22380 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
22381 }
22382 if($LogMode ne "n") {
22383 mkpath($LOG_DIR);
22384 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022385 $LOG_PATH{$LibVersion} = join_P(get_abs_path($LOG_DIR), $LOG_FILE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022386 if($Debug)
22387 { # debug directory
22388 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022389
22390 if(not $ExtraInfo)
22391 { # enable --extra-info
22392 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
22393 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022394 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022395 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022396}
22397
22398sub writeLog($$)
22399{
22400 my ($LibVersion, $Msg) = @_;
22401 if($LogMode ne "n") {
22402 appendFile($LOG_PATH{$LibVersion}, $Msg);
22403 }
22404}
22405
22406sub resetLogging($)
22407{
22408 my $LibVersion = $_[0];
22409 if($LogMode!~/a|n/)
22410 { # remove old log
22411 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022412 if($Debug) {
22413 rmtree($DEBUG_PATH{$LibVersion});
22414 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022415 }
22416}
22417
22418sub printErrorLog($)
22419{
22420 my $LibVersion = $_[0];
22421 if($LogMode ne "n") {
22422 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
22423 }
22424}
22425
22426sub isDump($)
22427{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022428 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
22429 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022430 return $1;
22431 }
22432 return 0;
22433}
22434
22435sub isDump_U($)
22436{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022437 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022438 return $1;
22439 }
22440 return 0;
22441}
22442
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022443sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022444{
22445 # read input XML descriptors or ABI dumps
22446 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022447 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022448 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022449 if(not -e $Descriptor{1}{"Path"}) {
22450 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022451 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022452
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022453 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022454 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022455 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022456 if(not -e $Descriptor{2}{"Path"}) {
22457 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022458 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022459
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022460 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022461
22462 if(not defined $DisableQuickEmptyReport)
22463 {
22464 if(isDump($Descriptor{1}{"Path"})
22465 and isDump($Descriptor{2}{"Path"}))
22466 { # optimization: equal ABI dumps
22467 quickEmptyReports();
22468 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022469 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022470
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022471 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022472
22473 if(isDump($Descriptor{1}{"Path"})) {
22474 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022475 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022476 else {
22477 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
22478 }
22479
22480 if(isDump($Descriptor{2}{"Path"})) {
22481 read_ABI_Dump(2, $Descriptor{2}{"Path"});
22482 }
22483 else {
22484 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022485 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022486
22487 if(not $Descriptor{1}{"Version"})
22488 { # set to default: X
22489 $Descriptor{1}{"Version"} = "X";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022490 print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022491 }
22492
22493 if(not $Descriptor{2}{"Version"})
22494 { # set to default: Y
22495 $Descriptor{2}{"Version"} = "Y";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022496 print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022497 }
22498
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030022499 if(not $UsedDump{1}{"V"}) {
22500 initLogging(1);
22501 }
22502
22503 if(not $UsedDump{2}{"V"}) {
22504 initLogging(2);
22505 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022506
22507 # check input data
22508 if(not $Descriptor{1}{"Headers"}) {
22509 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022510 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022511 if(not $Descriptor{2}{"Headers"}) {
22512 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022513 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022514
22515 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022516 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022517 if(not $Descriptor{1}{"Libs"}) {
22518 exitStatus("Error", "can't find libraries info in descriptor d1");
22519 }
22520 if(not $Descriptor{2}{"Libs"}) {
22521 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022522 }
22523 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022524
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022525 if($UseDumps)
22526 { # --use-dumps
22527 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022528 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
22529 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022530
22531 unlink($DumpPath1);
22532 unlink($DumpPath2);
22533
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022534 my $pid = fork();
22535 if($pid)
22536 { # dump on two CPU cores
22537 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22538 if($RelativeDirectory{1}) {
22539 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22540 }
22541 if($OutputLogPath{1}) {
22542 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22543 }
22544 if($CrossGcc) {
22545 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22546 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022547 if($Quiet)
22548 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022549 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022550 @PARAMS = (@PARAMS, "-logging-mode", "a");
22551 }
22552 elsif($LogMode and $LogMode ne "w")
22553 { # "w" is default
22554 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022555 }
22556 if($ExtendedCheck) {
22557 @PARAMS = (@PARAMS, "-extended");
22558 }
22559 if($UserLang) {
22560 @PARAMS = (@PARAMS, "-lang", $UserLang);
22561 }
22562 if($TargetVersion{1}) {
22563 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22564 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022565 if($BinaryOnly) {
22566 @PARAMS = (@PARAMS, "-binary");
22567 }
22568 if($SourceOnly) {
22569 @PARAMS = (@PARAMS, "-source");
22570 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022571 if($SortDump) {
22572 @PARAMS = (@PARAMS, "-sort");
22573 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022574 if($DumpFormat and $DumpFormat ne "perl") {
22575 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22576 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022577 if($CheckHeadersOnly) {
22578 @PARAMS = (@PARAMS, "-headers-only");
22579 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022580 if($Debug)
22581 {
22582 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022583 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022584 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022585 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022586 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022587 exit(1);
22588 }
22589 }
22590 else
22591 { # child
22592 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22593 if($RelativeDirectory{2}) {
22594 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22595 }
22596 if($OutputLogPath{2}) {
22597 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22598 }
22599 if($CrossGcc) {
22600 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22601 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022602 if($Quiet)
22603 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022604 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022605 @PARAMS = (@PARAMS, "-logging-mode", "a");
22606 }
22607 elsif($LogMode and $LogMode ne "w")
22608 { # "w" is default
22609 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022610 }
22611 if($ExtendedCheck) {
22612 @PARAMS = (@PARAMS, "-extended");
22613 }
22614 if($UserLang) {
22615 @PARAMS = (@PARAMS, "-lang", $UserLang);
22616 }
22617 if($TargetVersion{2}) {
22618 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22619 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022620 if($BinaryOnly) {
22621 @PARAMS = (@PARAMS, "-binary");
22622 }
22623 if($SourceOnly) {
22624 @PARAMS = (@PARAMS, "-source");
22625 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022626 if($SortDump) {
22627 @PARAMS = (@PARAMS, "-sort");
22628 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022629 if($DumpFormat and $DumpFormat ne "perl") {
22630 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22631 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022632 if($CheckHeadersOnly) {
22633 @PARAMS = (@PARAMS, "-headers-only");
22634 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022635 if($Debug)
22636 {
22637 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022638 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022639 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022640 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022641 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022642 exit(1);
22643 }
22644 else {
22645 exit(0);
22646 }
22647 }
22648 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022649
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022650 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022651 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22652 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022653 if($TargetTitle ne $TargetLibraryName) {
22654 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022655 }
22656 if($ShowRetVal) {
22657 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22658 }
22659 if($CrossGcc) {
22660 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22661 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022662 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22663 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022664 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022665 }
22666 if($ReportFormat and $ReportFormat ne "html")
22667 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022668 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22669 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022670 if($OutputReportPath) {
22671 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22672 }
22673 if($BinaryReportPath) {
22674 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22675 }
22676 if($SourceReportPath) {
22677 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22678 }
22679 if($LoggingPath) {
22680 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22681 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022682 if($CheckHeadersOnly) {
22683 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22684 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022685 if($BinaryOnly) {
22686 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22687 }
22688 if($SourceOnly) {
22689 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22690 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022691 if($Debug)
22692 {
22693 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22694 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022695 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022696 system("perl", $0, @CMP_PARAMS);
22697 exit($?>>8);
22698 }
22699 if(not $Descriptor{1}{"Dump"}
22700 or not $Descriptor{2}{"Dump"})
22701 { # need GCC toolchain to analyze
22702 # header files and libraries
22703 detect_default_paths("inc|lib|gcc");
22704 }
22705 if(not $Descriptor{1}{"Dump"})
22706 {
22707 if(not $CheckHeadersOnly) {
22708 readLibs(1);
22709 }
22710 if($CheckHeadersOnly) {
22711 setLanguage(1, "C++");
22712 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022713 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022714 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022715 }
22716 if(not $Descriptor{2}{"Dump"})
22717 {
22718 if(not $CheckHeadersOnly) {
22719 readLibs(2);
22720 }
22721 if($CheckHeadersOnly) {
22722 setLanguage(2, "C++");
22723 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022724 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022725 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022726 }
22727 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22728 { # support for old ABI dumps
22729 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022730 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022731 {
22732 $WORD_SIZE{1} = $WORD_SIZE{2};
22733 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22734 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022735 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022736 {
22737 $WORD_SIZE{2} = $WORD_SIZE{1};
22738 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22739 }
22740 }
22741 elsif(not $WORD_SIZE{1}
22742 and not $WORD_SIZE{2})
22743 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022744 $WORD_SIZE{1} = "4";
22745 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022746 }
22747 if($Descriptor{1}{"Dump"})
22748 { # support for old ABI dumps
22749 prepareTypes(1);
22750 }
22751 if($Descriptor{2}{"Dump"})
22752 { # support for old ABI dumps
22753 prepareTypes(2);
22754 }
22755 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22756 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22757 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022758 # process input data
22759 if($Descriptor{1}{"Headers"}
22760 and not $Descriptor{1}{"Dump"}) {
22761 readHeaders(1);
22762 }
22763 if($Descriptor{2}{"Headers"}
22764 and not $Descriptor{2}{"Dump"}) {
22765 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022766 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022767
22768 # clean memory
22769 %SystemHeaders = ();
22770 %mangled_name_gcc = ();
22771
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022772 prepareSymbols(1);
22773 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022774
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022775 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022776 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022777
22778 # Virtual Tables
22779 registerVTable(1);
22780 registerVTable(2);
22781
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022782 if(not checkDump(1, "1.22")
22783 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022784 { # support for old ABI dumps
22785 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22786 {
22787 if($ClassName=~/</)
22788 { # templates
22789 if(not defined $VirtualTable{1}{$ClassName})
22790 { # synchronize
22791 delete($VirtualTable{2}{$ClassName});
22792 }
22793 }
22794 }
22795 }
22796
22797 registerOverriding(1);
22798 registerOverriding(2);
22799
22800 setVirtFuncPositions(1);
22801 setVirtFuncPositions(2);
22802
22803 # Other
22804 addParamNames(1);
22805 addParamNames(2);
22806
22807 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022808}
22809
22810sub compareAPIs($)
22811{
22812 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022813
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022814 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022815 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022816
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022817 if($Level eq "Binary") {
22818 printMsg("INFO", "comparing ABIs ...");
22819 }
22820 else {
22821 printMsg("INFO", "comparing APIs ...");
22822 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022823
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022824 if($CheckHeadersOnly
22825 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022826 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022827 detectAdded_H($Level);
22828 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022829 }
22830 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022831 { # added/removed in libs
22832 detectAdded($Level);
22833 detectRemoved($Level);
22834 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022835
22836 mergeSymbols($Level);
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030022837
22838 if(not defined $DisableConstantsCheck)
22839 {
22840 if(keys(%{$CheckedSymbols{$Level}})) {
22841 mergeConstants($Level);
22842 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022843 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022844
22845 $Cache{"mergeTypes"} = (); # free memory
22846
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022847 if($CheckHeadersOnly
22848 or $Level eq "Source")
22849 { # added/removed in headers
22850 mergeHeaders($Level);
22851 }
22852 else
22853 { # added/removed in libs
22854 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022855 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022856
22857 foreach my $S (keys(%{$CompatProblems{$Level}}))
22858 {
22859 foreach my $K (keys(%{$CompatProblems{$Level}{$S}}))
22860 {
22861 foreach my $L (keys(%{$CompatProblems{$Level}{$S}{$K}}))
22862 {
22863 if(my $T = $CompatProblems{$Level}{$S}{$K}{$L}{"Type_Name"}) {
22864 $TypeProblemsIndex{$Level}{$T}{$S} = 1;
22865 }
22866 }
22867 }
22868 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022869}
22870
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022871sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022872{
22873 my %Opts = (
22874 "OStarget"=>$OStarget,
22875 "Debug"=>$Debug,
22876 "Quiet"=>$Quiet,
22877 "LogMode"=>$LogMode,
22878 "CheckHeadersOnly"=>$CheckHeadersOnly,
22879
22880 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022881 "GCC_PATH"=>$GCC_PATH,
22882 "TargetSysInfo"=>$TargetSysInfo,
22883 "CrossPrefix"=>$CrossPrefix,
22884 "TargetLibraryName"=>$TargetLibraryName,
22885 "CrossGcc"=>$CrossGcc,
22886 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022887 "NoStdInc"=>$NoStdInc,
Andrey Ponomarenko991da682016-09-07 19:09:50 +030022888 "CxxIncompat"=>$CxxIncompat,
22889 "SkipUnidentified"=>$SkipUnidentified,
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030022890 "DisableConstantsCheck"=>$DisableConstantsCheck,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022891
22892 "BinaryOnly" => $BinaryOnly,
22893 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022894 );
22895 return \%Opts;
22896}
22897
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022898sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022899{
22900 my %CODE_ERROR = reverse(%ERROR_CODE);
22901 return $CODE_ERROR{$_[0]};
22902}
22903
22904sub scenario()
22905{
22906 if($StdOut)
22907 { # enable quiet mode
22908 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022909 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022910 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022911 if(not $LogMode)
22912 { # default
22913 $LogMode = "w";
22914 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022915 if($UserLang)
22916 { # --lang=C++
22917 $UserLang = uc($UserLang);
22918 $COMMON_LANGUAGE{1}=$UserLang;
22919 $COMMON_LANGUAGE{2}=$UserLang;
22920 }
22921 if($LoggingPath)
22922 {
22923 $OutputLogPath{1} = $LoggingPath;
22924 $OutputLogPath{2} = $LoggingPath;
22925 if($Quiet) {
22926 $COMMON_LOG_PATH = $LoggingPath;
22927 }
22928 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022929
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022930 if($Quick) {
22931 $ADD_TMPL_INSTANCES = 0;
22932 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022933 if($OutputDumpPath)
22934 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022935 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022936 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22937 }
22938 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022939 if($BinaryOnly and $SourceOnly)
22940 { # both --binary and --source
22941 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022942 if(not $CmpSystems)
22943 {
22944 $BinaryOnly = 0;
22945 $SourceOnly = 0;
22946 }
22947
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022948 $DoubleReport = 1;
22949 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022950
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022951 if($OutputReportPath)
22952 { # --report-path
22953 $DoubleReport = 0;
22954 $JoinReport = 1;
22955 }
22956 }
22957 elsif($BinaryOnly or $SourceOnly)
22958 { # --binary or --source
22959 $DoubleReport = 0;
22960 $JoinReport = 0;
22961 }
22962 if($UseXML)
22963 { # --xml option
22964 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022965 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022966 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022967 if($ReportFormat)
22968 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022969 $ReportFormat = lc($ReportFormat);
22970 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022971 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022972 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022973 if($ReportFormat eq "htm")
22974 { # HTM == HTML
22975 $ReportFormat = "html";
22976 }
22977 elsif($ReportFormat eq "xml")
22978 { # --report-format=XML equal to --xml
22979 $UseXML = 1;
22980 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022981 }
22982 else
22983 { # default: HTML
22984 $ReportFormat = "html";
22985 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022986 if($DumpFormat)
22987 { # validate
22988 $DumpFormat = lc($DumpFormat);
22989 if($DumpFormat!~/\A(xml|perl)\Z/) {
22990 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22991 }
22992 if($DumpFormat eq "xml")
22993 { # --dump-format=XML equal to --xml
22994 $UseXML = 1;
22995 }
22996 }
22997 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022998 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022999 $DumpFormat = "perl";
23000 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023001 if($Quiet and $LogMode!~/a|n/)
23002 { # --quiet log
23003 if(-f $COMMON_LOG_PATH) {
23004 unlink($COMMON_LOG_PATH);
23005 }
23006 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040023007 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023008 $CheckUndefined = 1;
23009 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023010 if($TestTool and $UseDumps)
23011 { # --test && --use-dumps == --test-dump
23012 $TestDump = 1;
23013 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040023014 if($Tolerant)
23015 { # enable all
23016 $Tolerance = 1234;
23017 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023018 if($Help)
23019 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023020 HELP_MESSAGE();
23021 exit(0);
23022 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030023023 if($InfoMsg)
23024 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023025 INFO_MESSAGE();
23026 exit(0);
23027 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023028 if($ShowVersion)
23029 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030023030 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 +040023031 exit(0);
23032 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023033 if($DumpVersion)
23034 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023035 printMsg("INFO", $TOOL_VERSION);
23036 exit(0);
23037 }
23038 if($ExtendedCheck) {
23039 $CheckHeadersOnly = 1;
23040 }
23041 if($SystemRoot_Opt)
23042 { # user defined root
23043 if(not -e $SystemRoot_Opt) {
23044 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
23045 }
23046 $SystemRoot = $SystemRoot_Opt;
23047 $SystemRoot=~s/[\/]+\Z//g;
23048 if($SystemRoot) {
23049 $SystemRoot = get_abs_path($SystemRoot);
23050 }
23051 }
23052 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040023053
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023054 if($SortDump)
23055 {
23056 $Data::Dumper::Useperl = 1;
23057 $Data::Dumper::Sortkeys = \&dump_sorting;
23058 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040023059
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023060 if($TargetLibsPath)
23061 {
23062 if(not -f $TargetLibsPath) {
23063 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
23064 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030023065 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath)))
23066 {
23067 if($OSgroup eq "windows") {
23068 $TargetLibs{lc($Lib)} = 1;
23069 }
23070 else {
23071 $TargetLibs{$Lib} = 1;
23072 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023073 }
23074 }
23075 if($TargetHeadersPath)
23076 { # --headers-list
23077 if(not -f $TargetHeadersPath) {
23078 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
23079 }
23080 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
23081 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030023082 $TargetHeaders{1}{get_filename($Header)} = 1;
23083 $TargetHeaders{2}{get_filename($Header)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023084 }
23085 }
23086 if($TargetHeader)
23087 { # --header
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030023088 $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
23089 $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023090 }
23091 if($TestTool
23092 or $TestDump)
23093 { # --test, --test-dump
23094 detect_default_paths("bin|gcc"); # to compile libs
23095 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040023096 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030023097 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly, $OldStyle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023098 exit(0);
23099 }
23100 if($DumpSystem)
23101 { # --dump-system
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030023102 if(-d $MODULES_DIR."/Targets/"
23103 and -d $MODULES_DIR."/Targets/".$OStarget) {
23104 $TargetSysInfo = $MODULES_DIR."/Targets/".$OStarget;
23105 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030023106 if(not $TargetSysInfo) {
23107 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
23108 }
23109
23110 if(not -d $TargetSysInfo) {
23111 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
23112 }
23113
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023114 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023115 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023116 { # system XML descriptor
23117 if(not -f $DumpSystem) {
23118 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
23119 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030023120
23121 my $SDesc = readFile($DumpSystem);
23122 if(my $RelDir = $RelativeDirectory{1}) {
23123 $SDesc =~ s/{RELPATH}/$RelDir/g;
23124 }
23125
23126 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023127 foreach (@{$Ret->{"Tools"}})
23128 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023129 push_U($SystemPaths{"bin"}, $_);
23130 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023131 }
23132 if($Ret->{"CrossPrefix"}) {
23133 $CrossPrefix = $Ret->{"CrossPrefix"};
23134 }
23135 }
23136 elsif($SystemRoot_Opt)
23137 { # -sysroot "/" option
23138 # default target: /usr/lib, /usr/include
23139 # search libs: /usr/lib and /lib
23140 if(not -e $SystemRoot."/usr/lib") {
23141 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
23142 }
23143 if(not -e $SystemRoot."/lib") {
23144 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
23145 }
23146 if(not -e $SystemRoot."/usr/include") {
23147 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
23148 }
23149 readSystemDescriptor("
23150 <name>
23151 $DumpSystem
23152 </name>
23153 <headers>
23154 $SystemRoot/usr/include
23155 </headers>
23156 <libs>
23157 $SystemRoot/usr/lib
23158 </libs>
23159 <search_libs>
23160 $SystemRoot/lib
23161 </search_libs>");
23162 }
23163 else {
23164 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
23165 }
23166 detect_default_paths("bin|gcc"); # to check symbols
23167 if($OStarget eq "windows")
23168 { # to run dumpbin.exe
23169 # and undname.exe
23170 check_win32_env();
23171 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023172 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023173 exit(0);
23174 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023175
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023176 if($CmpSystems)
23177 { # --cmp-systems
23178 detect_default_paths("bin"); # to extract dumps
23179 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023180 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023181 exit(0);
23182 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023183
23184 if(not $CountSymbols)
23185 {
23186 if(not $TargetLibraryName) {
23187 exitStatus("Error", "library name is not selected (-l option)");
23188 }
23189 else
23190 { # validate library name
23191 if($TargetLibraryName=~/[\*\/\\]/) {
23192 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
23193 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023194 }
23195 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023196
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030023197 if(not $TargetTitle) {
23198 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023199 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030023200
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023201 if($SymbolsListPath)
23202 {
23203 if(not -f $SymbolsListPath) {
23204 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
23205 }
23206 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
23207 $SymbolsList{$Interface} = 1;
23208 }
23209 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030023210 if($TypesListPath)
23211 {
23212 if(not -f $TypesListPath) {
23213 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
23214 }
23215 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
23216 $TypesList{$Type} = 1;
23217 }
23218 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023219 if($SkipSymbolsListPath)
23220 {
23221 if(not -f $SkipSymbolsListPath) {
23222 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
23223 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030023224 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
23225 {
23226 $SkipSymbols{1}{$Interface} = 1;
23227 $SkipSymbols{2}{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023228 }
23229 }
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030023230 if($SkipTypesListPath)
23231 {
23232 if(not -f $SkipTypesListPath) {
23233 exitStatus("Access_Error", "can't access file \'$SkipTypesListPath\'");
23234 }
23235 foreach my $Type (split(/\s*\n\s*/, readFile($SkipTypesListPath)))
23236 {
23237 $SkipTypes{1}{$Type} = 1;
23238 $SkipTypes{2}{$Type} = 1;
23239 }
23240 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023241 if($SkipHeadersPath)
23242 {
23243 if(not -f $SkipHeadersPath) {
23244 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
23245 }
23246 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023247 { # register for both versions
23248 $SkipHeadersList{1}{$Path} = 1;
23249 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030023250
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023251 my ($CPath, $Type) = classifyPath($Path);
23252 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023253 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023254 }
23255 }
23256 if($ParamNamesPath)
23257 {
23258 if(not -f $ParamNamesPath) {
23259 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
23260 }
23261 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
23262 {
23263 if($Line=~s/\A(\w+)\;//)
23264 {
23265 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023266 if($Line=~/;(\d+);/)
23267 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023268 while($Line=~s/(\d+);(\w+)//) {
23269 $AddIntParams{$Interface}{$1}=$2;
23270 }
23271 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023272 else
23273 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023274 my $Num = 0;
23275 foreach my $Name (split(/;/, $Line)) {
23276 $AddIntParams{$Interface}{$Num++}=$Name;
23277 }
23278 }
23279 }
23280 }
23281 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023282
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023283 if($AppPath)
23284 {
23285 if(not -f $AppPath) {
23286 exitStatus("Access_Error", "can't access file \'$AppPath\'");
23287 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030023288
23289 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040023290 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023291 $SymbolsList_App{$Interface} = 1;
23292 }
23293 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023294
23295 if($CountSymbols)
23296 {
23297 if(not -e $CountSymbols) {
23298 exitStatus("Access_Error", "can't access \'$CountSymbols\'");
23299 }
23300
23301 read_ABI_Dump(1, $CountSymbols);
23302
23303 foreach my $Id (keys(%{$SymbolInfo{1}}))
23304 {
23305 my $MnglName = $SymbolInfo{1}{$Id}{"MnglName"};
23306 if(not $MnglName) {
23307 $MnglName = $SymbolInfo{1}{$Id}{"ShortName"}
23308 }
23309
23310 if(my $SV = $SymVer{1}{$MnglName}) {
23311 $CompleteSignature{1}{$SV} = $SymbolInfo{1}{$Id};
23312 }
23313 else {
23314 $CompleteSignature{1}{$MnglName} = $SymbolInfo{1}{$Id};
23315 }
23316
23317 if(my $Alias = $CompleteSignature{1}{$MnglName}{"Alias"}) {
23318 $CompleteSignature{1}{$Alias} = $SymbolInfo{1}{$Id};
23319 }
23320 }
23321
23322 my $Count = 0;
23323 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
23324 {
23325 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
23326 next;
23327 }
23328 if($CompleteSignature{1}{$Symbol}{"Private"}) {
23329 next;
23330 }
23331 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
23332 next;
23333 }
23334
23335 $Count += symbolFilter($Symbol, 1, "Affected + InlineVirt", "Binary");
23336 }
23337
23338 printMsg("INFO", $Count);
23339 exit(0);
23340 }
23341
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023342 if($DumpAPI)
23343 { # --dump-abi
23344 # make an API dump
23345 create_ABI_Dump();
23346 exit($COMPILE_ERRORS);
23347 }
23348 # default: compare APIs
23349 # -d1 <path>
23350 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023351 compareInit();
23352 if($JoinReport or $DoubleReport)
23353 {
23354 compareAPIs("Binary");
23355 compareAPIs("Source");
23356 }
23357 elsif($BinaryOnly) {
23358 compareAPIs("Binary");
23359 }
23360 elsif($SourceOnly) {
23361 compareAPIs("Source");
23362 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023363 exitReport();
23364}
23365
23366scenario();