blob: b21aedef8071c2ac7734ca57619bc26440c799cd [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko9c87bdb2016-10-20 18:15:38 +03003# ABI Compliance Checker (ABICC) 1.99.26
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004# A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005#
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006# Copyright (C) 2009-2011 Institute for System Programming, RAS
7# Copyright (C) 2011-2012 Nokia Corporation and/or its subsidiary(-ies)
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +03008# Copyright (C) 2011-2012 ROSA Laboratory
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +03009# Copyright (C) 2012-2016 Andrey Ponomarenko's ABI Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010#
11# Written by Andrey Ponomarenko
12#
13# PLATFORMS
14# =========
15# Linux, FreeBSD, Mac OS X, Haiku, MS Windows, Symbian
16#
17# REQUIREMENTS
18# ============
19# Linux
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +040020# - G++ (3.0-4.7, 4.8.3, 4.9 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021# - GNU Binutils (readelf, c++filt, objdump)
Andrey Ponomarenkodd172162016-10-04 19:41:25 +030022# - Perl 5
23# - Ctags
24# - ABI Dumper >= 0.99.15
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040025#
26# Mac OS X
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040027# - Xcode (g++, c++filt, otool, nm)
Andrey Ponomarenkodd172162016-10-04 19:41:25 +030028# - Ctags
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040029#
30# MS Windows
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +040031# - MinGW (3.0-4.7, 4.8.3, 4.9 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040032# - MS Visual C++ (dumpbin, undname, cl)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040033# - Active Perl 5 (5.8 or newer)
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030034# - Sigcheck v2.52 or newer
35# - GnuWin Zip and UnZip
Andrey Ponomarenkodd172162016-10-04 19:41:25 +030036# - Ctags (Exuberant or Universal)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040037# - Add tool locations to the PATH environment variable
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030038# - Run vcvars64.bat (C:\Microsoft Visual Studio 9.0\VC\bin\)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040039#
40# This program is free software: you can redistribute it and/or modify
41# it under the terms of the GNU General Public License or the GNU Lesser
42# General Public License as published by the Free Software Foundation.
43#
44# This program is distributed in the hope that it will be useful,
45# but WITHOUT ANY WARRANTY; without even the implied warranty of
46# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47# GNU General Public License for more details.
48#
49# You should have received a copy of the GNU General Public License
50# and the GNU Lesser General Public License along with this program.
51# If not, see <http://www.gnu.org/licenses/>.
52###########################################################################
53use Getopt::Long;
54Getopt::Long::Configure ("posix_default", "no_ignore_case");
55use File::Path qw(mkpath rmtree);
56use File::Temp qw(tempdir);
57use File::Copy qw(copy move);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040058use Cwd qw(abs_path cwd realpath);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040059use Storable qw(dclone);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040060use Data::Dumper;
Andrey Ponomarenko2fba6302012-03-29 17:44:47 +040061use Config;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040062
Andrey Ponomarenko9c87bdb2016-10-20 18:15:38 +030063my $TOOL_VERSION = "1.99.26";
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030064my $ABI_DUMP_VERSION = "3.3";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040065my $XML_REPORT_VERSION = "1.2";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040066my $XML_ABI_DUMP_VERSION = "1.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040067my $OSgroup = get_OSgroup();
68my $ORIG_DIR = cwd();
69my $TMP_DIR = tempdir(CLEANUP=>1);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030070my $LOCALE = "C.UTF-8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040071
72# Internal modules
73my $MODULES_DIR = get_Modules();
74push(@INC, get_dirname($MODULES_DIR));
75# Rules DB
76my %RULES_PATH = (
77 "Binary" => $MODULES_DIR."/RulesBin.xml",
78 "Source" => $MODULES_DIR."/RulesSrc.xml");
79
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030080my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040081$TestTool, $DumpAPI, $SymbolsListPath, $CheckHeadersOnly_Opt, $UseDumps,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030082$AppPath, $StrictCompat, $DumpVersion, $ParamNamesPath,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030083%RelativeDirectory, $TargetTitle, $TestDump, $LoggingPath,
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030084%TargetVersion, $InfoMsg, $CrossGcc, %OutputLogPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040085$OutputReportPath, $OutputDumpPath, $ShowRetVal, $SystemRoot_Opt, $DumpSystem,
86$CmpSystems, $TargetLibsPath, $Debug, $CrossPrefix, $UseStaticLibs, $NoStdInc,
87$TargetComponent_Opt, $TargetSysInfo, $TargetHeader, $ExtendedCheck, $Quiet,
Andrey Ponomarenko991da682016-09-07 19:09:50 +030088$SkipHeadersPath, $CxxCompat, $LogMode, $StdOut, $ListAffected, $ReportFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040089$UserLang, $TargetHeadersPath, $BinaryOnly, $SourceOnly, $BinaryReportPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030090$SourceReportPath, $UseXML, $SortDump, $DumpFormat,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040091$ExtraInfo, $ExtraDump, $Force, $Tolerance, $Tolerant, $SkipSymbolsListPath,
Andrey Ponomarenko991da682016-09-07 19:09:50 +030092$CheckInfo, $Quick, $AffectLimit, $AllAffected, $CxxIncompat,
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030093$SkipInternalSymbols, $SkipInternalTypes, $TargetArch, $GccOptions,
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030094$TypesListPath, $SkipTypesListPath, $CheckPrivateABI, $CountSymbols, $OldStyle,
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030095$DisableQuickEmptyReport, $SkipTypedefUncover, $MinGWCompat, $SkipUnidentified,
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030096$DisableConstantsCheck, $SkipAddedConstants, $SkipRemovedConstants, $TestABIDumper);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040097
98my $CmdName = get_filename($0);
99my %OS_LibExt = (
100 "dynamic" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400101 "linux"=>"so",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400102 "macos"=>"dylib",
103 "windows"=>"dll",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400104 "symbian"=>"dso",
105 "default"=>"so"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400106 },
107 "static" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400108 "linux"=>"a",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400109 "windows"=>"lib",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400110 "symbian"=>"lib",
111 "default"=>"a"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400112 }
113);
114
115my %OS_Archive = (
116 "windows"=>"zip",
117 "default"=>"tar.gz"
118);
119
120my %ERROR_CODE = (
121 # Compatible verdict
122 "Compatible"=>0,
123 "Success"=>0,
124 # Incompatible verdict
125 "Incompatible"=>1,
126 # Undifferentiated error code
127 "Error"=>2,
128 # System command is not found
129 "Not_Found"=>3,
130 # Cannot access input files
131 "Access_Error"=>4,
132 # Cannot compile header files
133 "Cannot_Compile"=>5,
134 # Header compiled with errors
135 "Compile_Error"=>6,
136 # Invalid input ABI dump
137 "Invalid_Dump"=>7,
138 # Incompatible version of ABI dump
139 "Dump_Version"=>8,
140 # Cannot find a module
141 "Module_Error"=>9,
142 # Empty intersection between
143 # headers and shared objects
144 "Empty_Intersection"=>10,
145 # Empty set of symbols in headers
146 "Empty_Set"=>11
147);
148
Andrey Ponomarenko26742a82016-09-27 18:27:08 +0300149my %HomePage = (
150 "Dev"=>"https://github.com/lvc/abi-compliance-checker",
151 "Wiki"=>"https://lvc.github.io/abi-compliance-checker/"
152);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400153
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400154my $ShortUsage = "ABI Compliance Checker (ABICC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400155A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300156Copyright (C) 2016 Andrey Ponomarenko's ABI Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400157License: GNU LGPL or GNU GPL
158
159Usage: $CmdName [options]
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400160Example: $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400161
162OLD.xml and NEW.xml are XML-descriptors:
163
164 <version>
165 1.0
166 </version>
167
168 <headers>
169 /path/to/headers/
170 </headers>
171
172 <libs>
173 /path/to/libraries/
174 </libs>
175
176More info: $CmdName --help\n";
177
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400178if($#ARGV==-1)
179{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400180 printMsg("INFO", $ShortUsage);
181 exit(0);
182}
183
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400184GetOptions("h|help!" => \$Help,
185 "i|info!" => \$InfoMsg,
186 "v|version!" => \$ShowVersion,
187 "dumpversion!" => \$DumpVersion,
188# general options
189 "l|lib|library=s" => \$TargetLibraryName,
190 "d1|old|o=s" => \$Descriptor{1}{"Path"},
191 "d2|new|n=s" => \$Descriptor{2}{"Path"},
192 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400193# extra options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400194 "app|application=s" => \$AppPath,
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300195 "static|static-libs!" => \$UseStaticLibs,
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +0400196 "gcc-path|cross-gcc=s" => \$CrossGcc,
197 "gcc-prefix|cross-prefix=s" => \$CrossPrefix,
198 "gcc-options=s" => \$GccOptions,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400199 "sysroot=s" => \$SystemRoot_Opt,
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +0300200 "v1|vnum1|version1|vnum=s" => \$TargetVersion{1},
201 "v2|vnum2|version2=s" => \$TargetVersion{2},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400202 "s|strict!" => \$StrictCompat,
203 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300204 "types-list=s" => \$TypesListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400205 "skip-symbols=s" => \$SkipSymbolsListPath,
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300206 "skip-types=s" => \$SkipTypesListPath,
Andrey Ponomarenko26742a82016-09-27 18:27:08 +0300207 "disable-constants-check!" => \$DisableConstantsCheck,
208 "skip-added-constants!" => \$SkipAddedConstants,
209 "skip-removed-constants!" => \$SkipRemovedConstants,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400210 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400211 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400212 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400213 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400214 "show-retval!" => \$ShowRetVal,
215 "use-dumps!" => \$UseDumps,
216 "nostdinc!" => \$NoStdInc,
217 "dump-system=s" => \$DumpSystem,
218 "sysinfo=s" => \$TargetSysInfo,
219 "cmp-systems!" => \$CmpSystems,
220 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400221 "ext|extended!" => \$ExtendedCheck,
222 "q|quiet!" => \$Quiet,
223 "stdout!" => \$StdOut,
224 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400225 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400226 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400227 "lang=s" => \$UserLang,
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400228 "arch=s" => \$TargetArch,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400229 "binary|bin|abi!" => \$BinaryOnly,
230 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400231 "limit-affected|affected-limit=s" => \$AffectLimit,
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +0300232 "count-symbols=s" => \$CountSymbols,
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +0300233 "old-style!" => \$OldStyle,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400234# other options
235 "test!" => \$TestTool,
236 "test-dump!" => \$TestDump,
Andrey Ponomarenko959dd192016-10-06 19:51:11 +0300237 "test-abi-dumper!" => \$TestABIDumper,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400238 "debug!" => \$Debug,
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300239 "cpp-compatible!" => \$CxxCompat,
240 "cxx-incompatible|cpp-incompatible!" => \$CxxIncompat,
241 "mingw-compatible!" => \$MinGWCompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400242 "p|params=s" => \$ParamNamesPath,
243 "relpath1|relpath=s" => \$RelativeDirectory{1},
244 "relpath2=s" => \$RelativeDirectory{2},
245 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400246 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400247 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400248 "bin-report-path=s" => \$BinaryReportPath,
249 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400250 "log-path=s" => \$LoggingPath,
251 "log1-path=s" => \$OutputLogPath{1},
252 "log2-path=s" => \$OutputLogPath{2},
253 "logging-mode=s" => \$LogMode,
254 "list-affected!" => \$ListAffected,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300255 "title|l-full|lib-full=s" => \$TargetTitle,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400256 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400257 "extra-info=s" => \$ExtraInfo,
258 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400259 "force!" => \$Force,
260 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400261 "tolerant!" => \$Tolerant,
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300262 "skip-unidentified!" => \$SkipUnidentified,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400263 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400264 "quick!" => \$Quick,
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300265 "disable-quick-empty-report!" => \$DisableQuickEmptyReport,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400266 "all-affected!" => \$AllAffected,
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300267 "skip-internal-symbols|skip-internal=s" => \$SkipInternalSymbols,
268 "skip-internal-types=s" => \$SkipInternalTypes,
Andrey Ponomarenko8580e852016-08-19 19:11:48 +0300269 "skip-typedef-uncover!" => \$SkipTypedefUncover,
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300270 "check-private-abi!" => \$CheckPrivateABI
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400271) or ERR_MESSAGE();
272
273sub ERR_MESSAGE()
274{
275 printMsg("INFO", "\n".$ShortUsage);
276 exit($ERROR_CODE{"Error"});
277}
278
279my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
280my $SLIB_TYPE = $LIB_TYPE;
281if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
282{ # show as "shared" library
283 $SLIB_TYPE = "shared";
284}
285my $LIB_EXT = getLIB_EXT($OSgroup);
286my $AR_EXT = getAR_EXT($OSgroup);
287my $BYTE_SIZE = 8;
288my $COMMON_LOG_PATH = "logs/run.log";
289
290my $HelpMessage="
291NAME:
292 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400293 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400294
295DESCRIPTION:
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400296 ABI Compliance Checker (ABICC) is a tool for checking backward binary and
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400297 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
298 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
299 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
300 and/or source-level compatibility: changes in calling stack, v-table changes,
301 removed symbols, renamed fields, etc. Binary incompatibility may result in
302 crashing or incorrect behavior of applications built with an old version of
303 a library if they run on a new one. Source incompatibility may result in
304 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400305
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400306 The tool is intended for developers of software libraries and maintainers
307 of operating systems who are interested in ensuring backward compatibility,
308 i.e. allow old applications to run or to be recompiled with newer library
309 versions.
310
311 Also the tool can be used by ISVs for checking applications portability to
312 new library versions. Found issues can be taken into account when adapting
313 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400314
315 This tool is free software: you can redistribute it and/or modify it
316 under the terms of the GNU LGPL or GNU GPL.
317
318USAGE:
319 $CmdName [options]
320
321EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400322 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400323
324 OLD.xml and NEW.xml are XML-descriptors:
325
326 <version>
327 1.0
328 </version>
329
330 <headers>
331 /path1/to/header(s)/
332 /path2/to/header(s)/
333 ...
334 </headers>
335
336 <libs>
337 /path1/to/library(ies)/
338 /path2/to/library(ies)/
339 ...
340 </libs>
341
342INFORMATION OPTIONS:
343 -h|-help
344 Print this help.
345
346 -i|-info
347 Print complete info.
348
349 -v|-version
350 Print version information.
351
352 -dumpversion
353 Print the tool version ($TOOL_VERSION) and don't do anything else.
354
355GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400356 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400357 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400358
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400359 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400360 Descriptor of 1st (old) library version.
361 It may be one of the following:
362
363 1. XML-descriptor (VERSION.xml file):
364
365 <version>
366 1.0
367 </version>
368
369 <headers>
370 /path1/to/header(s)/
371 /path2/to/header(s)/
372 ...
373 </headers>
374
375 <libs>
376 /path1/to/library(ies)/
377 /path2/to/library(ies)/
378 ...
379 </libs>
380
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300381 ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400382
383 2. ABI dump generated by -dump option
384 3. Directory with headers and/or $SLIB_TYPE libraries
385 4. Single header file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400386
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300387 If you are using an 2-4 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400388 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400389
390 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400391 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400392
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400393 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400394 Descriptor of 2nd (new) library version.
395
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400396 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400397 Create library ABI dump for the input XML descriptor. You can
398 transfer it anywhere and pass instead of the descriptor. Also
399 it can be used for debugging the tool.
400
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +0300401 Supported versions of ABI dump: 2.0<=V<=$ABI_DUMP_VERSION\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400402
403sub HELP_MESSAGE() {
404 printMsg("INFO", $HelpMessage."
405MORE INFO:
406 $CmdName --info\n");
407}
408
409sub INFO_MESSAGE()
410{
411 printMsg("INFO", "$HelpMessage
412EXTRA OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400413 -app|-application PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300414 This option allows to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400415 for portability to the new library version.
416
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300417 -static
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400418 Check static libraries instead of the shared ones. The <libs> section
419 of the XML-descriptor should point to static libraries location.
420
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300421 -gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400422 Path to the cross GCC compiler to use instead of the usual (host) GCC.
423
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300424 -gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400425 GCC toolchain prefix.
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300426
427 -gcc-options OPTS
428 Additional compiler options.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400429
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400430 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400431 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400432 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400433
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400434 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400435 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200436 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400437
438 In general case you should specify it in the XML-descriptor:
439 <version>
440 VERSION
441 </version>
442
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400443 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400444 Specify 2nd library version outside the descriptor.
445
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +0400446 -vnum NUM
447 Specify the library version in the generated ABI dump. The <version> section
448 of the input XML descriptor will be overwritten in this case.
449
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400450 -s|-strict
451 Treat all compatibility warnings as problems. Add a number of \"Low\"
452 severity problems to the return value of the tool.
453
454 -headers-only
455 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
456 provide a low quality compatibility report with false positives and
457 without detecting of added/removed symbols.
458
459 Alternatively you can write \"none\" word to the <libs> section
460 in the XML-descriptor:
461 <libs>
462 none
463 </libs>
464
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400465 -show-retval
466 Show the symbol's return type in the report.
467
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400468 -symbols-list PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300469 This option allows to specify a file with a list of symbols (mangled
470 names in C++) that should be checked. Other symbols will not be checked.
471
472 -types-list PATH
473 This option allows to specify a file with a list of types that should
474 be checked. Other types will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400475
476 -skip-symbols PATH
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300477 The list of symbols that should not be checked.
478
479 -skip-types PATH
480 The list of types that should not be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400481
Andrey Ponomarenko26742a82016-09-27 18:27:08 +0300482 -disable-constants-check
483 Do not check for changes in constants.
Andrey Ponomarenkodd172162016-10-04 19:41:25 +0300484
485 -skip-added-constants
486 Do not detect added constants.
487
488 -skip-removed-constants
489 Do not detect removed constants.
490
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400491 -headers-list PATH
492 The file with a list of headers, that should be checked/dumped.
493
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400494 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400495 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400496
497 -header NAME
498 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400499
500 -use-dumps
501 Make dumps for two versions of a library and compare dumps. This should
502 increase the performance of the tool and decrease the system memory usage.
503
504 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400505 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400506
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400507 -dump-system NAME -sysroot DIR
508 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400509 create XML descriptors and make ABI dumps for each library. The result
510 set of ABI dumps can be compared (--cmp-systems) with the other one
511 created for other version of operating system in order to check them for
512 compatibility. Do not forget to specify -cross-gcc option if your target
513 system requires some specific version of GCC compiler (different from
514 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400515 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400516
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400517 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400518 The same as the previous option but takes an XML descriptor of the target
519 system as input, where you should describe it:
520
521 /* Primary sections */
522
523 <name>
524 /* Name of the system */
525 </name>
526
527 <headers>
528 /* The list of paths to header files and/or
529 directories with header files, one per line */
530 </headers>
531
532 <libs>
533 /* The list of paths to shared libraries and/or
534 directories with shared libraries, one per line */
535 </libs>
536
537 /* Optional sections */
538
539 <search_headers>
540 /* List of directories to be searched
541 for header files to automatically
542 generate include paths, one per line */
543 </search_headers>
544
545 <search_libs>
546 /* List of directories to be searched
547 for shared libraries to resolve
548 dependencies, one per line */
549 </search_libs>
550
551 <tools>
552 /* List of directories with tools used
553 for analysis (GCC toolchain), one per line */
554 </tools>
555
556 <cross_prefix>
557 /* GCC toolchain prefix.
558 Examples:
559 arm-linux-gnueabi
560 arm-none-symbianelf */
561 </cross_prefix>
562
563 <gcc_options>
564 /* Additional GCC options, one per line */
565 </gcc_options>
566
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400567 -sysinfo DIR
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300568 This option should be used with -dump-system option to dump
569 ABI of operating systems and configure the dumping process.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400570
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400571 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300572 Compare two ABI dumps of a system. Create compatibility reports for
573 each system library and the common HTML report including the summary
574 of test results for all checked libraries.
575
576 Summary report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400577 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400578
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400579 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400580 The file with a list of libraries, that should be dumped by
581 the -dump-system option or should be checked by the -cmp-systems option.
582
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400583 -ext|-extended
584 If your library A is supposed to be used by other library B and you
585 want to control the ABI of B, then you should enable this option. The
586 tool will check for changes in all data types, even if they are not
587 used by any function in the library A. Such data types are not part
588 of the A library ABI, but may be a part of the ABI of the B library.
589
590 The short scheme is:
591 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
592
593 -q|-quiet
594 Print all messages to the file instead of stdout and stderr.
595 Default path (can be changed by -log-path option):
596 $COMMON_LOG_PATH
597
598 -stdout
599 Print analysis results (compatibility reports and ABI dumps) to stdout
600 instead of creating a file. This would allow piping data to other programs.
601
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400602 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400603 Change format of compatibility report.
604 Formats:
605 htm - HTML format (default)
606 xml - XML format
607
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400608 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400609 Change format of ABI dump.
610 Formats:
611 perl - Data::Dumper format (default)
612 xml - XML format
613
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400614 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400615 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400616
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400617 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400618 Set library language (C or C++). You can use this option if the tool
619 cannot auto-detect a language. This option may be useful for checking
620 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400621
622 -arch ARCH
623 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
624 ect.). The option is useful if the tool cannot detect correct architecture
625 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400626
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400627 -binary|-bin|-abi
628 Show \"Binary\" compatibility problems only.
629 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400630 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400631
632 -source|-src|-api
633 Show \"Source\" compatibility problems only.
634 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400635 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400636
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400637 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400638 The maximum number of affected symbols listed under the description
639 of the changed type in the report.
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +0300640
641 -count-symbols PATH
642 Count total public symbols in the ABI dump.
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +0300643
644 -old-style
645 Generate old-style report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400646
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400647OTHER OPTIONS:
648 -test
649 Run internal tests. Create two binary incompatible versions of a sample
650 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300651 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400652
653 -test-dump
654 Test ability to create, read and compare ABI dumps.
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300655
Andrey Ponomarenko959dd192016-10-06 19:51:11 +0300656 -test-abi-dumper
657 Compare ABI dumps created by the ABI Dumper tool.
658
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400659 -debug
660 Debugging mode. Print debug info on the screen. Save intermediate
661 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400662 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400663
Andrey Ponomarenko959dd192016-10-06 19:51:11 +0300664 Also consider using -dump option for debugging the tool.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400665
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400666 -cpp-compatible
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300667 Do nothing.
668
669 -cxx-incompatible
670 Set this option if input C header files use C++ keywords. The tool
671 will try to replace such keywords at preprocessor stage and replace
672 them back in the final TU dump.
673
674 -mingw-compatible
675 If input header files are compatible with the MinGW GCC compiler,
Andrey Ponomarenkodd172162016-10-04 19:41:25 +0300676 then you can tell the tool about this and speedup the analysis.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400677
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400678 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400679 Path to file with the function parameter names. It can be used
680 for improving report view if the library header files have no
681 parameter names. File format:
682
683 func1;param1;param2;param3 ...
684 func2;param1;param2;param3 ...
685 ...
686
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400687 -relpath PATH
688 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400689 for dumping the library ABI (see -dump option).
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300690
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400691 -relpath1 PATH
692 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400693
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400694 -relpath2 PATH
695 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400696
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400697 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400698 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400699 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400700 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400701
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400702 -sort
703 Enable sorting of data in ABI dumps.
704
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400705 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400706 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400707 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400708 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400709
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400710 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400711 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400712 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400713 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400714
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400715 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400716 Path to \"Source\" compatibility report.
717 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400718 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400719
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400720 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400721 Log path for all messages.
722 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400723 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400724
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400725 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400726 Log path for 1st version of a library.
727 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400728 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400729
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400730 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400731 Log path for 2nd version of a library.
732 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400733 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400734
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400735 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400736 Change logging mode.
737 Modes:
738 w - overwrite old logs (default)
739 a - append old logs
740 n - do not write any logs
741
742 -list-affected
743 Generate file with the list of incompatible
744 symbols beside the HTML compatibility report.
745 Use 'c++filt \@file' command from GNU binutils
746 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400747 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400748 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400749 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400750
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400751 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400752 The component name in the title and summary of the HTML report.
753 Default:
754 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300755
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300756 -title NAME
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400757 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400758 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400759
760 -extra-info DIR
761 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400762
763 -extra-dump
764 Create extended ABI dump containing all symbols
765 from the translation unit.
766
767 -force
Andrey Ponomarenko9c87bdb2016-10-20 18:15:38 +0300768 Try to enable this option if the tool checked not all
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300769 types and symbols in header files.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400770
771 -tolerance LEVEL
772 Apply a set of heuristics to successfully compile input
773 header files. You can enable several tolerance levels by
774 joining them into one string (e.g. 13, 124, etc.).
775 Levels:
776 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
777 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
Sangwoo Lee159324e2016-06-26 01:55:55 +0900778 3 - skip headers that include non-Linux headers
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400779 4 - skip headers included by others
780
781 -tolerant
782 Enable highest tolerance level [1234].
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300783
784 -skip-unidentified
785 Skip header files in 'headers' and 'include_preamble' sections
786 of the XML descriptor that cannot be found. This is useful if
787 you are trying to use the same descriptor for different targets.
788
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400789 -check
790 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400791
792 -quick
793 Quick analysis. Disable check of some template instances.
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300794
795 -disable-quick-empty-report
796 Do not generate quick empty report if input ABI dumps are equal.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400797
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300798 -skip-internal-symbols PATTERN
799 Do not check symbols matched by the pattern.
800
801 -skip-internal-types PATTERN
802 Do not check types matched by the pattern.
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300803
Andrey Ponomarenko8580e852016-08-19 19:11:48 +0300804 -skip-typedef-uncover
805 Do not report a problem if type is covered or
806 uncovered by typedef (useful for broken debug info).
807
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300808 -check-private-abi
809 Check data types from the private part of the ABI when
810 comparing ABI dumps created by the ABI Dumper tool with
811 use of the -public-headers option.
812
813 Requires ABI Dumper >= 0.99.14
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400814
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400815REPORT:
816 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400817 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400818
819 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400820 logs/LIB_NAME/V1/log.txt
821 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400822
823EXIT CODES:
824 0 - Compatible. The tool has run without any errors.
825 non-zero - Incompatible or the tool has run with errors.
826
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400827MORE INFORMATION:
Andrey Ponomarenko26742a82016-09-27 18:27:08 +0300828 ".$HomePage{"Wiki"}."
Andrey Ponomarenko868b1352016-09-29 14:13:30 +0300829 ".$HomePage{"Dev"}."\n\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400830}
831
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400832my %Operator_Indication = (
833 "not" => "~",
834 "assign" => "=",
835 "andassign" => "&=",
836 "orassign" => "|=",
837 "xorassign" => "^=",
838 "or" => "|",
839 "xor" => "^",
840 "addr" => "&",
841 "and" => "&",
842 "lnot" => "!",
843 "eq" => "==",
844 "ne" => "!=",
845 "lt" => "<",
846 "lshift" => "<<",
847 "lshiftassign" => "<<=",
848 "rshiftassign" => ">>=",
849 "call" => "()",
850 "mod" => "%",
851 "modassign" => "%=",
852 "subs" => "[]",
853 "land" => "&&",
854 "lor" => "||",
855 "rshift" => ">>",
856 "ref" => "->",
857 "le" => "<=",
858 "deref" => "*",
859 "mult" => "*",
860 "preinc" => "++",
861 "delete" => " delete",
862 "vecnew" => " new[]",
863 "vecdelete" => " delete[]",
864 "predec" => "--",
865 "postinc" => "++",
866 "postdec" => "--",
867 "plusassign" => "+=",
868 "plus" => "+",
869 "minus" => "-",
870 "minusassign" => "-=",
871 "gt" => ">",
872 "ge" => ">=",
873 "new" => " new",
874 "multassign" => "*=",
875 "divassign" => "/=",
876 "div" => "/",
877 "neg" => "-",
878 "pos" => "+",
879 "memref" => "->*",
880 "compound" => "," );
881
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400882my %UnknownOperator;
883
884my %NodeType= (
885 "array_type" => "Array",
886 "binfo" => "Other",
887 "boolean_type" => "Intrinsic",
888 "complex_type" => "Intrinsic",
889 "const_decl" => "Other",
890 "enumeral_type" => "Enum",
891 "field_decl" => "Other",
892 "function_decl" => "Other",
893 "function_type" => "FunctionType",
894 "identifier_node" => "Other",
895 "integer_cst" => "Other",
896 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400897 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400898 "method_type" => "MethodType",
899 "namespace_decl" => "Other",
900 "parm_decl" => "Other",
901 "pointer_type" => "Pointer",
902 "real_cst" => "Other",
903 "real_type" => "Intrinsic",
904 "record_type" => "Struct",
905 "reference_type" => "Ref",
906 "string_cst" => "Other",
907 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400908 "template_type_parm" => "TemplateParam",
909 "typename_type" => "TypeName",
910 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400911 "tree_list" => "Other",
912 "tree_vec" => "Other",
913 "type_decl" => "Other",
914 "union_type" => "Union",
915 "var_decl" => "Other",
916 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400917 "nop_expr" => "Other", #
918 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400919 "offset_type" => "Other" );
920
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400921my %CppKeywords_C = map {$_=>1} (
922 # C++ 2003 keywords
923 "public",
924 "protected",
925 "private",
926 "default",
927 "template",
928 "new",
929 #"asm",
930 "dynamic_cast",
931 "auto",
932 "try",
933 "namespace",
934 "typename",
935 "using",
936 "reinterpret_cast",
937 "friend",
938 "class",
939 "virtual",
940 "const_cast",
941 "mutable",
942 "static_cast",
943 "export",
944 # C++0x keywords
945 "noexcept",
946 "nullptr",
947 "constexpr",
948 "static_assert",
949 "explicit",
950 # cannot be used as a macro name
951 # as it is an operator in C++
952 "and",
953 #"and_eq",
954 "not",
955 #"not_eq",
956 "or"
957 #"or_eq",
958 #"bitand",
959 #"bitor",
960 #"xor",
961 #"xor_eq",
962 #"compl"
963);
964
965my %CppKeywords_F = map {$_=>1} (
966 "delete",
967 "catch",
968 "alignof",
969 "thread_local",
970 "decltype",
971 "typeid"
972);
973
974my %CppKeywords_O = map {$_=>1} (
975 "bool",
976 "register",
977 "inline",
978 "operator"
979);
980
981my %CppKeywords_A = map {$_=>1} (
982 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400983 "throw",
984 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400985);
986
987foreach (keys(%CppKeywords_C),
988keys(%CppKeywords_F),
989keys(%CppKeywords_O)) {
990 $CppKeywords_A{$_}=1;
991}
992
993# Header file extensions as described by gcc
994my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
995
996my %IntrinsicMangling = (
997 "void" => "v",
998 "bool" => "b",
999 "wchar_t" => "w",
1000 "char" => "c",
1001 "signed char" => "a",
1002 "unsigned char" => "h",
1003 "short" => "s",
1004 "unsigned short" => "t",
1005 "int" => "i",
1006 "unsigned int" => "j",
1007 "long" => "l",
1008 "unsigned long" => "m",
1009 "long long" => "x",
1010 "__int64" => "x",
1011 "unsigned long long" => "y",
1012 "__int128" => "n",
1013 "unsigned __int128" => "o",
1014 "float" => "f",
1015 "double" => "d",
1016 "long double" => "e",
1017 "__float80" => "e",
1018 "__float128" => "g",
1019 "..." => "z"
1020);
1021
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001022my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
1023
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001024my %StdcxxMangling = (
1025 "3std"=>"St",
1026 "3std9allocator"=>"Sa",
1027 "3std12basic_string"=>"Sb",
1028 "3std12basic_stringIcE"=>"Ss",
1029 "3std13basic_istreamIcE"=>"Si",
1030 "3std13basic_ostreamIcE"=>"So",
1031 "3std14basic_iostreamIcE"=>"Sd"
1032);
1033
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04001034my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001035my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
1036
1037my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenko9c87bdb2016-10-20 18:15:38 +03001038my $GCC_MISSED_MNGL = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001039
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001040my %ConstantSuffix = (
1041 "unsigned int"=>"u",
1042 "long"=>"l",
1043 "unsigned long"=>"ul",
1044 "long long"=>"ll",
1045 "unsigned long long"=>"ull"
1046);
1047
1048my %ConstantSuffixR =
1049reverse(%ConstantSuffix);
1050
1051my %OperatorMangling = (
1052 "~" => "co",
1053 "=" => "aS",
1054 "|" => "or",
1055 "^" => "eo",
1056 "&" => "an",#ad (addr)
1057 "==" => "eq",
1058 "!" => "nt",
1059 "!=" => "ne",
1060 "<" => "lt",
1061 "<=" => "le",
1062 "<<" => "ls",
1063 "<<=" => "lS",
1064 ">" => "gt",
1065 ">=" => "ge",
1066 ">>" => "rs",
1067 ">>=" => "rS",
1068 "()" => "cl",
1069 "%" => "rm",
1070 "[]" => "ix",
1071 "&&" => "aa",
1072 "||" => "oo",
1073 "*" => "ml",#de (deref)
1074 "++" => "pp",#
1075 "--" => "mm",#
1076 "new" => "nw",
1077 "delete" => "dl",
1078 "new[]" => "na",
1079 "delete[]" => "da",
1080 "+=" => "pL",
1081 "+" => "pl",#ps (pos)
1082 "-" => "mi",#ng (neg)
1083 "-=" => "mI",
1084 "*=" => "mL",
1085 "/=" => "dV",
1086 "&=" => "aN",
1087 "|=" => "oR",
1088 "%=" => "rM",
1089 "^=" => "eO",
1090 "/" => "dv",
1091 "->*" => "pm",
1092 "->" => "pt",#rf (ref)
1093 "," => "cm",
1094 "?" => "qu",
1095 "." => "dt",
1096 "sizeof"=> "sz"#st
1097);
1098
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001099my %Intrinsic_Keywords = map {$_=>1} (
1100 "true",
1101 "false",
1102 "_Bool",
1103 "_Complex",
1104 "const",
1105 "int",
1106 "long",
1107 "void",
1108 "short",
1109 "float",
1110 "volatile",
1111 "restrict",
1112 "unsigned",
1113 "signed",
1114 "char",
1115 "double",
1116 "class",
1117 "struct",
1118 "union",
1119 "enum"
1120);
1121
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001122my %GlibcHeader = map {$_=>1} (
1123 "aliases.h",
1124 "argp.h",
1125 "argz.h",
1126 "assert.h",
1127 "cpio.h",
1128 "ctype.h",
1129 "dirent.h",
1130 "envz.h",
1131 "errno.h",
1132 "error.h",
1133 "execinfo.h",
1134 "fcntl.h",
1135 "fstab.h",
1136 "ftw.h",
1137 "glob.h",
1138 "grp.h",
1139 "iconv.h",
1140 "ifaddrs.h",
1141 "inttypes.h",
1142 "langinfo.h",
1143 "limits.h",
1144 "link.h",
1145 "locale.h",
1146 "malloc.h",
1147 "math.h",
1148 "mntent.h",
1149 "monetary.h",
1150 "nl_types.h",
1151 "obstack.h",
1152 "printf.h",
1153 "pwd.h",
1154 "regex.h",
1155 "sched.h",
1156 "search.h",
1157 "setjmp.h",
1158 "shadow.h",
1159 "signal.h",
1160 "spawn.h",
1161 "stdarg.h",
1162 "stdint.h",
1163 "stdio.h",
1164 "stdlib.h",
1165 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001166 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001167 "tar.h",
1168 "termios.h",
1169 "time.h",
1170 "ulimit.h",
1171 "unistd.h",
1172 "utime.h",
1173 "wchar.h",
1174 "wctype.h",
1175 "wordexp.h" );
1176
1177my %GlibcDir = map {$_=>1} (
1178 "arpa",
1179 "bits",
1180 "gnu",
1181 "netinet",
1182 "net",
1183 "nfs",
1184 "rpc",
1185 "sys",
1186 "linux" );
1187
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001188my %WinHeaders = map {$_=>1} (
1189 "dos.h",
1190 "process.h",
1191 "winsock.h",
1192 "config-win.h",
1193 "mem.h",
1194 "windows.h",
1195 "winsock2.h",
1196 "crtdbg.h",
1197 "ws2tcpip.h"
1198);
1199
1200my %ObsoleteHeaders = map {$_=>1} (
1201 "iostream.h",
1202 "fstream.h"
1203);
1204
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001205my %AlienHeaders = map {$_=>1} (
1206 # Solaris
1207 "thread.h",
1208 "sys/atomic.h",
1209 # HPUX
1210 "sys/stream.h",
1211 # Symbian
1212 "AknDoc.h",
1213 # Atari ST
1214 "ext.h",
1215 "tos.h",
1216 # MS-DOS
1217 "alloc.h",
1218 # Sparc
1219 "sys/atomic.h"
1220);
1221
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001222my %ConfHeaders = map {$_=>1} (
1223 "atomic",
1224 "conf.h",
1225 "config.h",
1226 "configure.h",
1227 "build.h",
1228 "setup.h"
1229);
1230
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001231my %LocalIncludes = map {$_=>1} (
1232 "/usr/local/include",
1233 "/usr/local" );
1234
1235my %OS_AddPath=(
1236# These paths are needed if the tool cannot detect them automatically
1237 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001238 "include"=>[
1239 "/Library",
1240 "/Developer/usr/include"
1241 ],
1242 "lib"=>[
1243 "/Library",
1244 "/Developer/usr/lib"
1245 ],
1246 "bin"=>[
1247 "/Developer/usr/bin"
1248 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001249 },
1250 "beos"=>{
1251 # Haiku has GCC 2.95.3 by default
1252 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001253 "include"=>[
1254 "/boot/common",
1255 "/boot/develop"
1256 ],
1257 "lib"=>[
1258 "/boot/common/lib",
1259 "/boot/system/lib",
1260 "/boot/apps"
1261 ],
1262 "bin"=>[
1263 "/boot/common/bin",
1264 "/boot/system/bin",
1265 "/boot/develop/abi"
1266 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001268);
1269
1270my %Slash_Type=(
1271 "default"=>"/",
1272 "windows"=>"\\"
1273);
1274
1275my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1276
1277# Global Variables
1278my %COMMON_LANGUAGE=(
1279 1 => "C",
1280 2 => "C" );
1281
1282my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001283my $MAX_CPPFILT_FILE_SIZE = 50000;
1284my $CPPFILT_SUPPORT_FILE;
1285
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +03001286my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION, %CLANG_VERSION);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001287
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001288my $STDCXX_TESTING = 0;
1289my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001290my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001291
1292my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001293my $CheckUndefined = 0;
1294
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +03001295my $TargetComponent = undef;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001296if($TargetComponent_Opt) {
1297 $TargetComponent = lc($TargetComponent_Opt);
1298}
1299else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001300{ # default: library
1301 # other components: header, system, ...
1302 $TargetComponent = "library";
1303}
1304
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001305my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001306
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001307my $SystemRoot;
1308
1309my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001310my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001311my %LOG_PATH;
1312my %DEBUG_PATH;
1313my %Cache;
1314my %LibInfo;
1315my $COMPILE_ERRORS = 0;
1316my %CompilerOptions;
1317my %CheckedDyLib;
1318my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1319
1320# Constants (#defines)
1321my %Constants;
1322my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001323my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001324
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001325# Extra Info
1326my %SymbolHeader;
1327my %KnownLibs;
1328
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001329# Templates
1330my %TemplateInstance;
1331my %BasicTemplate;
1332my %TemplateArg;
1333my %TemplateDecl;
1334my %TemplateMap;
1335
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001336# Types
1337my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001338my %SkipTypes = (
1339 "1"=>{},
1340 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001341my %CheckedTypes;
1342my %TName_Tid;
1343my %EnumMembName_Id;
1344my %NestedNameSpaces = (
1345 "1"=>{},
1346 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001347my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001348my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001349my %ClassVTable;
1350my %ClassVTable_Content;
1351my %VTableClass;
1352my %AllocableClass;
1353my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001354my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001355my %Class_SubClasses;
1356my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001357my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001358my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001359
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001360my %CheckedTypeInfo;
1361
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001362# Typedefs
1363my %Typedef_BaseName;
1364my %Typedef_Tr;
1365my %Typedef_Eq;
1366my %StdCxxTypedef;
1367my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001368my %MissedBase;
1369my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001370my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001371
1372# Symbols
1373my %SymbolInfo;
1374my %tr_name;
1375my %mangled_name_gcc;
1376my %mangled_name;
1377my %SkipSymbols = (
1378 "1"=>{},
1379 "2"=>{} );
1380my %SkipNameSpaces = (
1381 "1"=>{},
1382 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001383my %AddNameSpaces = (
1384 "1"=>{},
1385 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001386my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001387my %TypesList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001388my %SymbolsList_App;
1389my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001390my %Symbol_Library = (
1391 "1"=>{},
1392 "2"=>{} );
1393my %Library_Symbol = (
1394 "1"=>{},
1395 "2"=>{} );
1396my %DepSymbol_Library = (
1397 "1"=>{},
1398 "2"=>{} );
1399my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001400 "1"=>{},
1401 "2"=>{} );
1402my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001403my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001404my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001405my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001406my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001407my %Library_Needed= (
1408 "1"=>{},
1409 "2"=>{} );
Andrey Ponomarenko991da682016-09-07 19:09:50 +03001410my $DisabledMSVCUnmangling = undef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001411
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001412# Extra Info
1413my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001414my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001415
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001416# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001417my %Include_Preamble = (
1418 "1"=>[],
1419 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001420my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001421my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001422my %HeaderName_Paths;
1423my %Header_Dependency;
1424my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001425my %Include_Paths = (
1426 "1"=>[],
1427 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001428my %INC_PATH_AUTODETECT = (
1429 "1"=>1,
1430 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001431my %Add_Include_Paths = (
1432 "1"=>[],
1433 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001434my %Skip_Include_Paths;
1435my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001436my %Header_ErrorRedirect;
1437my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001438my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001439my %Header_ShouldNotBeUsed;
1440my %RecursiveIncludes;
1441my %Header_Include_Prefix;
1442my %SkipHeaders;
1443my %SkipHeadersList=(
1444 "1"=>{},
1445 "2"=>{} );
1446my %SkipLibs;
1447my %Include_Order;
1448my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001449my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001450my %TUnit_Funcs;
1451my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001452
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001453my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001454 "1"=>0,
1455 "2"=>0 );
1456my %AutoPreambleMode = (
1457 "1"=>0,
1458 "2"=>0 );
1459my %MinGWMode = (
1460 "1"=>0,
1461 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001462my %Cpp0xMode = (
1463 "1"=>0,
1464 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001465
1466# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001467my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001468my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001469my %RegisteredSONAMEs;
1470my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001471
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001472my %CheckedArch;
1473
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001474# System Objects
1475my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001476my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001477my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001478
1479# System Headers
1480my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001481my @DefaultCppPaths;
1482my @DefaultGccPaths;
1483my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001484my %DefaultCppHeader;
1485my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001486my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001487
1488# Merging
1489my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001490my $Version;
1491my %AddedInt;
1492my %RemovedInt;
1493my %AddedInt_Virt;
1494my %RemovedInt_Virt;
1495my %VirtualReplacement;
1496my %ChangedTypedef;
1497my %CompatRules;
1498my %IncompleteRules;
1499my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001500my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001501my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001502my %ReturnedClass;
1503my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001504my %SourceAlternative;
1505my %SourceAlternative_B;
1506my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001507my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001508
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03001509#Report
1510my %TypeChanges;
1511
1512#Speedup
1513my %TypeProblemsIndex;
1514
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001515# Calling Conventions
1516my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001517 1=>{ "R"=>0, "P"=>0 },
1518 2=>{ "R"=>0, "P"=>0 }
1519);
1520
1521# ABI Dump
1522my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001523
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001524# Filters
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001525my %TargetLibs;
1526my %TargetHeaders;
1527
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001528# Format of objects
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001529my $OStarget = $OSgroup;
1530my %TargetTools;
1531
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001532# Recursion locks
1533my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001534my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001535my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001536my @RecurInclude;
1537my @RecurConstant;
1538
1539# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001540my %SystemPaths = (
1541 "include"=>[],
1542 "lib"=>[],
1543 "bin"=>[]
1544);
1545my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001546my $GCC_PATH;
1547
1548# Symbols versioning
1549my %SymVer = (
1550 "1"=>{},
1551 "2"=>{} );
1552
1553# Problem descriptions
1554my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001555my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001556my %TotalAffected;
1557
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001558# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001559my $ContentID = 1;
1560my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +03001561my $ContentSpanStart_Affected = "<span class=\"sect_aff\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1562my $ContentSpanStart_Info = "<span class=\"sect_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001563my $ContentSpanEnd = "</span>\n";
1564my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1565my $ContentDivEnd = "</div>\n";
1566my $Content_Counter = 0;
1567
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001568# Modes
1569my $JoinReport = 1;
1570my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001571
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001572my %Severity_Val=(
1573 "High"=>3,
1574 "Medium"=>2,
1575 "Low"=>1,
1576 "Safe"=>-1
1577);
1578
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001579sub get_Modules()
1580{
1581 my $TOOL_DIR = get_dirname($0);
1582 if(not $TOOL_DIR)
1583 { # patch for MS Windows
1584 $TOOL_DIR = ".";
1585 }
1586 my @SEARCH_DIRS = (
1587 # tool's directory
1588 abs_path($TOOL_DIR),
1589 # relative path to modules
1590 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001591 # install path
1592 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001593 );
1594 foreach my $DIR (@SEARCH_DIRS)
1595 {
1596 if(not is_abs($DIR))
1597 { # relative path
1598 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1599 }
1600 if(-d $DIR."/modules") {
1601 return $DIR."/modules";
1602 }
1603 }
1604 exitStatus("Module_Error", "can't find modules");
1605}
1606
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001607my %LoadedModules = ();
1608
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001609sub loadModule($)
1610{
1611 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001612 if(defined $LoadedModules{$Name}) {
1613 return;
1614 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001615 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1616 if(not -f $Path) {
1617 exitStatus("Module_Error", "can't access \'$Path\'");
1618 }
1619 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001620 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001621}
1622
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001623sub readModule($$)
1624{
1625 my ($Module, $Name) = @_;
1626 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1627 if(not -f $Path) {
1628 exitStatus("Module_Error", "can't access \'$Path\'");
1629 }
1630 return readFile($Path);
1631}
1632
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001633sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001634{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001635 my $Number = $_[0];
1636 if(not $Number) {
1637 $Number = 1;
1638 }
1639 else {
1640 $Number = int($Number)+1;
1641 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001642 if($Number>3) {
1643 return $Number."th";
1644 }
1645 elsif($Number==1) {
1646 return "1st";
1647 }
1648 elsif($Number==2) {
1649 return "2nd";
1650 }
1651 elsif($Number==3) {
1652 return "3rd";
1653 }
1654 else {
1655 return $Number;
1656 }
1657}
1658
1659sub search_Tools($)
1660{
1661 my $Name = $_[0];
1662 return "" if(not $Name);
1663 if(my @Paths = keys(%TargetTools))
1664 {
1665 foreach my $Path (@Paths)
1666 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001667 if(-f join_P($Path, $Name)) {
1668 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001669 }
1670 if($CrossPrefix)
1671 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001672 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001673 if(-f $Candidate) {
1674 return $Candidate;
1675 }
1676 }
1677 }
1678 }
1679 else {
1680 return "";
1681 }
1682}
1683
1684sub synch_Cmd($)
1685{
1686 my $Name = $_[0];
1687 if(not $GCC_PATH)
1688 { # GCC was not found yet
1689 return "";
1690 }
1691 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001692 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001693 return $Candidate;
1694 }
1695 return "";
1696}
1697
1698sub get_CmdPath($)
1699{
1700 my $Name = $_[0];
1701 return "" if(not $Name);
1702 if(defined $Cache{"get_CmdPath"}{$Name}) {
1703 return $Cache{"get_CmdPath"}{$Name};
1704 }
1705 my %BinUtils = map {$_=>1} (
1706 "c++filt",
1707 "objdump",
1708 "readelf"
1709 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001710 if($BinUtils{$Name} and $GCC_PATH)
1711 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001712 if(my $Dir = get_dirname($GCC_PATH)) {
1713 $TargetTools{$Dir}=1;
1714 }
1715 }
1716 my $Path = search_Tools($Name);
1717 if(not $Path and $OSgroup eq "windows") {
1718 $Path = search_Tools($Name.".exe");
1719 }
1720 if(not $Path and $BinUtils{$Name})
1721 {
1722 if($CrossPrefix)
1723 { # user-defined prefix
1724 $Path = search_Cmd($CrossPrefix."-".$Name);
1725 }
1726 }
1727 if(not $Path and $BinUtils{$Name})
1728 {
1729 if(my $Candidate = synch_Cmd($Name))
1730 { # synch with GCC
1731 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001732 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001733 if(-f $Candidate) {
1734 $Path = $Candidate;
1735 }
1736 }
1737 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001738 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001739 $Path = $Candidate;
1740 }
1741 }
1742 }
1743 if(not $Path) {
1744 $Path = search_Cmd($Name);
1745 }
1746 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001747 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001748 $Path=search_Cmd($Name.".exe");
1749 }
1750 if($Path=~/\s/) {
1751 $Path = "\"".$Path."\"";
1752 }
1753 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1754}
1755
1756sub search_Cmd($)
1757{
1758 my $Name = $_[0];
1759 return "" if(not $Name);
1760 if(defined $Cache{"search_Cmd"}{$Name}) {
1761 return $Cache{"search_Cmd"}{$Name};
1762 }
1763 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1764 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1765 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001766 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001767 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001768 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001769 if(-f $CmdPath)
1770 {
1771 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001772 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001773 }
1774 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1775 }
1776 }
1777 return ($Cache{"search_Cmd"}{$Name} = "");
1778}
1779
1780sub get_CmdPath_Default($)
1781{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001782 return "" if(not $_[0]);
1783 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1784 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001785 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001786 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1787}
1788
1789sub get_CmdPath_Default_I($)
1790{ # search in PATH
1791 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001792 if($Name=~/find/)
1793 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001794 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001795 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001796 }
1797 }
1798 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001799 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001800 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001801 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001802 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001803 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001804 if($OSgroup eq "windows")
1805 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001806 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001807 return $Name;
1808 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001809 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001810 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001811 {
1812 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001813 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001814 }
1815 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001816 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001817}
1818
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001819sub classifyPath($)
1820{
1821 my $Path = $_[0];
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001822 if($Path=~/[\*\+\(\[\|]/)
1823 { # pattern
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001824 return ($Path, "Pattern");
1825 }
1826 elsif($Path=~/[\/\\]/)
1827 { # directory or relative path
1828 return (path_format($Path, $OSgroup), "Path");
1829 }
1830 else {
1831 return ($Path, "Name");
1832 }
1833}
1834
1835sub readDescriptor($$)
1836{
1837 my ($LibVersion, $Content) = @_;
1838 return if(not $LibVersion);
1839 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1840 if(not $Content) {
1841 exitStatus("Error", "$DName is empty");
1842 }
1843 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001844 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001845 }
1846 $Content=~s/\/\*(.|\n)+?\*\///g;
1847 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001848
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001849 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1850 if($TargetVersion{$LibVersion}) {
1851 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1852 }
1853 if(not $Descriptor{$LibVersion}{"Version"}) {
1854 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1855 }
1856 if($Content=~/{RELPATH}/)
1857 {
1858 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1859 $Content =~ s/{RELPATH}/$RelDir/g;
1860 }
1861 else
1862 {
1863 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1864 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1865 }
1866 }
1867
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001868 my $DHeaders = parseTag(\$Content, "headers");
1869 if(not $DHeaders) {
1870 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1871 }
1872 elsif(lc($DHeaders) ne "none")
1873 { # append the descriptor headers list
1874 if($Descriptor{$LibVersion}{"Headers"})
1875 { # multiple descriptors
1876 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001877 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001878 else {
1879 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1880 }
1881 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1882 {
1883 if(not -e $Path) {
1884 exitStatus("Access_Error", "can't access \'$Path\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001885 }
1886 }
1887 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001888
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001889 if(not $CheckHeadersOnly_Opt)
1890 {
1891 my $DObjects = parseTag(\$Content, "libs");
1892 if(not $DObjects) {
1893 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1894 }
1895 elsif(lc($DObjects) ne "none")
1896 { # append the descriptor libraries list
1897 if($Descriptor{$LibVersion}{"Libs"})
1898 { # multiple descriptors
1899 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1900 }
1901 else {
1902 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1903 }
1904 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1905 {
1906 if(not -e $Path) {
1907 exitStatus("Access_Error", "can't access \'$Path\'");
1908 }
1909 }
1910 }
1911 }
1912 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1913 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001914 if(not -d $Path) {
1915 exitStatus("Access_Error", "can't access directory \'$Path\'");
1916 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001917 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001918 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001919 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001920 }
1921 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1922 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001923 if(not -d $Path) {
1924 exitStatus("Access_Error", "can't access directory \'$Path\'");
1925 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001926 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001927 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001928 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001929 }
1930 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1931 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001932 if(not -d $Path) {
1933 exitStatus("Access_Error", "can't access directory \'$Path\'");
1934 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001935 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001936 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001937 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001938 $TargetTools{$Path}=1;
1939 }
1940 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1941 $CrossPrefix = $Prefix;
1942 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001943 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001944 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1945 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001946 if(not -d $Path) {
1947 exitStatus("Access_Error", "can't access directory \'$Path\'");
1948 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001949 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001950 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001951 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001952 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001953 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001954 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1955 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001956 if(not -d $Path) {
1957 exitStatus("Access_Error", "can't access directory \'$Path\'");
1958 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001959 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001960 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001961 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001962 }
1963 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001964 { # skip some auto-generated include paths
1965 if(not is_abs($Path))
1966 {
1967 if(my $P = abs_path($Path)) {
1968 $Path = $P;
1969 }
1970 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001971 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001972 }
1973 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001974 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001975 my ($CPath, $Type) = classifyPath($Path);
1976 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001977 }
1978 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001979 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1980 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001981 if($Option!~/\A\-(Wl|l|L)/)
1982 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001983 $CompilerOptions{$LibVersion} .= " ".$Option;
1984 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001985 }
1986 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1987 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1988 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001989 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001990
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001991 my ($CPath, $Type) = classifyPath($Path);
1992 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001993 }
1994 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1995 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1996 {
1997 my ($CPath, $Type) = classifyPath($Path);
1998 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1999 }
2000 if(my $DDefines = parseTag(\$Content, "defines"))
2001 {
2002 if($Descriptor{$LibVersion}{"Defines"})
2003 { # multiple descriptors
2004 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
2005 }
2006 else {
2007 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
2008 }
2009 }
2010 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
2011 {
2012 if($Order=~/\A(.+):(.+)\Z/) {
2013 $Include_Order{$LibVersion}{$1} = $2;
2014 }
2015 }
2016 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
2017 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002018 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002019 $SkipTypes{$LibVersion}{$Type_Name} = 1;
2020 }
2021 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
2022 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002023 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002024 $SkipSymbols{$LibVersion}{$Symbol} = 1;
2025 }
2026 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
2027 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
2028 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04002029 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
2030 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
2031 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002032 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
2033 $SkipConstants{$LibVersion}{$Constant} = 1;
2034 }
2035 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
2036 {
2037 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002038 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002039 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
2040 }
2041 else {
2042 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2043 }
2044 }
2045}
2046
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002047sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002048{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002049 my $CodeRef = shift(@_);
2050 my $Tag = shift(@_);
2051 if(not $Tag or not $CodeRef) {
2052 return undef;
2053 }
2054 my $Sp = 0;
2055 if(@_) {
2056 $Sp = shift(@_);
2057 }
2058 my $Start = index(${$CodeRef}, "<$Tag>");
2059 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002060 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002061 my $End = index(${$CodeRef}, "</$Tag>");
2062 if($End!=-1)
2063 {
2064 my $TS = length($Tag)+3;
2065 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2066 substr($Content, 0, $TS-1, ""); # cut start tag
2067 substr($Content, -$TS, $TS, ""); # cut end tag
2068 if(not $Sp)
2069 {
2070 $Content=~s/\A\s+//g;
2071 $Content=~s/\s+\Z//g;
2072 }
2073 if(substr($Content, 0, 1) ne "<") {
2074 $Content = xmlSpecChars_R($Content);
2075 }
2076 return $Content;
2077 }
2078 }
2079 return undef;
2080}
2081
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002082sub getInfo($)
2083{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002084 my $DumpPath = $_[0];
2085 return if(not $DumpPath or not -f $DumpPath);
2086
2087 readTUDump($DumpPath);
2088
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002089 # processing info
2090 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002091
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002092 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002093 setAnonTypedef_All();
2094 }
2095
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002096 getTypeInfo_All();
2097 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002098 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002099 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002100 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002101
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002102 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002103 %LibInfo = ();
2104 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002105 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002106 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002107 %TemplateDecl = ();
2108 %StdCxxTypedef = ();
2109 %MissedTypedef = ();
2110 %Typedef_Tr = ();
2111 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002112 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002113
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002114 # clean cache
2115 delete($Cache{"getTypeAttr"});
2116 delete($Cache{"getTypeDeclId"});
2117
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002118 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002119 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002120 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002121 }
2122 else
2123 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002124 if($BinaryOnly and not $ExtendedCheck)
2125 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002126 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002127 }
2128 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002129 remove_Unused($Version, "Extended");
2130 }
2131 }
2132
2133 if($CheckInfo)
2134 {
2135 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2136 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2137 }
2138
2139 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2140 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002141 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002142 }
2143
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002144 if($Debug) {
2145 # debugMangling($Version);
2146 }
2147}
2148
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002149sub readTUDump($)
2150{
2151 my $DumpPath = $_[0];
2152
2153 open(TU_DUMP, $DumpPath);
2154 local $/ = undef;
2155 my $Content = <TU_DUMP>;
2156 close(TU_DUMP);
2157
2158 unlink($DumpPath);
2159
2160 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002161 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002162
2163 # clean memory
2164 undef $Content;
2165
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002166 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002167
2168 foreach (0 .. $#Lines)
2169 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002170 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002171 { # get a number and attributes of a node
2172 next if(not $NodeType{$2});
2173 $LibInfo{$Version}{"info_type"}{$1}=$2;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03002174 $LibInfo{$Version}{"info"}{$1}=$3." ";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002175 }
2176
2177 # clean memory
2178 delete($Lines[$_]);
2179 }
2180
2181 # clean memory
2182 undef @Lines;
2183}
2184
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002185sub simplifyConstants()
2186{
2187 foreach my $Constant (keys(%{$Constants{$Version}}))
2188 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002189 if(defined $Constants{$Version}{$Constant}{"Header"})
2190 {
2191 my $Value = $Constants{$Version}{$Constant}{"Value"};
2192 if(defined $EnumConstants{$Version}{$Value}) {
2193 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2194 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002195 }
2196 }
2197}
2198
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002199sub simplifyNames()
2200{
2201 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2202 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002203 if($Typedef_Eq{$Version}{$Base}) {
2204 next;
2205 }
2206 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2207 if($#Translations==0)
2208 {
2209 if(length($Translations[0])<=length($Base)) {
2210 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2211 }
2212 }
2213 else
2214 { # select most appropriate
2215 foreach my $Tr (@Translations)
2216 {
2217 if($Base=~/\A\Q$Tr\E/)
2218 {
2219 $Typedef_Eq{$Version}{$Base} = $Tr;
2220 last;
2221 }
2222 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002223 }
2224 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002225 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002226 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002227 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002228 if(not $TypeName) {
2229 next;
2230 }
2231 next if(index($TypeName,"<")==-1);# template instances only
2232 if($TypeName=~/>(::\w+)+\Z/)
2233 { # skip unused types
2234 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002235 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002236 foreach my $Base (sort {length($b)<=>length($a)}
2237 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002238 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002239 next if(not $Base);
2240 next if(index($TypeName,$Base)==-1);
2241 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002242 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002243 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002244 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2245 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2246 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002247 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002248 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2249 {
2250 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2251 {
2252 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2253 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002254 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002255 }
2256 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002257 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002258 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002259 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002260 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002261 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2262 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002263 }
2264}
2265
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002266sub setAnonTypedef_All()
2267{
2268 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2269 {
2270 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2271 {
2272 if(isAnon(getNameByInfo($InfoId))) {
2273 $TypedefToAnon{getTypeId($InfoId)} = 1;
2274 }
2275 }
2276 }
2277}
2278
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002279sub setTemplateParams_All()
2280{
2281 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2282 {
2283 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2284 setTemplateParams($_);
2285 }
2286 }
2287}
2288
2289sub setTemplateParams($)
2290{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002291 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002292 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002293 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002294 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002295 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002296 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002297 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002298 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002299 setTemplateInstParams($_[0], $TmplInst_Id);
2300 }
2301 }
2302
2303 $BasicTemplate{$Version}{$Tid} = $_[0];
2304
2305 if(my $Prms = getTreeAttr_Prms($_[0]))
2306 {
2307 if(my $Valu = getTreeAttr_Valu($Prms))
2308 {
2309 my $Vector = getTreeVec($Valu);
2310 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2311 {
2312 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2313 {
2314 if(my $Name = getNameByInfo($Val))
2315 {
2316 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2317 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2318 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2319 }
2320 else {
2321 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2322 }
2323 }
2324 }
2325 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002326 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002327 }
2328 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002329 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002330 {
2331 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2332 {
2333 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002334 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002335 }
2336 }
2337 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002338}
2339
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002340sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002341{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002342 my ($Tmpl, $Inst) = @_;
2343
2344 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002345 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002346 my ($Params_InfoId, $ElemId) = ();
2347 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2348 $Params_InfoId = $1;
2349 }
2350 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2351 $ElemId = $1;
2352 }
2353 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002354 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002355 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2356 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2357 {
2358 my ($PPos, $PTypeId) = ($1, $2);
2359 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2360 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002361 if($PType eq "template_type_parm") {
2362 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002363 }
2364 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002365 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2366 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002367 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002368 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002369 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002370 else
2371 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002372 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002373 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002374 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002375 }
2376 }
2377 }
2378}
2379
2380sub getTypeDeclId($)
2381{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002382 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002383 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002384 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2385 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2386 }
2387 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2388 {
2389 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2390 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2391 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002392 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002393 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002394 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002395}
2396
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002397sub getTypeInfo_All()
2398{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002399 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002400 { # support for GCC < 4.5
2401 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2402 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2403 # FIXME: check GCC versions
2404 addMissedTypes_Pre();
2405 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002406
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002407 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002408 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002409 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2410 if($IType=~/_type\Z/ and $IType ne "function_type"
2411 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002412 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002413 }
2414 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002415
2416 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002417 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002418 "Name" => "...",
2419 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002420 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002421 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002422 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002423
2424 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002425 { # support for GCC < 4.5
2426 addMissedTypes_Post();
2427 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002428
2429 if($ADD_TMPL_INSTANCES)
2430 {
2431 # templates
2432 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2433 {
2434 if(defined $TemplateMap{$Version}{$Tid}
2435 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2436 {
2437 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2438 {
2439 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2440 {
2441 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2442 {
2443 if(my %MAttr = getTypeAttr($MembTypeId))
2444 {
2445 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2446 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2447 }
2448 }
2449 }
2450 }
2451 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2452 {
2453 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2454 {
2455 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2456
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002457 if($NBid ne $Bid
2458 and $NBid ne $Tid)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002459 {
2460 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2461 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2462 }
2463 }
2464 }
2465 }
2466 }
2467 }
2468}
2469
2470sub createType($$)
2471{
2472 my ($Attr, $LibVersion) = @_;
2473 my $NewId = ++$MAX_ID;
2474
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002475 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002476 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002477 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002478
2479 return "$NewId";
2480}
2481
2482sub instType($$$)
2483{ # create template instances
2484 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002485
2486 if(not $TypeInfo{$LibVersion}{$Tid}) {
2487 return undef;
2488 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002489 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2490
2491 foreach my $Key (sort keys(%{$Map}))
2492 {
2493 if(my $Val = $Map->{$Key})
2494 {
2495 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2496
2497 if(defined $Attr->{"NameSpace"}) {
2498 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2499 }
2500 foreach (keys(%{$Attr->{"TParam"}})) {
2501 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2502 }
2503 }
2504 else
2505 { # remove absent
2506 # _Traits, etc.
2507 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002508 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002509 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2510 }
2511 foreach (keys(%{$Attr->{"TParam"}}))
2512 {
2513 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2514 delete($Attr->{"TParam"}{$_});
2515 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002516 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002517 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2518 }
2519 }
2520 }
2521 }
2522
2523 my $Tmpl = 0;
2524
2525 if(defined $Attr->{"TParam"})
2526 {
2527 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2528 {
2529 my $PName = $Attr->{"TParam"}{$_}{"name"};
2530
2531 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2532 {
2533 my %Base = get_BaseType($PTid, $LibVersion);
2534
2535 if($Base{"Type"} eq "TemplateParam"
2536 or defined $Base{"Template"})
2537 {
2538 $Tmpl = 1;
2539 last
2540 }
2541 }
2542 }
2543 }
2544
2545 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2546 return "$Id";
2547 }
2548 else
2549 {
2550 if(not $Tmpl) {
2551 delete($Attr->{"Template"});
2552 }
2553
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002554 my $New = createType($Attr, $LibVersion);
2555
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002556 my %EMap = ();
2557 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2558 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2559 }
2560 foreach (keys(%{$Map})) {
2561 $EMap{$_} = $Map->{$_};
2562 }
2563
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002564 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2565 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002566 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002567 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002568 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002569 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002570 {
2571 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2572
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002573 if($NBid ne $Bid
2574 and $NBid ne $New)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002575 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002576 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2577 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002578 }
2579 }
2580 }
2581
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002582 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002583 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002584 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2585 {
2586 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2587 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2588 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002589 }
2590 }
2591
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002592 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002593 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002594 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2595 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002596 }
2597 }
2598
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002599 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2600 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002601 }
2602
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002603 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002604 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002605}
2606
2607sub addMissedTypes_Pre()
2608{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002609 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002610 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2611 { # detecting missed typedefs
2612 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2613 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002614 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002615 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002616 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002617 if($TypeType eq "Unknown")
2618 { # template_type_parm
2619 next;
2620 }
2621 my $TypeDeclId = getTypeDeclId($TypeId);
2622 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2623 my $TypedefName = getNameByInfo($MissedTDid);
2624 next if(not $TypedefName);
2625 next if($TypedefName eq "__float80");
2626 next if(isAnon($TypedefName));
2627 if(not $TypeDeclId
2628 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002629 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002630 }
2631 }
2632 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002633 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002634 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002635 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002636 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002637 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002638 next;
2639 }
2640 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002641 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002642 if(not $TypedefName) {
2643 next;
2644 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002645 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002646 my %MissedInfo = ( # typedef info
2647 "Name" => $TypedefName,
2648 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002649 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002650 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002651 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002652 my ($H, $L) = getLocation($MissedTDid);
2653 $MissedInfo{"Header"} = $H;
2654 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002655 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002656 { # other types
2657 next;
2658 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002659 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002660 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002661 next;
2662 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002663 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002664 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002665 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002666 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002667 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002668 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002669 next;
2670 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002671 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002672 next;
2673 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002674 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002675 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002676 next;
2677 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002678 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002679 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002680 next;
2681 }
2682 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002683
2684 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2685
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002686 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002687 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002688 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002689 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002690 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002691
2692 # add missed & remove other
2693 $TypeInfo{$Version} = \%AddTypes;
2694 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002695}
2696
2697sub addMissedTypes_Post()
2698{
2699 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2700 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002701 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2702 {
2703 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2704 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2705 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2706 }
2707 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002708 }
2709}
2710
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002711sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002712{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002713 my $TypeId = $_[0];
2714 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2715 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002716 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002717 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002718 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002719}
2720
2721sub getArraySize($$)
2722{
2723 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002724 if(my $Size = getSize($TypeId))
2725 {
2726 my $Elems = $Size/$BYTE_SIZE;
2727 while($BaseName=~s/\s*\[(\d+)\]//) {
2728 $Elems/=$1;
2729 }
2730 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2731 {
2732 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2733 $Elems/=$BasicSize;
2734 }
2735 }
2736 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002737 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002738 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002739}
2740
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002741sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002742{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002743 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002744 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002745 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2746 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002747 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002748 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2749 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2750 if(not $NodeType)
2751 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002752 return ();
2753 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002754 if($NodeType eq "tree_vec")
2755 {
2756 if($Pos!=$#Positions)
2757 { # select last vector of parameters ( ns<P1>::type<P2> )
2758 next;
2759 }
2760 }
2761 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2762 foreach my $P (@Params)
2763 {
2764 if($P eq "") {
2765 return ();
2766 }
2767 elsif($P ne "\@skip\@") {
2768 @TmplParams = (@TmplParams, $P);
2769 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002770 }
2771 }
2772 return @TmplParams;
2773}
2774
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002775sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002776{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002777 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002778 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002779 if(defined $TypeInfo{$Version}{$TypeId}
2780 and $TypeInfo{$Version}{$TypeId}{"Name"})
2781 { # already created
2782 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002783 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002784 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2785 { # incomplete type
2786 return ();
2787 }
2788 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2789
2790 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002791 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002792
2793 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2794 {
2795 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2796 {
2797 if($Info=~/qual[ ]*:/)
2798 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002799 my $NewId = ++$MAX_ID;
2800
2801 $MissedBase{$Version}{$TypeId} = "$NewId";
2802 $MissedBase_R{$Version}{$NewId} = $TypeId;
2803 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2804 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002805 }
2806 }
2807 $TypeAttr{"Type"} = "Typedef";
2808 }
2809 else {
2810 $TypeAttr{"Type"} = getTypeType($TypeId);
2811 }
2812
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002813 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2814 {
2815 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2816 { # local code
2817 return ();
2818 }
2819 }
2820
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002821 if($TypeAttr{"Type"} eq "Unknown") {
2822 return ();
2823 }
2824 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2825 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002826 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002827 if(my $TName = $TypeAttr{"Name"})
2828 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002829 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002830 $TName_Tid{$Version}{$TName} = $TypeId;
2831 return %TypeAttr;
2832 }
2833 else {
2834 return ();
2835 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002836 }
2837 elsif($TypeAttr{"Type"} eq "Array")
2838 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002839 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2840 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002841 return ();
2842 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002843 if(my $Algn = getAlgn($TypeId)) {
2844 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2845 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002846 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002847 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002848 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002849 if(not $BTAttr{"Name"}) {
2850 return ();
2851 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002852 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002853 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002854 if(my $Size = getSize($TypeId)) {
2855 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2856 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002857 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002858 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2859 }
2860 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002861 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002862 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002863 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002864 else
2865 {
2866 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002867 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002868 $TypeAttr{"Name"} = $1."[]".$2;
2869 }
2870 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002871 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002872 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002873 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002874 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002875 if($BTAttr{"Header"}) {
2876 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002877 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002878 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002879 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2880 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002881 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002882 return ();
2883 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002884 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002885 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002886 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002887 if($TypeAttr{"Name"})
2888 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002889 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002890
2891 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2892 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002893 { # NOTE: register only one int: with built-in decl
2894 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2895 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2896 }
2897 }
2898 return %TypeAttr;
2899 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002900 else {
2901 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002902 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002903 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002904 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2905 {
2906 %TypeAttr = getTrivialTypeAttr($TypeId);
2907 if($TypeAttr{"Name"})
2908 {
2909 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2910 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2911 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2912 }
2913 return %TypeAttr;
2914 }
2915 else {
2916 return ();
2917 }
2918 }
2919 elsif($TypeAttr{"Type"} eq "SizeOf")
2920 {
2921 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2922 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2923 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2924 if($TypeAttr{"Name"})
2925 {
2926 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2927 return %TypeAttr;
2928 }
2929 else {
2930 return ();
2931 }
2932 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002933 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002934 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002935 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2936 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002937 return ();
2938 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002939 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002940 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002941 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002942 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002943 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002944 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002945 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002946 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002947 }
2948 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002949 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002950 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002951 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002952 return ();
2953 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002954 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002955 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002956 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002957 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002958 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002959 }
2960 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002961 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002962 {
2963 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002964 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002965 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002966 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002967 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2968 }
2969 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002970 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002971 }
2972 }
2973 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002974 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002975 }
2976 if($TypeAttr{"Type"} eq "Typedef")
2977 {
2978 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002979
2980 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2981 return ();
2982 }
2983
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002984 if(isAnon($TypeAttr{"Name"}))
2985 { # anon typedef to anon type: ._N
2986 return ();
2987 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002988
2989 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2990 { # artificial typedef of "struct X" to "X"
2991 $TypeAttr{"Artificial"} = 1;
2992 }
2993
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002994 if(my $NS = getNameSpace($TypeDeclId))
2995 {
2996 my $TypeName = $TypeAttr{"Name"};
2997 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2998 { # "some_type" is the typedef to "struct some_type" in C++
2999 if($3) {
3000 $TypeAttr{"Name"} = $3."::".$TypeName;
3001 }
3002 }
3003 else
3004 {
3005 $TypeAttr{"NameSpace"} = $NS;
3006 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003007
3008 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
3009 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
3010 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003011 if($BTAttr{"NameSpace"}
3012 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003013 { # types like "std::fpos<__mbstate_t>" are
3014 # not covered by typedefs in the TU dump
3015 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003016 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3017 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003018 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003019 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003020 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003021 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003022 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003023 }
3024 }
3025 }
3026 }
3027 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003028 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003029 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003030 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003031 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
3032 { # typedef int*const TYPEDEF; // first
3033 # int foo(TYPEDEF p); // const is optimized out
3034 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
3035 if($BTAttr{"Name"}=~/</)
3036 {
3037 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
3038 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3039 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003040 }
3041 }
3042 }
3043 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
3044 }
3045 if(not $TypeAttr{"Size"})
3046 {
3047 if($TypeAttr{"Type"} eq "Pointer") {
3048 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3049 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003050 elsif($BTAttr{"Size"}) {
3051 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003052 }
3053 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003054 if(my $Algn = getAlgn($TypeId)) {
3055 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3056 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003057 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003058 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3059 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003060 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003061 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003062 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003063 { # typedef to "class Class"
3064 # should not be registered in TName_Tid
3065 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3066 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3067 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003068 }
3069 return %TypeAttr;
3070 }
3071}
3072
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003073sub getTreeVec($)
3074{
3075 my %Vector = ();
3076 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3077 {
3078 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3079 { # string length is N-1 because of the null terminator
3080 $Vector{$1} = $2;
3081 }
3082 }
3083 return \%Vector;
3084}
3085
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003086sub get_TemplateParam($$)
3087{
3088 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003089 return () if(not $Type_Id);
3090 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3091 return () if(not $NodeType);
3092 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003093 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003094 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003095 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003096 my $Num = getNodeIntCst($Type_Id);
3097 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003098 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003099 }
3100 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003101 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003102 }
3103 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003104 elsif($NodeType eq "string_cst") {
3105 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003106 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003107 elsif($NodeType eq "tree_vec")
3108 {
3109 my $Vector = getTreeVec($Type_Id);
3110 my @Params = ();
3111 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3112 {
3113 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3114 push(@Params, $P2);
3115 }
3116 }
3117 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003118 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003119 elsif($NodeType eq "parm_decl")
3120 {
3121 (getNameByInfo($Type_Id));
3122 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003123 else
3124 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003125 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003126 my $PName = $ParamAttr{"Name"};
3127 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003128 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003129 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003130 if($PName=~/\>/)
3131 {
3132 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003133 $PName = $Cover;
3134 }
3135 }
3136 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003137 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003138 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3139 # template<typename _Key, typename _Compare = std::less<_Key>
3140 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3141 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3142 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3143 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003144 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003145 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003146 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003147 }
3148}
3149
3150sub cover_stdcxx_typedef($)
3151{
3152 my $TypeName = $_[0];
3153 if(my @Covers = sort {length($a)<=>length($b)}
3154 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3155 { # take the shortest typedef
3156 # FIXME: there may be more than
3157 # one typedefs to the same type
3158 return $Covers[0];
3159 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003160 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003161 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3162 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3163 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003164 if(my $Cover = $Covers[0])
3165 {
3166 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3167 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3168 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003169 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003170 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003171}
3172
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003173sub getNodeIntCst($)
3174{
3175 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003176 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003177 if($EnumMembName_Id{$Version}{$CstId}) {
3178 return $EnumMembName_Id{$Version}{$CstId};
3179 }
3180 elsif((my $Value = getTreeValue($CstId)) ne "")
3181 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003182 if($Value eq "0")
3183 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003184 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003185 return "false";
3186 }
3187 else {
3188 return "0";
3189 }
3190 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003191 elsif($Value eq "1")
3192 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003193 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003194 return "true";
3195 }
3196 else {
3197 return "1";
3198 }
3199 }
3200 else {
3201 return $Value;
3202 }
3203 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003204 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003205}
3206
3207sub getNodeStrCst($)
3208{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003209 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3210 {
3211 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003212 {
3213 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3214 { # string length is N-1 because of the null terminator
3215 return substr($1, 0, $2-1);
3216 }
3217 else
3218 { # identifier_node
3219 return substr($1, 0, $2);
3220 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003221 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003222 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003223 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003224}
3225
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003226sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003227{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003228 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003229 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3230 if($Type eq "FieldPtr") {
3231 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3232 }
3233 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3234 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003235 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003236 if($Type eq "MethodPtr")
3237 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003238 if(my $Size = getSize($TypeId))
3239 {
3240 $Size/=$BYTE_SIZE;
3241 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003242 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003243 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003244 if(my $Algn = getAlgn($TypeId)) {
3245 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3246 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003247 # Return
3248 if($Type eq "FieldPtr")
3249 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003250 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003251 if($ReturnAttr{"Name"}) {
3252 $MemPtrName .= $ReturnAttr{"Name"};
3253 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003254 $TypeAttr{"Return"} = $PtrId;
3255 }
3256 else
3257 {
3258 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3259 {
3260 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003261 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3262 if(not $ReturnAttr{"Name"})
3263 { # templates
3264 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003265 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003266 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003267 $TypeAttr{"Return"} = $ReturnTypeId;
3268 }
3269 }
3270 # Class
3271 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3272 {
3273 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003274 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003275 if($Class{"Name"}) {
3276 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3277 }
3278 else {
3279 $MemPtrName .= " (*)";
3280 }
3281 }
3282 else {
3283 $MemPtrName .= " (*)";
3284 }
3285 # Parameters
3286 if($Type eq "FuncPtr"
3287 or $Type eq "MethodPtr")
3288 {
3289 my @ParamTypeName = ();
3290 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3291 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003292 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003293 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003294 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003295 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003296 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3297 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003298 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003299 my $PTypeId = $1;
3300 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003301 if(not $ParamAttr{"Name"})
3302 { # templates (template_type_parm), etc.
3303 return ();
3304 }
3305 if($ParamAttr{"Name"} eq "void") {
3306 last;
3307 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003308 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003309 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003310 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003311 push(@ParamTypeName, $ParamAttr{"Name"});
3312 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003313 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3314 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003315 }
3316 else {
3317 last;
3318 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003319 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003320 else {
3321 last;
3322 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003323 }
3324 }
3325 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3326 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003327 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003328 return %TypeAttr;
3329}
3330
3331sub getTreeTypeName($)
3332{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003333 my $TypeId = $_[0];
3334 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003335 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003336 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003337 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003338 if(my $Name = getNameByInfo($TypeId))
3339 { # bit_size_type
3340 return $Name;
3341 }
3342 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003343 return "unsigned int";
3344 }
3345 else {
3346 return "int";
3347 }
3348 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003349 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003350 return getNameByInfo($1);
3351 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003352 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003353 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003354}
3355
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003356sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003357{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003358 my $Ptd = pointTo($_[0]);
3359 return 0 if(not $Ptd);
3360 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003361 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003362 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3363 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003364 }
3365 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003366 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3367 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003368 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003369 if($InfoT1 eq "pointer_type"
3370 and $InfoT2 eq "function_type") {
3371 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003372 }
3373 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003374 return 0;
3375}
3376
3377sub isMethodPtr($)
3378{
3379 my $Ptd = pointTo($_[0]);
3380 return 0 if(not $Ptd);
3381 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3382 {
3383 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3384 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3385 and $Info=~/ ptrmem /) {
3386 return 1;
3387 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003388 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003389 return 0;
3390}
3391
3392sub isFieldPtr($)
3393{
3394 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3395 {
3396 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3397 and $Info=~/ ptrmem /) {
3398 return 1;
3399 }
3400 }
3401 return 0;
3402}
3403
3404sub pointTo($)
3405{
3406 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3407 {
3408 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3409 return $1;
3410 }
3411 }
3412 return "";
3413}
3414
3415sub getTypeTypeByTypeId($)
3416{
3417 my $TypeId = $_[0];
3418 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3419 {
3420 my $NType = $NodeType{$TType};
3421 if($NType eq "Intrinsic") {
3422 return $NType;
3423 }
3424 elsif(isFuncPtr($TypeId)) {
3425 return "FuncPtr";
3426 }
3427 elsif(isMethodPtr($TypeId)) {
3428 return "MethodPtr";
3429 }
3430 elsif(isFieldPtr($TypeId)) {
3431 return "FieldPtr";
3432 }
3433 elsif($NType ne "Other") {
3434 return $NType;
3435 }
3436 }
3437 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003438}
3439
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003440my %UnQual = (
3441 "r"=>"restrict",
3442 "v"=>"volatile",
3443 "c"=>"const",
3444 "cv"=>"const volatile"
3445);
3446
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003447sub getQual($)
3448{
3449 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003450 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3451 {
3452 my ($Qual, $To) = ();
3453 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3454 $Qual = $UnQual{$1};
3455 }
3456 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3457 $To = $1;
3458 }
3459 if($Qual and $To) {
3460 return ($Qual, $To);
3461 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003462 }
3463 return ();
3464}
3465
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003466sub getQualType($)
3467{
3468 if($_[0] eq "const volatile") {
3469 return "ConstVolatile";
3470 }
3471 return ucfirst($_[0]);
3472}
3473
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003474sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003475{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003476 my $TypeId = $_[0];
3477 my $TypeDeclId = getTypeDeclId($TypeId);
3478 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003479 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003480 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3481 return "Typedef";
3482 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003483 }
3484 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3485 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003486 if(($Qual or $To) and $TypeDeclId
3487 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003488 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003489 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003490 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003491 elsif(not $MissedBase_R{$Version}{$TypeId}
3492 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003493 return "Typedef";
3494 }
3495 elsif($Qual)
3496 { # qualified types
3497 return getQualType($Qual);
3498 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003499
3500 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3501 { # typedef struct { ... } name
3502 $TypeTypedef{$Version}{$TypeId} = $1;
3503 }
3504
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003505 my $TypeType = getTypeTypeByTypeId($TypeId);
3506 if($TypeType eq "Struct")
3507 {
3508 if($TypeDeclId
3509 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3510 return "Template";
3511 }
3512 }
3513 return $TypeType;
3514}
3515
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003516sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003517{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003518 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003519 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003520 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3521 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3522 return 0;
3523 }
3524 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3525 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003526 if(my $TDid = getTypeDeclId($_[0]))
3527 {
3528 if(getTypeId($TDid) eq $_[0]
3529 and getNameByInfo($TDid))
3530 {
3531 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3532 return $1;
3533 }
3534 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003535 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003536 }
3537 }
3538 return 0;
3539}
3540
3541sub selectBaseType($)
3542{
3543 my $TypeId = $_[0];
3544 if(defined $MissedTypedef{$Version}{$TypeId})
3545 { # add missed typedefs
3546 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3547 return ($TypeId, "");
3548 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003549 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003550 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3551 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003552
3553 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3554 my $MB = $MissedBase{$Version}{$TypeId};
3555
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003556 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003557 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003558 and (getTypeId($1) ne $TypeId)
3559 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003560 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003561 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003562 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003563 elsif($MB)
3564 { # add base
3565 return ($MB, "");
3566 }
3567 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003568 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003569 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003570 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003571 elsif($Qual or $To)
3572 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003573 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003574 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003575 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003576 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003577 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003578 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003579 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003580 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003581 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003582 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003583 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003584 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003585 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003586 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003587 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003588 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003589 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003590 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003591 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003592 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003593
3594 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003595}
3596
3597sub getSymbolInfo_All()
3598{
3599 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3600 { # reverse order
3601 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003602 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003603 }
3604 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003605
3606 if($ADD_TMPL_INSTANCES)
3607 {
3608 # templates
3609 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3610 {
3611 my %Map = ();
3612
3613 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3614 {
3615 if(defined $TemplateMap{$Version}{$ClassId})
3616 {
3617 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3618 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3619 }
3620 }
3621 }
3622
3623 if(defined $TemplateMap{$Version}{$Sid})
3624 {
3625 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3626 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3627 }
3628 }
3629
3630 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3631 {
3632 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3633 {
3634 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3635 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3636 }
3637 }
3638 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3639 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3640 }
3641 }
3642 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003643}
3644
3645sub getVarInfo_All()
3646{
3647 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3648 { # reverse order
3649 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003650 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003651 }
3652 }
3653}
3654
3655sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003656 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003657}
3658
3659sub getVarInfo($)
3660{
3661 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003662 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003663 {
3664 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3665 if($NSInfoType and $NSInfoType eq "function_decl") {
3666 return;
3667 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003668 }
3669 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3670 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3671 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3672 delete($SymbolInfo{$Version}{$InfoId});
3673 return;
3674 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003675 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003676 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003677 delete($SymbolInfo{$Version}{$InfoId});
3678 return;
3679 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003680 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3681 delete($SymbolInfo{$Version}{$InfoId});
3682 return;
3683 }
3684 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003685 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3686 {
3687 if($OSgroup eq "windows")
3688 { # cut the offset
3689 $MnglName=~s/\@\d+\Z//g;
3690 }
3691 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003693 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003694 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003695 { # validate mangled name
3696 delete($SymbolInfo{$Version}{$InfoId});
3697 return;
3698 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003699 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003700 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003701 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003702 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003703 }
3704 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3705 { # non-public global data
3706 delete($SymbolInfo{$Version}{$InfoId});
3707 return;
3708 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003709 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003710 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003711 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003712 if(not defined $TypeInfo{$Version}{$Rid}
3713 or not $TypeInfo{$Version}{$Rid}{"Name"})
3714 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003715 delete($SymbolInfo{$Version}{$InfoId});
3716 return;
3717 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003718 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3719 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003720 if(defined $Val) {
3721 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3722 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003723 }
3724 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003725 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3726 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003727 if(not defined $TypeInfo{$Version}{$ClassId}
3728 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3729 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003730 delete($SymbolInfo{$Version}{$InfoId});
3731 return;
3732 }
3733 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003734 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3735 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003736 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003737 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003738 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003739 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003740 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003741 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003742 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003743 if(not $CheckHeadersOnly)
3744 {
3745 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3746 {
3747 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3748 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3749 {
3750 if(link_symbol($ShortName, $Version, "-Deps"))
3751 { # "const" global data is mangled as _ZL... in the TU dump
3752 # but not mangled when compiling a C shared library
3753 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3754 }
3755 }
3756 }
3757 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003758 if($COMMON_LANGUAGE{$Version} eq "C++")
3759 {
3760 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3761 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003762 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003763 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3764 }
3765 }
3766 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3767 { # try to mangle symbol (link with libraries)
3768 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3769 }
3770 if($OStarget eq "windows")
3771 {
3772 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3773 { # link MS C++ symbols from library with GCC symbols from headers
3774 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3775 }
3776 }
3777 }
3778 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3779 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3780 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003781 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3782 {
3783 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3784 { # non-target symbols
3785 delete($SymbolInfo{$Version}{$InfoId});
3786 return;
3787 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003788 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003789 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3790 {
3791 if(defined $MissedTypedef{$Version}{$Rid})
3792 {
3793 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3794 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3795 }
3796 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003797 }
3798 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003799 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003800 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3801 }
3802 if($ShortName=~/\A(_Z|\?)/) {
3803 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3804 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003805
3806 if($ExtraDump) {
3807 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3808 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003809}
3810
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003811sub isConstType($$)
3812{
3813 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003814 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003815 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003816 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003817 }
3818 return ($Base{"Type"} eq "Const");
3819}
3820
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003821sub getTrivialName($$)
3822{
3823 my ($TypeInfoId, $TypeId) = @_;
3824 my %TypeAttr = ();
3825 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3826 if(not $TypeAttr{"Name"}) {
3827 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3828 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003829 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003830 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003831 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003832 if(isAnon($TypeAttr{"Name"}))
3833 {
3834 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003835 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003836 { # searching for a first not anon scope
3837 if($NSId eq $NameSpaceId) {
3838 last;
3839 }
3840 else
3841 {
3842 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3843 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003844 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003845 last;
3846 }
3847 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003848 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003849 }
3850 }
3851 else
3852 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003853 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003854 {
3855 if($NameSpaceId ne $TypeId) {
3856 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3857 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003858 }
3859 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003860 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003861 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3862 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003863 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003864 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003865 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003866 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003867 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003868 if($TypeAttr{"NameSpace"}) {
3869 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3870 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003871 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003872 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3873 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003874 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003875 if(my @TParams = getTParams($TypeId, "Type")) {
3876 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3877 }
3878 else {
3879 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3880 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003881 }
3882 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3883}
3884
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003885sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003886{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003887 my $TypeId = $_[0];
3888 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003889
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003890 my %TypeAttr = ();
3891
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003892 if($TemplateDecl{$Version}{$TypeId})
3893 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003894 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003895 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003896
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003897 setTypeAccess($TypeId, \%TypeAttr);
3898 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3899 if(isBuiltIn($TypeAttr{"Header"}))
3900 {
3901 delete($TypeAttr{"Header"});
3902 delete($TypeAttr{"Line"});
3903 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003904
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003905 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003906 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3907 if(not $TypeAttr{"Name"}) {
3908 return ();
3909 }
3910 if(not $TypeAttr{"NameSpace"}) {
3911 delete($TypeAttr{"NameSpace"});
3912 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003913
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003914 if($TypeAttr{"Type"} eq "Intrinsic")
3915 {
3916 if(defined $TypeAttr{"Header"})
3917 {
3918 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3919 { # support for SUSE 11.2
3920 # integer_type has srcp dump{1-2}.i
3921 delete($TypeAttr{"Header"});
3922 }
3923 }
3924 }
3925
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003926 my $Tmpl = undef;
3927
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003928 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003929 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003930 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3931
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003932 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003933 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003934 foreach my $Pos (0 .. $#TParams)
3935 {
3936 my $Val = $TParams[$Pos];
3937 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3938
3939 if(not defined $TypeAttr{"Template"})
3940 {
3941 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3942
3943 if($Base{"Type"} eq "TemplateParam"
3944 or defined $Base{"Template"}) {
3945 $TypeAttr{"Template"} = 1;
3946 }
3947 }
3948
3949 if($Tmpl)
3950 {
3951 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3952 {
3953 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3954
3955 if($Val eq $Arg) {
3956 $TypeAttr{"Template"} = 1;
3957 }
3958 }
3959 }
3960 }
3961
3962 if($Tmpl)
3963 {
3964 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3965 {
3966 if($Pos>$#TParams)
3967 {
3968 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3969 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3970 }
3971 }
3972 }
3973 }
3974
3975 if($ADD_TMPL_INSTANCES)
3976 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003977 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003978 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003979 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003980 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003981 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003982 {
3983 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3984 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3985 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003986 }
3987 if(not getTreeAttr_Binf($TypeId))
3988 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003989 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3990 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3991 }
3992 }
3993 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003994 }
3995 }
3996 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003997
3998 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3999
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004000 if(my $Size = getSize($TypeId))
4001 {
4002 $Size = $Size/$BYTE_SIZE;
4003 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004004 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004005 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004006 {
4007 if($ExtraDump)
4008 {
4009 if(not defined $TypeAttr{"Memb"}
4010 and not $Tmpl)
4011 { # declaration only
4012 $TypeAttr{"Forward"} = 1;
4013 }
4014 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004015 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004016
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004017 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004018 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004019 {
4020 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004021 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004022 }
4023 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004024 or $TypeAttr{"Type"} eq "Class")
4025 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004026 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004027 if($Skip) {
4028 return ();
4029 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004030 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004031 if(my $Algn = getAlgn($TypeId)) {
4032 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
4033 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004034 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004035
4036 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
4037 {
4038 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004039 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004040 {
4041 if(not isAnon($TypeAttr{"Name"})) {
4042 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
4043 }
4044 }
4045 }
4046
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004047 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004048 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4049 {
4050 my @Entries = split(/\n/, $VTable);
4051 foreach (1 .. $#Entries)
4052 {
4053 my $Entry = $Entries[$_];
4054 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004055 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004056 }
4057 }
4058 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004059
4060 if($TypeAttr{"Type"} eq "Enum")
4061 {
4062 if(not $TypeAttr{"NameSpace"})
4063 {
4064 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4065 {
4066 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004067 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004068 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004069 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004070 "Header"=>$TypeAttr{"Header"}
4071 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004072 if(isAnon($TypeAttr{"Name"}))
4073 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004074 if($ExtraDump
4075 or is_target_header($TypeAttr{"Header"}, $Version))
4076 {
4077 %{$Constants{$Version}{$MName}} = (
4078 "Value" => $MVal,
4079 "Header" => $TypeAttr{"Header"}
4080 );
4081 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004082 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004083 }
4084 }
4085 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004086 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004087 {
4088 if(defined $TypedefToAnon{$TypeId}) {
4089 $TypeAttr{"AnonTypedef"} = 1;
4090 }
4091 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004092
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004093 return %TypeAttr;
4094}
4095
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004096sub simplifyVTable($)
4097{
4098 my $Content = $_[0];
4099 if($Content=~s/ \[with (.+)]//)
4100 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4101 if(my @Elems = separate_Params($1, 0, 0))
4102 {
4103 foreach my $Elem (@Elems)
4104 {
4105 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4106 {
4107 my ($Arg, $Val) = ($1, $2);
4108
4109 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4110 $Content=~s/,\s*$Arg\b//g;
4111 }
4112 else {
4113 $Content=~s/\b$Arg\b/$Val/g;
4114 }
4115 }
4116 }
4117 }
4118 }
4119
4120 return $Content;
4121}
4122
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004123sub detect_lang($)
4124{
4125 my $TypeId = $_[0];
4126 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004127 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004128 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004129 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4130 }
4131 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004132 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004133 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004134 while($Fncs)
4135 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004136 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004137 return 1;
4138 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004139 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004140 }
4141 }
4142 return 0;
4143}
4144
4145sub setSpec($$)
4146{
4147 my ($TypeId, $TypeAttr) = @_;
4148 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4149 if($Info=~/\s+spec\s+/) {
4150 $TypeAttr->{"Spec"} = 1;
4151 }
4152}
4153
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004154sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004155{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004156 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004157 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004158 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004159 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004160 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004161 my $Pos = 0;
4162 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4163 {
4164 my ($Access, $BInfoId) = ($1, $2);
4165 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004166
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03004167 if($ClassId eq $TypeId)
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004168 { # class A<N>:public A<N-1>
4169 next;
4170 }
4171
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004172 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4173 if(not $CType or $CType eq "template_type_parm"
4174 or $CType eq "typename_type")
4175 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004176 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004177 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004178 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004179 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004180 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4181 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004182 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004183 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4184 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004185 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004186 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004187 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004188 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4189 }
4190 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004191 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004192 }
4193 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004194 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004195}
4196
4197sub getBinfClassId($)
4198{
4199 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03004200 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
4201 return $1;
4202 }
4203
4204 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004205}
4206
4207sub unmangledFormat($$)
4208{
4209 my ($Name, $LibVersion) = @_;
4210 $Name = uncover_typedefs($Name, $LibVersion);
4211 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4212 $Name=~s/\(\w+\)(\d)/$1/;
4213 return $Name;
4214}
4215
4216sub modelUnmangled($$)
4217{
4218 my ($InfoId, $Compiler) = @_;
4219 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4220 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4221 }
4222 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4223 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4224 $PureSignature = "~".$PureSignature;
4225 }
4226 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4227 {
4228 my (@Params, @ParamTypes) = ();
4229 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4230 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4231 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4232 }
4233 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4234 { # checking parameters
4235 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004236 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004237 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004238 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004239
4240 if($PName eq "this"
4241 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4242 {
4243 next;
4244 }
4245
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004246 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004247 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004248 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004249 }
4250 @ParamTypes = (@ParamTypes, $PTName);
4251 }
4252 if(@ParamTypes) {
4253 $PureSignature .= "(".join(", ", @ParamTypes).")";
4254 }
4255 else
4256 {
4257 if($Compiler eq "MSVC")
4258 {
4259 $PureSignature .= "(void)";
4260 }
4261 else
4262 { # GCC
4263 $PureSignature .= "()";
4264 }
4265 }
4266 $PureSignature = delete_keywords($PureSignature);
4267 }
4268 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4269 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004270 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004271 $PureSignature = $ClassName."::".$PureSignature;
4272 }
4273 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4274 $PureSignature = $NS."::".$PureSignature;
4275 }
4276 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4277 $PureSignature .= " const";
4278 }
4279 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4280 $PureSignature .= " volatile";
4281 }
4282 my $ShowReturn = 0;
4283 if($Compiler eq "MSVC"
4284 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4285 {
4286 $ShowReturn=1;
4287 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004288 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4289 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004290 {
4291 $ShowReturn=1;
4292 }
4293 if($ShowReturn)
4294 { # mangled names for template function specializations include return value
4295 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4296 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004297 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004298 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4299 $PureSignature = $ReturnName." ".$PureSignature;
4300 }
4301 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004302 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004303}
4304
4305sub mangle_symbol($$$)
4306{ # mangling for simple methods
4307 # see gcc-4.6.0/gcc/cp/mangle.c
4308 my ($InfoId, $LibVersion, $Compiler) = @_;
4309 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4310 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4311 }
4312 my $Mangled = "";
4313 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004314 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004315 }
4316 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004317 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004318 }
4319 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4320}
4321
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004322sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004323{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004324 my ($InfoId, $LibVersion) = @_;
4325 return "";
4326}
4327
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004328sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004329{ # see gcc-4.6.0/gcc/cp/mangle.c
4330 my ($InfoId, $LibVersion) = @_;
4331 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004332 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004333 my %Repl = ();# SN_ replacements
4334 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4335 {
4336 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4337 if($MangledClass!~/\AN/) {
4338 $MangledClass = "N".$MangledClass;
4339 }
4340 else {
4341 $MangledClass=~s/E\Z//;
4342 }
4343 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4344 $MangledClass=~s/\AN/NV/;
4345 }
4346 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4347 $MangledClass=~s/\AN/NK/;
4348 }
4349 $Mangled .= $MangledClass;
4350 }
4351 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4352 { # mangled by name due to the absence of structured info
4353 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4354 if($MangledNS!~/\AN/) {
4355 $MangledNS = "N".$MangledNS;
4356 }
4357 else {
4358 $MangledNS=~s/E\Z//;
4359 }
4360 $Mangled .= $MangledNS;
4361 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004362 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004363 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004364 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004365 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004366 foreach (@TPos) {
4367 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4368 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004369 }
4370 elsif($TmplParams)
4371 { # remangling mode
4372 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004373 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004374 }
4375 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4376 $Mangled .= "C1";
4377 }
4378 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4379 $Mangled .= "D0";
4380 }
4381 elsif($ShortName)
4382 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004383 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4384 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004385 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004386 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004387 { # "const" global data is mangled as _ZL...
4388 $Mangled .= "L";
4389 }
4390 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004391 if($ShortName=~/\Aoperator(\W.*)\Z/)
4392 {
4393 my $Op = $1;
4394 $Op=~s/\A[ ]+//g;
4395 if(my $OpMngl = $OperatorMangling{$Op}) {
4396 $Mangled .= $OpMngl;
4397 }
4398 else { # conversion operator
4399 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4400 }
4401 }
4402 else {
4403 $Mangled .= length($ShortName).$ShortName;
4404 }
4405 if(@TParams)
4406 { # templates
4407 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004408 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004409 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4410 }
4411 $Mangled .= "E";
4412 }
4413 if(not $ClassId and @TParams) {
4414 add_substitution($ShortName, \%Repl, 0);
4415 }
4416 }
4417 if($ClassId or $NameSpace) {
4418 $Mangled .= "E";
4419 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004420 if(@TParams)
4421 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004422 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004423 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4424 }
4425 }
4426 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4427 {
4428 my @Params = ();
4429 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4430 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4431 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4432 }
4433 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4434 { # checking parameters
4435 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4436 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4437 }
4438 if(not @Params) {
4439 $Mangled .= "v";
4440 }
4441 }
4442 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4443 $Mangled = write_stdcxx_substitution($Mangled);
4444 if($Mangled eq "_Z") {
4445 return "";
4446 }
4447 return $Mangled;
4448}
4449
4450sub correct_incharge($$$)
4451{
4452 my ($InfoId, $LibVersion, $Mangled) = @_;
4453 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4454 {
4455 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004456 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004457 }
4458 }
4459 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4460 {
4461 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004462 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004463 }
4464 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004465 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004466 }
4467 }
4468 return $Mangled;
4469}
4470
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004471sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004472{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004473 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004474 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004475 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004476 return $Name;
4477 }
4478 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004479 while(my $CPos = find_center($TParams, "<"))
4480 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004481 $TParams = substr($TParams, $CPos);
4482 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004483 if($TParams=~s/\A<(.+)>\Z/$1/) {
4484 $Name=~s/<\Q$TParams\E>\Z//;
4485 }
4486 else
4487 { # error
4488 $TParams = "";
4489 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004490 return ($Name, $TParams);
4491}
4492
4493sub get_sub_ns($)
4494{
4495 my $Name = $_[0];
4496 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004497 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004498 {
4499 push(@NS, substr($Name, 0, $CPos));
4500 $Name = substr($Name, $CPos);
4501 $Name=~s/\A:://;
4502 }
4503 return (join("::", @NS), $Name);
4504}
4505
4506sub mangle_ns($$$)
4507{
4508 my ($Name, $LibVersion, $Repl) = @_;
4509 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4510 {
4511 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4512 $Mangled=~s/\AN(.+)E\Z/$1/;
4513 return $Mangled;
4514
4515 }
4516 else
4517 {
4518 my ($MangledNS, $SubNS) = ("", "");
4519 ($SubNS, $Name) = get_sub_ns($Name);
4520 if($SubNS) {
4521 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4522 }
4523 $MangledNS .= length($Name).$Name;
4524 add_substitution($MangledNS, $Repl, 0);
4525 return $MangledNS;
4526 }
4527}
4528
4529sub mangle_param($$$)
4530{
4531 my ($PTid, $LibVersion, $Repl) = @_;
4532 my ($MPrefix, $Mangled) = ("", "");
4533 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004534 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004535 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004536 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004537 if(not $BaseType_Name) {
4538 return "";
4539 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004540 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004541 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004542 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4543 while($Suffix=~/(&|\*|const)\Z/)
4544 {
4545 if($Suffix=~s/[ ]*&\Z//) {
4546 $MPrefix .= "R";
4547 }
4548 if($Suffix=~s/[ ]*\*\Z//) {
4549 $MPrefix .= "P";
4550 }
4551 if($Suffix=~s/[ ]*const\Z//)
4552 {
4553 if($MPrefix=~/R|P/
4554 or $Suffix=~/&|\*/) {
4555 $MPrefix .= "K";
4556 }
4557 }
4558 if($Suffix=~s/[ ]*volatile\Z//) {
4559 $MPrefix .= "V";
4560 }
4561 #if($Suffix=~s/[ ]*restrict\Z//) {
4562 #$MPrefix .= "r";
4563 #}
4564 }
4565 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4566 $Mangled .= $Token;
4567 }
4568 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4569 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004570 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004571 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004572 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004573 foreach (@TPos) {
4574 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4575 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004576 }
4577 elsif($TmplParams)
4578 { # remangling mode
4579 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004580 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004581 }
4582 my $MangledNS = "";
4583 my ($SubNS, $SName) = get_sub_ns($ShortName);
4584 if($SubNS) {
4585 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4586 }
4587 $MangledNS .= length($SName).$SName;
4588 if(@TParams) {
4589 add_substitution($MangledNS, $Repl, 0);
4590 }
4591 $Mangled .= "N".$MangledNS;
4592 if(@TParams)
4593 { # templates
4594 $Mangled .= "I";
4595 foreach my $TParam (@TParams) {
4596 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4597 }
4598 $Mangled .= "E";
4599 }
4600 $Mangled .= "E";
4601 }
4602 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4603 {
4604 if($BaseType{"Type"} eq "MethodPtr") {
4605 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4606 }
4607 else {
4608 $Mangled .= "PF";
4609 }
4610 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4611 my @Params = keys(%{$BaseType{"Param"}});
4612 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4613 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4614 }
4615 if(not @Params) {
4616 $Mangled .= "v";
4617 }
4618 $Mangled .= "E";
4619 }
4620 elsif($BaseType{"Type"} eq "FieldPtr")
4621 {
4622 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4623 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4624 }
4625 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4626 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4627 {
4628 if($Mangled eq $Optimized)
4629 {
4630 if($ShortName!~/::/)
4631 { # remove "N ... E"
4632 if($MPrefix) {
4633 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4634 }
4635 else {
4636 $Mangled=~s/\AN(.+)E\Z/$1/g;
4637 }
4638 }
4639 }
4640 else {
4641 $Mangled = $Optimized;
4642 }
4643 }
4644 add_substitution($Mangled, $Repl, 1);
4645 return $Mangled;
4646}
4647
4648sub mangle_template_param($$$)
4649{ # types + literals
4650 my ($TParam, $LibVersion, $Repl) = @_;
4651 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4652 return mangle_param($TPTid, $LibVersion, $Repl);
4653 }
4654 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4655 { # class_name<1u>::method(...)
4656 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4657 }
4658 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4659 { # class_name<(signed char)1>::method(...)
4660 return "L".$IntrinsicMangling{$1}.$2."E";
4661 }
4662 elsif($TParam eq "true")
4663 { # class_name<true>::method(...)
4664 return "Lb1E";
4665 }
4666 elsif($TParam eq "false")
4667 { # class_name<true>::method(...)
4668 return "Lb0E";
4669 }
4670 else { # internal error
4671 return length($TParam).$TParam;
4672 }
4673}
4674
4675sub add_substitution($$$)
4676{
4677 my ($Value, $Repl, $Rec) = @_;
4678 if($Rec)
4679 { # subtypes
4680 my @Subs = ($Value);
4681 while($Value=~s/\A(R|P|K)//) {
4682 push(@Subs, $Value);
4683 }
4684 foreach (reverse(@Subs)) {
4685 add_substitution($_, $Repl, 0);
4686 }
4687 return;
4688 }
4689 return if($Value=~/\AS(\d*)_\Z/);
4690 $Value=~s/\AN(.+)E\Z/$1/g;
4691 return if(defined $Repl->{$Value});
4692 return if(length($Value)<=1);
4693 return if($StdcxxMangling{$Value});
4694 # check for duplicates
4695 my $Base = $Value;
4696 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4697 {
4698 my $Num = $Repl->{$Type};
4699 my $Replace = macro_mangle($Num);
4700 $Base=~s/\Q$Replace\E/$Type/;
4701 }
4702 if(my $OldNum = $Repl->{$Base})
4703 {
4704 $Repl->{$Value} = $OldNum;
4705 return;
4706 }
4707 my @Repls = sort {$b<=>$a} values(%{$Repl});
4708 if(@Repls) {
4709 $Repl->{$Value} = $Repls[0]+1;
4710 }
4711 else {
4712 $Repl->{$Value} = -1;
4713 }
4714 # register duplicates
4715 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004716 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004717 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4718 {
4719 next if($Base eq $Type);
4720 my $Num = $Repl->{$Type};
4721 my $Replace = macro_mangle($Num);
4722 $Base=~s/\Q$Type\E/$Replace/;
4723 $Repl->{$Base} = $Repl->{$Value};
4724 }
4725}
4726
4727sub macro_mangle($)
4728{
4729 my $Num = $_[0];
4730 if($Num==-1) {
4731 return "S_";
4732 }
4733 else
4734 {
4735 my $Code = "";
4736 if($Num<10)
4737 { # S0_, S1_, S2_, ...
4738 $Code = $Num;
4739 }
4740 elsif($Num>=10 and $Num<=35)
4741 { # SA_, SB_, SC_, ...
4742 $Code = chr(55+$Num);
4743 }
4744 else
4745 { # S10_, S11_, S12_
4746 $Code = $Num-26; # 26 is length of english alphabet
4747 }
4748 return "S".$Code."_";
4749 }
4750}
4751
4752sub write_stdcxx_substitution($)
4753{
4754 my $Mangled = $_[0];
4755 if($StdcxxMangling{$Mangled}) {
4756 return $StdcxxMangling{$Mangled};
4757 }
4758 else
4759 {
4760 my @Repls = keys(%StdcxxMangling);
4761 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4762 foreach my $MangledType (@Repls)
4763 {
4764 my $Replace = $StdcxxMangling{$MangledType};
4765 #if($Mangled!~/$Replace/) {
4766 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4767 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4768 #}
4769 }
4770 }
4771 return $Mangled;
4772}
4773
4774sub write_substitution($$)
4775{
4776 my ($Mangled, $Repl) = @_;
4777 if(defined $Repl->{$Mangled}
4778 and my $MnglNum = $Repl->{$Mangled}) {
4779 $Mangled = macro_mangle($MnglNum);
4780 }
4781 else
4782 {
4783 my @Repls = keys(%{$Repl});
4784 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4785 # FIXME: how to apply replacements? by num or by pos
4786 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4787 foreach my $MangledType (@Repls)
4788 {
4789 my $Replace = macro_mangle($Repl->{$MangledType});
4790 if($Mangled!~/$Replace/) {
4791 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4792 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4793 }
4794 }
4795 }
4796 return $Mangled;
4797}
4798
4799sub delete_keywords($)
4800{
4801 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004802 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004803 return $TypeName;
4804}
4805
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004806sub uncover_typedefs($$)
4807{
4808 my ($TypeName, $LibVersion) = @_;
4809 return "" if(not $TypeName);
4810 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4811 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4812 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004813 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004814 while($TypeName_New ne $TypeName_Pre)
4815 {
4816 $TypeName_Pre = $TypeName_New;
4817 my $TypeName_Copy = $TypeName_New;
4818 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004819 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004820 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004821 if(not $Intrinsic_Keywords{$1}) {
4822 $Words{$1} = 1;
4823 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004824 }
4825 foreach my $Word (keys(%Words))
4826 {
4827 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4828 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004829 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004830 if($BaseType_Name=~/\([\*]+\)/)
4831 { # FuncPtr
4832 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4833 {
4834 my $Type_Suffix = $1;
4835 $TypeName_New = $BaseType_Name;
4836 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004837 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004838 }
4839 }
4840 }
4841 else
4842 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004843 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004844 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004845 }
4846 }
4847 }
4848 }
4849 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4850}
4851
4852sub isInternal($)
4853{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004854 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4855 {
4856 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4857 {
4858 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4859 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4860 return 1;
4861 }
4862 }
4863 }
4864 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004865}
4866
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004867sub getDataVal($$)
4868{
4869 my ($InfoId, $TypeId) = @_;
4870 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4871 {
4872 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4873 {
4874 if(defined $LibInfo{$Version}{"info_type"}{$1}
4875 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004876 {
4877 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004878 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004879 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4880 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004881 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004882 if(my $Addr = getTreeAttr_Op($1)) {
4883 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004884 }
4885 }
4886 }
4887 }
4888 else {
4889 return getInitVal($1, $TypeId);
4890 }
4891 }
4892 }
4893 return undef;
4894}
4895
4896sub getInitVal($$)
4897{
4898 my ($InfoId, $TypeId) = @_;
4899 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4900 {
4901 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4902 {
4903 if($InfoType eq "integer_cst")
4904 {
4905 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004906 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004907 { # characters
4908 $Val = chr($Val);
4909 }
4910 return $Val;
4911 }
4912 elsif($InfoType eq "string_cst") {
4913 return getNodeStrCst($InfoId);
4914 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004915 elsif($InfoType eq "var_decl")
4916 {
4917 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4918 return $Name;
4919 }
4920 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004921 }
4922 }
4923 return undef;
4924}
4925
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004926sub set_Class_And_Namespace($)
4927{
4928 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004929 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004930 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004931 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004932 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004933 my $NSInfoId = $1;
4934 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4935 {
4936 if($InfoType eq "namespace_decl") {
4937 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4938 }
4939 elsif($InfoType eq "record_type") {
4940 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4941 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004942 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004943 }
4944 }
4945 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4946 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004947 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004948 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004949 { # skip
4950 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004951 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004952 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004953
4954 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004955}
4956
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004957sub debugMangling($)
4958{
4959 my $LibVersion = $_[0];
4960 my %Mangled = ();
4961 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4962 {
4963 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4964 {
4965 if($Mngl=~/\A(_Z|\?)/) {
4966 $Mangled{$Mngl}=$InfoId;
4967 }
4968 }
4969 }
4970 translateSymbols(keys(%Mangled), $LibVersion);
4971 foreach my $Mngl (keys(%Mangled))
4972 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004973 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4974 my $U2 = $tr_name{$Mngl};
4975 if($U1 ne $U2) {
4976 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004977 }
4978 }
4979}
4980
4981sub linkSymbol($)
4982{ # link symbols from shared libraries
4983 # with the symbols from header files
4984 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004985 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004986 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004987 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenko9c87bdb2016-10-20 18:15:38 +03004988 or $GCC_MISSED_MNGL)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004989 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4990 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
Andrey Ponomarenko9c87bdb2016-10-20 18:15:38 +03004991 # GCC 4.8.[012] and 6.[12].0 don't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004992 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004993 {
4994 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4995 return correct_incharge($InfoId, $Version, $Mangled);
4996 }
4997 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004998 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004999 or not $BinaryOnly
Andrey Ponomarenko9c87bdb2016-10-20 18:15:38 +03005000 or $GCC_MISSED_MNGL)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005001 { # 1. --headers-only mode
5002 # 2. not mangled src-only symbols
5003 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
5004 return $Mangled;
5005 }
5006 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005007 }
5008 return "";
5009}
5010
5011sub setLanguage($$)
5012{
5013 my ($LibVersion, $Lang) = @_;
5014 if(not $UserLang) {
5015 $COMMON_LANGUAGE{$LibVersion} = $Lang;
5016 }
5017}
5018
5019sub getSymbolInfo($)
5020{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005021 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005022 if(isInternal($InfoId)) {
5023 return;
5024 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005025 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
5026 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005027 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
5028 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005029 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005030 return;
5031 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005032 setFuncAccess($InfoId);
5033 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005034 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
5035 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005036 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005037 return;
5038 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005039
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005040 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005041 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005042 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005043 if(not defined $TypeInfo{$Version}{$Return}
5044 or not $TypeInfo{$Version}{$Return}{"Name"})
5045 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005046 delete($SymbolInfo{$Version}{$InfoId});
5047 return;
5048 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005049 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005050 }
5051 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5052 {
5053 if(defined $MissedTypedef{$Version}{$Rid})
5054 {
5055 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5056 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5057 }
5058 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005059 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005060 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5061 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005062 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005063 my $Orig = getFuncOrig($InfoId);
5064 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005065 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5066 {
5067 delete($SymbolInfo{$Version}{$InfoId});
5068 return;
5069 }
5070
5071 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005072 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005073 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005074 return;
5075 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005076
5077 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005078 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005079 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5080
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005081 my @TParams = getTParams($Orig, "Func");
5082 if(not @TParams)
5083 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005084 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005085 return;
5086 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005087 foreach my $Pos (0 .. $#TParams)
5088 {
5089 my $Val = $TParams[$Pos];
5090 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5091
5092 if($Tmpl)
5093 {
5094 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5095 {
5096 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5097 }
5098 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005099 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005100
5101 if($Tmpl)
5102 {
5103 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5104 {
5105 if($Pos>$#TParams)
5106 {
5107 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5108 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5109 }
5110 }
5111 }
5112
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005113 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5114 { # operator<< <T>, operator>> <T>
5115 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5116 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005117 if(@TParams) {
5118 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5119 }
5120 else {
5121 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5122 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005123 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005124 }
5125 else
5126 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005127 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005128 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005129 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5130 {
5131 if($OSgroup eq "windows")
5132 { # cut the offset
5133 $MnglName=~s/\@\d+\Z//g;
5134 }
5135 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5136
5137 # NOTE: mangling of some symbols may change depending on GCC version
5138 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5139 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5140 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005141
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005142 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005143 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005144 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005145 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005146 return;
5147 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005148 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005149 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005150 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005151 if($Skip)
5152 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005153 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005154 return;
5155 }
5156 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005157 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5158 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5159 }
5160
5161 if(set_Class_And_Namespace($InfoId))
5162 {
5163 delete($SymbolInfo{$Version}{$InfoId});
5164 return;
5165 }
5166
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005167 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5168 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005169 if(not defined $TypeInfo{$Version}{$ClassId}
5170 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5171 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005172 delete($SymbolInfo{$Version}{$InfoId});
5173 return;
5174 }
5175 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005176 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5177 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005178 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005179 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005180 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005181 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005182 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005183 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005184 }
5185 if($COMMON_LANGUAGE{$Version} eq "C++")
5186 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005187 # C++ or --headers-only mode
5188 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005189 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005190 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5191 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005192 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005193 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005194 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005195 if(my $Mangled = linkSymbol($InfoId)) {
5196 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005197 }
5198 }
5199 if($OStarget eq "windows")
5200 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005201 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005202 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005203 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005204 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005205 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005206 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005207 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005208 }
5209 }
5210 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005211 else
5212 { # not mangled in C
5213 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5214 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005215 if(not $CheckHeadersOnly
5216 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5217 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5218 {
5219 my $Incorrect = 0;
5220
5221 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5222 {
5223 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5224 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5225 { # mangled in the TU dump, but not mangled in the library
5226 $Incorrect = 1;
5227 }
5228 }
5229 else
5230 {
5231 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5232 { # all C++ functions are not mangled in the TU dump
5233 $Incorrect = 1;
5234 }
5235 }
5236 if($Incorrect)
5237 {
5238 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5239 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5240 }
5241 }
5242 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005243 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005244 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005245 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005246 return;
5247 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005248 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005249 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005250 { # identify virtual and pure virtual functions
5251 # NOTE: constructors cannot be virtual
5252 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5253 # in the TU dump, so taking it from the original symbol
5254 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5255 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5256 { # NOTE: D2 destructors are not present in a v-table
5257 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5258 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005259 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005260 if(isInline($InfoId)) {
5261 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005262 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005263 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005264 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5265 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005266 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5267 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005268 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005269 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005270 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005271 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005272 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005273 }
5274 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005275 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5276 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005277 if(not $ExtraDump)
5278 {
5279 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5280 { # non-target symbols
5281 delete($SymbolInfo{$Version}{$InfoId});
5282 return;
5283 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005284 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005285 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005286 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5287 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5288 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5289 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005290 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005291 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5292 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005293 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005294 return;
5295 }
5296 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005297 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005298 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005299 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005300 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005301 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005302 return;
5303 }
5304 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005305 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005306 }
5307 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005308 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5309 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5310 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005311 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005312 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5313 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005314 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005315 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005316 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005317 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005318 }
5319 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005320 if(getFuncLink($InfoId) eq "Static") {
5321 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005322 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005323 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5324 {
5325 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5326 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005327 if($Unmangled=~/\.\_\d/)
5328 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005329 delete($SymbolInfo{$Version}{$InfoId});
5330 return;
5331 }
5332 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005333 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005334
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005335 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5336 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005337 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005338 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5339 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005340 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005341
5342 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5343 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5344 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005345
5346 if($ExtraDump) {
5347 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5348 }
5349}
5350
5351sub guessHeader($)
5352{
5353 my $InfoId = $_[0];
5354 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5355 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5356 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5357 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5358 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5359 {
5360 if(get_filename($HPath) eq $Header)
5361 {
5362 my $HDir = get_filename(get_dirname($HPath));
5363 if($HDir ne "include"
5364 and $HDir=~/\A[a-z]+\Z/i) {
5365 return join_P($HDir, $Header);
5366 }
5367 }
5368 }
5369 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005370}
5371
5372sub isInline($)
5373{ # "body: undefined" in the tree
5374 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005375 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5376 {
5377 if($Info=~/ undefined /i) {
5378 return 0;
5379 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005380 }
5381 return 1;
5382}
5383
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005384sub hasThrow($)
5385{
5386 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5387 {
5388 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5389 return getTreeAttr_Unql($1, "unql");
5390 }
5391 }
5392 return 1;
5393}
5394
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005395sub getTypeId($)
5396{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005397 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5398 {
5399 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5400 return $1;
5401 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005402 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005403 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005404}
5405
5406sub setTypeMemb($$)
5407{
5408 my ($TypeId, $TypeAttr) = @_;
5409 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005410 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005411 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005412 if($TypeType eq "Enum")
5413 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005414 my $MInfoId = getTreeAttr_Csts($TypeId);
5415 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005416 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005417 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5418 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005419 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005420 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5421 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005422 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005423 }
5424 }
5425 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5426 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005427 my $MInfoId = getTreeAttr_Flds($TypeId);
5428 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005429 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005430 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5431 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005432 if(not $IType or $IType ne "field_decl")
5433 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005434
5435 if($IType eq "var_decl")
5436 { # static field
5437 $StaticFields = 1;
5438 }
5439
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005440 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005441 next;
5442 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005443 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005444 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005445 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005446 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005447 }
5448 if(not $StructMembName)
5449 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005450 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005451 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005452 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005453 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5454 if(isAnon($UnnamedTName))
5455 { # rename unnamed fields to unnamed0, unnamed1, ...
5456 $StructMembName = "unnamed".($UnnamedPos++);
5457 }
5458 }
5459 }
5460 if(not $StructMembName)
5461 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005462 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005463 next;
5464 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005465 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005466 if(defined $MissedTypedef{$Version}{$MembTypeId})
5467 {
5468 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5469 $MembTypeId = $AddedTid;
5470 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005471 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005472
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005473 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5474 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005475 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005476 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005477 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5478 }
5479 if($MInfo=~/spec:\s*mutable /)
5480 { # mutable fields
5481 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005482 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005483 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005484 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5485 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005486 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005487 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005488 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005489 }
5490 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005491 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005492 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5493 { # template
5494 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5495 }
5496 else {
5497 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5498 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005499 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005500
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005501 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005502 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005503 }
5504 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005505
5506 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005507}
5508
5509sub setFuncParams($)
5510{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005511 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005512 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005513
5514 my $FType = getFuncType($InfoId);
5515
5516 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005517 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005518 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5519 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005520 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005521 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005522 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5523 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005524 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005525 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5526 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005527 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005528 else
5529 { # skip
5530 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005531 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005532 # skip "this"-parameter
5533 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005534 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005535 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005536 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005537 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005538 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5539 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5540 if(not $ParamName)
5541 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005542 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005543 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005544 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5545 {
5546 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5547 $ParamTypeId = $AddedTid;
5548 }
5549 }
5550 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005551 if(not $PType or $PType eq "Unknown") {
5552 return 1;
5553 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005554 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005555 if(not $PTName) {
5556 return 1;
5557 }
5558 if($PTName eq "void") {
5559 last;
5560 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005561 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005562 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005563 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005564 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005565 $ParamInfoId = getNextElem($ParamInfoId);
5566 next;
5567 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005568 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005569
5570 if(my %Base = get_BaseType($ParamTypeId, $Version))
5571 {
5572 if(defined $Base{"Template"}) {
5573 return 1;
5574 }
5575 }
5576
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005577 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005578 if(my $Algn = getAlgn($ParamInfoId)) {
5579 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5580 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005581 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5582 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005583 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005584 }
5585 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005586 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005587 if($ParamName ne "this" or $FType ne "Method") {
5588 $PPos += 1;
5589 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005590 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005591 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005592 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005593 }
5594 return 0;
5595}
5596
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005597sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005598{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005599 my ($InfoId, $Vtt_Pos) = @_;
5600 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005601 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005602 my $FType = getFuncType($InfoId);
5603
5604 if($FType eq "Method")
5605 {
5606 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005607 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005608 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005609 if(not $ParamListElemId)
5610 { # foo(...)
5611 return 1;
5612 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005613 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005614 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005615 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005616 { # actual params: may differ from formal args
5617 # formal int*const
5618 # actual: int*
5619 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005620 {
5621 $Vtt_Pos=-1;
5622 $ParamListElemId = getNextElem($ParamListElemId);
5623 next;
5624 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005625 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5626 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005627 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005628 $HaveVoid = 1;
5629 last;
5630 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005631 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005632 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005633 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5634 {
5635 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5636 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5637 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005638 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005639 }
5640 }
5641 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5642 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005643 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005644 { # params
5645 if($OldId ne $ParamTypeId)
5646 {
5647 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5648 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5649
5650 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5651 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5652 }
5653 }
5654 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005655 }
5656 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005657 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005658 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005659 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5660 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005661 if($PurpType eq "nop_expr")
5662 { # func ( const char* arg = (const char*)(void*)0 )
5663 $PurpId = getTreeAttr_Op($PurpId);
5664 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005665 my $Val = getInitVal($PurpId, $ParamTypeId);
5666 if(defined $Val) {
5667 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5668 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005669 }
5670 }
5671 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005672 if($Pos!=0 or $FType ne "Method") {
5673 $PPos += 1;
5674 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005675 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005676 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005677 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005678}
5679
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005680sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005681{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005682 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5683 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005684 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5685 return $1;
5686 }
5687 }
5688 return "";
5689}
5690
5691sub getTreeAttr_Chain($)
5692{
5693 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5694 {
5695 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5696 return $1;
5697 }
5698 }
5699 return "";
5700}
5701
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005702sub getTreeAttr_Unql($)
5703{
5704 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5705 {
5706 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5707 return $1;
5708 }
5709 }
5710 return "";
5711}
5712
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005713sub getTreeAttr_Scpe($)
5714{
5715 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5716 {
5717 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5718 return $1;
5719 }
5720 }
5721 return "";
5722}
5723
5724sub getTreeAttr_Type($)
5725{
5726 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5727 {
5728 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5729 return $1;
5730 }
5731 }
5732 return "";
5733}
5734
5735sub getTreeAttr_Name($)
5736{
5737 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5738 {
5739 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5740 return $1;
5741 }
5742 }
5743 return "";
5744}
5745
5746sub getTreeAttr_Mngl($)
5747{
5748 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5749 {
5750 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5751 return $1;
5752 }
5753 }
5754 return "";
5755}
5756
5757sub getTreeAttr_Prms($)
5758{
5759 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5760 {
5761 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5762 return $1;
5763 }
5764 }
5765 return "";
5766}
5767
5768sub getTreeAttr_Fncs($)
5769{
5770 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5771 {
5772 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5773 return $1;
5774 }
5775 }
5776 return "";
5777}
5778
5779sub getTreeAttr_Csts($)
5780{
5781 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5782 {
5783 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5784 return $1;
5785 }
5786 }
5787 return "";
5788}
5789
5790sub getTreeAttr_Purp($)
5791{
5792 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5793 {
5794 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5795 return $1;
5796 }
5797 }
5798 return "";
5799}
5800
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005801sub getTreeAttr_Op($)
5802{
5803 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5804 {
5805 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5806 return $1;
5807 }
5808 }
5809 return "";
5810}
5811
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005812sub getTreeAttr_Valu($)
5813{
5814 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5815 {
5816 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5817 return $1;
5818 }
5819 }
5820 return "";
5821}
5822
5823sub getTreeAttr_Flds($)
5824{
5825 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5826 {
5827 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5828 return $1;
5829 }
5830 }
5831 return "";
5832}
5833
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005834sub getTreeAttr_Binf($)
5835{
5836 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5837 {
5838 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5839 return $1;
5840 }
5841 }
5842 return "";
5843}
5844
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005845sub getTreeAttr_Args($)
5846{
5847 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5848 {
5849 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005850 return $1;
5851 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005852 }
5853 return "";
5854}
5855
5856sub getTreeValue($)
5857{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005858 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5859 {
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03005860 if($Info=~/(low|int)[ ]*:[ ]*([^ ]+) /) {
5861 return $2;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005862 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005863 }
5864 return "";
5865}
5866
5867sub getTreeAccess($)
5868{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005869 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005870 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005871 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5872 {
5873 my $Access = $1;
5874 if($Access eq "prot") {
5875 return "protected";
5876 }
5877 elsif($Access eq "priv") {
5878 return "private";
5879 }
5880 }
5881 elsif($Info=~/ protected /)
5882 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005883 return "protected";
5884 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005885 elsif($Info=~/ private /)
5886 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005887 return "private";
5888 }
5889 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005890 return "public";
5891}
5892
5893sub setFuncAccess($)
5894{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005895 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005896 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005897 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005898 }
5899 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005900 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005901 }
5902}
5903
5904sub setTypeAccess($$)
5905{
5906 my ($TypeId, $TypeAttr) = @_;
5907 my $Access = getTreeAccess($TypeId);
5908 if($Access eq "protected") {
5909 $TypeAttr->{"Protected"} = 1;
5910 }
5911 elsif($Access eq "private") {
5912 $TypeAttr->{"Private"} = 1;
5913 }
5914}
5915
5916sub setFuncKind($)
5917{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005918 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5919 {
5920 if($Info=~/pseudo tmpl/) {
5921 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5922 }
5923 elsif($Info=~/ constructor /) {
5924 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5925 }
5926 elsif($Info=~/ destructor /) {
5927 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5928 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005929 }
5930}
5931
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005932sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005933{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005934 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5935 {
5936 if($Info=~/spec[ ]*:[ ]*pure /) {
5937 return "PureVirt";
5938 }
5939 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5940 return "Virt";
5941 }
5942 elsif($Info=~/ pure\s+virtual /)
5943 { # support for old GCC versions
5944 return "PureVirt";
5945 }
5946 elsif($Info=~/ virtual /)
5947 { # support for old GCC versions
5948 return "Virt";
5949 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005950 }
5951 return "";
5952}
5953
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005954sub getFuncLink($)
5955{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005956 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5957 {
5958 if($Info=~/link[ ]*:[ ]*static /) {
5959 return "Static";
5960 }
5961 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005962 return $1;
5963 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005964 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005965 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005966}
5967
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005968sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005969{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005970 my ($Symbol, $LibVersion) = @_;
5971 return "" if(not $Symbol or not $LibVersion);
5972 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5973 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005974 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005975 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5976 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5977 }
5978 }
5979 if($NS)
5980 {
5981 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5982 return $NS;
5983 }
5984 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005985 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005986 while($NS=~s/::[^:]+\Z//)
5987 {
5988 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5989 return $NS;
5990 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005991 }
5992 }
5993 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005994
5995 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005996}
5997
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005998sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005999{
6000 my ($TypeName, $LibVersion) = @_;
6001 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006002 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006003 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006004 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6005 return $NS;
6006 }
6007 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006008 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006009 while($NS=~s/::[^:]+\Z//)
6010 {
6011 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6012 return $NS;
6013 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006014 }
6015 }
6016 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006017 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006018}
6019
6020sub getNameSpace($)
6021{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006022 my $InfoId = $_[0];
6023 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006024 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006025 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006026 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006027 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006028 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006029 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
6030 {
6031 my $NameSpace = getTreeStr($1);
6032 if($NameSpace eq "::")
6033 { # global namespace
6034 return "";
6035 }
6036 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
6037 $NameSpace = $BaseNameSpace."::".$NameSpace;
6038 }
6039 $NestedNameSpaces{$Version}{$NameSpace} = 1;
6040 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006041 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006042 else {
6043 return "";
6044 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006045 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006046 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006047 { # inside data type
6048 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6049 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006050 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006051 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006052 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006053 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006054}
6055
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006056sub getEnumMembVal($)
6057{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006058 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006059 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006060 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6061 {
6062 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6063 {
6064 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6065 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6066 return getTreeValue($1);
6067 }
6068 else
6069 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6070 return getTreeValue($1);
6071 }
6072 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006073 }
6074 }
6075 return "";
6076}
6077
6078sub getSize($)
6079{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006080 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6081 {
6082 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6083 return getTreeValue($1);
6084 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006085 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006086 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006087}
6088
6089sub getAlgn($)
6090{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006091 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6092 {
6093 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6094 return $1;
6095 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006096 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006097 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006098}
6099
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006100sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006101{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006102 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6103 {
6104 if($Info=~/ bitfield /) {
6105 return getSize($_[0]);
6106 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006107 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006108 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006109}
6110
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006111sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006112{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006113 if(my $Chan = getTreeAttr_Chan($_[0])) {
6114 return $Chan;
6115 }
6116 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6117 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006118 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006119 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006120}
6121
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006122sub registerHeader($$)
6123{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006124 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006125 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006126 return "";
6127 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006128 if(is_abs($Header) and not -f $Header)
6129 { # incorrect absolute path
6130 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006131 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006132 if(skipHeader($Header, $LibVersion))
6133 { # skip
6134 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006135 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006136 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6137 {
6138 detect_header_includes($Header_Path, $LibVersion);
6139
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006140 if(defined $Tolerance and $Tolerance=~/3/)
6141 { # 3 - skip headers that include non-Linux headers
6142 if($OSgroup ne "windows")
6143 {
6144 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6145 {
6146 if(specificHeader($Inc, "windows")) {
6147 return "";
6148 }
6149 }
6150 }
6151 }
6152
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006153 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6154 { # redirect
6155 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6156 or skipHeader($RHeader_Path, $LibVersion))
6157 { # skip
6158 return "";
6159 }
6160 $Header_Path = $RHeader_Path;
6161 }
6162 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6163 { # skip
6164 return "";
6165 }
6166
6167 if(my $HName = get_filename($Header_Path))
6168 { # register
6169 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6170 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6171 }
6172
6173 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6174 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006175 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006176 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006177 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006178 }
6179
6180 if($CheckHeadersOnly
6181 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6182 { # /usr/include/c++/4.6.1/...
6183 $STDCXX_TESTING = 1;
6184 }
6185
6186 return $Header_Path;
6187 }
6188 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006189}
6190
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006191sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006192{
6193 my ($Dir, $WithDeps, $LibVersion) = @_;
6194 $Dir=~s/[\/\\]+\Z//g;
6195 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006196 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006197
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006198 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006199 if($WithDeps)
6200 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006201 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6202 return;
6203 }
6204 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6205 $Mode = "DepsOnly";
6206 }
6207 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006208 else
6209 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006210 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6211 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6212 return;
6213 }
6214 }
6215 $Header_Dependency{$LibVersion}{$Dir} = 1;
6216 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6217 if($Mode eq "DepsOnly")
6218 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006219 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006220 $Header_Dependency{$LibVersion}{$Path} = 1;
6221 }
6222 return;
6223 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006224 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006225 {
6226 if($WithDeps)
6227 {
6228 my $SubDir = $Path;
6229 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6230 { # register all sub directories
6231 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6232 }
6233 }
6234 next if(is_not_header($Path));
6235 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006236 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006237 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006238 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6239 }
6240 }
6241 if(get_filename($Dir) eq "include")
6242 { # search for "lib/include/" directory
6243 my $LibDir = $Dir;
6244 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006245 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006246 }
6247 }
6248}
6249
6250sub parse_redirect($$$)
6251{
6252 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006253 my @Errors = ();
6254 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6255 push(@Errors, $1);
6256 }
6257 my $Redirect = "";
6258 foreach (@Errors)
6259 {
6260 s/\s{2,}/ /g;
6261 if(/(only|must\ include
6262 |update\ to\ include
6263 |replaced\ with
6264 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006265 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006266 {
6267 $Redirect = $2;
6268 last;
6269 }
6270 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6271 {
6272 $Redirect = $2;
6273 last;
6274 }
6275 elsif(/this\ header\ should\ not\ be\ used
6276 |programs\ should\ not\ directly\ include
6277 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6278 |is\ not\ supported\ API\ for\ general\ use
6279 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006280 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006281 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6282 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6283 }
6284 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006285 if($Redirect)
6286 {
6287 $Redirect=~s/\A<//g;
6288 $Redirect=~s/>\Z//g;
6289 }
6290 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006291}
6292
6293sub parse_includes($$)
6294{
6295 my ($Content, $Path) = @_;
6296 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006297 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006298 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006299 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006300 my $Method = substr($Header, 0, 1, "");
6301 substr($Header, length($Header)-1, 1, "");
6302 $Header = path_format($Header, $OSgroup);
6303 if($Method eq "\"" or is_abs($Header))
6304 {
6305 if(-e join_P(get_dirname($Path), $Header))
6306 { # relative path exists
6307 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006308 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006309 else
6310 { # include "..." that doesn't exist is equal to include <...>
6311 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006312 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006313 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006314 else {
6315 $Includes{$Header} = 1;
6316 }
6317 }
6318 if($ExtraInfo)
6319 {
6320 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6321 { # FT_FREETYPE_H
6322 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006323 }
6324 }
6325 return \%Includes;
6326}
6327
6328sub ignore_path($)
6329{
6330 my $Path = $_[0];
6331 if($Path=~/\~\Z/)
6332 {# skipping system backup files
6333 return 1;
6334 }
6335 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6336 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6337 return 1;
6338 }
6339 return 0;
6340}
6341
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006342sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006343{
6344 my ($ArrRef, $W) = @_;
6345 return if(length($W)<2);
6346 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6347}
6348
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006349sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006350{
6351 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006352
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006353 $H1=~s/\.[a-z]+\Z//ig;
6354 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006355
6356 my $Hname1 = get_filename($H1);
6357 my $Hname2 = get_filename($H2);
6358 my $HDir1 = get_dirname($H1);
6359 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006360 my $Dirname1 = get_filename($HDir1);
6361 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006362
6363 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6364 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6365
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006366 if($_[0] eq $_[1]
6367 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006368 return 0;
6369 }
6370 elsif($H1=~/\A\Q$H2\E/) {
6371 return 1;
6372 }
6373 elsif($H2=~/\A\Q$H1\E/) {
6374 return -1;
6375 }
6376 elsif($HDir1=~/\Q$Hname1\E/i
6377 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006378 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006379 return -1;
6380 }
6381 elsif($HDir2=~/\Q$Hname2\E/i
6382 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006383 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006384 return 1;
6385 }
6386 elsif($Hname1=~/\Q$Dirname1\E/i
6387 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006388 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006389 return -1;
6390 }
6391 elsif($Hname2=~/\Q$Dirname2\E/i
6392 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006393 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006394 return 1;
6395 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006396 elsif($Hname1=~/(config|lib|util)/i
6397 and $Hname2!~/(config|lib|util)/i)
6398 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006399 return -1;
6400 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006401 elsif($Hname2=~/(config|lib|util)/i
6402 and $Hname1!~/(config|lib|util)/i)
6403 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006404 return 1;
6405 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006406 else
6407 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006408 my $R1 = checkRelevance($H1);
6409 my $R2 = checkRelevance($H2);
6410 if($R1 and not $R2)
6411 { # libebook/e-book.h
6412 return -1;
6413 }
6414 elsif($R2 and not $R1)
6415 { # libebook/e-book.h
6416 return 1;
6417 }
6418 else
6419 {
6420 return (lc($H1) cmp lc($H2));
6421 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006422 }
6423}
6424
6425sub searchForHeaders($)
6426{
6427 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006428
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006429 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006430 registerGccHeaders();
6431
6432 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6433 { # c++ standard include paths
6434 registerCppHeaders();
6435 }
6436
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006437 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006438 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6439 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006440 {
6441 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006442 if($SystemRoot)
6443 {
6444 if(is_abs($Path)) {
6445 $Path = $SystemRoot.$Path;
6446 }
6447 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006448 if(not -e $Path) {
6449 exitStatus("Access_Error", "can't access \'$Path\'");
6450 }
6451 elsif(-f $Path) {
6452 exitStatus("Access_Error", "\'$Path\' - not a directory");
6453 }
6454 elsif(-d $Path)
6455 {
6456 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006457 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006458 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6459 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006460 }
6461 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006462 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006463 }
6464 }
6465 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006466 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006467 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6468 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006469
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006470 # registering directories
6471 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6472 {
6473 next if(not -e $Path);
6474 $Path = get_abs_path($Path);
6475 $Path = path_format($Path, $OSgroup);
6476 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006477 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006478 }
6479 elsif(-f $Path)
6480 {
6481 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006482 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006483 and not $LocalIncludes{$Dir})
6484 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006485 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006486 # if(my $OutDir = get_dirname($Dir))
6487 # { # registering the outer directory
6488 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6489 # and not $LocalIncludes{$OutDir}) {
6490 # registerDir($OutDir, 0, $LibVersion);
6491 # }
6492 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006493 }
6494 }
6495 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006496
6497 # clean memory
6498 %RegisteredDirs = ();
6499
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006500 # registering headers
6501 my $Position = 0;
6502 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6503 {
6504 if(is_abs($Dest) and not -e $Dest) {
6505 exitStatus("Access_Error", "can't access \'$Dest\'");
6506 }
6507 $Dest = path_format($Dest, $OSgroup);
6508 if(is_header($Dest, 1, $LibVersion))
6509 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006510 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006511 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6512 }
6513 }
6514 elsif(-d $Dest)
6515 {
6516 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006517 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006518 {
6519 next if(ignore_path($Path));
6520 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006521 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006522 push(@Registered, $HPath);
6523 }
6524 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006525 @Registered = sort {sortHeaders($a, $b)} @Registered;
6526 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006527 foreach my $Path (@Registered) {
6528 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6529 }
6530 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03006531 elsif(not defined $SkipUnidentified) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006532 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6533 }
6534 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006535
6536 if(defined $Tolerance and $Tolerance=~/4/)
6537 { # 4 - skip headers included by others
6538 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6539 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006540 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006541 delete($Registered_Headers{$LibVersion}{$Path});
6542 }
6543 }
6544 }
6545
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006546 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6547 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006548 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006549 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006550 if(is_abs($Header) and not -f $Header) {
6551 exitStatus("Access_Error", "can't access file \'$Header\'");
6552 }
6553 $Header = path_format($Header, $OSgroup);
6554 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6555 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006556 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006557 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006558 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03006559 elsif($SkipUnidentified) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006560 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6561 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006562 }
6563 }
6564 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6565 { # set relative paths (for duplicates)
6566 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6567 { # search for duplicates
6568 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6569 my $Prefix = get_dirname($FirstPath);
6570 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6571 { # detect a shortest distinguishing prefix
6572 my $NewPrefix = $1;
6573 my %Identity = ();
6574 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6575 {
6576 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6577 $Identity{$Path} = $1;
6578 }
6579 }
6580 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006581 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006582 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6583 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6584 }
6585 last;
6586 }
6587 $Prefix = $NewPrefix; # increase prefix
6588 }
6589 }
6590 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006591
6592 # clean memory
6593 %HeaderName_Paths = ();
6594
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006595 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6596 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006597 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006598 my ($Pos, $PairPos) = (-1, -1);
6599 my ($Path, $PairPath) = ();
6600 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6601 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6602 foreach my $Header_Path (@Paths)
6603 {
6604 if(get_filename($Header_Path) eq $PairName)
6605 {
6606 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6607 $PairPath = $Header_Path;
6608 }
6609 if(get_filename($Header_Path) eq $HeaderName)
6610 {
6611 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6612 $Path = $Header_Path;
6613 }
6614 }
6615 if($PairPos!=-1 and $Pos!=-1
6616 and int($PairPos)<int($Pos))
6617 {
6618 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6619 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6620 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6621 }
6622 }
6623 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6624 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6625 }
6626}
6627
6628sub detect_real_includes($$)
6629{
6630 my ($AbsPath, $LibVersion) = @_;
6631 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6632 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6633 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6634 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6635 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006636 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6637
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006638 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6639 return () if(not $Path);
6640 open(PREPROC, $Path);
6641 while(<PREPROC>)
6642 {
6643 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6644 {
6645 my $Include = path_format($1, $OSgroup);
6646 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6647 next;
6648 }
6649 if($Include eq $AbsPath) {
6650 next;
6651 }
6652 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6653 }
6654 }
6655 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006656 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6657}
6658
6659sub detect_header_includes($$)
6660{
6661 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006662 return if(not $LibVersion or not $Path);
6663 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6664 return;
6665 }
6666 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6667
6668 if(not -e $Path) {
6669 return;
6670 }
6671
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006672 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006673 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6674 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006675 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006676 {
6677 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006678 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006679 }
6680 if($RedirectPath ne $Path) {
6681 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6682 }
6683 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006684 else
6685 { # can't find
6686 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6687 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006688 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006689 if(my $Inc = parse_includes($Content, $Path))
6690 {
6691 foreach my $Include (keys(%{$Inc}))
6692 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006693 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006694
6695 if(defined $Tolerance and $Tolerance=~/4/)
6696 {
6697 if(my $HPath = identifyHeader($Include, $LibVersion))
6698 {
6699 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6700 }
6701 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006702 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006703 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006704}
6705
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006706sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006707{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006708 my $Path = $_[0];
6709 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006710 if($OStarget eq "symbian")
6711 {
6712 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6713 { # epoc32/include/libc/{stdio, ...}.h
6714 return 1;
6715 }
6716 }
6717 else
6718 {
6719 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6720 { # /usr/include/{stdio, ...}.h
6721 return 1;
6722 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006723 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006724 return 0;
6725}
6726
6727sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006728{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006729 my $Dir = $_[0];
6730 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006731 if($OStarget eq "symbian")
6732 {
6733 if(get_filename($OutDir) eq "libc"
6734 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6735 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6736 return 1;
6737 }
6738 }
6739 else
6740 { # linux
6741 if($OutDir eq "/usr/include"
6742 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6743 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6744 return 1;
6745 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006746 }
6747 return 0;
6748}
6749
6750sub detect_recursive_includes($$)
6751{
6752 my ($AbsPath, $LibVersion) = @_;
6753 return () if(not $AbsPath);
6754 if(isCyclical(\@RecurInclude, $AbsPath)) {
6755 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6756 }
6757 my ($AbsDir, $Name) = separate_path($AbsPath);
6758 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006759 { # system GLIBC internals
6760 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006761 }
6762 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6763 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6764 }
6765 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006766
6767 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6768 { # skip /usr/include/c++/*/ headers
6769 return () if(not $ExtraInfo);
6770 }
6771
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006772 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006773 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006774 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006775 { # check "real" (non-"model") include paths
6776 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6777 pop(@RecurInclude);
6778 return @Paths;
6779 }
6780 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6781 detect_header_includes($AbsPath, $LibVersion);
6782 }
6783 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6784 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006785 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006786 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006787 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006788 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006789 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006790 if(-f $Candidate) {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03006791 $HPath = realpath_F($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006792 }
6793 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006794 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006795 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006796 { # search for the nearest header
6797 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006798 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006799 if(-f $Candidate) {
6800 $HPath = $Candidate;
6801 }
6802 }
6803 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006804 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006805 }
6806 next if(not $HPath);
6807 if($HPath eq $AbsPath) {
6808 next;
6809 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006810
6811 if($Debug)
6812 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006813# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6814# {
6815# print STDERR "$AbsPath -> $HPath\n";
6816# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006817 }
6818
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006819 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6820 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006821 { # only include <...>, skip include "..." prefixes
6822 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6823 }
6824 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6825 {
6826 if($IncPath eq $AbsPath) {
6827 next;
6828 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006829 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6830 if($RIncType==-1)
6831 { # include "..."
6832 $RIncType = $IncType;
6833 }
6834 elsif($RIncType==2)
6835 {
6836 if($IncType!=-1) {
6837 $RIncType = $IncType;
6838 }
6839 }
6840 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006841 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6842 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6843 }
6844 }
6845 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6846 {
6847 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6848 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6849 { # distinguish math.h from glibc and math.h from the tested library
6850 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6851 last;
6852 }
6853 }
6854 }
6855 pop(@RecurInclude);
6856 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6857}
6858
6859sub find_in_framework($$$)
6860{
6861 my ($Header, $Framework, $LibVersion) = @_;
6862 return "" if(not $Header or not $Framework or not $LibVersion);
6863 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6864 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6865 }
6866 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6867 {
6868 if(get_filename($Dependency) eq $Framework
6869 and -f get_dirname($Dependency)."/".$Header) {
6870 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6871 }
6872 }
6873 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6874}
6875
6876sub find_in_defaults($)
6877{
6878 my $Header = $_[0];
6879 return "" if(not $Header);
6880 if(defined $Cache{"find_in_defaults"}{$Header}) {
6881 return $Cache{"find_in_defaults"}{$Header};
6882 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006883 foreach my $Dir (@DefaultIncPaths,
6884 @DefaultGccPaths,
6885 @DefaultCppPaths,
6886 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006887 {
6888 next if(not $Dir);
6889 if(-f $Dir."/".$Header) {
6890 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6891 }
6892 }
6893 return ($Cache{"find_in_defaults"}{$Header}="");
6894}
6895
6896sub cmp_paths($$)
6897{
6898 my ($Path1, $Path2) = @_;
6899 my @Parts1 = split(/[\/\\]/, $Path1);
6900 my @Parts2 = split(/[\/\\]/, $Path2);
6901 foreach my $Num (0 .. $#Parts1)
6902 {
6903 my $Part1 = $Parts1[$Num];
6904 my $Part2 = $Parts2[$Num];
6905 if($GlibcDir{$Part1}
6906 and not $GlibcDir{$Part2}) {
6907 return 1;
6908 }
6909 elsif($GlibcDir{$Part2}
6910 and not $GlibcDir{$Part1}) {
6911 return -1;
6912 }
6913 elsif($Part1=~/glib/
6914 and $Part2!~/glib/) {
6915 return 1;
6916 }
6917 elsif($Part1!~/glib/
6918 and $Part2=~/glib/) {
6919 return -1;
6920 }
6921 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6922 return $CmpRes;
6923 }
6924 }
6925 return 0;
6926}
6927
6928sub checkRelevance($)
6929{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006930 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006931 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006932
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006933 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006934 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006935 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006936
6937 my $Name = lc(get_filename($Path));
6938 my $Dir = lc(get_dirname($Path));
6939
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006940 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006941
6942 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006943 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006944 my $Len = length($Token);
6945 next if($Len<=1);
6946 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6947 { # include/evolution-data-server-1.4/libebook/e-book.h
6948 return 1;
6949 }
6950 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006951 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006952 return 1;
6953 }
6954 }
6955 return 0;
6956}
6957
6958sub checkFamily(@)
6959{
6960 my @Paths = @_;
6961 return 1 if($#Paths<=0);
6962 my %Prefix = ();
6963 foreach my $Path (@Paths)
6964 {
6965 if($SystemRoot) {
6966 $Path = cut_path_prefix($Path, $SystemRoot);
6967 }
6968 if(my $Dir = get_dirname($Path))
6969 {
6970 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6971 $Prefix{$Dir} += 1;
6972 $Prefix{get_dirname($Dir)} += 1;
6973 }
6974 }
6975 foreach (sort keys(%Prefix))
6976 {
6977 if(get_depth($_)>=3
6978 and $Prefix{$_}==$#Paths+1) {
6979 return 1;
6980 }
6981 }
6982 return 0;
6983}
6984
6985sub isAcceptable($$$)
6986{
6987 my ($Header, $Candidate, $LibVersion) = @_;
6988 my $HName = get_filename($Header);
6989 if(get_dirname($Header))
6990 { # with prefix
6991 return 1;
6992 }
6993 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6994 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6995 return 1;
6996 }
6997 if(checkRelevance($Candidate))
6998 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6999 return 1;
7000 }
7001 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
7002 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
7003 # /usr/include/qt4/Qt/qsslconfiguration.h
7004 return 1;
7005 }
7006 if($OStarget eq "symbian")
7007 {
7008 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
7009 return 1;
7010 }
7011 }
7012 return 0;
7013}
7014
7015sub isRelevant($$$)
7016{ # disallow to search for "abstract" headers in too deep directories
7017 my ($Header, $Candidate, $LibVersion) = @_;
7018 my $HName = get_filename($Header);
7019 if($OStarget eq "symbian")
7020 {
7021 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
7022 return 0;
7023 }
7024 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007025 if($OStarget ne "bsd")
7026 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007027 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
7028 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
7029 return 0;
7030 }
7031 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007032 if($OStarget ne "windows")
7033 {
7034 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
7035 { # skip /usr/include/wine/msvcrt
7036 return 0;
7037 }
7038 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007039 if(not get_dirname($Header)
7040 and $Candidate=~/[\/\\]wx[\/\\]/)
7041 { # do NOT search in system /wx/ directory
7042 # for headers without a prefix: sstream.h
7043 return 0;
7044 }
7045 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7046 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7047 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7048 return 0;
7049 }
7050 if($Candidate=~/[\/\\]asm-/
7051 and (my $Arch = getArch($LibVersion)) ne "unknown")
7052 { # arch-specific header files
7053 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7054 {# skip ../asm-arm/ if using x86 architecture
7055 return 0;
7056 }
7057 }
7058 my @Candidates = getSystemHeaders($HName, $LibVersion);
7059 if($#Candidates==1)
7060 { # unique header
7061 return 1;
7062 }
7063 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7064 if($#SCandidates==1)
7065 { # unique name
7066 return 1;
7067 }
7068 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7069 if(get_depth($Candidate)-$SystemDepth>=5)
7070 { # abstract headers in too deep directories
7071 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7072 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7073 return 0;
7074 }
7075 }
7076 if($Header eq "parser.h"
7077 and $Candidate!~/\/libxml2\//)
7078 { # select parser.h from xml2 library
7079 return 0;
7080 }
7081 if(not get_dirname($Header)
7082 and keys(%{$SystemHeaders{$HName}})>=3)
7083 { # many headers with the same name
7084 # like thread.h included without a prefix
7085 if(not checkFamily(@Candidates)) {
7086 return 0;
7087 }
7088 }
7089 return 1;
7090}
7091
7092sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007093{ # cache function
7094 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7095 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7096 }
7097 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7098}
7099
7100sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007101{
7102 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007103 if(-f $Header) {
7104 return $Header;
7105 }
7106 if(is_abs($Header) and not -f $Header)
7107 { # incorrect absolute path
7108 return "";
7109 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007110 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007111 { # too abstract configuration headers
7112 return "";
7113 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007114 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007115 if($OSgroup ne "windows")
7116 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007117 if(defined $WinHeaders{lc($HName)}
7118 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007119 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007120 return "";
7121 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007122 }
7123 if($OSgroup ne "macos")
7124 {
7125 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007126 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007127 return "";
7128 }
7129 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007130
7131 if(defined $ObsoleteHeaders{$HName})
7132 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007133 return "";
7134 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007135 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7136 {
7137 if(defined $AlienHeaders{$HName}
7138 or defined $AlienHeaders{$Header})
7139 { # alien headers from other systems
7140 return "";
7141 }
7142 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007143
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007144 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007145 { # search in default paths
7146 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007147 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007148 }
7149 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007150 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007151 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007152 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007153 }
7154 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7155 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7156 {
7157 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007158 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007159 }
7160 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007161 # error
7162 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007163}
7164
7165sub getSystemHeaders($$)
7166{
7167 my ($Header, $LibVersion) = @_;
7168 my @Candidates = ();
7169 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7170 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007171 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007172 next;
7173 }
7174 push(@Candidates, $Candidate);
7175 }
7176 return @Candidates;
7177}
7178
7179sub cut_path_prefix($$)
7180{
7181 my ($Path, $Prefix) = @_;
7182 return $Path if(not $Prefix);
7183 $Prefix=~s/[\/\\]+\Z//;
7184 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7185 return $Path;
7186}
7187
7188sub is_default_include_dir($)
7189{
7190 my $Dir = $_[0];
7191 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007192 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007193}
7194
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007195sub identifyHeader($$)
7196{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007197 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007198 if(not $Header) {
7199 return "";
7200 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007201 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007202 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7203 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007204 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007205 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007206}
7207
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007208sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007209{ # search for header by absolute path, relative path or name
7210 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007211 if(-f $Header)
7212 { # it's relative or absolute path
7213 return get_abs_path($Header);
7214 }
7215 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7216 and my $HeaderDir = find_in_defaults($Header))
7217 { # search for libc headers in the /usr/include
7218 # for non-libc target library before searching
7219 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007220 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007221 }
7222 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7223 { # search in the target library paths
7224 return $Path;
7225 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007226 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007227 { # search in the internal GCC include paths
7228 return $DefaultGccHeader{$Header};
7229 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007230 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007231 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007232 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007233 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007234 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007235 { # search in the default G++ include paths
7236 return $DefaultCppHeader{$Header};
7237 }
7238 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7239 { # search everywhere in the system
7240 return $AnyPath;
7241 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007242 elsif($OSgroup eq "macos")
7243 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7244 if(my $Dir = get_dirname($Header))
7245 {
7246 my $RelPath = "Headers\/".get_filename($Header);
7247 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007248 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007249 }
7250 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007251 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007252 # cannot find anything
7253 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007254}
7255
7256sub getLocation($)
7257{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007258 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7259 {
7260 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007261 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007262 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007263 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007264 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007265}
7266
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007267sub getNameByInfo($)
7268{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007269 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007270 {
7271 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7272 {
7273 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7274 {
7275 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7276 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007277 my $Str = $1;
7278 if($CppMode{$Version}
7279 and $Str=~/\Ac99_(.+)\Z/)
7280 {
7281 if($CppKeywords_A{$1}) {
7282 $Str=$1;
7283 }
7284 }
7285 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007286 }
7287 }
7288 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007289 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007290 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007291}
7292
7293sub getTreeStr($)
7294{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007295 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007296 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007297 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7298 {
7299 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007300 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007301 and $Str=~/\Ac99_(.+)\Z/)
7302 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007303 if($CppKeywords_A{$1}) {
7304 $Str=$1;
7305 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007306 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007307 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007308 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007309 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007310 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007311}
7312
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007313sub getFuncShortName($)
7314{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007315 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007316 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007317 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007318 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007319 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007320 {
7321 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7322 {
7323 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7324 return "operator ".$RName;
7325 }
7326 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007327 }
7328 else
7329 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007330 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7331 {
7332 if(my $Ind = $Operator_Indication{$1}) {
7333 return "operator".$Ind;
7334 }
7335 elsif(not $UnknownOperator{$1})
7336 {
7337 printMsg("WARNING", "unknown operator $1");
7338 $UnknownOperator{$1} = 1;
7339 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007340 }
7341 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007342 }
7343 else
7344 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007345 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7346 return getTreeStr($1);
7347 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007348 }
7349 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007350 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007351}
7352
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007353sub getFuncReturn($)
7354{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007355 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7356 {
7357 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7358 {
7359 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7360 return $1;
7361 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007362 }
7363 }
7364 return "";
7365}
7366
7367sub getFuncOrig($)
7368{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007369 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7370 {
7371 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7372 return $1;
7373 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007374 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007375 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007376}
7377
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007378sub unmangleArray(@)
7379{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007380 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007381 { # MSVC mangling
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007382 if(defined $DisabledMSVCUnmangling) {
7383 return @_;
7384 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007385 my $UndNameCmd = get_CmdPath("undname");
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007386 if(not $UndNameCmd)
7387 {
7388 if($OSgroup eq "windows") {
7389 exitStatus("Not_Found", "can't find \"undname\"");
7390 }
7391 elsif(not defined $DisabledMSVCUnmangling)
7392 {
7393 printMsg("WARNING", "can't find \"undname\", disable MSVC unmangling");
7394 $DisabledMSVCUnmangling = 1;
7395 return @_;
7396 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007397 }
7398 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007399 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007400 }
7401 else
7402 { # GCC mangling
7403 my $CppFiltCmd = get_CmdPath("c++filt");
7404 if(not $CppFiltCmd) {
7405 exitStatus("Not_Found", "can't find c++filt in PATH");
7406 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007407 if(not defined $CPPFILT_SUPPORT_FILE)
7408 {
7409 my $Info = `$CppFiltCmd -h 2>&1`;
7410 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7411 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007412 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007413 if($CPPFILT_SUPPORT_FILE)
7414 { # new versions of c++filt can take a file
7415 if($#_>$MAX_CPPFILT_FILE_SIZE)
7416 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7417 # this is fixed in the oncoming version of Binutils
7418 my @Half = splice(@_, 0, ($#_+1)/2);
7419 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007420 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007421 else
7422 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007423 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7424 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7425 if($?==139)
7426 { # segmentation fault
7427 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7428 }
7429 return split(/\n/, $Res);
7430 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007431 }
7432 else
7433 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007434 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7435 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007436 my @Half = splice(@_, 0, ($#_+1)/2);
7437 return (unmangleArray(@Half), unmangleArray(@_))
7438 }
7439 else
7440 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007441 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007442 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7443 if($?==139)
7444 { # segmentation fault
7445 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7446 }
7447 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007448 }
7449 }
7450 }
7451}
7452
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007453sub get_ChargeLevel($$)
7454{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007455 my ($Symbol, $LibVersion) = @_;
7456 return "" if($Symbol!~/\A(_Z|\?)/);
7457 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7458 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007459 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007460 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007461 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007462 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007463 return "[in-charge]";
7464 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007465 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007466 return "[not-in-charge]";
7467 }
7468 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007469 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007470 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007471 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007472 return "[in-charge]";
7473 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007474 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007475 return "[not-in-charge]";
7476 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007477 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007478 return "[in-charge-deleting]";
7479 }
7480 }
7481 }
7482 else
7483 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007484 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007485 return "[in-charge]";
7486 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007487 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007488 return "[not-in-charge]";
7489 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007490 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007491 return "[in-charge]";
7492 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007493 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007494 return "[not-in-charge]";
7495 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007496 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007497 return "[in-charge-deleting]";
7498 }
7499 }
7500 return "";
7501}
7502
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007503sub get_Signature_M($$)
7504{
7505 my ($Symbol, $LibVersion) = @_;
7506 my $Signature_M = $tr_name{$Symbol};
7507 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7508 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007509 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007510 }
7511 return $Signature_M;
7512}
7513
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007514sub get_Signature($$)
7515{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007516 my ($Symbol, $LibVersion) = @_;
7517 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7518 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007519 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007520 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007521 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03007522
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007523 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007524
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007525 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007526 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007527 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7528 {
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007529 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
7530 $ClassName=~s/\bstruct //g;
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007531
7532 if(index($Symbol, "_ZTV")==0) {
7533 return "vtable for $ClassName [data]";
7534 }
7535
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007536 $Signature .= $ClassName."::";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007537 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7538 $Signature .= "~";
7539 }
7540 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007541 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007542 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007543 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007544 }
7545 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007546 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007547 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007548 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7549 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007550 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007551 else
7552 {
7553 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007554 }
7555 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007556 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007557 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007558 if($Pos eq "") {
7559 next;
7560 }
7561
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007562 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007563 if(not $ParamTypeId) {
7564 next;
7565 }
7566
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007567 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007568 if(not $ParamTypeName) {
7569 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7570 }
7571 foreach my $Typedef (keys(%ChangedTypedef))
7572 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007573 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7574 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7575 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007576 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007577 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7578 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007579 if($ParamName eq "this"
7580 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007581 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007582 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007583 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007584 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007585 }
7586 else {
7587 push(@ParamArray, $ParamTypeName);
7588 }
7589 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007590 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7591 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007592 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007593 }
7594 else
7595 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007596 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007597 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007598 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007599 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007600 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007601 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7602 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007603 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007604 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007605 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7606 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007607 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007608 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007609 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7610 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007611 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007612 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007613 }
7614 }
7615 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007616 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007617 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007618 }
7619 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007620 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007621 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007622 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007623}
7624
7625sub create_member_decl($$)
7626{
7627 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007628 if($TName=~/\([\*]+\)/)
7629 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007630 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7631 return $TName;
7632 }
7633 else
7634 {
7635 my @ArraySizes = ();
7636 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7637 push(@ArraySizes, $1);
7638 }
7639 return $TName." ".$Member.join("", @ArraySizes);
7640 }
7641}
7642
7643sub getFuncType($)
7644{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007645 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7646 {
7647 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7648 {
7649 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7650 {
7651 if($Type eq "method_type") {
7652 return "Method";
7653 }
7654 elsif($Type eq "function_type") {
7655 return "Function";
7656 }
7657 else {
7658 return "Other";
7659 }
7660 }
7661 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007662 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007663 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007664}
7665
7666sub getFuncTypeId($)
7667{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007668 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7669 {
7670 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7671 return $1;
7672 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007673 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007674 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007675}
7676
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007677sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007678{ # "._N" or "$_N" in older GCC versions
7679 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007680}
7681
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007682sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007683{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007684 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7685 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007686 }
7687
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007688 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007689
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007690 if($_[1] ne "S")
7691 {
7692 $N=~s/\A[ ]+//g;
7693 $N=~s/[ ]+\Z//g;
7694 $N=~s/[ ]{2,}/ /g;
7695 }
7696
7697 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007698
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007699 $N=~s/\b(const|volatile) ([\w\:]+)([\*&,>]|\Z)/$2 $1$3/g; # "const void" to "void const"
7700
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007701 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007702
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007703 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7704 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007705
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007706 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007707
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007708 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007709
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007710 if($_[1] eq "S")
7711 {
7712 if(index($N, "operator")!=-1) {
7713 $N=~s/\b(operator[ ]*)> >/$1>>/;
7714 }
7715 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007716
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +03007717 $N=~s/,([^ ])/, $1/g;
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007718
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007719 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007720}
7721
7722sub get_HeaderDeps($$)
7723{
7724 my ($AbsPath, $LibVersion) = @_;
7725 return () if(not $AbsPath or not $LibVersion);
7726 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7727 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7728 }
7729 my %IncDir = ();
7730 detect_recursive_includes($AbsPath, $LibVersion);
7731 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7732 {
7733 next if(not $HeaderPath);
7734 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7735 my $Dir = get_dirname($HeaderPath);
7736 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7737 {
7738 my $Dep = $Dir;
7739 if($Prefix)
7740 {
7741 if($OSgroup eq "windows")
7742 { # case insensitive seach on windows
7743 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7744 next;
7745 }
7746 }
7747 elsif($OSgroup eq "macos")
7748 { # seach in frameworks
7749 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7750 {
7751 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7752 {# frameworks
7753 my ($HFramework, $HName) = ($1, $2);
7754 $Dep = $HFramework;
7755 }
7756 else
7757 {# mismatch
7758 next;
7759 }
7760 }
7761 }
7762 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7763 { # Linux, FreeBSD
7764 next;
7765 }
7766 }
7767 if(not $Dep)
7768 { # nothing to include
7769 next;
7770 }
7771 if(is_default_include_dir($Dep))
7772 { # included by the compiler
7773 next;
7774 }
7775 if(get_depth($Dep)==1)
7776 { # too short
7777 next;
7778 }
7779 if(isLibcDir($Dep))
7780 { # do NOT include /usr/include/{sys,bits}
7781 next;
7782 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007783 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007784 }
7785 }
7786 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7787 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7788}
7789
7790sub sortIncPaths($$)
7791{
7792 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007793 if(not $ArrRef or $#{$ArrRef}<0) {
7794 return $ArrRef;
7795 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007796 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7797 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007798 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007799 return $ArrRef;
7800}
7801
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007802sub sortDeps($$$)
7803{
7804 if($Header_Dependency{$_[2]}{$_[0]}
7805 and not $Header_Dependency{$_[2]}{$_[1]}) {
7806 return 1;
7807 }
7808 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7809 and $Header_Dependency{$_[2]}{$_[1]}) {
7810 return -1;
7811 }
7812 return 0;
7813}
7814
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007815sub join_P($$)
7816{
7817 my $S = "/";
7818 if($OSgroup eq "windows") {
7819 $S = "\\";
7820 }
7821 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007822}
7823
7824sub get_namespace_additions($)
7825{
7826 my $NameSpaces = $_[0];
7827 my ($Additions, $AddNameSpaceId) = ("", 1);
7828 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7829 {
7830 next if($SkipNameSpaces{$Version}{$NS});
7831 next if(not $NS or $NameSpaces->{$NS}==-1);
7832 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7833 next if($NS=~/\A__/i);
7834 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007835 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007836 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7837 my @NS_Parts = split(/::/, $NS);
7838 next if($#NS_Parts==-1);
7839 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7840 foreach my $NS_Part (@NS_Parts)
7841 {
7842 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7843 $TypeDecl_Suffix .= "}";
7844 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007845 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007846 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7847 $Additions.=" $TypeDecl\n $FuncDecl\n";
7848 $AddNameSpaceId+=1;
7849 }
7850 return $Additions;
7851}
7852
7853sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007854{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007855 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007856 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007857 if($Fmt eq "windows")
7858 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007859 $Path=~s/\//\\/g;
7860 $Path=lc($Path);
7861 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007862 else
7863 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007864 $Path=~s/\\/\//g;
7865 }
7866 return $Path;
7867}
7868
7869sub inc_opt($$)
7870{
7871 my ($Path, $Style) = @_;
7872 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007873 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007874 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007875 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007876 return "-I\"".path_format($Path, "unix")."\"";
7877 }
7878 elsif($OSgroup eq "macos"
7879 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007880 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007881 return "-F".esc(get_dirname($Path));
7882 }
7883 else {
7884 return "-I".esc($Path);
7885 }
7886 }
7887 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007888 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007889 }
7890 return "";
7891}
7892
7893sub platformSpecs($)
7894{
7895 my $LibVersion = $_[0];
7896 my $Arch = getArch($LibVersion);
7897 if($OStarget eq "symbian")
7898 { # options for GCCE compiler
7899 my %Symbian_Opts = map {$_=>1} (
7900 "-D__GCCE__",
7901 "-DUNICODE",
7902 "-fexceptions",
7903 "-D__SYMBIAN32__",
7904 "-D__MARM_INTERWORK__",
7905 "-D_UNICODE",
7906 "-D__S60_50__",
7907 "-D__S60_3X__",
7908 "-D__SERIES60_3X__",
7909 "-D__EPOC32__",
7910 "-D__MARM__",
7911 "-D__EABI__",
7912 "-D__MARM_ARMV5__",
7913 "-D__SUPPORT_CPP_EXCEPTIONS__",
7914 "-march=armv5t",
7915 "-mapcs",
7916 "-mthumb-interwork",
7917 "-DEKA2",
7918 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7919 );
7920 return join(" ", keys(%Symbian_Opts));
7921 }
7922 elsif($OSgroup eq "windows"
7923 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7924 { # add options to MinGW compiler
7925 # to simulate the MSVC compiler
7926 my %MinGW_Opts = map {$_=>1} (
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007927 "-D__unaligned=\" \"",
7928 "-D__nullptr=\"nullptr\"",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007929 "-D_WIN32",
7930 "-D_STDCALL_SUPPORTED",
7931 "-D__int64=\"long long\"",
7932 "-D__int32=int",
7933 "-D__int16=short",
7934 "-D__int8=char",
7935 "-D__possibly_notnullterminated=\" \"",
7936 "-D__nullterminated=\" \"",
7937 "-D__nullnullterminated=\" \"",
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007938 "-D__assume=\" \"",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007939 "-D__w64=\" \"",
7940 "-D__ptr32=\" \"",
7941 "-D__ptr64=\" \"",
7942 "-D__forceinline=inline",
7943 "-D__inline=inline",
7944 "-D__uuidof(x)=IID()",
7945 "-D__try=",
7946 "-D__except(x)=",
7947 "-D__declspec(x)=__attribute__((x))",
7948 "-D__pragma(x)=",
7949 "-D_inline=inline",
7950 "-D__forceinline=__inline",
7951 "-D__stdcall=__attribute__((__stdcall__))",
7952 "-D__cdecl=__attribute__((__cdecl__))",
7953 "-D__fastcall=__attribute__((__fastcall__))",
7954 "-D__thiscall=__attribute__((__thiscall__))",
7955 "-D_stdcall=__attribute__((__stdcall__))",
7956 "-D_cdecl=__attribute__((__cdecl__))",
7957 "-D_fastcall=__attribute__((__fastcall__))",
7958 "-D_thiscall=__attribute__((__thiscall__))",
7959 "-DSHSTDAPI_(x)=x",
7960 "-D_MSC_EXTENSIONS",
7961 "-DSECURITY_WIN32",
7962 "-D_MSC_VER=1500",
7963 "-D_USE_DECLSPECS_FOR_SAL",
7964 "-D__noop=\" \"",
7965 "-DDECLSPEC_DEPRECATED=\" \"",
7966 "-D__builtin_alignof(x)=__alignof__(x)",
7967 "-DSORTPP_PASS");
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007968 if($Arch eq "x86")
7969 {
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007970 $MinGW_Opts{"-D_X86_=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007971 $MinGW_Opts{"-D_M_IX86=300"}=1;
7972 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007973 elsif($Arch eq "x86_64")
7974 {
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007975 $MinGW_Opts{"-D_AMD64_=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007976 $MinGW_Opts{"-D_M_AMD64=300"}=1;
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007977 $MinGW_Opts{"-D_M_X64=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007978 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007979 elsif($Arch eq "ia64")
7980 {
7981 $MinGW_Opts{"-D_IA64_=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007982 $MinGW_Opts{"-D_M_IA64=300"}=1;
7983 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007984 return join(" ", sort keys(%MinGW_Opts));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007985 }
7986 return "";
7987}
7988
7989my %C_Structure = map {$_=>1} (
7990# FIXME: Can't separate union and struct data types before dumping,
7991# so it sometimes cause compilation errors for unknown reason
7992# when trying to declare TYPE* tmp_add_class_N
7993# This is a list of such structures + list of other C structures
7994 "sigval",
7995 "sigevent",
7996 "sigaction",
7997 "sigvec",
7998 "sigstack",
7999 "timeval",
8000 "timezone",
8001 "rusage",
8002 "rlimit",
8003 "wait",
8004 "flock",
8005 "stat",
8006 "_stat",
8007 "stat32",
8008 "_stat32",
8009 "stat64",
8010 "_stat64",
8011 "_stati64",
8012 "if_nameindex",
8013 "usb_device",
8014 "sigaltstack",
8015 "sysinfo",
8016 "timeLocale",
8017 "tcp_debug",
8018 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008019 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008020 "timespec",
8021 "random_data",
8022 "drand48_data",
8023 "_IO_marker",
8024 "_IO_FILE",
8025 "lconv",
8026 "sched_param",
8027 "tm",
8028 "itimerspec",
8029 "_pthread_cleanup_buffer",
8030 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008031 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008032 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008033 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008034 "sigcontext",
8035 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008036 # Mac
8037 "_timex",
8038 "_class_t",
8039 "_category_t",
8040 "_class_ro_t",
8041 "_protocol_t",
8042 "_message_ref_t",
8043 "_super_message_ref_t",
8044 "_ivar_t",
8045 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008046);
8047
8048sub getCompileCmd($$$)
8049{
8050 my ($Path, $Opt, $Inc) = @_;
8051 my $GccCall = $GCC_PATH;
8052 if($Opt) {
8053 $GccCall .= " ".$Opt;
8054 }
8055 $GccCall .= " -x ";
8056 if($OSgroup eq "macos") {
8057 $GccCall .= "objective-";
8058 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04008059
Andrey Ponomarenko9c87bdb2016-10-20 18:15:38 +03008060 if($GCC_MISSED_MNGL)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04008061 { # workaround for GCC 4.8 (C only)
8062 $GccCall .= "c++";
8063 }
8064 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008065 { # compile as "C++" header
8066 # to obtain complete dump using GCC 4.0
8067 $GccCall .= "c++-header";
8068 }
8069 else
8070 { # compile as "C++" source
8071 # GCC 3.3 cannot compile headers
8072 $GccCall .= "c++";
8073 }
8074 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008075 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008076 $GccCall .= " ".$Opts;
8077 }
8078 # allow extra qualifications
8079 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008080 $GccCall .= " -fpermissive";
8081 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008082 if($NoStdInc)
8083 {
8084 $GccCall .= " -nostdinc";
8085 $GccCall .= " -nostdinc++";
8086 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008087 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008088 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008089 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008090 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008091 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008092 if($Inc)
8093 { # include paths
8094 $GccCall .= " ".$Inc;
8095 }
8096 return $GccCall;
8097}
8098
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008099sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008100{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008101 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008102 my %HeaderElems = (
8103 # Types
8104 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008105 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008106 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8107 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008108 "time.h" => ["time_t"],
8109 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008110 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8111 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008112 "stdbool.h" => ["_Bool"],
8113 "rpc/xdr.h" => ["bool_t"],
8114 "in_systm.h" => ["n_long", "n_short"],
8115 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008116 "arpa/inet.h" => ["fw_src", "ip_src"],
8117 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008118 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008119 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008120 );
8121 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008122 foreach (keys(%HeaderElems))
8123 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008124 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008125 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008126 }
8127 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008128 my %Types = ();
8129 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8130 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008131 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008132 }
8133 if(keys(%Types))
8134 {
8135 my %AddHeaders = ();
8136 foreach my $Type (keys(%Types))
8137 {
8138 if(my $Header = $AutoPreamble{$Type})
8139 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008140 if(my $Path = identifyHeader($Header, $LibVersion))
8141 {
8142 if(skipHeader($Path, $LibVersion)) {
8143 next;
8144 }
8145 $Path = path_format($Path, $OSgroup);
8146 $AddHeaders{$Path}{"Type"} = $Type;
8147 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008148 }
8149 }
8150 }
8151 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008152 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008153 }
8154 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008155 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008156}
8157
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008158sub checkCTags($)
8159{
8160 my $Path = $_[0];
8161 if(not $Path) {
8162 return;
8163 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008164 my $CTags = undef;
8165
8166 if($OSgroup eq "bsd")
8167 { # use ectags on BSD
8168 $CTags = get_CmdPath("ectags");
8169 if(not $CTags) {
8170 printMsg("WARNING", "can't find \'ectags\' program");
8171 }
8172 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008173 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008174 $CTags = get_CmdPath("ctags");
8175 }
8176 if(not $CTags)
8177 {
8178 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008179 return;
8180 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008181
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008182 if($OSgroup ne "linux")
8183 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008184 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkodd172162016-10-04 19:41:25 +03008185 if($Info!~/universal|exuberant/i)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008186 {
8187 printMsg("WARNING", "incompatible version of \'ctags\' program");
8188 return;
8189 }
8190 }
8191
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008192 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008193 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008194 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008195 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008196 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008197 open(CTAGS, "<", $Out);
8198 while(my $Line = <CTAGS>)
8199 {
8200 chomp($Line);
8201 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008202 if(defined $Intrinsic_Keywords{$Name})
8203 { # noise
8204 next;
8205 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008206 if($Type eq "n")
8207 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008208 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008209 next;
8210 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008211 if(index($Scpe, "struct:")==0) {
8212 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008213 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008214 if(index($Scpe, "namespace:")==0)
8215 {
8216 if($Scpe=~s/\Anamespace://) {
8217 $Name = $Scpe."::".$Name;
8218 }
8219 }
8220 $TUnit_NameSpaces{$Version}{$Name} = 1;
8221 }
8222 elsif($Type eq "p")
8223 {
8224 if(not $Scpe or index($Scpe, "namespace:")==0) {
8225 $TUnit_Funcs{$Version}{$Name} = 1;
8226 }
8227 }
8228 elsif($Type eq "x")
8229 {
8230 if(not $Scpe or index($Scpe, "namespace:")==0) {
8231 $TUnit_Vars{$Version}{$Name} = 1;
8232 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008233 }
8234 }
8235 close(CTAGS);
8236}
8237
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008238sub preChange($$)
8239{
8240 my ($HeaderPath, $IncStr) = @_;
8241
8242 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8243 my $Content = undef;
8244
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008245 if(not defined $MinGWCompat and $OStarget eq "windows"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008246 and get_dumpmachine($GCC_PATH)=~/mingw/i
8247 and $MinGWMode{$Version}!=-1)
8248 { # modify headers to compile by MinGW
8249 if(not $Content)
8250 { # preprocessing
8251 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8252 }
8253 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8254 { # __asm { ... }
8255 $MinGWMode{$Version}=1;
8256 }
8257 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8258 { # comments after preprocessing
8259 $MinGWMode{$Version}=1;
8260 }
8261 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8262 { # 0xffui8
8263 $MinGWMode{$Version}=1;
8264 }
8265
8266 if($MinGWMode{$Version}) {
8267 printMsg("INFO", "Using MinGW compatibility mode");
8268 }
8269 }
8270
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008271 if(defined $CxxIncompat and ($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8272 and $CppMode{$Version}!=-1 and not $CPP_HEADERS)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008273 { # rename C++ keywords in C code
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008274 printMsg("INFO", "Checking the code for C++ keywords");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008275 if(not $Content)
8276 { # preprocessing
8277 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8278 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008279
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008280 my $RegExp_C = join("|", keys(%CppKeywords_C));
8281 my $RegExp_F = join("|", keys(%CppKeywords_F));
8282 my $RegExp_O = join("|", keys(%CppKeywords_O));
8283
8284 my $Detected = undef;
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008285 my $Sentence_O = undef;
8286 my $Sentence_N = undef;
8287 my $Regex = undef;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008288
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008289 $Regex = qr/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*([\,\)\;\.\[]|\-\>|\:\s*\d))/;
8290 while($Content=~/$Regex/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008291 { # MATCH:
8292 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008293 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008294 # unsigned private: 8;
8295 # DO NOT MATCH:
8296 # #pragma GCC visibility push(default)
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008297 $Sentence_O = "$1$2$3$4";
8298 $Sentence_N = "$1$2c99_$3$4";
8299
8300 if($Sentence_O=~/\s+decltype\(/)
8301 { # C++
8302 # decltype(nullptr)
8303 last;
8304 }
8305 else
8306 {
8307 $Content=~s/$Regex/$Sentence_N/g;
8308 $CppMode{$Version} = 1;
8309 if(not defined $Detected) {
8310 $Detected = $Sentence_O;
8311 }
8312 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008313 }
8314 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8315 { # MATCH:
8316 # int delete(...);
8317 # int explicit(...);
8318 # DO NOT MATCH:
8319 # void operator delete(...)
8320 $CppMode{$Version} = 1;
8321 $Detected = "$1$2$3" if(not defined $Detected);
8322 }
8323 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8324 { # MATCH:
8325 # int bool;
8326 # DO NOT MATCH:
8327 # bool X;
8328 # return *this;
8329 # throw;
8330 $CppMode{$Version} = 1;
8331 $Detected = "$1$2$3" if(not defined $Detected);
8332 }
8333 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8334 { # MATCH:
8335 # int operator(...);
8336 # DO NOT MATCH:
8337 # int operator()(...);
8338 $CppMode{$Version} = 1;
8339 $Detected = "$1$2$3" if(not defined $Detected);
8340 }
8341 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8342 { # MATCH:
8343 # int foo(int operator);
8344 # int foo(int operator, int other);
8345 # DO NOT MATCH:
8346 # int operator,(...);
8347 $CppMode{$Version} = 1;
8348 $Detected = "$1$2$3" if(not defined $Detected);
8349 }
8350 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8351 { # MATCH:
8352 # int foo(gboolean *bool);
8353 # DO NOT MATCH:
8354 # void setTabEnabled(int index, bool);
8355 $CppMode{$Version} = 1;
8356 $Detected = "$1$2$3" if(not defined $Detected);
8357 }
8358 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8359 { # MATCH:
8360 # int foo(int* this);
8361 # int bar(int this);
8362 # int baz(int throw);
8363 # DO NOT MATCH:
8364 # foo(X, this);
8365 $CppMode{$Version} = 1;
8366 $Detected = "$1$2$3$4" if(not defined $Detected);
8367 }
8368 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8369 { # MATCH:
8370 # struct template {...};
8371 # extern template foo(...);
8372 $CppMode{$Version} = 1;
8373 $Detected = "$1$2" if(not defined $Detected);
8374 }
8375
8376 if($CppMode{$Version} == 1)
8377 {
8378 if($Debug)
8379 {
8380 $Detected=~s/\A\s+//g;
8381 printMsg("INFO", "Detected code: \"$Detected\"");
8382 }
8383 }
8384
8385 # remove typedef enum NAME NAME;
8386 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8387 my $N = 0;
8388 while($N<=$#FwdTypedefs-1)
8389 {
8390 my $S = $FwdTypedefs[$N];
8391 if($S eq $FwdTypedefs[$N+1])
8392 {
8393 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008394 $CppMode{$Version} = 1;
8395
8396 if($Debug) {
8397 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8398 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008399 }
8400 $N+=2;
8401 }
8402
8403 if($CppMode{$Version}==1) {
8404 printMsg("INFO", "Using C++ compatibility mode");
8405 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008406 else {
8407 printMsg("INFO", "C++ keywords in the C code are not found");
8408 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008409 }
8410
8411 if($CppMode{$Version}==1
8412 or $MinGWMode{$Version}==1)
8413 {
8414 my $IPath = $TMP_DIR."/dump$Version.i";
8415 writeFile($IPath, $Content);
8416 return $IPath;
8417 }
8418
8419 return undef;
8420}
8421
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008422sub getDump()
8423{
8424 if(not $GCC_PATH) {
8425 exitStatus("Error", "internal error - GCC path is not set");
8426 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008427
8428 my @Headers = keys(%{$Registered_Headers{$Version}});
8429 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8430
8431 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8432
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008433 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008434 my $HeaderPath = $TmpHeaderPath;
8435
8436 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008437 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008438 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8439 {
8440 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008441 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008442 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008443 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008444 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8445 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008446 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008447 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008448 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008449 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8450 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8451 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008452 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008453 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008454
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008455 if($ExtraInfo)
8456 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008457 if($IncludeString) {
8458 writeFile($ExtraInfo."/include-string", $IncludeString);
8459 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008460 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8461 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008462
8463 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8464 {
8465 my $REDIR = "";
8466 foreach my $P1 (sort @Redirects) {
8467 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8468 }
8469 writeFile($ExtraInfo."/include-redirect", $REDIR);
8470 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008471 }
8472
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008473 if(not keys(%{$TargetHeaders{$Version}}))
8474 { # Target headers
8475 addTargetHeaders($Version);
8476 }
8477
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008478 # clean memory
8479 %RecursiveIncludes = ();
8480 %Header_Include_Prefix = ();
8481 %Header_Includes = ();
8482
8483 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008484 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008485 delete($Cache{"detect_header_includes"});
8486 delete($Cache{"selectSystemHeader"});
8487
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008488 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008489 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8490 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008491
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008492 if($ExtraInfo)
8493 { # extra information for other tools
8494 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8495 }
8496
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008497 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008498 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008499 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008500
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008501 if($COMMON_LANGUAGE{$Version} eq "C++") {
8502 checkCTags($Pre);
8503 }
8504
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008505 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8506 { # try to correct the preprocessor output
8507 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008508 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008509
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008510 if($COMMON_LANGUAGE{$Version} eq "C++")
8511 { # add classes and namespaces to the dump
8512 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008513 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008514 or $MinGWMode{$Version}==1) {
8515 $CHdump .= " -fpreprocessed";
8516 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008517 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008518 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008519 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008520 chdir($ORIG_DIR);
8521 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8522 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008523 my $Content = readFile($ClassDump);
8524 foreach my $ClassInfo (split(/\n\n/, $Content))
8525 {
8526 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8527 {
8528 my $CName = $1;
8529 next if($CName=~/\A(__|_objc_|_opaque_)/);
8530 $TUnit_NameSpaces{$Version}{$CName} = -1;
8531 if($CName=~/\A[\w:]+\Z/)
8532 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008533 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008534 }
8535 if($CName=~/(\w[\w:]*)::/)
8536 { # namespaces
8537 my $NS = $1;
8538 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8539 $TUnit_NameSpaces{$Version}{$NS} = 1;
8540 }
8541 }
8542 }
8543 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8544 { # read v-tables (advanced approach)
8545 my ($CName, $VTable) = ($1, $2);
8546 $ClassVTable_Content{$Version}{$CName} = $VTable;
8547 }
8548 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008549 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8550 { # add user-defined namespaces
8551 $TUnit_NameSpaces{$Version}{$NS} = 1;
8552 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008553 if($Debug)
8554 { # debug mode
8555 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008556 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008557 }
8558 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008559 }
8560
8561 # add namespaces and classes
8562 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8563 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008564 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008565 }
8566 # some GCC versions don't include class methods to the TU dump by default
8567 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008568 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008569 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8570 {
8571 next if($C_Structure{$CName});
8572 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008573 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008574 if(not $Force and $GCC_44
8575 and $OSgroup eq "linux")
8576 { # optimization for linux with GCC >= 4.4
8577 # disable this code by -force option
8578 if(index($CName, "::")!=-1)
8579 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008580 next;
8581 }
8582 }
8583 else
8584 {
8585 if($CName=~/\A(.+)::[^:]+\Z/
8586 and $TUnit_Classes{$Version}{$1})
8587 { # classes inside other classes
8588 next;
8589 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008590 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008591 if(defined $TUnit_Funcs{$Version}{$CName})
8592 { # the same name for a function and type
8593 next;
8594 }
8595 if(defined $TUnit_Vars{$Version}{$CName})
8596 { # the same name for a variable and type
8597 next;
8598 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008599 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8600 }
8601 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008602 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008603 }
8604 }
8605 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8606 # create TU dump
8607 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008608 if($UserLang eq "C") {
8609 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8610 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008611 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008612 or $MinGWMode{$Version}==1) {
8613 $TUdump .= " -fpreprocessed";
8614 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008615 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008616 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8617 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008618 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008619 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008620 if($?)
8621 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008622 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008623 { # try to recompile
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008624 # FIXME: handle errors and try to recompile
8625 if($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008626 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008627 { # add auto preamble headers and try again
8628 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008629 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008630 foreach my $Num (0 .. $#Headers)
8631 {
8632 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008633 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8634 {
8635 push_U($Include_Preamble{$Version}, $Path);
8636 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008637 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008638 }
8639 resetLogging($Version);
8640 $TMP_DIR = tempdir(CLEANUP=>1);
8641 return getDump();
8642 }
8643 elsif($Cpp0xMode{$Version}!=-1
8644 and ($Errors=~/\Q-std=c++0x\E/
8645 or $Errors=~/is not a class or namespace/))
8646 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008647 if(check_gcc($GCC_PATH, "4.6"))
8648 {
8649 $Cpp0xMode{$Version}=-1;
8650 printMsg("INFO", "Enabling c++0x mode");
8651 resetLogging($Version);
8652 $TMP_DIR = tempdir(CLEANUP=>1);
8653 $CompilerOptions{$Version} .= " -std=c++0x";
8654 return getDump();
8655 }
8656 else {
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008657 printMsg("WARNING", "Probably c++0x element detected");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008658 }
8659
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008660 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008661 #elsif($MinGWMode{$Version}==1)
8662 #{ # disable MinGW mode and try again
8663 # $MinGWMode{$Version}=-1;
8664 # resetLogging($Version);
8665 # $TMP_DIR = tempdir(CLEANUP=>1);
8666 # return getDump();
8667 #}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008668 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008669 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008670 else {
8671 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008672 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008673 printMsg("ERROR", "some errors occurred when compiling headers");
8674 printErrorLog($Version);
8675 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008676 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008677 }
8678 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008679 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008680 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008681
8682 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8683 return $TUs[0];
8684 }
8685 else
8686 {
8687 my $Msg = "can't compile header(s)";
8688 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8689 $Msg .= "\nDid you install G++?";
8690 }
8691 exitStatus("Cannot_Compile", $Msg);
8692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008693}
8694
8695sub cmd_file($)
8696{
8697 my $Path = $_[0];
8698 return "" if(not $Path or not -e $Path);
8699 if(my $CmdPath = get_CmdPath("file")) {
8700 return `$CmdPath -b \"$Path\"`;
8701 }
8702 return "";
8703}
8704
8705sub getIncString($$)
8706{
8707 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008708 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008709 my $String = "";
8710 foreach (@{$ArrRef}) {
8711 $String .= " ".inc_opt($_, $Style);
8712 }
8713 return $String;
8714}
8715
8716sub getIncPaths(@)
8717{
8718 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008719 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008720 if($INC_PATH_AUTODETECT{$Version})
8721 { # auto-detecting dependencies
8722 my %Includes = ();
8723 foreach my $HPath (@HeaderPaths)
8724 {
8725 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8726 {
8727 if($Skip_Include_Paths{$Version}{$Dir}) {
8728 next;
8729 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008730 if($SystemRoot)
8731 {
8732 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8733 next;
8734 }
8735 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008736 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008737 }
8738 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008739 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008740 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008741 }
8742 }
8743 else
8744 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008745 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008746 }
8747 return \@IncPaths;
8748}
8749
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008750sub push_U($@)
8751{ # push unique
8752 if(my $Array = shift @_)
8753 {
8754 if(@_)
8755 {
8756 my %Exist = map {$_=>1} @{$Array};
8757 foreach my $Elem (@_)
8758 {
8759 if(not defined $Exist{$Elem})
8760 {
8761 push(@{$Array}, $Elem);
8762 $Exist{$Elem} = 1;
8763 }
8764 }
8765 }
8766 }
8767}
8768
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008769sub callPreprocessor($$$)
8770{
8771 my ($Path, $Inc, $LibVersion) = @_;
8772 return "" if(not $Path or not -f $Path);
8773 my $IncludeString=$Inc;
8774 if(not $Inc) {
8775 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8776 }
8777 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008778 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008779 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008780 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008781}
8782
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008783sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008784{ # native "find" is much faster than File::Find (~6x)
8785 # also the File::Find doesn't support --maxdepth N option
8786 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008787 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008788 return () if(not $Path or not -e $Path);
8789 if($OSgroup eq "windows")
8790 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008791 $Path = get_abs_path($Path);
8792 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008793 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008794 if($MaxDepth!=1) {
8795 $Cmd .= " /S";
8796 }
8797 if($Type eq "d") {
8798 $Cmd .= " /AD";
8799 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008800 elsif($Type eq "f") {
8801 $Cmd .= " /A-D";
8802 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008803 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008804 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008805 {
8806 if(not $UseRegex)
8807 { # FIXME: how to search file names in MS shell?
8808 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008809 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008810 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008811 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008812 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008813 }
8814 my @AbsPaths = ();
8815 foreach my $File (@Files)
8816 {
8817 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008818 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008819 }
8820 if($Type eq "f" and not -f $File)
8821 { # skip dirs
8822 next;
8823 }
8824 push(@AbsPaths, path_format($File, $OSgroup));
8825 }
8826 if($Type eq "d") {
8827 push(@AbsPaths, $Path);
8828 }
8829 return @AbsPaths;
8830 }
8831 else
8832 {
8833 my $FindCmd = get_CmdPath("find");
8834 if(not $FindCmd) {
8835 exitStatus("Not_Found", "can't find a \"find\" command");
8836 }
8837 $Path = get_abs_path($Path);
8838 if(-d $Path and -l $Path
8839 and $Path!~/\/\Z/)
8840 { # for directories that are symlinks
8841 $Path.="/";
8842 }
8843 my $Cmd = $FindCmd." \"$Path\"";
8844 if($MaxDepth) {
8845 $Cmd .= " -maxdepth $MaxDepth";
8846 }
8847 if($Type) {
8848 $Cmd .= " -type $Type";
8849 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008850 if($Name and not $UseRegex)
8851 { # wildcards
8852 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008853 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008854 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008855 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008856 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8857 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008858 my @Files = split(/\n/, $Res);
8859 if($Name and $UseRegex)
8860 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008861 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008862 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008863 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008864 }
8865}
8866
8867sub unpackDump($)
8868{
8869 my $Path = $_[0];
8870 return "" if(not $Path or not -e $Path);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008871
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008872 $Path = get_abs_path($Path);
8873 $Path = path_format($Path, $OSgroup);
8874 my ($Dir, $FileName) = separate_path($Path);
8875 my $UnpackDir = $TMP_DIR."/unpack";
8876 rmtree($UnpackDir);
8877 mkpath($UnpackDir);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008878
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008879 if($FileName=~s/\Q.zip\E\Z//g)
8880 { # *.zip
8881 my $UnzipCmd = get_CmdPath("unzip");
8882 if(not $UnzipCmd) {
8883 exitStatus("Not_Found", "can't find \"unzip\" command");
8884 }
8885 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008886 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008887 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008888 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008889 }
8890 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008891 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008892 if(not @Contents) {
8893 exitStatus("Error", "can't extract \'$Path\'");
8894 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008895 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008896 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008897 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008898 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008899 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008900 if($OSgroup eq "windows")
8901 { # -xvzf option is not implemented in tar.exe (2003)
8902 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8903 my $TarCmd = get_CmdPath("tar");
8904 if(not $TarCmd) {
8905 exitStatus("Not_Found", "can't find \"tar\" command");
8906 }
8907 my $GzipCmd = get_CmdPath("gzip");
8908 if(not $GzipCmd) {
8909 exitStatus("Not_Found", "can't find \"gzip\" command");
8910 }
8911 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008912 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008913 if($?) {
8914 exitStatus("Error", "can't extract \'$Path\'");
8915 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008916 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008917 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008918 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008919 }
8920 chdir($ORIG_DIR);
8921 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008922 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008923 if(not @Contents) {
8924 exitStatus("Error", "can't extract \'$Path\'");
8925 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008926 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008927 }
8928 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008929 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008930 my $TarCmd = get_CmdPath("tar");
8931 if(not $TarCmd) {
8932 exitStatus("Not_Found", "can't find \"tar\" command");
8933 }
8934 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008935 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008936 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008937 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008938 }
8939 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008940 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008941 if(not @Contents) {
8942 exitStatus("Error", "can't extract \'$Path\'");
8943 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008944 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008945 }
8946 }
8947}
8948
8949sub createArchive($$)
8950{
8951 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008952 if(not $To) {
8953 $To = ".";
8954 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008955 if(not $Path or not -e $Path
8956 or not -d $To) {
8957 return "";
8958 }
8959 my ($From, $Name) = separate_path($Path);
8960 if($OSgroup eq "windows")
8961 { # *.zip
8962 my $ZipCmd = get_CmdPath("zip");
8963 if(not $ZipCmd) {
8964 exitStatus("Not_Found", "can't find \"zip\"");
8965 }
8966 my $Pkg = $To."/".$Name.".zip";
8967 unlink($Pkg);
8968 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008969 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008970 if($?)
8971 { # cannot allocate memory (or other problems with "zip")
8972 unlink($Path);
8973 exitStatus("Error", "can't pack the ABI dump: ".$!);
8974 }
8975 chdir($ORIG_DIR);
8976 unlink($Path);
8977 return $Pkg;
8978 }
8979 else
8980 { # *.tar.gz
8981 my $TarCmd = get_CmdPath("tar");
8982 if(not $TarCmd) {
8983 exitStatus("Not_Found", "can't find \"tar\"");
8984 }
8985 my $GzipCmd = get_CmdPath("gzip");
8986 if(not $GzipCmd) {
8987 exitStatus("Not_Found", "can't find \"gzip\"");
8988 }
8989 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8990 unlink($Pkg);
8991 chdir($From);
8992 system($TarCmd, "-czf", $Pkg, $Name);
8993 if($?)
8994 { # cannot allocate memory (or other problems with "tar")
8995 unlink($Path);
8996 exitStatus("Error", "can't pack the ABI dump: ".$!);
8997 }
8998 chdir($ORIG_DIR);
8999 unlink($Path);
9000 return $To."/".$Name.".tar.gz";
9001 }
9002}
9003
9004sub is_header_file($)
9005{
9006 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
9007 return $_[0];
9008 }
9009 return 0;
9010}
9011
9012sub is_not_header($)
9013{
9014 if($_[0]=~/\.\w+\Z/
9015 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
9016 return 1;
9017 }
9018 return 0;
9019}
9020
9021sub is_header($$$)
9022{
9023 my ($Header, $UserDefined, $LibVersion) = @_;
9024 return 0 if(-d $Header);
9025 if(-f $Header) {
9026 $Header = get_abs_path($Header);
9027 }
9028 else
9029 {
9030 if(is_abs($Header))
9031 { # incorrect absolute path
9032 return 0;
9033 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009034 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009035 $Header = $HPath;
9036 }
9037 else
9038 { # can't find header
9039 return 0;
9040 }
9041 }
9042 if($Header=~/\.\w+\Z/)
9043 { # have an extension
9044 return is_header_file($Header);
9045 }
9046 else
9047 {
9048 if($UserDefined==2)
9049 { # specified on the command line
9050 if(cmd_file($Header)!~/HTML|XML/i) {
9051 return $Header;
9052 }
9053 }
9054 elsif($UserDefined)
9055 { # specified in the XML-descriptor
9056 # header file without an extension
9057 return $Header;
9058 }
9059 else
9060 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04009061 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009062 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009063 { # !~/HTML|XML|shared|dynamic/i
9064 return $Header;
9065 }
9066 }
9067 }
9068 return 0;
9069}
9070
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009071sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009072{
9073 my $LibVersion = $_[0];
9074 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9075 {
9076 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009077 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009078
9079 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9080 detect_recursive_includes($RegHeader, $LibVersion);
9081 }
9082
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009083 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9084 {
9085 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009086
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009087 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009088 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9089 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009090 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009091 }
9092 }
9093 }
9094}
9095
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009096sub familiarDirs($$)
9097{
9098 my ($D1, $D2) = @_;
9099 if($D1 eq $D2) {
9100 return 1;
9101 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009102
9103 my $U1 = index($D1, "/usr/");
9104 my $U2 = index($D2, "/usr/");
9105
9106 if($U1==0 and $U2!=0) {
9107 return 0;
9108 }
9109
9110 if($U2==0 and $U1!=0) {
9111 return 0;
9112 }
9113
9114 if(index($D2, $D1."/")==0) {
9115 return 1;
9116 }
9117
9118 # /usr/include/DIR
9119 # /home/user/DIR
9120
9121 my $DL = get_depth($D1);
9122
9123 my @Dirs1 = ($D1);
9124 while($DL - get_depth($D1)<=2
9125 and get_depth($D1)>=4
9126 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9127 push(@Dirs1, $D1);
9128 }
9129
9130 my @Dirs2 = ($D2);
9131 while(get_depth($D2)>=4
9132 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9133 push(@Dirs2, $D2);
9134 }
9135
9136 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009137 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009138 foreach my $P2 (@Dirs2)
9139 {
9140
9141 if($P1 eq $P2) {
9142 return 1;
9143 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009144 }
9145 }
9146 return 0;
9147}
9148
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009149sub readHeaders($)
9150{
9151 $Version = $_[0];
9152 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9153 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009154 if($Debug)
9155 { # debug mode
9156 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009157 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009158 }
9159 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009160}
9161
9162sub prepareTypes($)
9163{
9164 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009165 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009166 { # support for old ABI dumps
9167 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009168 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009169 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009170 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9171 if($TName=~/\A(\w+)::(\w+)/) {
9172 my ($P1, $P2) = ($1, $2);
9173 if($P1 eq $P2) {
9174 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009175 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009176 else {
9177 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9178 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009179 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009180 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009181 }
9182 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009183 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009184 { # support for old ABI dumps
9185 # V < 2.5: array size == "number of elements"
9186 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009187 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009188 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009189 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009190 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009191 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009192 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009193 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009194 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009195 $Size *= $Base{"Size"};
9196 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009197 }
9198 else
9199 { # array[] is a pointer
9200 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009201 }
9202 }
9203 }
9204 }
9205 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009206 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009207 { # support for old ABI dumps
9208 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009209 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009210 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009211 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009212 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009213 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009214 my %Type = get_Type($TypeId, $LibVersion);
9215 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9216 my %Type2 = get_Type($TypeId_2, $V2);
9217 if($Type{"Size"} ne $Type2{"Size"}) {
9218 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009219 }
9220 }
9221 }
9222 }
9223}
9224
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009225sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009226{
9227 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009228
9229 if(not keys(%{$SymbolInfo{$LibVersion}}))
9230 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009231 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009232 {
9233 if($CheckHeadersOnly) {
9234 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9235 }
9236 else {
9237 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9238 }
9239 }
9240 }
9241
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009242 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009243 if(not checkDump(1, "2.10")
9244 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009245 { # different formats
9246 $Remangle = 1;
9247 }
9248 if($CheckHeadersOnly)
9249 { # different languages
9250 if($UserLang)
9251 { # --lang=LANG for both versions
9252 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9253 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9254 {
9255 if($UserLang eq "C++")
9256 { # remangle symbols
9257 $Remangle = 1;
9258 }
9259 elsif($UserLang eq "C")
9260 { # remove mangling
9261 $Remangle = -1;
9262 }
9263 }
9264 }
9265 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009266
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009267 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009268 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009269 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009270 { # support for old ABI dumps
9271 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9272 {
9273 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9274 {
9275 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9276 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009277 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009278 if(defined $DVal and $DVal ne "")
9279 {
9280 if($TName eq "char") {
9281 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9282 }
9283 elsif($TName eq "bool") {
9284 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9285 }
9286 }
9287 }
9288 }
9289 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009290 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009291 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009292 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9293 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009294 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009295 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9296 # + support for old ABI dumps
9297 next;
9298 }
9299 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009300 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009301 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009302 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009303 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009304
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009305 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009306 if(not checkDump(1, "2.12")
9307 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009308 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009309 if($ShortName eq "operator>>")
9310 {
9311 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9312 { # corrected mangling of operator>>
9313 $SRemangle = 1;
9314 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009315 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009316 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9317 {
9318 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9319 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9320 { # corrected mangling of const global data
9321 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9322 # and incorrectly mangled by old ACC versions
9323 $SRemangle = 1;
9324 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009325 }
9326 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009327 if(not $CheckHeadersOnly)
9328 { # support for old ABI dumps
9329 if(not checkDump(1, "2.17")
9330 or not checkDump(2, "2.17"))
9331 {
9332 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9333 {
9334 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9335 {
9336 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9337 {
9338 $MnglName = $ShortName;
9339 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9340 }
9341 }
9342 }
9343 }
9344 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009345 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009346 { # support for old ABI dumps: some symbols are not mangled in old dumps
9347 # mangle both sets of symbols (old and new)
9348 # NOTE: remangling all symbols by the same mangler
9349 if($MnglName=~/\A_ZN(V|)K/)
9350 { # mangling may be incorrect on old ABI dumps
9351 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009352 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009353 }
9354 if($MnglName=~/\A_ZN(K|)V/)
9355 { # mangling may be incorrect on old ABI dumps
9356 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009357 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009358 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009359 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9360 or (not $ClassID and $CheckHeadersOnly)
9361 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9362 { # support for old ABI dumps, GCC >= 4.0
9363 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009364 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009365 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009366 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009367 $MangledNames{$LibVersion}{$MnglName} = 1;
9368 }
9369 }
9370 }
9371 elsif($Remangle==-1)
9372 { # remove mangling
9373 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009374 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009375 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009376 if(not $MnglName) {
9377 next;
9378 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009379
9380 # NOTE: duplicated entries in the ABI Dump
9381 if(defined $CompleteSignature{$LibVersion}{$MnglName})
9382 {
9383 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9384 {
9385 if($SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} eq "p1")
9386 {
9387 next;
9388 }
9389 }
9390 }
9391
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009392 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9393 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009394 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9395
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009396 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009397 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009398 { # support for old dumps
9399 # add "Volatile" attribute
9400 if($MnglName=~/_Z(K|)V/) {
9401 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9402 }
9403 }
9404 # symbol and its symlink have same signatures
9405 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009406 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009407 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009408
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009409 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9410 {
9411 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009412
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009413 if($SymVer{$LibVersion}{$Alias}) {
9414 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9415 }
9416 }
9417
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009418 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009419 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009420 }
9421 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9422 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9423 }
9424 if($ExtendedCheck)
9425 { # --ext option
9426 addExtension($LibVersion);
9427 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009428
9429 # clean memory
9430 delete($SymbolInfo{$LibVersion});
9431
9432 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009433 { # detect allocable classes with public exported constructors
9434 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009435 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009436 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009437 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009438 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009439 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9440 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009441 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009442 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009443 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009444 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009445 $AllocableClass{$LibVersion}{$ClassName} = 1;
9446 }
9447 }
9448 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009449 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009450 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009451 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009452 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009453 if($CheckHeadersOnly)
9454 {
9455 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9456 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9457 { # all symbols except non-virtual inline
9458 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9459 }
9460 }
9461 else {
9462 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009463 }
9464 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009465 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009466 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009467 }
9468 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009469 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009470 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009471 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009472 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009473 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009474 if(defined $Base{"Type"}
9475 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009476 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009477 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009478 if($Name=~/<([^<>\s]+)>/)
9479 {
9480 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9481 $ReturnedClass{$LibVersion}{$Tid} = 1;
9482 }
9483 }
9484 else {
9485 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9486 }
9487 }
9488 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009489 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009490 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009491 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009492 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009493 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009494 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009495 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009496 if($Base{"Type"}=~/Struct|Class/)
9497 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009498 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009499 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9500 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009501 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009502 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009503 }
9504 }
9505 }
9506 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009507
9508 # mapping {short name => symbols}
9509 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009510 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009511 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009512 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009513 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009514 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009515 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009516 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009517 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9518 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009519 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009520 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009521 }
9522 }
9523 }
9524 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009525
9526 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009527 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009528 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009529 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009530 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009531 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9532 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009533 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009534 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009535 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009536 $ClassNames{$LibVersion}{$TName} = 1;
9537 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009538 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009539 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9540 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009541 }
9542 }
9543 }
9544 }
9545 }
9546}
9547
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009548sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009549{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009550 my ($Tid, $LibVersion) = @_;
9551 if(not $Tid) {
9552 return $Tid;
9553 }
9554
9555 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9556 {
9557 if($TName_Tid{$LibVersion}{$Name}) {
9558 return $TName_Tid{$LibVersion}{$Name};
9559 }
9560 }
9561
9562 return $Tid;
9563}
9564
9565sub register_SymbolUsage($$$)
9566{
9567 my ($InfoId, $UsedType, $LibVersion) = @_;
9568
9569 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9570 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9571 {
9572 register_TypeUsage($RTid, $UsedType, $LibVersion);
9573 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9574 }
9575 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9576 {
9577 register_TypeUsage($FCid, $UsedType, $LibVersion);
9578 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9579
9580 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9581 { # register "this" pointer
9582 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9583 }
9584 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9585 { # register "this" pointer (const method)
9586 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9587 }
9588 }
9589 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9590 {
9591 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9592 {
9593 register_TypeUsage($PTid, $UsedType, $LibVersion);
9594 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9595 }
9596 }
9597 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9598 {
9599 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9600 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9601 register_TypeUsage($TTid, $UsedType, $LibVersion);
9602 }
9603 }
9604}
9605
9606sub register_TypeUsage($$$)
9607{
9608 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009609 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009610 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009611 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009612 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009613 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009614 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009615 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009616
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009617 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009618 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009619 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009620 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009621 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009622 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9623 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9624 }
9625 }
9626
9627 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9628 {
9629 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009630 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009631 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009632 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9633 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009634 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009635 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9636 {
9637 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9638 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009639 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009640 }
9641 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009642 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009643 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009644 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009645 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9646 {
9647 register_TypeUsage($MTid, $UsedType, $LibVersion);
9648 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009649 }
9650 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009651 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009652 or $TInfo{"Type"} eq "MethodPtr"
9653 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009654 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009655 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009656 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009657 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009658 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009659 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009660 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9661 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009662 }
9663 }
9664 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009665 if($TInfo{"Type"} eq "FieldPtr")
9666 {
9667 if(my $RTid = $TInfo{"Return"}) {
9668 register_TypeUsage($RTid, $UsedType, $LibVersion);
9669 }
9670 if(my $CTid = $TInfo{"Class"}) {
9671 register_TypeUsage($CTid, $UsedType, $LibVersion);
9672 }
9673 }
9674 if($TInfo{"Type"} eq "MethodPtr")
9675 {
9676 if(my $CTid = $TInfo{"Class"}) {
9677 register_TypeUsage($CTid, $UsedType, $LibVersion);
9678 }
9679 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009680 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009681 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009682 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009683 $UsedType->{$TypeId} = 1;
9684 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9685 {
9686 register_TypeUsage($BTid, $UsedType, $LibVersion);
9687 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9688 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009689 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009690 else
9691 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9692 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009693 }
9694 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009695}
9696
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009697sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009698{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009699 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9700
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009701 if($Level eq "Dump")
9702 {
9703 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9704 { # TODO: check if this symbol is from
9705 # base classes of other target symbols
9706 return 1;
9707 }
9708 }
9709
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009710 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9711 { # stdc++ interfaces
9712 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009713 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009714
9715 my $Target = 0;
9716 if(my $Header = $SInfo->{"Header"}) {
9717 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9718 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009719 if($ExtendedCheck)
9720 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009721 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009722 $Target = 1;
9723 }
9724 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009725 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009726 {
9727 if($Target)
9728 {
9729 if($Level eq "Dump")
9730 { # dumped
9731 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009732 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009733 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009734 return 1;
9735 }
9736 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009737 else {
9738 return 1;
9739 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009740 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009741 elsif($Level eq "Source")
9742 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009743 return 1;
9744 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009745 elsif($Level eq "Binary")
9746 { # checked
9747 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9748 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9749 return 1;
9750 }
9751 }
9752 }
9753 }
9754 else
9755 { # library is available
9756 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9757 { # exported symbols
9758 return 1;
9759 }
9760 if($Level eq "Dump")
9761 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009762 if($BinaryOnly)
9763 {
9764 if($SInfo->{"Data"})
9765 {
9766 if($Target) {
9767 return 1;
9768 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009769 }
9770 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009771 else
9772 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009773 if($Target) {
9774 return 1;
9775 }
9776 }
9777 }
9778 elsif($Level eq "Source")
9779 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009780 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009781 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009782 { # skip LOCAL symbols
9783 if($Target) {
9784 return 1;
9785 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009786 }
9787 }
9788 elsif($Level eq "Binary")
9789 { # checked
9790 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9791 {
9792 if($Target) {
9793 return 1;
9794 }
9795 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009796 }
9797 }
9798 return 0;
9799}
9800
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009801sub cleanDump($)
9802{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009803 my $LibVersion = $_[0];
9804 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9805 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009806 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9807 {
9808 delete($SymbolInfo{$LibVersion}{$InfoId});
9809 next;
9810 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009811 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009812 if(not $MnglName)
9813 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009814 delete($SymbolInfo{$LibVersion}{$InfoId});
9815 next;
9816 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009817 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009818 if(not $ShortName)
9819 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009820 delete($SymbolInfo{$LibVersion}{$InfoId});
9821 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009822 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009823 if($MnglName eq $ShortName)
9824 { # remove duplicate data
9825 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009826 }
9827 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9828 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9829 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009830 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9831 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9832 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009833 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009834 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009835 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009836 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009837 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9838 {
9839 delete($TypeInfo{$LibVersion}{$Tid});
9840 next;
9841 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009842 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009843 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009844 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009845 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9846 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9847 }
9848 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009849 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9850 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9851 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009852 }
9853}
9854
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009855sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009856{
9857 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009858
9859 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9860 {
9861 if(defined $TypeInfo{$LibVersion}{$Dupl})
9862 {
9863 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9864 { # duplicate
9865 return 0;
9866 }
9867 }
9868 }
9869
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009870 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9871
9872 if(isBuiltIn($THeader)) {
9873 return 0;
9874 }
9875
9876 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9877 return 0;
9878 }
9879
9880 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9881 return 0;
9882 }
9883
9884 if(selfTypedef($Tid, $LibVersion)) {
9885 return 0;
9886 }
9887
9888 if(not isTargetType($Tid, $LibVersion)) {
9889 return 0;
9890 }
9891
9892 return 0;
9893}
9894
9895sub isTargetType($$)
9896{
9897 my ($Tid, $LibVersion) = @_;
9898
9899 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9900 { # derived
9901 return 1;
9902 }
9903
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009904 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009905 { # NOTE: header is defined to source if undefined (DWARF dumps)
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009906 if(not is_target_header($THeader, $LibVersion))
9907 { # from target headers
9908 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009909 }
9910 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009911 else
9912 { # NOTE: if type is defined in source
9913 if($UsedDump{$LibVersion}{"Public"})
9914 {
9915 if(isPrivateABI($Tid, $LibVersion)) {
9916 return 0;
9917 }
9918 else {
9919 return 1;
9920 }
9921 }
9922 else {
9923 return 0;
9924 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +03009925 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009926
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +03009927 if($SkipInternalTypes)
9928 {
9929 if($TypeInfo{$LibVersion}{$Tid}{"Name"}=~/($SkipInternalTypes)/)
9930 {
9931 return 0;
9932 }
9933 }
9934
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009935 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009936}
9937
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009938sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009939{ # remove unused data types from the ABI dump
9940 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009941
9942 my %UsedType = ();
9943
9944 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009945 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009946 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009947 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009948 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009949 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009950 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009951 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009952 next;
9953 }
9954
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009955 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009956 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009957 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009958 {
9959 my %Tree = ();
9960 register_TypeUsage($Tid, \%Tree, $LibVersion);
9961
9962 my $Tmpl = 0;
9963 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9964 {
9965 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9966 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9967 {
9968 $Tmpl = 1;
9969 last;
9970 }
9971 }
9972 if(not $Tmpl)
9973 {
9974 foreach (keys(%Tree)) {
9975 $UsedType{$_} = 1;
9976 }
9977 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009978 }
9979 }
9980 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009981
9982 my %Delete = ();
9983
9984 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009985 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009986 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009987 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009988 next;
9989 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009990
9991 if($Kind eq "Extra")
9992 {
9993 my %Tree = ();
9994 register_TypeUsage($Tid, \%Tree, $LibVersion);
9995
9996 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9997 {
9998 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9999 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
10000 {
10001 $Delete{$Tid} = 1;
10002 last;
10003 }
10004 }
10005 }
10006 else
10007 {
10008 # remove type
10009 delete($TypeInfo{$LibVersion}{$Tid});
10010 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010011 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010012
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010013 if($Kind eq "Extra")
10014 { # remove duplicates
10015 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
10016 {
10017 if($UsedType{$Tid})
10018 { # All & Extended
10019 next;
10020 }
10021
10022 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10023
10024 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
10025 delete($TypeInfo{$LibVersion}{$Tid});
10026 }
10027 }
10028 }
10029
10030 foreach my $Tid (keys(%Delete))
10031 {
10032 delete($TypeInfo{$LibVersion}{$Tid});
10033 }
10034}
10035
10036sub check_Completeness($$)
10037{
10038 my ($Info, $LibVersion) = @_;
10039
10040 # data types
10041 if(defined $Info->{"Memb"})
10042 {
10043 foreach my $Pos (keys(%{$Info->{"Memb"}}))
10044 {
10045 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
10046 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
10047 }
10048 }
10049 }
10050 if(defined $Info->{"Base"})
10051 {
10052 foreach my $Bid (keys(%{$Info->{"Base"}})) {
10053 check_TypeInfo($Bid, $LibVersion);
10054 }
10055 }
10056 if(defined $Info->{"BaseType"}) {
10057 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
10058 }
10059 if(defined $Info->{"TParam"})
10060 {
10061 foreach my $Pos (keys(%{$Info->{"TParam"}}))
10062 {
10063 my $TName = $Info->{"TParam"}{$Pos}{"name"};
10064 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
10065 next;
10066 }
10067 if($TName eq "_BoolType") {
10068 next;
10069 }
10070 if($TName=~/\Asizeof\(/) {
10071 next;
10072 }
10073 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
10074 check_TypeInfo($Tid, $LibVersion);
10075 }
10076 else
10077 {
10078 if(defined $Debug) {
10079 printMsg("WARNING", "missed type $TName");
10080 }
10081 }
10082 }
10083 }
10084
10085 # symbols
10086 if(defined $Info->{"Param"})
10087 {
10088 foreach my $Pos (keys(%{$Info->{"Param"}}))
10089 {
10090 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10091 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10092 }
10093 }
10094 }
10095 if(defined $Info->{"Return"}) {
10096 check_TypeInfo($Info->{"Return"}, $LibVersion);
10097 }
10098 if(defined $Info->{"Class"}) {
10099 check_TypeInfo($Info->{"Class"}, $LibVersion);
10100 }
10101}
10102
10103sub check_TypeInfo($$)
10104{
10105 my ($Tid, $LibVersion) = @_;
10106
10107 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10108 return;
10109 }
10110 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10111
10112 if(defined $TypeInfo{$LibVersion}{$Tid})
10113 {
10114 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10115 printMsg("ERROR", "missed type name ($Tid)");
10116 }
10117 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10118 }
10119 else {
10120 printMsg("ERROR", "missed type id $Tid");
10121 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010122}
10123
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010124sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010125{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010126 my ($TypeId, $LibVersion) = @_;
10127 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010128 if($Type{"Type"} eq "Typedef")
10129 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010130 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010131 if($Base{"Type"}=~/Class|Struct/)
10132 {
10133 if($Type{"Name"} eq $Base{"Name"}) {
10134 return 1;
10135 }
10136 elsif($Type{"Name"}=~/::(\w+)\Z/)
10137 {
10138 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10139 { # QPointer<QWidget>::QPointer
10140 return 1;
10141 }
10142 }
10143 }
10144 }
10145 return 0;
10146}
10147
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010148sub addExtension($)
10149{
10150 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010151 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010152 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +030010153 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010154 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010155 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10156 $TName=~s/\A(struct|union|class|enum) //;
10157 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010158
10159 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10160 "Header" => "extended.h",
10161 "ShortName" => $Symbol,
10162 "MnglName" => $Symbol,
10163 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10164 );
10165
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010166 $ExtendedSymbols{$Symbol} = 1;
10167 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10168 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010169 }
10170 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010171 $ExtendedSymbols{"external_func_0"} = 1;
10172 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10173 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010174}
10175
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010176sub findMethod($$$)
10177{
10178 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010179 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010180 {
10181 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10182 return $VirtMethodInClass;
10183 }
10184 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10185 return $VirtMethodInBaseClasses;
10186 }
10187 }
10188 return "";
10189}
10190
10191sub findMethod_Class($$$)
10192{
10193 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010194 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010195 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10196 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10197 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10198 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10199 { # search for interface with the same parameters suffix (overridden)
10200 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10201 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010202 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10203 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010204 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10205 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010206 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10207 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10208 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10209 return $Candidate;
10210 }
10211 }
10212 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010213 else
10214 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010215 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10216 return $Candidate;
10217 }
10218 }
10219 }
10220 }
10221 return "";
10222}
10223
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010224sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010225{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010226 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010227 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010228 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010229 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10230 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010231 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010232 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010233 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010234 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10235 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010236 { # pure virtual D2-destructors are marked as "virt" in the dump
10237 # virtual D2-destructors are NOT marked as "virt" in the dump
10238 # both destructors are not presented in the v-table
10239 next;
10240 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010241 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010242 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10243 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010244 }
10245}
10246
10247sub registerOverriding($)
10248{
10249 my $LibVersion = $_[0];
10250 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010251 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010252 foreach my $ClassName (@Classes)
10253 {
10254 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10255 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010256 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10257 { # pure virtuals
10258 next;
10259 }
10260 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10261 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010262 {
10263 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10264 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10265 { # both overridden virtual methods
10266 # and implemented pure virtual methods
10267 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10268 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10269 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10270 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010271 }
10272 }
10273 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10274 delete($VirtualTable{$LibVersion}{$ClassName});
10275 }
10276 }
10277}
10278
10279sub setVirtFuncPositions($)
10280{
10281 my $LibVersion = $_[0];
10282 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10283 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010284 my ($Num, $Rel) = (1, 0);
10285
10286 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010287 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010288 if($UsedDump{$LibVersion}{"DWARF"}) {
10289 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10290 }
10291 else {
10292 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10293 }
10294 foreach my $VirtFunc (@Funcs)
10295 {
10296 if($UsedDump{$LibVersion}{"DWARF"}) {
10297 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10298 }
10299 else {
10300 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10301 }
10302
10303 # set relative positions
10304 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10305 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10306 { # relative position excluding added and removed virtual functions
10307 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10308 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10309 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10310 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010311 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010312 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010313 }
10314 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010315 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010316 {
10317 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010318 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010319 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010320 }
10321 }
10322}
10323
10324sub get_sub_classes($$$)
10325{
10326 my ($ClassId, $LibVersion, $Recursive) = @_;
10327 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10328 my @Subs = ();
10329 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10330 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010331 if($Recursive)
10332 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010333 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10334 push(@Subs, $SubSubId);
10335 }
10336 }
10337 push(@Subs, $SubId);
10338 }
10339 return @Subs;
10340}
10341
10342sub get_base_classes($$$)
10343{
10344 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010345 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010346 return () if(not defined $ClassType{"Base"});
10347 my @Bases = ();
10348 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10349 keys(%{$ClassType{"Base"}}))
10350 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010351 if($Recursive)
10352 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010353 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10354 push(@Bases, $SubBaseId);
10355 }
10356 }
10357 push(@Bases, $BaseId);
10358 }
10359 return @Bases;
10360}
10361
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010362sub getVTable_Model($$)
10363{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010364 my ($ClassId, $LibVersion) = @_;
10365 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10366 my @Elements = ();
10367 foreach my $BaseId (@Bases, $ClassId)
10368 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010369 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010370 {
10371 if(defined $VirtualTable{$LibVersion}{$BName})
10372 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010373 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10374 if($UsedDump{$LibVersion}{"DWARF"}) {
10375 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10376 }
10377 else {
10378 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10379 }
10380 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010381 push(@Elements, $VFunc);
10382 }
10383 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010384 }
10385 }
10386 return @Elements;
10387}
10388
10389sub getVShift($$)
10390{
10391 my ($ClassId, $LibVersion) = @_;
10392 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10393 my $VShift = 0;
10394 foreach my $BaseId (@Bases)
10395 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010396 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010397 {
10398 if(defined $VirtualTable{$LibVersion}{$BName}) {
10399 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10400 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010401 }
10402 }
10403 return $VShift;
10404}
10405
10406sub getShift($$)
10407{
10408 my ($ClassId, $LibVersion) = @_;
10409 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10410 my $Shift = 0;
10411 foreach my $BaseId (@Bases)
10412 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010413 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010414 {
10415 if($Size!=1)
10416 { # not empty base class
10417 $Shift+=$Size;
10418 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010419 }
10420 }
10421 return $Shift;
10422}
10423
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010424sub getVTable_Size($$)
10425{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010426 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010427 my $Size = 0;
10428 # three approaches
10429 if(not $Size)
10430 { # real size
10431 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10432 $Size = keys(%VTable);
10433 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010434 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010435 if(not $Size)
10436 { # shared library symbol size
10437 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10438 $Size /= $WORD_SIZE{$LibVersion};
10439 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010440 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010441 if(not $Size)
10442 { # model size
10443 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10444 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10445 }
10446 }
10447 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010448}
10449
10450sub isCopyingClass($$)
10451{
10452 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010453 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010454}
10455
10456sub isLeafClass($$)
10457{
10458 my ($ClassId, $LibVersion) = @_;
10459 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10460}
10461
10462sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010463{ # check structured type for public fields
10464 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010465}
10466
10467sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010468{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010469 my ($TypePtr, $Skip, $Start, $End) = @_;
10470 return 0 if(not $TypePtr);
10471 if($End==-1) {
10472 $End = keys(%{$TypePtr->{"Memb"}})-1;
10473 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030010474 foreach my $MemPos (sort {int($a)<=>int($b)} keys(%{$TypePtr->{"Memb"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010475 {
10476 if($Skip and $Skip->{$MemPos})
10477 { # skip removed/added fields
10478 next;
10479 }
10480 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10481 {
10482 if(isPublic($TypePtr, $MemPos)) {
10483 return ($MemPos+1);
10484 }
10485 }
10486 }
10487 return 0;
10488}
10489
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010490sub isReserved($)
10491{ # reserved fields == private
10492 my $MName = $_[0];
10493 if($MName=~/reserved|padding|f_spare/i) {
10494 return 1;
10495 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010496 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010497 return 1;
10498 }
10499 if($MName=~/(pad\d+)/i) {
10500 return 1;
10501 }
10502 return 0;
10503}
10504
10505sub isPublic($$)
10506{
10507 my ($TypePtr, $FieldPos) = @_;
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010508
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010509 return 0 if(not $TypePtr);
10510 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10511 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010512
10513 my $Access = $TypePtr->{"Memb"}{$FieldPos}{"access"};
10514 if($Access eq "private")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010515 { # by access in C++ language
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010516 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010517 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010518
10519 # by name in C language
10520 # TODO: add other methods to detect private members
10521 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030010522 if($MName=~/priv|abidata|parent_object|impl/i)
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010523 { # C-styled private data
10524 return 0;
10525 }
10526 if(lc($MName) eq "abi")
10527 { # ABI information/reserved field
10528 return 0;
10529 }
10530 if(isReserved($MName))
10531 { # reserved fields
10532 return 0;
10533 }
10534
10535 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010536}
10537
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010538sub getVTable_Real($$)
10539{
10540 my ($ClassName, $LibVersion) = @_;
10541 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10542 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010543 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010544 if(defined $Type{"VTable"}) {
10545 return %{$Type{"VTable"}};
10546 }
10547 }
10548 return ();
10549}
10550
10551sub cmpVTables($)
10552{
10553 my $ClassName = $_[0];
10554 my $Res = cmpVTables_Real($ClassName, 1);
10555 if($Res==-1) {
10556 $Res = cmpVTables_Model($ClassName);
10557 }
10558 return $Res;
10559}
10560
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010561sub cmpVTables_Model($)
10562{
10563 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010564 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010565 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010566 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010567 return 1;
10568 }
10569 }
10570 return 0;
10571}
10572
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010573sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010574{
10575 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010576 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10577 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010578 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010579 my %VTable_Old = getVTable_Real($ClassName, 1);
10580 my %VTable_New = getVTable_Real($ClassName, 2);
10581 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010582 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010583 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010584 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010585 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010586 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10587 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010588 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010589 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010590 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010591 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010592 my $Entry1 = $VTable_Old{$Offset};
10593 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010594 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010595 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010596 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010597 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010598
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010599 $Entry1 = simpleVEntry($Entry1);
10600 $Entry2 = simpleVEntry($Entry2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010601
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030010602 if($Entry1=~/ 0x/ or $Entry2=~/ 0x/)
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010603 { # NOTE: problem with vtable-dumper
10604 next;
10605 }
10606
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010607 if($Entry1 ne $Entry2)
10608 { # register as changed
10609 if($Entry1=~/::([^:]+)\Z/)
10610 {
10611 my $M1 = $1;
10612 if($Entry2=~/::([^:]+)\Z/)
10613 {
10614 my $M2 = $1;
10615 if($M1 eq $M2)
10616 { # overridden
10617 next;
10618 }
10619 }
10620 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010621 if(differentDumps("G"))
10622 {
10623 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10624 {
10625 # GCC 4.6.1: -0x00000000000000010
10626 # GCC 4.7.0: -16
10627 next;
10628 }
10629 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010630 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010631 }
10632 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010633 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010634}
10635
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010636sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010637{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010638 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010639 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10640 {
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010641 my $ClassId = $TName_Tid{1}{$ClassName};
10642 if(isPrivateABI($ClassId, 1)) {
10643 next;
10644 }
10645
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010646 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010647 { # already registered
10648 next;
10649 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010650 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010651 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010652 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010653 foreach my $Symbol (@Affected)
10654 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010655 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010656 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010657 "Target"=>$ClassName);
10658 }
10659 }
10660 }
10661}
10662
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010663sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010664{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010665 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010666 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010667 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010668 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010669 next if(not $ClassId);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010670
10671 if(isPrivateABI($ClassId, 1)) {
10672 next;
10673 }
10674
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010675 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010676 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010677 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010678 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010679 if($TName_Tid{1}{$ClassName}
10680 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010681 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010682 if(defined $CompleteSignature{1}{$Symbol}
10683 and $CompleteSignature{1}{$Symbol}{"Virt"})
10684 { # override some method in v.1
10685 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010686 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010687 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010688 }
10689 }
10690 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010691 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010692 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010693 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010694 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010695 if($TName_Tid{2}{$ClassName}
10696 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010697 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010698 if(defined $CompleteSignature{2}{$Symbol}
10699 and $CompleteSignature{2}{$Symbol}{"Virt"})
10700 { # override some method in v.2
10701 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010702 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010703 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010704 }
10705 }
10706 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010707 if($Level eq "Binary")
10708 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010709 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010710 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10711 { # check replacements, including pure virtual methods
10712 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10713 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010714 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010715 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10716 if($AddedPos==$RemovedPos)
10717 {
10718 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10719 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10720 last; # other methods will be reported as "added" or "removed"
10721 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010722 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010723 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10724 {
10725 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10726 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010727 next;
10728 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010729 my $ProblemType = "Virtual_Replacement";
10730 my @Affected = ($RemovedVFunc);
10731 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10732 { # pure methods
10733 if(not isUsedClass($ClassId, 1, $Level))
10734 { # not a parameter of some exported method
10735 next;
10736 }
10737 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010738
10739 # affected all methods (both virtual and non-virtual ones)
10740 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10741 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010742 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010743 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010744 foreach my $AffectedInt (@Affected)
10745 {
10746 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10747 { # affected exported methods only
10748 next;
10749 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010750 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10751 next;
10752 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010753 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10754 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010755 "Target"=>get_Signature($AddedVFunc, 2),
10756 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10757 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010758 }
10759 }
10760 }
10761 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010762 if(not checkDump(1, "2.0")
10763 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010764 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010765 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010766 return;
10767 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010768 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010769 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010770 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010771 next if(not $ClassId_Old);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010772
10773 if(isPrivateABI($ClassId_Old, 1)) {
10774 next;
10775 }
10776
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010777 if(not isCreatable($ClassId_Old, 1))
10778 { # skip classes without public constructors (including auto-generated)
10779 # example: class has only a private exported or private inline constructor
10780 next;
10781 }
10782 if($ClassName=~/>/)
10783 { # skip affected template instances
10784 next;
10785 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010786 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010787 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010788 if(not $ClassId_New) {
10789 next;
10790 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010791 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010792 if($Class_New{"Type"}!~/Class|Struct/)
10793 { # became typedef
10794 if($Level eq "Binary") {
10795 next;
10796 }
10797 if($Level eq "Source")
10798 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010799 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010800 if($Class_New{"Type"}!~/Class|Struct/) {
10801 next;
10802 }
10803 $ClassId_New = $Class_New{"Tid"};
10804 }
10805 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010806
10807 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10808 { # incomplete info in the ABI dump
10809 next;
10810 }
10811
10812
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010813 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10814 my @Bases_New = sort {$Class_New{"Base"}{$a}{"pos"}<=>$Class_New{"Base"}{$b}{"pos"}} keys(%{$Class_New{"Base"}});
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010815
10816 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10817 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10818
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010819 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010820 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10821 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010822 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10823 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010824 my $Shift_Old = getShift($ClassId_Old, 1);
10825 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010826 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010827 my ($Added, $Removed) = (0, 0);
10828 my @StableBases_Old = ();
10829 foreach my $BaseId (@Bases_Old)
10830 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010831 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010832 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010833 push(@StableBases_Old, $BaseId);
10834 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010835 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010836 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010837 { # removed base
10838 # excluding namespace::SomeClass to SomeClass renaming
10839 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010840 if($Level eq "Binary")
10841 { # Binary-level
10842 if($Shift_Old ne $Shift_New)
10843 { # affected fields
10844 if(havePubFields(\%Class_Old)) {
10845 $ProblemKind .= "_And_Shift";
10846 }
10847 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10848 $ProblemKind .= "_And_Size";
10849 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010850 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010851 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10852 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010853 { # affected v-table
10854 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010855 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010856 }
10857 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010858 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010859 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10860 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010861 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10862 {
10863 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10864 if($ProblemKind=~/VTable/) {
10865 $VTableChanged_M{$SubName}=1;
10866 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010867 }
10868 }
10869 foreach my $Interface (@Affected)
10870 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010871 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10872 next;
10873 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010874 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010875 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010876 "Target"=>$BaseName,
10877 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10878 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10879 "Shift"=>abs($Shift_New-$Shift_Old) );
10880 }
10881 $Removed+=1;
10882 }
10883 }
10884 my @StableBases_New = ();
10885 foreach my $BaseId (@Bases_New)
10886 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010887 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010888 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010889 push(@StableBases_New, $BaseId);
10890 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010891 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010892 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010893 { # added base
10894 # excluding namespace::SomeClass to SomeClass renaming
10895 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010896 if($Level eq "Binary")
10897 { # Binary-level
10898 if($Shift_Old ne $Shift_New)
10899 { # affected fields
10900 if(havePubFields(\%Class_Old)) {
10901 $ProblemKind .= "_And_Shift";
10902 }
10903 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10904 $ProblemKind .= "_And_Size";
10905 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010906 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010907 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10908 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010909 { # affected v-table
10910 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010911 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010912 }
10913 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010914 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010915 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10916 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010917 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10918 {
10919 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10920 if($ProblemKind=~/VTable/) {
10921 $VTableChanged_M{$SubName}=1;
10922 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010923 }
10924 }
10925 foreach my $Interface (@Affected)
10926 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010927 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10928 next;
10929 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010930 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010931 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010932 "Target"=>$BaseName,
10933 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10934 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10935 "Shift"=>abs($Shift_New-$Shift_Old) );
10936 }
10937 $Added+=1;
10938 }
10939 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010940 if($Level eq "Binary")
10941 { # Binary-level
10942 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010943 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10944 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010945 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010946 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010947 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010948 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010949 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010950 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10951 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010952 if($NewPos!=$OldPos)
10953 { # changed position of the base class
10954 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010955 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010956 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10957 next;
10958 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010959 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10960 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010961 "Target"=>$BaseName,
10962 "Old_Value"=>$OldPos-1,
10963 "New_Value"=>$NewPos-1 );
10964 }
10965 }
10966 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10967 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10968 { # became non-virtual base
10969 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10970 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010971 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10972 next;
10973 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010974 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10975 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010976 "Target"=>$BaseName );
10977 }
10978 }
10979 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10980 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10981 { # became virtual base
10982 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10983 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010984 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10985 next;
10986 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010987 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10988 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010989 "Target"=>$BaseName );
10990 }
10991 }
10992 }
10993 }
10994 # detect size changes in base classes
10995 if($Shift_Old!=$Shift_New)
10996 { # size of allocable class
10997 foreach my $BaseId (@StableBases_Old)
10998 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010999 my %BaseType = get_Type($BaseId, 1);
11000 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011001 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011002 if($Size_Old ne $Size_New
11003 and $Size_Old and $Size_New)
11004 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011005 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011006 if(isCopyingClass($BaseId, 1)) {
11007 $ProblemType = "Size_Of_Copying_Class";
11008 }
11009 elsif($AllocableClass{1}{$BaseType{"Name"}})
11010 {
11011 if($Size_New>$Size_Old)
11012 { # increased size
11013 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011014 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011015 else
11016 { # decreased size
11017 $ProblemType = "Size_Of_Allocable_Class_Decreased";
11018 if(not havePubFields(\%Class_Old))
11019 { # affected class has no public members
11020 next;
11021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011022 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011023 }
11024 next if(not $ProblemType);
11025 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
11026 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011027 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
11028 next;
11029 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011030 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
11031 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011032 "Target"=>$BaseType{"Name"},
11033 "Old_Size"=>$Size_Old*$BYTE_SIZE,
11034 "New_Size"=>$Size_New*$BYTE_SIZE );
11035 }
11036 }
11037 }
11038 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011039 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011040 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011041 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011042 { # compare virtual tables size in base classes
11043 my $VShift_Old = getVShift($ClassId_Old, 1);
11044 my $VShift_New = getVShift($ClassId_New, 2);
11045 if($VShift_Old ne $VShift_New)
11046 { # changes in the base class or changes in the list of base classes
11047 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
11048 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
11049 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011050 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011051 foreach my $BaseId (@AllBases_Old)
11052 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011053 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011054 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011055 { # lost base
11056 next;
11057 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011058 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
11059 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011060 if($VSize_Old!=$VSize_New)
11061 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011062 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011063 { # TODO: affected non-virtual methods?
11064 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011065 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
11066 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011067 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011068 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011069 { # skip interfaces that have not changed the absolute virtual position
11070 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011071 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011072 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
11073 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011074 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011075 $VTableChanged_M{$BaseType{"Name"}} = 1;
11076 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011077 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
11078 { # the reason of the layout change: added virtual functions
11079 next if($VirtualReplacement{$VirtFunc});
11080 my $ProblemType = "Added_Virtual_Method";
11081 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
11082 $ProblemType = "Added_Pure_Virtual_Method";
11083 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011084 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011085 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011086 "Target"=>get_Signature($VirtFunc, 2) );
11087 }
11088 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
11089 { # the reason of the layout change: removed virtual functions
11090 next if($VirtualReplacement{$VirtFunc});
11091 my $ProblemType = "Removed_Virtual_Method";
11092 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11093 $ProblemType = "Removed_Pure_Virtual_Method";
11094 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011095 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011096 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011097 "Target"=>get_Signature($VirtFunc, 1) );
11098 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011099 }
11100 }
11101 }
11102 }
11103 }
11104 }
11105 }
11106}
11107
11108sub isCreatable($$)
11109{
11110 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011111 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011112 or isCopyingClass($ClassId, $LibVersion)) {
11113 return 1;
11114 }
11115 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11116 { # Fix for incomplete data: if this class has
11117 # a base class then it should also has a constructor
11118 return 1;
11119 }
11120 if($ReturnedClass{$LibVersion}{$ClassId})
11121 { # returned by some method of this class
11122 # or any other class
11123 return 1;
11124 }
11125 return 0;
11126}
11127
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011128sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011129{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011130 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011131 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11132 { # parameter of some exported method
11133 return 1;
11134 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011135 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11136 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011137 { # method from target class
11138 return 1;
11139 }
11140 return 0;
11141}
11142
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011143sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011144{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011145 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011146 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011147 # - virtual
11148 # - pure-virtual
11149 # - non-virtual
11150 if($CompleteSignature{1}{$Interface}{"Data"})
11151 { # global data is not affected
11152 return;
11153 }
11154 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011155 if(not $Class_Id) {
11156 return;
11157 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011158 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011159 if(cmpVTables_Real($CName, 1)==0)
11160 { # no changes
11161 return;
11162 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011163 $CheckedTypes{$Level}{$CName} = 1;
11164 if($Level eq "Binary")
11165 { # Binary-level
11166 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11167 and not isUsedClass($Class_Id, 1, $Level))
11168 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011169 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011170 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011171 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011172 }
11173 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11174 {
11175 if(defined $VirtualTable{2}{$CName}{$Func}
11176 and defined $CompleteSignature{2}{$Func})
11177 {
11178 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11179 and $CompleteSignature{2}{$Func}{"PureVirt"})
11180 { # became pure virtual
11181 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11182 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011183 "Target"=>get_Signature_M($Func, 1) );
11184 $VTableChanged_M{$CName} = 1;
11185 }
11186 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11187 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11188 { # became non-pure virtual
11189 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11190 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011191 "Target"=>get_Signature_M($Func, 1) );
11192 $VTableChanged_M{$CName} = 1;
11193 }
11194 }
11195 }
11196 if($Level eq "Binary")
11197 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011198 # check virtual table structure
11199 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11200 {
11201 next if($Interface eq $AddedVFunc);
11202 next if($VirtualReplacement{$AddedVFunc});
11203 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11204 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11205 { # pure virtual methods affect all others (virtual and non-virtual)
11206 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011207 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011208 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011209 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011210 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011211 elsif(not defined $VirtualTable{1}{$CName}
11212 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011213 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011214 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011215 { # became polymorphous class, added v-table pointer
11216 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011217 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011218 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011219 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011220 }
11221 else
11222 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011223 my $VSize_Old = getVTable_Size($CName, 1);
11224 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011225 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011226 if(isCopyingClass($Class_Id, 1))
11227 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11228 my $ProblemType = "Added_Virtual_Method";
11229 if(isLeafClass($Class_Id, 1)) {
11230 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11231 }
11232 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11233 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011234 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011235 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011236 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011237 else
11238 {
11239 my $ProblemType = "Added_Virtual_Method";
11240 if(isLeafClass($Class_Id, 1)) {
11241 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11242 }
11243 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11244 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011245 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011246 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011247 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011248 }
11249 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011250 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11251 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011252 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011253 if(defined $VirtualTable{1}{$CName}
11254 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011255 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011256 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11257 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011258
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011259 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011260 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011261 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11262 foreach my $ASymbol (@Affected)
11263 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011264 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11265 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011266 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011267 next;
11268 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011269 }
11270 $CheckedSymbols{$Level}{$ASymbol} = 1;
11271 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11272 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011273 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011274 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011275 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011276 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011277 }
11278 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011279 else {
11280 # safe
11281 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011282 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011283 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11284 {
11285 next if($VirtualReplacement{$RemovedVFunc});
11286 if($RemovedVFunc eq $Interface
11287 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11288 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011289 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011290 next;
11291 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011292 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011293 { # became non-polymorphous class, removed v-table pointer
11294 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11295 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011296 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011297 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011298 }
11299 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11300 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11301 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011302 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011303 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011304 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11305 next;
11306 }
11307 my $VPos_New = -1;
11308 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011309 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011310 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11311 }
11312 else
11313 {
11314 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011315 next;
11316 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011317 }
11318 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11319 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11320 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11321 {
11322 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11323 foreach my $ASymbol (@Affected)
11324 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011325 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11326 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011327 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011328 next;
11329 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011330 }
11331 my $ProblemType = "Removed_Virtual_Method";
11332 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11333 $ProblemType = "Removed_Pure_Virtual_Method";
11334 }
11335 $CheckedSymbols{$Level}{$ASymbol} = 1;
11336 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11337 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011338 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011339 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011340 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011341 }
11342 }
11343 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011344 }
11345 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011346 else
11347 { # Source-level
11348 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011349 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011350 next if($Interface eq $AddedVFunc);
11351 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011352 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011353 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11354 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011355 "Target"=>get_Signature($AddedVFunc, 2) );
11356 }
11357 }
11358 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11359 {
11360 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11361 {
11362 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11363 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011364 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011365 }
11366 }
11367 }
11368}
11369
11370sub find_MemberPair_Pos_byName($$)
11371{
11372 my ($Member_Name, $Pair_Type) = @_;
11373 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11374 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11375 {
11376 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11377 {
11378 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11379 $Name=~s/\A[_]+|[_]+\Z//g;
11380 if($Name eq $Member_Name) {
11381 return $MemberPair_Pos;
11382 }
11383 }
11384 }
11385 return "lost";
11386}
11387
11388sub find_MemberPair_Pos_byVal($$)
11389{
11390 my ($Member_Value, $Pair_Type) = @_;
11391 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11392 {
11393 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11394 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11395 return $MemberPair_Pos;
11396 }
11397 }
11398 return "lost";
11399}
11400
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011401sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011402{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011403 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011404 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011405 if( $_->{"T1"} eq $_[0]
11406 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011407 {
11408 return 1;
11409 }
11410 }
11411 return 0;
11412}
11413
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011414sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011415{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011416 my %IDs = (
11417 "T1" => $_[0],
11418 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011419 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011420 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011421}
11422
11423sub isRenamed($$$$$)
11424{
11425 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11426 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11427 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011428 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011429 if(not defined $Type2->{"Memb"}{$MemPos}) {
11430 return "";
11431 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011432 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011433 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011434
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011435 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11436 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011437 if($MemberPair_Pos_Rev eq "lost")
11438 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011439 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11440 { # base type match
11441 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011442 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011443 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11444 { # exact type match
11445 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011446 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011447 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11448 { # size match
11449 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011450 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011451 if(isReserved($Pair_Name))
11452 { # reserved fields
11453 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011454 }
11455 }
11456 return "";
11457}
11458
11459sub isLastElem($$)
11460{
11461 my ($Pos, $TypeRef) = @_;
11462 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030011463 if($Name=~/last|count|max|total|num/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011464 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11465 return 1;
11466 }
11467 elsif($Name=~/END|NLIMITS\Z/)
11468 { # __RLIMIT_NLIMITS
11469 return 1;
11470 }
11471 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11472 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11473 { # NImageFormats, NColorRoles
11474 return 1;
11475 }
11476 return 0;
11477}
11478
11479sub nonComparable($$)
11480{
11481 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011482
11483 my $N1 = $T1->{"Name"};
11484 my $N2 = $T2->{"Name"};
11485
11486 $N1=~s/\A(struct|union|enum) //;
11487 $N2=~s/\A(struct|union|enum) //;
11488
11489 if($N1 ne $N2
11490 and not isAnon($N1)
11491 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011492 { # different names
11493 if($T1->{"Type"} ne "Pointer"
11494 or $T2->{"Type"} ne "Pointer")
11495 { # compare base types
11496 return 1;
11497 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011498 if($N1!~/\Avoid\s*\*/
11499 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011500 {
11501 return 1;
11502 }
11503 }
11504 elsif($T1->{"Type"} ne $T2->{"Type"})
11505 { # different types
11506 if($T1->{"Type"} eq "Class"
11507 and $T2->{"Type"} eq "Struct")
11508 { # "class" to "struct"
11509 return 0;
11510 }
11511 elsif($T2->{"Type"} eq "Class"
11512 and $T1->{"Type"} eq "Struct")
11513 { # "struct" to "class"
11514 return 0;
11515 }
11516 else
11517 { # "class" to "enum"
11518 # "union" to "class"
11519 # ...
11520 return 1;
11521 }
11522 }
11523 return 0;
11524}
11525
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011526sub isOpaque($)
11527{
11528 my $T = $_[0];
11529 if(not defined $T->{"Memb"})
11530 {
11531 return 1;
11532 }
11533 return 0;
11534}
11535
11536sub removeVPtr($)
11537{ # support for old ABI dumps
11538 my $TPtr = $_[0];
11539 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11540 if($#Pos>=1)
11541 {
11542 foreach my $Pos (0 .. $#Pos-1)
11543 {
11544 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11545 }
11546 delete($TPtr->{"Memb"}{$#Pos});
11547 }
11548}
11549
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011550sub isPrivateABI($$)
11551{
11552 my ($TypeId, $LibVersion) = @_;
11553
11554 if($CheckPrivateABI) {
11555 return 0;
11556 }
11557
11558 if(defined $TypeInfo{$LibVersion}{$TypeId}{"PrivateABI"}) {
11559 return 1;
11560 }
11561
11562 return 0;
11563}
11564
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011565sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011566{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011567 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011568 return {} if(not $Type1_Id or not $Type2_Id);
11569
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011570 if(defined $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011571 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011572 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011573 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011574
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011575 my %Type1 = get_Type($Type1_Id, 1);
11576 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011577 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011578 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011579 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011580
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011581 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11582 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011583
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011584 if(defined $UsedDump{1}{"DWARF"})
11585 {
11586 if($Type1_Pure{"Name"} eq "__unknown__"
11587 or $Type2_Pure{"Name"} eq "__unknown__")
11588 { # Error ABI dump
11589 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11590 }
11591 }
11592
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011593 if(isPrivateABI($Type1_Id, 1)) {
11594 return {};
11595 }
11596
11597 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
11598 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11599
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011600 my %SubProblems = ();
11601
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011602 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11603 {
11604 if($Type1_Pure{"Type"}=~/Struct|Union/
11605 and $Type2_Pure{"Type"}=~/Struct|Union/)
11606 {
11607 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11608 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011609 if(not defined $UsedDump{1}{"DWARF"}
11610 and not defined $UsedDump{2}{"DWARF"})
11611 {
11612 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11613 "Target"=>$Type1_Pure{"Name"},
11614 "Type_Name"=>$Type1_Pure{"Name"} );
11615 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011616
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011617 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011618 }
11619 }
11620 }
11621
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011622 if(not $Type1_Pure{"Size"}
11623 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011624 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011625 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11626 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11627 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011628 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011629 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011630 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011631 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011632 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011633 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011634 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011635 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11636 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11637 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011638
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011639 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11640 return {};
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011641 }
11642
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011643 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11644 { # support for old ABI dumps
11645 # _vptr field added in 3.0
11646 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11647 {
11648 if(defined $Type2_Pure{"Memb"}
11649 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11650 {
11651 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11652 delete($Type2_Pure{"Memb"}{0});
11653 }
11654 else {
11655 removeVPtr(\%Type2_Pure);
11656 }
11657 }
11658 }
11659 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11660 {
11661 if(defined $Type1_Pure{"Memb"}
11662 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11663 {
11664 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11665 delete($Type1_Pure{"Memb"}{0});
11666 }
11667 else {
11668 removeVPtr(\%Type1_Pure);
11669 }
11670 }
11671 }
11672 }
11673
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011674 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11675 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011676
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011677 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011678 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11679 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011680 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011681 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11682 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011683 if($Base_1{"Name"} ne $Base_2{"Name"})
11684 {
11685 if(differentDumps("G")
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030011686 or differentDumps("V")
11687 or $SkipTypedefUncover)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011688 { # different GCC versions or different dumps
11689 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11690 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11691 # std::__va_list and __va_list
11692 $Base_1{"Name"}=~s/\A(\w+::)+//;
11693 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011694 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11695 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011696 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011697 }
11698 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11699 and $Base_1{"Name"} ne $Base_2{"Name"})
11700 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011701 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011702 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011703 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011704 {
11705 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11706 "Target"=>$Typedef_1{"Name"},
11707 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011708 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11709 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11710 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011711 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11712 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011713
11714 if(defined $UsedDump{1}{"DWARF"})
11715 {
11716 if($Base1_Pure{"Name"}=~/\b__unknown__\b/
11717 or $Base2_Pure{"Name"}=~/\b__unknown__\b/)
11718 { # Error ABI dump
11719 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11720 }
11721 }
11722
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011723 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011724 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011725 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11726 {
11727 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11728 "Target"=>$Typedef_1{"Name"},
11729 "Type_Name"=>$Typedef_1{"Name"},
11730 "Old_Value"=>$Base_1{"Name"},
11731 "New_Value"=>$Base_2{"Name"} );
11732 }
11733 else
11734 {
11735 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11736 "Target"=>$Typedef_1{"Name"},
11737 "Type_Name"=>$Typedef_1{"Name"},
11738 "Old_Value"=>$Base_1{"Name"},
11739 "New_Value"=>$Base_2{"Name"} );
11740 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011741 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011742 }
11743 }
11744 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11745 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011746 my $TT1 = $Type1_Pure{"Type"};
11747 my $TT2 = $Type2_Pure{"Type"};
11748
11749 if($TT1 ne $TT2
11750 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011751 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011752 my $Short1 = $Type1_Pure{"Name"};
11753 my $Short2 = $Type2_Pure{"Name"};
11754
11755 $Short1=~s/\A\Q$TT1\E //ig;
11756 $Short2=~s/\A\Q$TT2\E //ig;
11757
11758 if($Short1 eq $Short2)
11759 {
11760 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11761 "Target"=>$Type1_Pure{"Name"},
11762 "Type_Name"=>$Type1_Pure{"Name"},
11763 "Old_Value"=>lc($Type1_Pure{"Type"}),
11764 "New_Value"=>lc($Type2_Pure{"Type"}) );
11765 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011766 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011767 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011768 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011769
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011770 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011771
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011772 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11773 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11774 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11775 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011776 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011777 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011778 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011779 {
11780 my $ProblemKind = "DataType_Size";
11781 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011782 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011783 {
11784 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11785 $ProblemKind = "Size_Of_Copying_Class";
11786 }
11787 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11788 {
11789 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11790 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11791 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011792 else
11793 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011794 # descreased size of allocable class
11795 # it has no special effects
11796 }
11797 }
11798 }
11799 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11800 "Target"=>$Type1_Pure{"Name"},
11801 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011802 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011803 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011804 }
11805 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011806 if(defined $Type1_Pure{"BaseType"}
11807 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011808 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011809 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11810 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011811 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011812 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11813 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011814 }
11815 }
11816 }
11817 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11818 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11819 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11820 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11821 { # detect removed and renamed fields
11822 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11823 next if(not $Member_Name);
11824 my $MemberPair_Pos = (defined $Type2_Pure{"Memb"}{$Member_Pos} and $Type2_Pure{"Memb"}{$Member_Pos}{"name"} eq $Member_Name)?$Member_Pos:find_MemberPair_Pos_byName($Member_Name, \%Type2_Pure);
11825 if($MemberPair_Pos eq "lost")
11826 {
11827 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11828 {
11829 if(isUnnamed($Member_Name))
11830 { # support for old-version dumps
11831 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011832 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011833 next;
11834 }
11835 }
11836 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11837 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011838 $RenamedField{$Member_Pos} = $RenamedTo;
11839 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011840 }
11841 else
11842 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011843 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011844 }
11845 }
11846 elsif($Type1_Pure{"Type"} eq "Enum")
11847 {
11848 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11849 next if($Member_Value1 eq "");
11850 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11851 if($MemberPair_Pos ne "lost")
11852 { # renamed
11853 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11854 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11855 if($MemberPair_Pos_Rev eq "lost")
11856 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011857 $RenamedField{$Member_Pos} = $RenamedTo;
11858 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011859 }
11860 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011861 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011862 }
11863 }
11864 else
11865 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011866 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011867 }
11868 }
11869 }
11870 else
11871 { # related
11872 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11873 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11874 }
11875 }
11876 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11877 { # detect added fields
11878 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11879 next if(not $Member_Name);
11880 my $MemberPair_Pos = (defined $Type1_Pure{"Memb"}{$Member_Pos} and $Type1_Pure{"Memb"}{$Member_Pos}{"name"} eq $Member_Name)?$Member_Pos:find_MemberPair_Pos_byName($Member_Name, \%Type1_Pure);
11881 if($MemberPair_Pos eq "lost")
11882 {
11883 if(isUnnamed($Member_Name))
11884 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011885 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011886 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011887 next;
11888 }
11889 }
11890 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11891 {
11892 if(not $RenamedField_Rev{$Member_Pos})
11893 { # added
11894 $AddedField{$Member_Pos}=1;
11895 }
11896 }
11897 }
11898 }
11899 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11900 { # detect moved fields
11901 my (%RelPos, %RelPosName, %AbsPos) = ();
11902 my $Pos = 0;
11903 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11904 { # relative positions in 1st version
11905 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11906 next if(not $Member_Name);
11907 if(not $RemovedField{$Member_Pos})
11908 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011909 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011910 $RelPosName{1}{$Pos} = $Member_Name;
11911 $AbsPos{1}{$Pos++} = $Member_Pos;
11912 }
11913 }
11914 $Pos = 0;
11915 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11916 { # relative positions in 2nd version
11917 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11918 next if(not $Member_Name);
11919 if(not $AddedField{$Member_Pos})
11920 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011921 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011922 $RelPosName{2}{$Pos} = $Member_Name;
11923 $AbsPos{2}{$Pos++} = $Member_Pos;
11924 }
11925 }
11926 foreach my $Member_Name (keys(%{$RelPos{1}}))
11927 {
11928 my $RPos1 = $RelPos{1}{$Member_Name};
11929 my $AbsPos1 = $NameToPosA{$Member_Name};
11930 my $Member_Name2 = $Member_Name;
11931 if(my $RenamedTo = $RenamedField{$AbsPos1})
11932 { # renamed
11933 $Member_Name2 = $RenamedTo;
11934 }
11935 my $RPos2 = $RelPos{2}{$Member_Name2};
11936 if($RPos2 ne "" and $RPos1 ne $RPos2)
11937 { # different relative positions
11938 my $AbsPos2 = $NameToPosB{$Member_Name2};
11939 if($AbsPos1 ne $AbsPos2)
11940 { # different absolute positions
11941 my $ProblemType = "Moved_Field";
11942 if(not isPublic(\%Type1_Pure, $AbsPos1))
11943 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011944 if($Level eq "Source") {
11945 next;
11946 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011947 $ProblemType = "Moved_Private_Field";
11948 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011949 if($Level eq "Binary"
11950 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011951 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011952 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011953 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011954 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011955 if($MemSize1 ne $MemSize2) {
11956 $ProblemType .= "_And_Size";
11957 }
11958 }
11959 if($ProblemType eq "Moved_Private_Field") {
11960 next;
11961 }
11962 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11963 "Target"=>$Member_Name,
11964 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011965 "Old_Value"=>$RPos1,
11966 "New_Value"=>$RPos2 );
11967 }
11968 }
11969 }
11970 }
11971 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011972 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011973 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11974 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011975 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011976 if(my $RenamedTo = $RenamedField{$Member_Pos})
11977 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011978 if(defined $Constants{2}{$Member_Name})
11979 {
11980 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11981 { # define OLD NEW
11982 next; # Safe
11983 }
11984 }
11985
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011986 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11987 {
11988 if(isPublic(\%Type1_Pure, $Member_Pos))
11989 {
11990 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11991 "Target"=>$Member_Name,
11992 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011993 "Old_Value"=>$Member_Name,
11994 "New_Value"=>$RenamedTo );
11995 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011996 elsif(isReserved($Member_Name))
11997 {
11998 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11999 "Target"=>$Member_Name,
12000 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012001 "Old_Value"=>$Member_Name,
12002 "New_Value"=>$RenamedTo );
12003 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012004 }
12005 elsif($Type1_Pure{"Type"} eq "Enum")
12006 {
12007 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
12008 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
12009 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012010 "Old_Value"=>$Member_Name,
12011 "New_Value"=>$RenamedTo );
12012 }
12013 }
12014 elsif($RemovedField{$Member_Pos})
12015 { # removed
12016 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12017 {
12018 my $ProblemType = "Removed_Field";
12019 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012020 or isUnnamed($Member_Name))
12021 {
12022 if($Level eq "Source") {
12023 next;
12024 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012025 $ProblemType = "Removed_Private_Field";
12026 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012027 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012028 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012029 {
12030 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
12031 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012032 if(getOffset($MNum-1, \%Type1_Pure, $TypeInfo{1}, getArch(1), $WORD_SIZE{1})!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012033 { # changed offset
12034 $ProblemType .= "_And_Layout";
12035 }
12036 }
12037 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
12038 { # affected size
12039 $ProblemType .= "_And_Size";
12040 }
12041 }
12042 if($ProblemType eq "Removed_Private_Field") {
12043 next;
12044 }
12045 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12046 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012047 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012048 }
12049 elsif($Type2_Pure{"Type"} eq "Union")
12050 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012051 if($Level eq "Binary"
12052 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012053 {
12054 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
12055 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012056 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012057 }
12058 else
12059 {
12060 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
12061 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012062 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012063 }
12064 }
12065 elsif($Type1_Pure{"Type"} eq "Enum")
12066 {
12067 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
12068 "Target"=>$Member_Name,
12069 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012070 "Old_Value"=>$Member_Name );
12071 }
12072 }
12073 else
12074 { # changed
12075 my $MemberPair_Pos = $RelatedField{$Member_Pos};
12076 if($Type1_Pure{"Type"} eq "Enum")
12077 {
12078 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
12079 next if($Member_Value1 eq "");
12080 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
12081 next if($Member_Value2 eq "");
12082 if($Member_Value1 ne $Member_Value2)
12083 {
12084 my $ProblemType = "Enum_Member_Value";
12085 if(isLastElem($Member_Pos, \%Type1_Pure)) {
12086 $ProblemType = "Enum_Last_Member_Value";
12087 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012088 if($SkipConstants{1}{$Member_Name}) {
12089 $ProblemType = "Enum_Private_Member_Value";
12090 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012091 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12092 "Target"=>$Member_Name,
12093 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012094 "Old_Value"=>$Member_Value1,
12095 "New_Value"=>$Member_Value2 );
12096 }
12097 }
12098 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
12099 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012100 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
12101 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
12102
12103 if($Access1 ne "private"
12104 and $Access2 eq "private")
12105 {
12106 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12107 "Target"=>$Member_Name,
12108 "Type_Name"=>$Type1_Pure{"Name"});
12109 }
12110 elsif($Access1 ne "protected"
12111 and $Access1 ne "private"
12112 and $Access2 eq "protected")
12113 {
12114 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12115 "Target"=>$Member_Name,
12116 "Type_Name"=>$Type1_Pure{"Name"});
12117 }
12118
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012119 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12120 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012121 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012122 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12123 $SizeV1 = $BSize1;
12124 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012125 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012126 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12127 $SizeV2 = $BSize2;
12128 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012129 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12130 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012131 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012132 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012133 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012134 {
12135 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12136 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12137 { # field size change (including anon-structures and unions)
12138 # - same types
12139 # - unnamed types
12140 # - bitfields
12141 my $ProblemType = "Field_Size";
12142 if(not isPublic(\%Type1_Pure, $Member_Pos)
12143 or isUnnamed($Member_Name))
12144 { # should not be accessed by applications, goes to "Low Severity"
12145 # example: "abidata" members in GStreamer types
12146 $ProblemType = "Private_".$ProblemType;
12147 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012148 if(not isMemPadded($Member_Pos, $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012149 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012150 if($Type2_Pure{"Type"} ne "Union"
12151 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012152 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012153 if(getOffset($MNum-1, \%Type1_Pure, $TypeInfo{1}, getArch(1), $WORD_SIZE{1})!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012154 { # changed offset
12155 $ProblemType .= "_And_Layout";
12156 }
12157 }
12158 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12159 $ProblemType .= "_And_Type_Size";
12160 }
12161 }
12162 if($ProblemType eq "Private_Field_Size")
12163 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012164 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012165 if($ProblemType eq "Field_Size")
12166 {
12167 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12168 { # Low severity
12169 $ProblemType = "Struct_Field_Size_Increased";
12170 }
12171 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012172 if($ProblemType)
12173 { # register a problem
12174 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12175 "Target"=>$Member_Name,
12176 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012177 "Old_Size"=>$SizeV1,
12178 "New_Size"=>$SizeV2);
12179 }
12180 }
12181 }
12182 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12183 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12184 { # do NOT check bitfield type changes
12185 next;
12186 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012187 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012188 {
12189 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12190 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12191 {
12192 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12193 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012194 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012195 }
12196 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12197 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12198 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012199 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012200 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012201 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012202 }
12203 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012204 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12205 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012206 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012207 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12208 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012209
12210 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012211 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012212 or $ProblemType eq "Field_Type_And_Size"
12213 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012214 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012215 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012216 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012217 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012218 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012219 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012220 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012221 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012222 }
12223 }
12224 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12225 {
12226 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012227 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012228 }
12229 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012230 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012231 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012232 }
12233 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12234 {
12235 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012236 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012237 }
12238 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012239 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012240 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012241 }
12242 }
12243 }
12244
12245 if($Level eq "Source")
12246 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012247 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012248 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012249 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12250 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012251
12252 if($ProblemType eq "Field_Type")
12253 {
12254 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012255 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012256 }
12257 }
12258 }
12259 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012260
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012261 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012262 {
12263 my $ProblemType_Init = $ProblemType;
12264 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012265 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012266 if(not isPublic(\%Type1_Pure, $Member_Pos)
12267 or isUnnamed($Member_Name)) {
12268 $ProblemType = "Private_".$ProblemType;
12269 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012270 if(not isMemPadded($Member_Pos, $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012271 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012272 if($Type2_Pure{"Type"} ne "Union"
12273 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012274 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012275 if(getOffset($MNum-1, \%Type1_Pure, $TypeInfo{1}, getArch(1), $WORD_SIZE{1})!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012276 { # changed offset
12277 $ProblemType .= "_And_Layout";
12278 }
12279 }
12280 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12281 $ProblemType .= "_And_Type_Size";
12282 }
12283 }
12284 }
12285 else
12286 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012287 # TODO: Private_Field_Type rule?
12288
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012289 if(not isPublic(\%Type1_Pure, $Member_Pos)
12290 or isUnnamed($Member_Name)) {
12291 next;
12292 }
12293 }
12294 if($ProblemType eq "Private_Field_Type_And_Size")
12295 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012296 }
12297 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12298 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012299 "Type_Name"=>$Type1_Pure{"Name"});
12300
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012301 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012302 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012303 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012304 }
12305 }
12306 if(not isPublic(\%Type1_Pure, $Member_Pos))
12307 { # do NOT check internal type changes
12308 next;
12309 }
12310 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012311 { # checking member type changes
12312 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12313
12314 my %DupProblems = ();
12315
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012316 foreach my $Sub_SubProblemType (sort keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012317 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012318 foreach my $Sub_SubLocation (sort {length($a)<=>length($b)} sort keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012319 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012320 if(not defined $AllAffected)
12321 {
12322 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12323 next;
12324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012325 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012326
12327 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12328 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12329
12330 if(not defined $AllAffected)
12331 {
12332 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012333 }
12334 }
12335 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012336
12337 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012338 }
12339 }
12340 }
12341 }
12342 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12343 { # checking added members, public and private
12344 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12345 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012346 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012347 if($AddedField{$Member_Pos})
12348 { # added
12349 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12350 {
12351 my $ProblemType = "Added_Field";
12352 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012353 or isUnnamed($Member_Name))
12354 {
12355 if($Level eq "Source") {
12356 next;
12357 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012358 $ProblemType = "Added_Private_Field";
12359 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012360 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012361 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012362 {
12363 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12364 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012365 if(getOffset($MNum-1, \%Type2_Pure, $TypeInfo{2}, getArch(2), $WORD_SIZE{2})!=getOffset($RelatedField_Rev{$MNum-1}, \%Type1_Pure, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012366 { # changed offset
12367 $ProblemType .= "_And_Layout";
12368 }
12369 }
12370 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12371 $ProblemType .= "_And_Size";
12372 }
12373 }
12374 if($ProblemType eq "Added_Private_Field")
12375 { # skip added private fields
12376 next;
12377 }
12378 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12379 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012380 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012381 }
12382 elsif($Type2_Pure{"Type"} eq "Union")
12383 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012384 if($Level eq "Binary"
12385 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012386 {
12387 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12388 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012389 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012390 }
12391 else
12392 {
12393 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12394 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012395 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012396 }
12397 }
12398 elsif($Type2_Pure{"Type"} eq "Enum")
12399 {
12400 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12401 next if($Member_Value eq "");
12402 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12403 "Target"=>$Member_Name,
12404 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012405 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012406 }
12407 }
12408 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012409
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012410 if($Type1_Pure{"Type"} eq "FuncPtr")
12411 {
12412 foreach my $PPos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Param"}}))
12413 {
12414 if(not defined $Type2_Pure{"Param"}{$PPos}) {
12415 next;
12416 }
12417
12418 my $PT1 = $Type1_Pure{"Param"}{$PPos}{"type"};
12419 my $PT2 = $Type2_Pure{"Param"}{$PPos}{"type"};
12420
12421 my $PName = "p".$PPos;
12422
12423 my $FP_SubProblems = mergeTypes($PT1, $PT2, $Level);
12424 my %DupProblems = ();
12425
12426 foreach my $FP_SubProblemType (keys(%{$FP_SubProblems}))
12427 {
12428 foreach my $FP_SubLocation (keys(%{$FP_SubProblems->{$FP_SubProblemType}}))
12429 {
12430 if(not defined $AllAffected)
12431 {
12432 if(defined $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}}) {
12433 next;
12434 }
12435 }
12436
12437 my $NewLocation = ($FP_SubLocation)?$PName."->".$FP_SubLocation:$PName;
12438 $SubProblems{$FP_SubProblemType}{$NewLocation} = $FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation};
12439
12440 if(not defined $AllAffected)
12441 {
12442 $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}} = 1;
12443 }
12444 }
12445 }
12446
12447 %DupProblems = ();
12448 }
12449 }
12450
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012451 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012452 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012453}
12454
12455sub isUnnamed($) {
12456 return $_[0]=~/\Aunnamed\d+\Z/;
12457}
12458
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012459sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012460{
12461 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012462 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12463 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12464 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12465 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012466 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012467 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012468 }
12469 return $TypeName;
12470}
12471
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012472sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012473{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012474 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012475 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012476 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12477 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012478 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012479 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12480 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012481 return () if(not $Type{"Type"});
12482 if($Type{"Type"} ne $Type_Type)
12483 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012484 return () if(not $Type{"BaseType"});
12485 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012486 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012487 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012488 return %Type;
12489}
12490
12491my %TypeSpecAttributes = (
12492 "Const" => 1,
12493 "Volatile" => 1,
12494 "ConstVolatile" => 1,
12495 "Restrict" => 1,
12496 "Typedef" => 1
12497);
12498
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012499sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012500{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012501 my ($TypeId, $Info) = @_;
12502 if(not $TypeId or not $Info
12503 or not $Info->{$TypeId}) {
12504 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012505 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012506 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12507 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12508 }
12509 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012510 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012511 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012512 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012513 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012514 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012515 return %Type;
12516}
12517
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012518sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012519{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012520 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012521 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012522 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12523 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012524 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012525 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12526 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012527 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12528 my $PLevel = 0;
12529 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12530 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012531 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012532 return $PLevel if(not $Type{"BaseType"});
12533 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12534 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12535 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012536}
12537
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012538sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012539{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012540 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012541 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012542 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12543 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012544 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012545 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12546 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012547 return %Type if(not $Type{"BaseType"});
12548 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012549 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012550 return %Type;
12551}
12552
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012553sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012554{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012555 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012556 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012557 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12558 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012559 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012560 my $Qual = "";
12561 if($Type{"Type"} eq "Pointer") {
12562 $Qual .= "*";
12563 }
12564 elsif($Type{"Type"} eq "Ref") {
12565 $Qual .= "&";
12566 }
12567 elsif($Type{"Type"} eq "ConstVolatile") {
12568 $Qual .= "const volatile";
12569 }
12570 elsif($Type{"Type"} eq "Const"
12571 or $Type{"Type"} eq "Volatile"
12572 or $Type{"Type"} eq "Restrict") {
12573 $Qual .= lc($Type{"Type"});
12574 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012575 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012576 return $BQual.$Qual;
12577}
12578
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012579sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012580{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012581 my ($TypeId, $Info) = @_;
12582 if(not $TypeId or not $Info
12583 or not $Info->{$TypeId}) {
12584 return ();
12585 }
12586 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012587 return %Type if(not $Type{"BaseType"});
12588 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012589 {
12590 if($Info->{$BTid}) {
12591 return %{$Info->{$BTid}};
12592 }
12593 else { # something is going wrong
12594 return ();
12595 }
12596 }
12597 else {
12598 return %Type;
12599 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012600}
12601
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012602sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012603{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012604 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012605 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012606 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12607 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012608}
12609
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012610sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012611{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012612 my $Symbol = $_[0];
12613 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12614}
12615
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012616sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012617 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12618}
12619
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012620sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012621{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012622 my ($SInfo, $LibVersion) = @_;
12623
12624 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012625 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012626 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012627 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012628 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012629 return 1;
12630 }
12631 }
12632 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012633 if(my $ShortName = $SInfo->{"ShortName"})
12634 {
12635 if(index($ShortName,"<")!=-1
12636 and index($ShortName,">")!=-1) {
12637 return 1;
12638 }
12639 }
12640
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012641 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012642}
12643
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012644sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012645{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012646 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012647 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012648 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012649 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012650 { # class specialization
12651 return 1;
12652 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012653 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012654 { # method specialization
12655 return 1;
12656 }
12657 }
12658 return 0;
12659}
12660
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012661sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012662{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012663 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012664
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012665 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012666 { # non-public global data
12667 return 0;
12668 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012669
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012670 if(defined $SkipInternalSymbols)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012671 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012672 return 0 if($Symbol=~/($SkipInternalSymbols)/);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012673 }
12674
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012675 if($Symbol=~/\A_Z/)
12676 {
12677 if($Symbol=~/[CD][3-4]E/) {
12678 return 0;
12679 }
12680 }
12681
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012682 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012683 { # support for old ABI dumps in --headers-only mode
12684 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12685 {
12686 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12687 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012688 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012689 if(not $PType or $PType eq "Unknown") {
12690 return 0;
12691 }
12692 }
12693 }
12694 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012695 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012696 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012697 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12698
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012699 if($SkipSymbols{$LibVersion}{$Symbol})
12700 { # user defined symbols to ignore
12701 return 0;
12702 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012703
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012704 if($SymbolsListPath and not $SymbolsList{$Symbol})
12705 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012706 if(not $TargetHeadersPath or not $Header
12707 or not is_target_header($Header, 1))
12708 { # -symbols-list | -headers-list
12709 return 0;
12710 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012711 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012712
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012713 if($AppPath and not $SymbolsList_App{$Symbol})
12714 { # user defined symbols (in application)
12715 return 0;
12716 }
12717
12718 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12719
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012720 if($ClassId)
12721 {
12722 if(not isTargetType($ClassId, $LibVersion)) {
12723 return 0;
12724 }
12725 }
12726
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012727 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12728 if(not $NameSpace and $ClassId)
12729 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012730 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012731 }
12732 if($NameSpace)
12733 { # user defined namespaces to ignore
12734 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12735 return 0;
12736 }
12737 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12738 { # nested namespaces
12739 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12740 return 0;
12741 }
12742 }
12743 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012744 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012745 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012746 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012747 { # --skip-headers or <skip_headers> (not <skip_including>)
12748 if($Skip==1) {
12749 return 0;
12750 }
12751 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012752 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012753 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012754 { # user defined types
12755 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12756
12757 if(not $TypesList{$CName})
12758 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012759 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12760 {
12761 $CName=~s/\A\Q$NS\E\:\://g;
12762 }
12763
12764 if(not $TypesList{$CName})
12765 {
12766 my $Found = 0;
12767
12768 while($CName=~s/\:\:.+?\Z//)
12769 {
12770 if($TypesList{$CName})
12771 {
12772 $Found = 1;
12773 last;
12774 }
12775 }
12776
12777 if(not $Found) {
12778 return 0;
12779 }
12780 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012781 }
12782 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012783
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012784 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12785 { # non-target symbols
12786 return 0;
12787 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012788 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012789 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012790 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12791 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012792 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012793 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12794 { # inline virtual methods
12795 if($Type=~/InlineVirt/) {
12796 return 1;
12797 }
12798 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12799 if(not $Allocable)
12800 { # check bases
12801 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12802 {
12803 if(not isCopyingClass($DCId, $LibVersion))
12804 { # exists a derived class without default c-tor
12805 $Allocable=1;
12806 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012807 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012808 }
12809 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012810 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012811 return 0;
12812 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012813 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012814 else
12815 { # inline non-virtual methods
12816 return 0;
12817 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012818 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012819 }
12820 }
12821 return 1;
12822}
12823
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012824sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012825{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012826 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012827 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12828 {
12829 if(link_symbol($Symbol, 1, "+Deps"))
12830 { # linker can find a new symbol
12831 # in the old-version library
12832 # So, it's not a new symbol
12833 next;
12834 }
12835 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012836 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012837 next;
12838 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012839 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012840 }
12841}
12842
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012843sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012844{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012845 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012846 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12847 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012848 if(link_symbol($Symbol, 2, "+Deps"))
12849 { # linker can find an old symbol
12850 # in the new-version library
12851 next;
12852 }
12853 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012854 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012855 next;
12856 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012857 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012858 }
12859}
12860
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012861sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012862{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012863 my $Level = $_[0];
12864 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012865 { # checking added symbols
12866 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012867 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012868 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012869 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012870 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012871 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012872 { # checking removed symbols
12873 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012874 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012875 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012876 { # skip v-tables for templates, that should not be imported by applications
12877 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012878 if(my $CName = $VTableClass{$Symbol})
12879 {
12880 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12881 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012882 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012883 next;
12884 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012885 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012886
12887 if($SkipSymbols{1}{$Symbol})
12888 { # user defined symbols to ignore
12889 next;
12890 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012891 }
12892 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012893 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012894 }
12895 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12896 { # symbols for pure virtual methods cannot be called by clients
12897 next;
12898 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012899 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012900 }
12901}
12902
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012903sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012904{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012905 my ($LibVersion, $V) = @_;
12906 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12907 return $Cache{"checkDump"}{$LibVersion}{$V};
12908 }
12909 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012910}
12911
12912sub detectAdded_H($)
12913{
12914 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012915 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12916 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012917 if($Level eq "Source")
12918 { # remove symbol version
12919 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12920 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012921
12922 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12923 { # skip artificial constructors
12924 next;
12925 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012926 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012927 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12928 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012929 next;
12930 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012931 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012932 next;
12933 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012934 if(not defined $CompleteSignature{1}{$Symbol}
12935 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12936 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012937 if($UsedDump{2}{"SrcBin"})
12938 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012939 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012940 { # support for old and different (!) ABI dumps
12941 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12942 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012943 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012944 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012945 {
12946 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12947 {
12948 if($Lang eq "C")
12949 { # support for old ABI dumps: missed extern "C" functions
12950 next;
12951 }
12952 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012953 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012954 else
12955 {
12956 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012957 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012958 next;
12959 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012960 }
12961 }
12962 }
12963 }
12964 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012965 }
12966 }
12967}
12968
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012969sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012970{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012971 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012972 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12973 {
Andrey Ponomarenko9c87bdb2016-10-20 18:15:38 +030012974 my $ISymbol = $Symbol;
12975
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012976 if($Level eq "Source")
12977 { # remove symbol version
12978 my ($SN, $SS, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko9c87bdb2016-10-20 18:15:38 +030012979 $Symbol = $SN;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012980 }
Andrey Ponomarenko9c87bdb2016-10-20 18:15:38 +030012981
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012982 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12983 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012984 next;
12985 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012986 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012987 next;
12988 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012989 if(not defined $CompleteSignature{2}{$Symbol}
12990 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012991 {
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030012992 if(defined $UsedDump{1}{"DWARF"}
Andrey Ponomarenkoe30363a2016-10-07 19:40:50 +030012993 and defined $UsedDump{2}{"DWARF"}
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030012994 and $Level eq "Source")
Andrey Ponomarenko9c87bdb2016-10-20 18:15:38 +030012995 { # not present in debug-info,
12996 # but present in dynsym
12997 if(link_symbol($Symbol, 2, "-Deps")) {
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030012998 next;
12999 }
Andrey Ponomarenko9c87bdb2016-10-20 18:15:38 +030013000
13001 if($ISymbol ne $Symbol)
13002 {
13003 if(link_symbol($ISymbol, 2, "-Deps")) {
13004 next;
13005 }
13006 }
13007
13008 if(my $SVer = $SymVer{2}{$Symbol})
13009 {
13010 if(link_symbol($SVer, 2, "-Deps")) {
13011 next;
13012 }
13013 }
13014
13015 if(my $Alias = $CompleteSignature{1}{$ISymbol}{"Alias"})
13016 {
13017 if(link_symbol($Alias, 2, "-Deps")) {
13018 next;
13019 }
13020
13021 if(my $SAVer = $SymVer{2}{$Alias})
13022 {
13023 if(link_symbol($SAVer, 2, "-Deps")) {
13024 next;
13025 }
13026 }
13027 }
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030013028 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013029 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013030 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013031 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013032 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013033 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
13034 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013035 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013036 if($CheckHeadersOnly)
13037 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013038 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
13039 {
13040 if($Lang eq "C")
13041 { # support for old ABI dumps: missed extern "C" functions
13042 next;
13043 }
13044 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013045 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013046 else
13047 {
13048 if(not link_symbol($Symbol, 1, "-Deps"))
13049 { # skip removed inline symbols
13050 next;
13051 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013052 }
13053 }
13054 }
13055 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040013056 if(not checkDump(1, "2.15"))
13057 {
13058 if($Symbol=~/_IT_E\Z/)
13059 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
13060 next;
13061 }
13062 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013063 if(not $CompleteSignature{1}{$Symbol}{"Class"})
13064 {
13065 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
13066 {
13067 if(defined $Constants{2}{$Short})
13068 {
13069 my $Val = $Constants{2}{$Short}{"Value"};
13070 if(defined $Func_ShortName{2}{$Val})
13071 { # old name defined to new
13072 next;
13073 }
13074 }
13075 }
13076
13077 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013078 $RemovedInt{$Level}{$Symbol} = 1;
13079 if($Level eq "Source")
13080 { # search for a source-compatible equivalent
13081 setAlternative($Symbol, $Level);
13082 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013083 }
13084 }
13085}
13086
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013087sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013088{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013089 my $Level = $_[0];
13090 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013091 { # checking added symbols
13092 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013093 next if($CompleteSignature{2}{$Symbol}{"Private"});
13094 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013095 if($Level eq "Binary")
13096 {
13097 if($CompleteSignature{2}{$Symbol}{"InLine"})
13098 {
13099 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
13100 { # skip inline non-virtual functions
13101 next;
13102 }
13103 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013104 }
13105 else
13106 { # Source
13107 if($SourceAlternative_B{$Symbol}) {
13108 next;
13109 }
13110 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013111 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013112 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013113 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013114 { # checking removed symbols
13115 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013116 next if($CompleteSignature{1}{$Symbol}{"Private"});
13117 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013118 if($Level eq "Binary")
13119 {
13120 if($CompleteSignature{1}{$Symbol}{"InLine"})
13121 {
13122 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
13123 { # skip inline non-virtual functions
13124 next;
13125 }
13126 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013127 }
13128 else
13129 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013130 if(my $Alt = $SourceAlternative{$Symbol})
13131 {
13132 if(defined $CompleteSignature{1}{$Alt}
13133 and $CompleteSignature{1}{$Symbol}{"Const"})
13134 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013135 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013136 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013137 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013138 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013139 }
13140 else
13141 { # do NOT show removed symbol
13142 next;
13143 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013144 }
13145 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013146 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013147 }
13148}
13149
13150sub addParamNames($)
13151{
13152 my $LibraryVersion = $_[0];
13153 return if(not keys(%AddIntParams));
13154 my $SecondVersion = $LibraryVersion==1?2:1;
13155 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13156 {
13157 next if(not keys(%{$AddIntParams{$Interface}}));
13158 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013159 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013160 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13161 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013162 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013163 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13164 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13165 {
13166 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13167 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13168 }
13169 }
13170 else {
13171 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13172 }
13173 }
13174 }
13175 }
13176}
13177
13178sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013179{ # detect changed typedefs to show
13180 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013181 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13182 {
13183 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013184 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13185 if(not $BName1 or isAnon($BName1)) {
13186 next;
13187 }
13188 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13189 if(not $BName2 or isAnon($BName2)) {
13190 next;
13191 }
13192 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013193 $ChangedTypedef{$Typedef} = 1;
13194 }
13195 }
13196}
13197
13198sub get_symbol_suffix($$)
13199{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013200 my ($Symbol, $Full) = @_;
13201 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013202 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013203 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013204 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013205 if(not $Full) {
13206 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13207 }
13208 return $Suffix;
13209}
13210
13211sub get_symbol_prefix($$)
13212{
13213 my ($Symbol, $LibVersion) = @_;
13214 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13215 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13216 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013217 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013218 }
13219 return $ShortName;
13220}
13221
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013222sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013223{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013224 my $Symbol = $_[0];
13225 my $PSymbol = $Symbol;
13226 if(not defined $CompleteSignature{2}{$PSymbol}
13227 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13228 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13229 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013230 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013231 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013232 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013233 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013234 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13235 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013236 {
13237 if(defined $CompleteSignature{2}{$PSymbol}
13238 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13239 {
13240 $SourceAlternative{$Symbol} = $PSymbol;
13241 $SourceAlternative_B{$PSymbol} = $Symbol;
13242 if(not defined $CompleteSignature{1}{$PSymbol}
13243 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13244 $SourceReplacement{$Symbol} = $PSymbol;
13245 }
13246 }
13247 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013248 }
13249 else
13250 {
13251 foreach my $Sp ("KV", "VK", "K", "V")
13252 {
13253 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13254 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13255 {
13256 if(defined $CompleteSignature{2}{$PSymbol}
13257 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13258 {
13259 $SourceAlternative{$Symbol} = $PSymbol;
13260 $SourceAlternative_B{$PSymbol} = $Symbol;
13261 if(not defined $CompleteSignature{1}{$PSymbol}
13262 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13263 $SourceReplacement{$Symbol} = $PSymbol;
13264 }
13265 }
13266 }
13267 $PSymbol = $Symbol;
13268 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013269 }
13270 }
13271 }
13272 return "";
13273}
13274
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013275sub getSymKind($$)
13276{
13277 my ($Symbol, $LibVersion) = @_;
13278 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13279 {
13280 return "Global_Data";
13281 }
13282 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13283 {
13284 return "Method";
13285 }
13286 return "Function";
13287}
13288
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013289sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013290{
13291 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013292 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013293
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013294 mergeBases($Level);
13295
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013296 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013297 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013298 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013299 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013300 next;
13301 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013302 if(defined $CompleteSignature{1}{$Symbol}
13303 and $CompleteSignature{1}{$Symbol}{"Header"})
13304 { # double-check added symbol
13305 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013306 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013307 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013308 next;
13309 }
13310 if($Symbol=~/\A(_Z|\?)/)
13311 { # C++
13312 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13313 }
13314 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13315 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013316 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13317 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013318 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013319 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013320 {
13321 if($TName_Tid{1}{$AffectedClass_Name})
13322 { # class should exist in previous version
13323 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13324 { # old v-table is NOT copied by old applications
13325 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13326 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013327 "Target"=>get_Signature($Symbol, 2),
13328 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013329 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013330 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013331 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013332 }
13333 }
13334 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013335 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13336 { # check all removed exported symbols
13337 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013338 next;
13339 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013340 if(defined $CompleteSignature{2}{$Symbol}
13341 and $CompleteSignature{2}{$Symbol}{"Header"})
13342 { # double-check removed symbol
13343 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013344 }
13345 if($CompleteSignature{1}{$Symbol}{"Private"})
13346 { # skip private methods
13347 next;
13348 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013349 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013350 next;
13351 }
13352 $CheckedSymbols{$Level}{$Symbol} = 1;
13353 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13354 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013355 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13356 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013357 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013358 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13359 {
13360 if($TName_Tid{2}{$AffectedClass_Name})
13361 { # class should exist in newer version
13362 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13363 { # old v-table is NOT copied by old applications
13364 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13365 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013366 "Target"=>get_Signature($OverriddenMethod, 1),
13367 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013368 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013369 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013370 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013371 }
13372 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013373 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013374 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013375 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013376 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013377 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013378 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013379 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013380 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013381 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013382 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013383 {
13384 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13385 "Target"=>$tr_name{$Symbol},
13386 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013387 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013388 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013389 else
13390 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013391 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013392 "Target"=>$tr_name{$Symbol},
13393 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013394 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013395 }
13396 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013397 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013398 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013399 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013400 {
13401 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13402 "Target"=>$tr_name{$Symbol},
13403 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013404 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013405 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013406 else
13407 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013408 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013409 "Target"=>$tr_name{$Symbol},
13410 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013411 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013412 }
13413 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013414 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13415 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13416 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13417 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13418 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013419 {
13420 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013421 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013422 $ProblemType = "Global_Data_Symbol_Changed_Type";
13423 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013424 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13425 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013426 "Old_Type"=>$RTName1,
13427 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013428 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013429 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013430 }
13431 }
13432 }
13433 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013434 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013435 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013436 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013437 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013438 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013439 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013440 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013441 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13442 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013443 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013444 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013445 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013446 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013447 }
13448 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013449 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13450 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013451 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013452 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013453 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013454 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013455 }
13456 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013457 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013458 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013459 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013460 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013461 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013462 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013463 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013464 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013465 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013466 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013467 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013468 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013469 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013470 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013471 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013472 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013473 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013474 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013475 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013476 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013477 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013478 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013479 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013480 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013481 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013482 { # "volatile" to non-"volatile"
13483
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013484 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013485 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013486 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013487 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013488 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013489 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013490 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013491 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013492 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013493 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013494 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013495 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013496 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013497 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013498 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013499 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013500 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013501 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13502 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013503 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013504 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013505 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013506 }
13507 }
13508 }
13509 }
13510 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013511 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13512 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013513 $CurrentSymbol = $Symbol;
13514
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013515 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13516 if($Level eq "Source")
13517 { # remove symbol version
13518 $Symbol=$SN;
13519 }
13520 else
13521 { # Binary
13522 if(not $SV)
13523 { # symbol without version
13524 if(my $VSym = $SymVer{1}{$Symbol})
13525 { # the symbol is linked with versioned symbol
13526 if($CompleteSignature{2}{$VSym}{"MnglName"})
13527 { # show report for symbol@ver only
13528 next;
13529 }
13530 elsif(not link_symbol($VSym, 2, "-Deps"))
13531 { # changed version: sym@v1 to sym@v2
13532 # do NOT show report for symbol
13533 next;
13534 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013535 }
13536 }
13537 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013538 my $PSymbol = $Symbol;
13539 if($Level eq "Source"
13540 and my $S = $SourceReplacement{$Symbol})
13541 { # take a source-compatible replacement function
13542 $PSymbol = $S;
13543 }
13544 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013545 { # private symbols
13546 next;
13547 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013548 if(not defined $CompleteSignature{1}{$Symbol}
13549 or not defined $CompleteSignature{2}{$PSymbol})
13550 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013551 next;
13552 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013553 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13554 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13555 { # no mangled name
13556 next;
13557 }
13558 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13559 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013560 { # without a header
13561 next;
13562 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013563
13564 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13565 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13566 { # became pure
13567 next;
13568 }
13569 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13570 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13571 { # became non-pure
13572 next;
13573 }
13574
13575 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13576 { # exported, target, inline virtual and pure virtual
13577 next;
13578 }
13579 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13580 { # exported, target, inline virtual and pure virtual
13581 next;
13582 }
13583
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013584 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013585 {
13586 if($CompleteSignature{1}{$Symbol}{"Data"}
13587 and $CompleteSignature{2}{$PSymbol}{"Data"})
13588 {
13589 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13590 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13591 if(defined $Value1)
13592 {
13593 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13594 if(defined $Value2)
13595 {
13596 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13597 if($Value1 ne $Value2)
13598 {
13599 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13600 "Old_Value"=>$Value1,
13601 "New_Value"=>$Value2,
13602 "Target"=>get_Signature($Symbol, 1) );
13603 }
13604 }
13605 }
13606 }
13607 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013608
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013609 if($CompleteSignature{2}{$PSymbol}{"Private"})
13610 {
13611 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13612 "Target"=>get_Signature_M($PSymbol, 2) );
13613 }
13614 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13615 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13616 {
13617 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13618 "Target"=>get_Signature_M($PSymbol, 2) );
13619 }
13620 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13621 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13622 {
13623 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13624 "Target"=>get_Signature_M($PSymbol, 2) );
13625 }
13626
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013627 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013628 mergeVirtualTables($Symbol, $Level);
13629
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013630 if($COMPILE_ERRORS)
13631 { # if some errors occurred at the compiling stage
13632 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013633 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013634 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013635 { # missed information about parameters in newer version
13636 next;
13637 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013638 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013639 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013640 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013641 next;
13642 }
13643 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013644 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013645 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013646 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013647 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13648 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013649 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13650 "Target"=>get_Signature($Symbol, 1)
13651 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013652 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013653 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013654 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13655 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013656 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013657 "Target"=>get_Signature($Symbol, 1)
13658 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013659 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013660 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13661 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013662 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013663 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013664 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013665 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13666 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13667 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013668 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013669 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013670 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13671 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013672 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013673 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013674 my $ProblemType = "Virtual_Method_Position";
13675 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13676 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013677 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013678 if(isUsedClass($Class_Id, 1, $Level))
13679 {
13680 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013681 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013682 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013683 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13684 next;
13685 }
13686 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013687 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013688 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13689 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013690 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013691 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013692 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013693 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013694 }
13695 }
13696 }
13697 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013698 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13699 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013700 { # do NOT check type changes in pure virtuals
13701 next;
13702 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013703 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013704 if($Symbol=~/\A(_Z|\?)/
13705 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013706 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013707 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013708 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013709 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013710 }
13711 }
13712 else
13713 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013714 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013715 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013716 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013717 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13718 last if($PType2_Name eq "...");
13719 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13720 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013721 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013722 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013723 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013724 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13725 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013726 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13727 $ParamPos_Prev = "lost";
13728 }
13729 }
13730 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013731 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013732 }
13733 if($ParamPos_Prev eq "lost")
13734 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013735 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013736 {
13737 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013738 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013739 $ProblemType = "Added_Unnamed_Parameter";
13740 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013741 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013742 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013743 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013744 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013745 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013746 }
13747 else
13748 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013749 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013750 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013751 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013752 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13753 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013754 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013755 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013756 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013757 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013758 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013759 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013760 "Param_Type"=>$PType2_Name,
13761 "Old_Value"=>$PName_Old,
13762 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013763 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013764 }
13765 }
13766 else
13767 {
13768 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013769 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013770 $ProblemType = "Added_Middle_Unnamed_Parameter";
13771 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013772 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013773 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013774 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013775 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013776 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013777 }
13778 }
13779 }
13780 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013781 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013782 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013783 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013784 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013785 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013786 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013787 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013788 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013789 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013790 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13791 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013792 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013793 }
13794 }
13795 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013796 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013797 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013798 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013799 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13800 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013801 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13802 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013803 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013804 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013805 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013806 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13807 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013808 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13809 $ParamPos_New = "lost";
13810 }
13811 }
13812 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013813 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013814 }
13815 if($ParamPos_New eq "lost")
13816 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013817 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013818 {
13819 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013820 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013821 $ProblemType = "Removed_Unnamed_Parameter";
13822 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013823 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013824 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013825 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013826 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013827 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013828 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013829 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013830 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013831 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013832 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013833 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013834 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013835 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013836 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013837 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013838 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013839 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013840 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013841 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013842 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013843 "Old_Value"=>$PName,
13844 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013845 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013846 }
13847 }
13848 else
13849 {
13850 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013851 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013852 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13853 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013854 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013855 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013856 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013857 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013858 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013859 }
13860 }
13861 }
13862 }
13863 }
13864 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013865 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13866 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013867 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013868
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013869 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013870 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013871 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13872 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013873 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013874
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013875 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013876 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013877 if($SubProblemType eq "Return_Type_And_Size") {
13878 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13879 }
13880 elsif($SubProblemType eq "Return_Type_Format") {
13881 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13882 }
13883 else {
13884 $ProblemTypes{"Global_Data_Type"} = 1;
13885 }
13886
13887 # quals
13888 if($SubProblemType eq "Return_Type"
13889 or $SubProblemType eq "Return_Type_And_Size"
13890 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013891 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013892 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13893 { # const to non-const
13894 if($RR==2) {
13895 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13896 }
13897 else {
13898 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13899 }
13900 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013901 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013902 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13903 { # non-const to const
13904 if($RA==2) {
13905 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13906 }
13907 else {
13908 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13909 }
13910 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013911 }
13912 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013913 }
13914 else
13915 {
13916 # quals
13917 if($SubProblemType eq "Return_Type"
13918 or $SubProblemType eq "Return_Type_And_Size"
13919 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013920 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013921 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013922 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013923 if(addedQual($Old_Value, $New_Value, "volatile"))
13924 {
13925 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13926 if($Level ne "Source"
13927 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13928 $ProblemTypes{"Return_Type"} = 1;
13929 }
13930 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013931 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013932 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13933 {
13934 if($RA==2) {
13935 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13936 }
13937 else {
13938 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13939 }
13940 if($Level ne "Source"
13941 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13942 $ProblemTypes{"Return_Type"} = 1;
13943 }
13944 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013945 }
13946 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013947 if($Level eq "Binary"
13948 and not $CompleteSignature{1}{$Symbol}{"Data"})
13949 {
13950 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13951 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13952 { # if one of the architectures is unknown
13953 # then set other arhitecture to unknown too
13954 ($Arch1, $Arch2) = ("unknown", "unknown");
13955 }
13956 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013957 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013958 {
13959 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13960 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13961 }
13962 else
13963 {
13964 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13965 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13966 }
13967
13968 if($SubProblemType eq "Return_Type_Became_Void")
13969 {
13970 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13971 { # parameters stack has been affected
13972 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013973 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013974 }
13975 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013976 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013977 }
13978 }
13979 }
13980 elsif($SubProblemType eq "Return_Type_From_Void")
13981 {
13982 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13983 { # parameters stack has been affected
13984 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013985 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013986 }
13987 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013988 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013989 }
13990 }
13991 }
13992 elsif($SubProblemType eq "Return_Type"
13993 or $SubProblemType eq "Return_Type_And_Size"
13994 or $SubProblemType eq "Return_Type_Format")
13995 {
13996 if($Conv1{"Method"} ne $Conv2{"Method"})
13997 {
13998 if($Conv1{"Method"} eq "stack")
13999 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014000 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014001 }
14002 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014003 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014004 }
14005 }
14006 else
14007 {
14008 if($Conv1{"Method"} eq "reg")
14009 {
14010 if($Conv1{"Registers"} ne $Conv2{"Registers"})
14011 {
14012 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014013 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014014 }
14015 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014016 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014017 }
14018 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014019 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014020 }
14021 }
14022 }
14023 }
14024 }
14025 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014026
14027 if(not keys(%ProblemTypes))
14028 { # default
14029 $ProblemTypes{$SubProblemType} = 1;
14030 }
14031
14032 foreach my $ProblemType (keys(%ProblemTypes))
14033 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014034 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014035 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014036 }
14037 if($ReturnType1_Id and $ReturnType2_Id)
14038 {
14039 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014040 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
14041
14042 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014043
14044 if($CompleteSignature{1}{$Symbol}{"Data"})
14045 {
14046 if($Level eq "Binary")
14047 {
14048 if(get_PLevel($ReturnType1_Id, 1)==0)
14049 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014050 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014051 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014052
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014053 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
14054 {
14055 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014056 {
14057 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
14058 {
14059 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
14060 last;
14061 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014062 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014063 }
14064 }
14065 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014066 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014067 {
14068 if(defined $GlobalDataObject{1}{$Symbol}
14069 and defined $GlobalDataObject{2}{$Symbol})
14070 {
14071 my $Old_Size = $GlobalDataObject{1}{$Symbol};
14072 my $New_Size = $GlobalDataObject{2}{$Symbol};
14073 if($Old_Size!=$New_Size)
14074 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014075 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014076 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014077 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014078 }
14079 }
14080 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014081 }
14082 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014083
14084 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014085 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014086 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014087 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014088 my $NewLocation = "retval";
14089 if($SubLocation and $SubLocation ne "retval") {
14090 $NewLocation = "retval->".$SubLocation;
14091 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014092 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
14093 }
14094 }
14095
14096 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
14097 {
14098 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
14099 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014100 my $NewLocation = "retval";
14101 if($SubLocation and $SubLocation ne "retval") {
14102 $NewLocation = "retval->".$SubLocation;
14103 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014104 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014105 }
14106 }
14107 }
14108
14109 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014110 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
14111 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
14112 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014113 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014114 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014115 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
14116 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014117 if($ThisPtr1_Id and $ThisPtr2_Id)
14118 {
14119 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014120 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
14121 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014122 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014123 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014124 {
14125 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014126 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014127 }
14128 }
14129 }
14130 }
14131 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014132 if($Level eq "Binary") {
14133 mergeVTables($Level);
14134 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014135 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14136 $CheckedSymbols{$Level}{$Symbol} = 1;
14137 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014138}
14139
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014140sub rmQuals($$)
14141{
14142 my ($Value, $Qual) = @_;
14143 if(not $Qual) {
14144 return $Value;
14145 }
14146 if($Qual eq "all")
14147 { # all quals
14148 $Qual = "const|volatile|restrict";
14149 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014150 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014151 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014152 }
14153 return $Value;
14154}
14155
14156sub cmpBTypes($$$$)
14157{
14158 my ($T1, $T2, $V1, $V2) = @_;
14159 $T1 = uncover_typedefs($T1, $V1);
14160 $T2 = uncover_typedefs($T2, $V2);
14161 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14162}
14163
14164sub addedQual($$$)
14165{
14166 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014167 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014168}
14169
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014170sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014171{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014172 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014173 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014174}
14175
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014176sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014177{
14178 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14179 $Old_Value = uncover_typedefs($Old_Value, $V1);
14180 $New_Value = uncover_typedefs($New_Value, $V2);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014181
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014182 if($Old_Value eq $New_Value)
14183 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014184 return 0;
14185 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014186 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014187 { # without a qual
14188 return 0;
14189 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014190 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014191 { # became non-qual
14192 return 1;
14193 }
14194 else
14195 {
14196 my @BQ1 = getQualModel($Old_Value, $Qual);
14197 my @BQ2 = getQualModel($New_Value, $Qual);
14198 foreach (0 .. $#BQ1)
14199 { # removed qual
14200 if($BQ1[$_]==1
14201 and $BQ2[$_]!=1)
14202 {
14203 return 2;
14204 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014205 }
14206 }
14207 return 0;
14208}
14209
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014210sub getQualModel($$)
14211{
14212 my ($Value, $Qual) = @_;
14213 if(not $Qual) {
14214 return $Value;
14215 }
14216
14217 # cleaning
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014218 while($Value=~/(\w+)/)
14219 {
14220 my $W = $1;
14221
14222 if($W eq $Qual) {
14223 $Value=~s/\b$W\b/\@/g;
14224 }
14225 else {
14226 $Value=~s/\b$W\b//g;
14227 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014228 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014229
14230 $Value=~s/\@/$Qual/g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014231 $Value=~s/[^\*\&\w]+//g;
14232
14233 # modeling
14234 # int*const*const == 011
14235 # int**const == 001
14236 my @Model = ();
14237 my @Elems = split(/[\*\&]/, $Value);
14238 if(not @Elems) {
14239 return (0);
14240 }
14241 foreach (@Elems)
14242 {
14243 if($_ eq $Qual) {
14244 push(@Model, 1);
14245 }
14246 else {
14247 push(@Model, 0);
14248 }
14249 }
14250
14251 return @Model;
14252}
14253
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014254my %StringTypes = map {$_=>1} (
14255 "char*",
14256 "char const*"
14257);
14258
14259my %CharTypes = map {$_=>1} (
14260 "char",
14261 "char const"
14262);
14263
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014264sub showVal($$$)
14265{
14266 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014267 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014268 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014269 if(substr($Value, 0, 2) eq "_Z")
14270 {
14271 if(my $Unmangled = $tr_name{$Value}) {
14272 return $Unmangled;
14273 }
14274 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014275 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014276 { # strings
14277 return "\"$Value\"";
14278 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014279 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014280 { # characters
14281 return "\'$Value\'";
14282 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014283 if($Value eq "")
14284 { # other
14285 return "\'\'";
14286 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014287 return $Value;
14288}
14289
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014290sub getRegs($$$)
14291{
14292 my ($LibVersion, $Symbol, $Pos) = @_;
14293
14294 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14295 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014296 my %Regs = ();
14297 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14298 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014299 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014300 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14301 }
14302 }
14303
14304 return join(", ", sort keys(%Regs));
14305 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014306 elsif(defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}
14307 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}
14308 and not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}{"offset"})
14309 {
14310 return "unknown";
14311 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014312
14313 return undef;
14314}
14315
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014316sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014317{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014318 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014319 if(not $Symbol) {
14320 return;
14321 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014322 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14323 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14324 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14325 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014326 if(not $PType1_Id
14327 or not $PType2_Id) {
14328 return;
14329 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014330
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014331 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014332 { # do not merge "this"
14333 if($PName1 eq "this" or $PName2 eq "this") {
14334 return;
14335 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014336 }
14337
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014338 my %Type1 = get_Type($PType1_Id, 1);
14339 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014340
14341 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14342
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014343 my %BaseType1 = get_BaseType($PType1_Id, 1);
14344 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014345
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014346 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014347
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014348 if($Level eq "Binary")
14349 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014350 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014351 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14352 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14353 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14354 {
14355 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014356 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014357 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014358 }
14359 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14360 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14361 {
14362 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014363 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014364 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014365 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014366 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014367
14368 if(defined $UsedDump{1}{"DWARF"}
14369 and defined $UsedDump{2}{"DWARF"})
14370 {
14371 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14372 {
14373 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14374 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014375
14376 if($Old_Regs ne "unknown"
14377 and $New_Regs ne "unknown")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014378 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014379 if($Old_Regs and $New_Regs)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014380 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014381 if($Old_Regs ne $New_Regs)
14382 {
14383 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14384 "Target"=>$PName1,
14385 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14386 "Old_Value"=>$Old_Regs,
14387 "New_Value"=>$New_Regs );
14388 }
14389 }
14390 elsif($Old_Regs and not $New_Regs)
14391 {
14392 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014393 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014394 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014395 "Old_Value"=>$Old_Regs );
14396 }
14397 elsif(not $Old_Regs and $New_Regs)
14398 {
14399 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14400 "Target"=>$PName1,
14401 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014402 "New_Value"=>$New_Regs );
14403 }
14404 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014405
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014406 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14407 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14408 {
14409 if($Old_Offset ne $New_Offset)
14410 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014411 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14412 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14413
14414 $Old_Offset = $Old_Offset - $Start1;
14415 $New_Offset = $New_Offset - $Start2;
14416
14417 if($Old_Offset ne $New_Offset)
14418 {
14419 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14420 "Target"=>$PName1,
14421 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14422 "Old_Value"=>$Old_Offset,
14423 "New_Value"=>$New_Offset );
14424 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014425 }
14426 }
14427 }
14428 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014429 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014430 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14431 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014432 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014433 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014434 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14435 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014436 if(not checkDump(1, "2.13")
14437 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014438 { # support for old ABI dumps
14439 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014440 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014441 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014442 and $Value_Old eq "false" and $Value_New eq "0")
14443 { # int class::method ( bool p = 0 );
14444 # old ABI dumps: "false"
14445 # new ABI dumps: "0"
14446 $Value_Old = "0";
14447 }
14448 }
14449 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014450 if(not checkDump(1, "2.18")
14451 and checkDump(2, "2.18"))
14452 { # support for old ABI dumps
14453 if(not defined $Value_Old
14454 and substr($Value_New, 0, 2) eq "_Z") {
14455 $Value_Old = $Value_New;
14456 }
14457 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014458 if(defined $Value_Old)
14459 {
14460 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14461 if(defined $Value_New)
14462 {
14463 $Value_New = showVal($Value_New, $PType2_Id, 2);
14464 if($Value_Old ne $Value_New)
14465 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014466 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014467 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014468 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014469 "Old_Value"=>$Value_Old,
14470 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014471 }
14472 }
14473 else
14474 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014475 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014476 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014477 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014478 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014479 }
14480 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014481 elsif(defined $Value_New)
14482 {
14483 $Value_New = showVal($Value_New, $PType2_Id, 2);
14484 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14485 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014486 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014487 "New_Value"=>$Value_New );
14488 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014489 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014490
14491 if($ChkRnmd)
14492 {
14493 if($PName1 and $PName2 and $PName1 ne $PName2
14494 and $PType1_Id!=-1 and $PType2_Id!=-1
14495 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14496 { # except unnamed "..." value list (Id=-1)
14497 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14498 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014499 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014500 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14501 "Old_Value"=>$PName1,
14502 "New_Value"=>$PName2,
14503 "New_Signature"=>get_Signature($Symbol, 2) );
14504 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014505 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014506
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014507 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014508 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014509
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014510 foreach my $SubProblemType (keys(%SubProblems))
14511 { # add new problems, remove false alarms
14512 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14513 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014514
14515 # quals
14516 if($SubProblemType eq "Parameter_Type"
14517 or $SubProblemType eq "Parameter_Type_And_Size"
14518 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014519 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014520 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014521 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014522 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014523 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014524 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014525 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14526 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14527 }
14528 }
14529 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14530 {
14531 if(removedQual($Old_Value, $New_Value, "volatile")) {
14532 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014533 }
14534 }
14535 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14536 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14537 { # int to "int const"
14538 delete($SubProblems{$SubProblemType});
14539 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014540 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014541 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14542 { # "int const" to int
14543 delete($SubProblems{$SubProblemType});
14544 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014545 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14546 { # "const" to non-"const"
14547 if($RR==2) {
14548 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14549 }
14550 else {
14551 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14552 }
14553 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014554 }
14555 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014556
14557 if($Level eq "Source")
14558 {
14559 foreach my $SubProblemType (keys(%SubProblems))
14560 {
14561 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14562 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14563
14564 if($SubProblemType eq "Parameter_Type")
14565 {
14566 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14567 delete($SubProblems{$SubProblemType});
14568 }
14569 }
14570 }
14571 }
14572
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014573 foreach my $SubProblemType (keys(%SubProblems))
14574 { # modify/register problems
14575 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14576 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014577 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14578 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014579
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014580 my $NewProblemType = $SubProblemType;
14581 if($Old_Value eq "..." and $New_Value ne "...")
14582 { # change from "..." to "int"
14583 if($ParamPos1==0)
14584 { # ISO C requires a named argument before "..."
14585 next;
14586 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014587 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014588 }
14589 elsif($New_Value eq "..." and $Old_Value ne "...")
14590 { # change from "int" to "..."
14591 if($ParamPos2==0)
14592 { # ISO C requires a named argument before "..."
14593 next;
14594 }
14595 $NewProblemType = "Parameter_Became_VaList";
14596 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014597 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014598 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014599 {
14600 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014601 if($Arch1 eq "unknown"
14602 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014603 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014604 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014605 ($Arch1, $Arch2) = ("unknown", "unknown");
14606 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014607 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014608 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014609 { # real
14610 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14611 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14612 }
14613 else
14614 { # model
14615 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14616 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14617 }
14618 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014619 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014620 if($Conv1{"Method"} eq "stack")
14621 {
14622 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14623 $NewProblemType = "Parameter_Type_And_Stack";
14624 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014625 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014626 elsif($Conv1{"Method"} eq "reg")
14627 {
14628 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14629 $NewProblemType = "Parameter_Type_And_Register";
14630 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014631 }
14632 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014633 elsif($Conv1{"Method"} ne "unknown"
14634 and $Conv2{"Method"} ne "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014635 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014636 if($Conv1{"Method"} eq "stack") {
14637 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014638 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014639 elsif($Conv1{"Method"} eq "register") {
14640 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014641 }
14642 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014643 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14644 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014645 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014646 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014647 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014648 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014649 "New_Signature"=>get_Signature($Symbol, 2) );
14650 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014651 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014652
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014653 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014654
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014655 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014656 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14657 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014658 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014659 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014660 {
14661 my $NewProblemType = $SubProblemType;
14662 if($SubProblemType eq "DataType_Size")
14663 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014664 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014665 { # stack has been affected
14666 $NewProblemType = "DataType_Size_And_Stack";
14667 }
14668 }
14669 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014670 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014671 }
14672 }
14673}
14674
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014675sub find_ParamPair_Pos_byName($$$)
14676{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014677 my ($Name, $Symbol, $LibVersion) = @_;
14678 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014679 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014680 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14681 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014682 {
14683 return $ParamPos;
14684 }
14685 }
14686 return "lost";
14687}
14688
14689sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14690{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014691 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014692 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014693 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014694 {
14695 next if($Order eq "backward" and $ParamPos>$MediumPos);
14696 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014697 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14698 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014699 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014700 push(@Positions, $ParamPos);
14701 }
14702 }
14703 return @Positions;
14704}
14705
14706sub getTypeIdByName($$)
14707{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014708 my ($TypeName, $LibVersion) = @_;
14709 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014710}
14711
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014712sub diffTypes($$$)
14713{
14714 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14715 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14716 }
14717 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14718 { # skip recursive declarations
14719 return 0;
14720 }
14721
14722 pushType($_[0], $_[1], \@RecurTypes_Diff);
14723 my $Diff = diffTypes_I(@_);
14724 pop(@RecurTypes_Diff);
14725
14726 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14727}
14728
14729sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014730{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014731 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014732
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014733 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14734 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014735
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014736 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14737 { # equal types
14738 return 0;
14739 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014740 if($Type1_Pure{"Name"} eq "void")
14741 { # from void* to something
14742 return 0;
14743 }
Andrey Ponomarenkof9f25c92016-07-26 17:20:17 +030014744 if($Type2_Pure{"Name"} eq "void")
14745 { # from something to void*
14746 return 0;
14747 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014748 if($Type1_Pure{"Name"}=~/\*/
14749 or $Type2_Pure{"Name"}=~/\*/)
14750 { # compared in detectTypeChange()
14751 return 0;
14752 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014753
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014754 my %FloatType = map {$_=>1} (
14755 "float",
14756 "double",
14757 "long double"
14758 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014759
14760 my $T1 = $Type1_Pure{"Type"};
14761 my $T2 = $Type2_Pure{"Type"};
14762
14763 if($T1 eq "Struct"
14764 and $T2 eq "Class")
14765 { # compare as data structures
14766 $T2 = "Struct";
14767 }
14768
14769 if($T1 eq "Class"
14770 and $T2 eq "Struct")
14771 { # compare as data structures
14772 $T1 = "Struct";
14773 }
14774
14775 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014776 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014777 if($T1 eq "Intrinsic"
14778 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014779 { # "int" to "enum"
14780 return 0;
14781 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014782 elsif($T2 eq "Intrinsic"
14783 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014784 { # "enum" to "int"
14785 return 0;
14786 }
14787 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014788 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014789 # ...
14790 return 1;
14791 }
14792 }
14793 else
14794 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014795 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014796 {
14797 if($FloatType{$Type1_Pure{"Name"}}
14798 or $FloatType{$Type2_Pure{"Name"}})
14799 { # "float" to "double"
14800 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014801 if($Level eq "Source")
14802 { # Safe
14803 return 0;
14804 }
14805 else {
14806 return 1;
14807 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014808 }
14809 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014810 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014811 {
14812 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14813 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014814 if(not @Membs1
14815 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014816 { # private
14817 return 0;
14818 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014819 if($#Membs1!=$#Membs2)
14820 { # different number of elements
14821 return 1;
14822 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014823 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014824 {
14825 foreach my $Pos (@Membs1)
14826 { # compare elements by name and value
14827 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14828 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14829 { # different names
14830 return 1;
14831 }
14832 }
14833 }
14834 else
14835 {
14836 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014837 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014838 if($Level eq "Source")
14839 {
14840 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14841 { # different names
14842 return 1;
14843 }
14844 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014845
14846 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14847 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14848
14849 if($MT1{"Name"} ne $MT2{"Name"}
14850 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14851 {
14852 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14853 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14854
14855 if($PL1 ne $PL2)
14856 { # different pointer level
14857 return 1;
14858 }
14859
14860 # compare base types
14861 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14862 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14863
14864 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14865 { # different types
14866 return 1;
14867 }
14868 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014869 }
14870 }
14871 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014872 else
14873 {
14874 # TODO: arrays, etc.
14875 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014876 }
14877 return 0;
14878}
14879
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014880sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014881{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014882 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014883 if(not $Type1_Id or not $Type2_Id) {
14884 return ();
14885 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014886 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014887 my %Type1 = get_Type($Type1_Id, 1);
14888 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014889 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14890 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014891
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030014892 if(defined $SkipTypedefUncover)
14893 {
14894 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}) {
14895 return ();
14896 }
14897
14898 if(cmpBTypes($Type1_Pure{"Name"}, $Type2_Pure{"Name"}, 1, 2)) {
14899 return ();
14900 }
14901 }
14902
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014903 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14904 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 +040014905
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014906 if(defined $UsedDump{1}{"DWARF"})
14907 {
14908 if($Type1_Pure{"Name"} eq "__unknown__"
14909 or $Type2_Pure{"Name"} eq "__unknown__"
14910 or $Type1_Base{"Name"} eq "__unknown__"
14911 or $Type2_Base{"Name"} eq "__unknown__")
14912 { # Error ABI dump
14913 return ();
14914 }
14915 }
14916
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014917 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14918 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014919 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14920 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14921 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14922 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14923 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14924 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14925 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014926 if($Type1{"Name"} eq $Type2{"Name"})
14927 {
14928 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14929 { # will be reported in mergeTypes() as typedef problem
14930 return ();
14931 }
14932 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14933 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14934 if(%Typedef_1 and %Typedef_2)
14935 {
14936 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14937 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14938 { # const Typedef
14939 return ();
14940 }
14941 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014942 }
14943 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14944 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014945 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014946 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14947 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014948 {
14949 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14950 "Old_Value"=>$Type1_Base{"Name"},
14951 "New_Value"=>$Type2_Base{"Name"},
14952 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014953 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014954 }
14955 else
14956 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014957 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014958 { # format change
14959 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14960 "Old_Value"=>$Type1_Base{"Name"},
14961 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014962 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014963 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014964 }
14965 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14966 {
14967 %{$LocalProblems{$Prefix."_BaseType"}}=(
14968 "Old_Value"=>$Type1_Base{"Name"},
14969 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014970 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014971 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014972 }
14973 }
14974 }
14975 }
14976 elsif($Type1{"Name"} ne $Type2{"Name"})
14977 { # type change
14978 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14979 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014980 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014981 and $Type1_Pure{"Name"} eq "void")
14982 {
14983 %{$LocalProblems{"Return_Type_From_Void"}}=(
14984 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014985 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014986 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014987 elsif($Prefix eq "Return"
14988 and $Type2_Pure{"Name"} eq "void")
14989 {
14990 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14991 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014992 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014993 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014994 else
14995 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014996 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014997 and $Type1{"Size"} and $Type2{"Size"}
14998 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014999 {
15000 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
15001 "Old_Value"=>$Type1{"Name"},
15002 "New_Value"=>$Type2{"Name"},
15003 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015004 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015005 }
15006 else
15007 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015008 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015009 { # format change
15010 %{$LocalProblems{$Prefix."_Type_Format"}}=(
15011 "Old_Value"=>$Type1{"Name"},
15012 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015013 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015014 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015015 }
15016 elsif(tNameLock($Type1_Id, $Type2_Id))
15017 { # FIXME: correct this condition
15018 %{$LocalProblems{$Prefix."_Type"}}=(
15019 "Old_Value"=>$Type1{"Name"},
15020 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015021 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015022 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015023 }
15024 }
15025 }
15026 }
15027 }
15028 if($Type1_PLevel!=$Type2_PLevel)
15029 {
15030 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
15031 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
15032 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015033 if($Level eq "Source")
15034 {
15035 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015036 "Old_Value"=>$Type1_PLevel,
15037 "New_Value"=>$Type2_PLevel);
15038 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015039 else
15040 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015041 if($Type2_PLevel>$Type1_PLevel)
15042 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015043 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
15044 "Old_Value"=>$Type1_PLevel,
15045 "New_Value"=>$Type2_PLevel);
15046 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015047 else
15048 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015049 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
15050 "Old_Value"=>$Type1_PLevel,
15051 "New_Value"=>$Type2_PLevel);
15052 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015053 }
15054 }
15055 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040015056 if($Type1_Pure{"Type"} eq "Array"
15057 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015058 { # base_type[N] -> base_type[N]
15059 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015060 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015061 foreach my $SubProblemType (keys(%SubProblems))
15062 {
15063 $SubProblemType=~s/_Type/_BaseType/g;
15064 next if(defined $LocalProblems{$SubProblemType});
15065 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
15066 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
15067 }
15068 }
15069 }
15070 return %LocalProblems;
15071}
15072
15073sub tNameLock($$)
15074{
15075 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015076 my $Changed = 0;
15077 if(differentDumps("G"))
15078 { # different GCC versions
15079 $Changed = 1;
15080 }
15081 elsif(differentDumps("V"))
15082 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015083 if(not checkDump(1, "2.20")
15084 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015085 { # latest names update
15086 # 2.6: added restrict qualifier
15087 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015088 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015089 $Changed = 1;
15090 }
15091 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015092
15093 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
15094 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
15095
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015096 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
15097 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
15098
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015099 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015100 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015101 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015102 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015103 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015104 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015105 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015106 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015107 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015108 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015109 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
15110 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
15111 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015112 { # equal base types
15113 return 0;
15114 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015115
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015116 if(not checkDump(1, "2.13")
15117 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015118 { # broken array names in ABI dumps < 2.13
15119 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015120 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015121 return 0;
15122 }
15123 }
15124
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015125 if(not checkDump(1, "2.6")
15126 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015127 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015128 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015129 and $TN2=~/\brestrict\b/) {
15130 return 0;
15131 }
15132 }
15133
15134 if(not checkDump(1, "2.20")
15135 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015136 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015137 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
15138 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015139 return 0;
15140 }
15141 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015142 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015143 else
15144 {
15145 # typedef struct {...} type_t
15146 # typedef struct type_t {...} type_t
15147 if(index($TN1, " ".$TN2)!=-1)
15148 {
15149 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
15150 return 0;
15151 }
15152 }
15153 if(index($TN2, " ".$TN1)!=-1)
15154 {
15155 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
15156 return 0;
15157 }
15158 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015159
15160 if($TT1 eq "FuncPtr"
15161 and $TT2 eq "FuncPtr")
15162 {
15163 my $TN1_C = $TN1;
15164 my $TN2_C = $TN2;
15165
15166 $TN1_C=~s/\b(struct|union) //g;
15167 $TN2_C=~s/\b(struct|union) //g;
15168
15169 if($TN1_C eq $TN2_C) {
15170 return 0;
15171 }
15172 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015173 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015174
15175 my ($N1, $N2) = ($TN1, $TN2);
15176 $N1=~s/\b(struct|union) //g;
15177 $N2=~s/\b(struct|union) //g;
15178
15179 if($N1 eq $N2)
15180 { # QList<struct QUrl> and QList<QUrl>
15181 return 0;
15182 }
15183
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015184 return 1;
15185}
15186
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015187sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015188{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015189 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015190 if(defined $Cache{"differentDumps"}{$Check}) {
15191 return $Cache{"differentDumps"}{$Check};
15192 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015193 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015194 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015195 if($Check eq "G")
15196 {
15197 if(getGccVersion(1) ne getGccVersion(2))
15198 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015199 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015200 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015201 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015202 if($Check eq "V")
15203 {
15204 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15205 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15206 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015207 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015208 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015209 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015210 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015211 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015212}
15213
15214sub formatVersion($$)
15215{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015216 my ($V, $Digits) = @_;
15217 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015218 return join(".", splice(@Elems, 0, $Digits));
15219}
15220
15221sub htmlSpecChars($)
15222{
15223 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015224 if(not $Str) {
15225 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015226 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015227 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15228 $Str=~s/</&lt;/g;
15229 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15230 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015231 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15232 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015233 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015234 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015235 $Str=~s/\n/<br\/>/g;
15236 $Str=~s/\"/&quot;/g;
15237 $Str=~s/\'/&#39;/g;
15238 return $Str;
15239}
15240
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015241sub xmlSpecChars($)
15242{
15243 my $Str = $_[0];
15244 if(not $Str) {
15245 return $Str;
15246 }
15247
15248 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15249 $Str=~s/</&lt;/g;
15250 $Str=~s/>/&gt;/g;
15251
15252 $Str=~s/\"/&quot;/g;
15253 $Str=~s/\'/&#39;/g;
15254
15255 return $Str;
15256}
15257
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015258sub xmlSpecChars_R($)
15259{
15260 my $Str = $_[0];
15261 if(not $Str) {
15262 return $Str;
15263 }
15264
15265 $Str=~s/&amp;/&/g;
15266 $Str=~s/&lt;/</g;
15267 $Str=~s/&gt;/>/g;
15268
15269 $Str=~s/&quot;/"/g;
15270 $Str=~s/&#39;/'/g;
15271
15272 return $Str;
15273}
15274
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015275sub black_name($)
15276{
15277 my $Name = $_[0];
15278 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15279}
15280
15281sub highLight_Signature($)
15282{
15283 my $Signature = $_[0];
15284 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15285}
15286
15287sub highLight_Signature_Italic_Color($)
15288{
15289 my $Signature = $_[0];
15290 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15291}
15292
15293sub separate_symbol($)
15294{
15295 my $Symbol = $_[0];
15296 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15297 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15298 ($Name, $Spec, $Ver) = ($1, $2, $3);
15299 }
15300 return ($Name, $Spec, $Ver);
15301}
15302
15303sub cut_f_attrs($)
15304{
15305 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15306 return $2;
15307 }
15308 return "";
15309}
15310
15311sub highLight_Signature_PPos_Italic($$$$$)
15312{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015313 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15314 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015315 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15316 my $Return = "";
15317 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15318 $Return = $2;
15319 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015320 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015321 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015322 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015323 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015324 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015325 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015326 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015327 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015328 }
15329 return $Signature;
15330 }
15331 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15332 $Begin.=" " if($Begin!~/ \Z/);
15333 $End = cut_f_attrs($Signature);
15334 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015335 my ($Short, $Params) = split_Signature($Signature);
15336 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015337 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015338 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015339 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015340 $Part=~s/\A\s+|\s+\Z//g;
15341 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15342 if($Part=~/\([\*]+(\w+)\)/i) {
15343 $ParamName = $1;#func-ptr
15344 }
15345 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15346 $ParamName = $1;
15347 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015348 if(not $ParamName)
15349 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015350 push(@Parts, $Part_Styled);
15351 next;
15352 }
15353 if($ItalicParams and not $TName_Tid{1}{$Part}
15354 and not $TName_Tid{2}{$Part})
15355 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015356 my $Style = "<i>$ParamName</i>";
15357
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015358 if($Param_Pos ne ""
15359 and $Pos==$Param_Pos) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015360 $Style = "<span class=\'fp\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015361 }
15362 elsif($ColorParams) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015363 $Style = "<span class=\'color_p\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015364 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015365
15366 $Part_Styled=~s!(\W)$ParamName([\,\)]|\Z)!$1$Style$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015367 }
15368 $Part_Styled=~s/,(\w)/, $1/g;
15369 push(@Parts, $Part_Styled);
15370 }
15371 if(@Parts)
15372 {
15373 foreach my $Num (0 .. $#Parts)
15374 {
15375 if($Num==$#Parts)
15376 { # add ")" to the last parameter
15377 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15378 }
15379 elsif(length($Parts[$Num])<=45) {
15380 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15381 }
15382 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015383 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015384 }
15385 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015386 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015387 }
15388 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015389 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015390 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015391 $Signature=~s!\[\]![&#160;]!g;
15392 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015393 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15394 if($SymbolVersion) {
15395 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15396 }
15397 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015398}
15399
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015400sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015401{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015402 my $Signature = $_[0];
15403 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15404 {
15405 $Signature=~s/\A\Q$ShortName\E\(//g;
15406 cut_f_attrs($Signature);
15407 $Signature=~s/\)\Z//;
15408 return ($ShortName, $Signature);
15409 }
15410
15411 # error
15412 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015413}
15414
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015415sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015416{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015417 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015418 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015419 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15420 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015421 foreach my $Pos (0 .. length($Params) - 1)
15422 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015423 my $S = substr($Params, $Pos, 1);
15424 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015425 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015426 }
15427 if($S eq "," and
15428 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015429 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015430 if($Comma)
15431 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015432 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015433 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015434 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015435 }
15436 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015437 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015438 }
15439 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015440 if(not $Sp)
15441 { # remove spaces
15442 foreach (@Parts)
15443 {
15444 s/\A //g;
15445 s/ \Z//g;
15446 }
15447 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015448 return @Parts;
15449}
15450
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015451sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015452{
15453 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015454 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015455 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015456 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15457 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015458 $Center+=length($1);
15459 }
15460 foreach my $Pos (0 .. length($Sign)-1)
15461 {
15462 my $S = substr($Sign, $Pos, 1);
15463 if($S eq $Target)
15464 {
15465 if($B{"("}==$B{")"}
15466 and $B{"<"}==$B{">"}) {
15467 return $Center;
15468 }
15469 }
15470 if(defined $B{$S}) {
15471 $B{$S}+=1;
15472 }
15473 $Center+=1;
15474 }
15475 return 0;
15476}
15477
15478sub appendFile($$)
15479{
15480 my ($Path, $Content) = @_;
15481 return if(not $Path);
15482 if(my $Dir = get_dirname($Path)) {
15483 mkpath($Dir);
15484 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015485 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015486 print FILE $Content;
15487 close(FILE);
15488}
15489
15490sub writeFile($$)
15491{
15492 my ($Path, $Content) = @_;
15493 return if(not $Path);
15494 if(my $Dir = get_dirname($Path)) {
15495 mkpath($Dir);
15496 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015497 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015498 print FILE $Content;
15499 close(FILE);
15500}
15501
15502sub readFile($)
15503{
15504 my $Path = $_[0];
15505 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015506 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015507 local $/ = undef;
15508 my $Content = <FILE>;
15509 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015510 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015511 $Content=~s/\r/\n/g;
15512 }
15513 return $Content;
15514}
15515
15516sub get_filename($)
15517{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015518 if(defined $Cache{"get_filename"}{$_[0]}) {
15519 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015520 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015521 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15522 return ($Cache{"get_filename"}{$_[0]}=$1);
15523 }
15524 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015525}
15526
15527sub get_dirname($)
15528{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015529 if(defined $Cache{"get_dirname"}{$_[0]}) {
15530 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015531 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015532 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15533 return ($Cache{"get_dirname"}{$_[0]}=$1);
15534 }
15535 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015536}
15537
15538sub separate_path($) {
15539 return (get_dirname($_[0]), get_filename($_[0]));
15540}
15541
15542sub esc($)
15543{
15544 my $Str = $_[0];
15545 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15546 return $Str;
15547}
15548
15549sub readLineNum($$)
15550{
15551 my ($Path, $Num) = @_;
15552 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015553 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015554 foreach (1 ... $Num) {
15555 <FILE>;
15556 }
15557 my $Line = <FILE>;
15558 close(FILE);
15559 return $Line;
15560}
15561
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015562sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015563{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015564 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015565 return () if(not $Path or not -f $Path);
15566 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015567 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15568 {
15569 foreach my $AttrVal (split(/;/, $1))
15570 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015571 if($AttrVal=~/(.+):(.+)/)
15572 {
15573 my ($Name, $Value) = ($1, $2);
15574 $Attributes{$Name} = $Value;
15575 }
15576 }
15577 }
15578 return \%Attributes;
15579}
15580
15581sub is_abs($) {
15582 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15583}
15584
15585sub get_abs_path($)
15586{ # abs_path() should NOT be called for absolute inputs
15587 # because it can change them
15588 my $Path = $_[0];
15589 if(not is_abs($Path)) {
15590 $Path = abs_path($Path);
15591 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030015592 return path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015593}
15594
15595sub get_OSgroup()
15596{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015597 my $N = $Config{"osname"};
15598 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015599 return "macos";
15600 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015601 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015602 return "bsd";
15603 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015604 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015605 return "beos";
15606 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015607 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015608 return "symbian";
15609 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015610 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015611 return "windows";
15612 }
15613 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015614 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015615 }
15616}
15617
15618sub getGccVersion($)
15619{
15620 my $LibVersion = $_[0];
15621 if($GCC_VERSION{$LibVersion})
15622 { # dump version
15623 return $GCC_VERSION{$LibVersion};
15624 }
15625 elsif($UsedDump{$LibVersion}{"V"})
15626 { # old-version dumps
15627 return "unknown";
15628 }
15629 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15630 if(not $GccVersion) {
15631 return "unknown";
15632 }
15633 return $GccVersion;
15634}
15635
15636sub showArch($)
15637{
15638 my $Arch = $_[0];
15639 if($Arch eq "arm"
15640 or $Arch eq "mips") {
15641 return uc($Arch);
15642 }
15643 return $Arch;
15644}
15645
15646sub getArch($)
15647{
15648 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015649
15650 if($TargetArch) {
15651 return $TargetArch;
15652 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015653 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015654 { # dump
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015655 return $CPU_ARCH{$LibVersion};
15656 }
15657 elsif($UsedDump{$LibVersion}{"V"})
15658 { # old-version dumps
15659 return "unknown";
15660 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015661
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015662 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015663}
15664
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015665sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015666{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015667 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015668
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015669 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015670 if(getArch(1) ne getArch(2)
15671 or getArch(1) eq "unknown"
15672 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015673 { # don't show architecture in the header
15674 $ArchInfo="";
15675 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015676 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015677 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015678 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015679 }
15680 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015681 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015682 }
15683 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015684 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015685 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015686
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015687 my $V1 = $Descriptor{1}{"Version"};
15688 my $V2 = $Descriptor{2}{"Version"};
15689
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015690 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15691 {
15692 my $M1 = $UsedDump{1}{"M"};
15693 my $M2 = $UsedDump{2}{"M"};
15694
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015695 my $M1S = $M1;
15696 my $M2S = $M2;
15697
15698 $M1S=~s/(\.so|\.ko)\..+/$1/ig;
15699 $M2S=~s/(\.so|\.ko)\..+/$1/ig;
15700
15701 if($M1S eq $M2S
15702 and $V1 ne "X" and $V2 ne "Y")
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015703 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015704 $Title .= " report for the <span style='color:Blue;'>$M1S</span> $TargetComponent";
15705 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015706 }
15707 else
15708 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015709 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$V1."</span>)";
15710 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$V2."</span>) objects";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015711 }
15712 }
15713 else
15714 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015715 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015716 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015717 }
15718
15719 $Title .= $ArchInfo;
15720
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015721 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015722 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015723 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015724 $Title = "<h1>".$Title."</h1>\n";
15725 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015726}
15727
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015728sub get_CheckedHeaders($)
15729{
15730 my $LibVersion = $_[0];
15731
15732 my @Headers = ();
15733
15734 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15735 {
15736 my $File = get_filename($Path);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015737
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015738 if(not is_target_header($File, $LibVersion)) {
15739 next;
15740 }
15741
15742 if(skipHeader($File, $LibVersion)) {
15743 next;
15744 }
15745
15746 push(@Headers, $Path);
15747 }
15748
15749 return @Headers;
15750}
15751
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015752sub get_SourceInfo()
15753{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015754 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015755
15756 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015757 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015758 $CheckedHeaders = "<a name='Headers'></a>";
15759 if($OldStyle) {
15760 $CheckedHeaders .= "<h2>Header Files (".($#Headers+1).")</h2>";
15761 }
15762 else {
15763 $CheckedHeaders .= "<h2>Header Files <span class='gray'>&nbsp;".($#Headers+1)."&nbsp;</span></h2>";
15764 }
15765 $CheckedHeaders .= "<hr/>\n<div class='h_list'>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015766 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 +040015767 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015768 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15769 my $Name = get_filename($Identity);
15770 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15771 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015772 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015773 $CheckedHeaders .= "</div>\n";
15774 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015775 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015776
15777 if(my @Sources = keys(%{$Registered_Sources{1}}))
15778 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015779 $CheckedSources = "<a name='Sources'></a>";
15780 if($OldStyle) {
15781 $CheckedSources .= "<h2>Source Files (".($#Sources+1).")</h2>";
15782 }
15783 else {
15784 $CheckedSources .= "<h2>Source Files <span class='gray'>&nbsp;".($#Sources+1)."&nbsp;</span></h2>";
15785 }
15786 $CheckedSources .= "<hr/>\n<div class='h_list'>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015787 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15788 {
15789 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15790 my $Name = get_filename($Identity);
15791 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15792 $CheckedSources .= $Name.$Comment."<br/>\n";
15793 }
15794 $CheckedSources .= "</div>\n";
15795 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15796 }
15797
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015798 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015799 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015800 $CheckedLibs = "<a name='Libs'></a>";
15801 if($OldStyle) {
15802 $CheckedLibs .= "<h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2>";
15803 }
15804 else {
15805 $CheckedLibs .= "<h2>".get_ObjTitle()." <span class='gray'>&nbsp;".keys(%{$Library_Symbol{1}})."&nbsp;</span></h2>";
15806 }
15807 $CheckedLibs .= "<hr/>\n<div class='lib_list'>\n";
15808 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}})) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015809 $CheckedLibs .= $Library."<br/>\n";
15810 }
15811 $CheckedLibs .= "</div>\n";
15812 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015813 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015814
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015815 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15816}
15817
15818sub get_ObjTitle()
15819{
15820 if(defined $UsedDump{1}{"DWARF"}) {
15821 return "Objects";
15822 }
15823 else {
15824 return ucfirst($SLIB_TYPE)." Libraries";
15825 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015826}
15827
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015828sub get_TypeProblems_Count($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015829{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015830 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015831 my $Type_Problems_Count = 0;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015832
15833 foreach my $Type_Name (sort keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015834 {
15835 my %Kinds_Target = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015836 foreach my $Kind (keys(%{$TypeChanges{$Level}{$Type_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015837 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015838 foreach my $Location (keys(%{$TypeChanges{$Level}{$Type_Name}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015839 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015840 my $Target = $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015841 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015842
15843 if($Severity ne $TargetSeverity) {
15844 next;
15845 }
15846
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015847 if($Kinds_Target{$Kind}{$Target}) {
15848 next;
15849 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015850
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015851 $Kinds_Target{$Kind}{$Target} = 1;
15852 $Type_Problems_Count += 1;
15853 }
15854 }
15855 }
15856 return $Type_Problems_Count;
15857}
15858
15859sub get_Summary($)
15860{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015861 my $Level = $_[0];
15862 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015863 $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 +040015864 %{$RESULT{$Level}} = (
15865 "Problems"=>0,
15866 "Warnings"=>0,
15867 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015868 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015869 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015870 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015871 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015872 {
15873 if(not defined $CompatRules{$Level}{$Kind})
15874 { # unknown rule
15875 if(not $UnknownRules{$Level}{$Kind})
15876 { # only one warning
15877 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15878 $UnknownRules{$Level}{$Kind}=1;
15879 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015880 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015881 }
15882 }
15883 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015884 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15885 {
15886 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15887 {
15888 if(not defined $CompatRules{$Level}{$Kind})
15889 { # unknown rule
15890 if(not $UnknownRules{$Level}{$Kind})
15891 { # only one warning
15892 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15893 $UnknownRules{$Level}{$Kind}=1;
15894 }
15895 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15896 }
15897 }
15898 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015899 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015900 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015901 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015902 {
15903 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15904 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015905 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015906 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015907 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015908 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015909 $Added += 1;
15910 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015911 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015912 {
15913 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015914 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015915 }
15916 else
15917 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015918 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015919 $I_Other += 1;
15920 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015921 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015922 $I_Problems_High += 1;
15923 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015924 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015925 $I_Problems_Medium += 1;
15926 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015927 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015928 $I_Problems_Low += 1;
15929 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015930 if(($Severity ne "Low" or $StrictCompat)
15931 and $Severity ne "Safe") {
15932 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015933 }
15934 }
15935 }
15936 }
15937 }
15938 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015939
15940 my %MethodTypeIndex = ();
15941
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015942 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015943 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015944 my @Kinds = sort keys(%{$CompatProblems{$Level}{$Interface}});
15945 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015946 {
15947 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15948 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015949 my @Locs = sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}});
15950 foreach my $Location (@Locs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015951 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015952 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15953 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015954
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015955 if(defined $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target})
15956 { # one location for one type and target
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015957 next;
15958 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015959 $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target} = 1;
15960 $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15961
15962 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015963
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015964 if(($Severity ne "Low" or $StrictCompat)
15965 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015966 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015967 if(my $Sev = $TotalAffected{$Level}{$Interface})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015968 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015969 if($Severity_Val{$Severity}>$Severity_Val{$Sev}) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015970 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015971 }
15972 }
15973 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015974 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015975 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015976 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015977 }
15978 }
15979 }
15980 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015981
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015982 $T_Problems_High = get_TypeProblems_Count("High", $Level);
15983 $T_Problems_Medium = get_TypeProblems_Count("Medium", $Level);
15984 $T_Problems_Low = get_TypeProblems_Count("Low", $Level);
15985 $T_Other = get_TypeProblems_Count("Safe", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015986
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015987 # changed and removed public symbols
15988 my $SCount = keys(%{$CheckedSymbols{$Level}});
15989 if($ExtendedCheck)
15990 { # don't count external_func_0 for constants
15991 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015992 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015993 if($SCount)
15994 {
15995 my %Weight = (
15996 "High" => 100,
15997 "Medium" => 50,
15998 "Low" => 25
15999 );
16000 foreach (keys(%{$TotalAffected{$Level}})) {
16001 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016002 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016003 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016004 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016005 else {
16006 $RESULT{$Level}{"Affected"} = 0;
16007 }
16008
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016009 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
16010 if($RESULT{$Level}{"Affected"}>=100) {
16011 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016012 }
16013
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016014 $RESULT{$Level}{"Problems"} += $Removed;
16015 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016016 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016017 if($StrictCompat) {
16018 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
16019 }
16020 else {
16021 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
16022 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016023
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016024 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016025 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016026 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016027 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016028 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016029 if($Severity eq "Safe")
16030 {
16031 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016032 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016033 elsif($Severity eq "Low")
16034 {
16035 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016036 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016037 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016038 }
16039
16040 if($C_Problems_Low)
16041 {
16042 if($StrictCompat) {
16043 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
16044 }
16045 else {
16046 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016047 }
16048 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016049 if($RESULT{$Level}{"Problems"}
16050 and $RESULT{$Level}{"Affected"}) {
16051 $RESULT{$Level}{"Verdict"} = "incompatible";
16052 }
16053 else {
16054 $RESULT{$Level}{"Verdict"} = "compatible";
16055 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016056
16057 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
16058 if(not $TotalTypes)
16059 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016060 $TotalTypes = keys(%{$TName_Tid{1}});
16061 }
16062
16063 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
16064 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016065 my ($ClangV1, $ClangV2) = ($CLANG_VERSION{1}, $CLANG_VERSION{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016066
16067 my ($TestInfo, $TestResults, $Problem_Summary) = ();
16068
16069 if($ReportFormat eq "xml")
16070 { # XML
16071 # test info
16072 $TestInfo .= " <library>$TargetLibraryName</library>\n";
16073 $TestInfo .= " <version1>\n";
16074 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016075 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016076 if($GccV1) {
16077 $TestInfo .= " <gcc>$GccV1</gcc>\n";
16078 }
16079 elsif($ClangV1) {
16080 $TestInfo .= " <clang>$ClangV1</clang>\n";
16081 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016082 $TestInfo .= " </version1>\n";
16083
16084 $TestInfo .= " <version2>\n";
16085 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016086 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016087 if($GccV2) {
16088 $TestInfo .= " <gcc>$GccV2</gcc>\n";
16089 }
16090 elsif($ClangV2) {
16091 $TestInfo .= " <clang>$ClangV2</clang>\n";
16092 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016093 $TestInfo .= " </version2>\n";
16094 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
16095
16096 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016097 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016098 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016099 $TestResults .= " <headers>\n";
16100 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
16101 {
16102 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
16103 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
16104 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
16105 }
16106 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016107 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016108
16109 if(my @Sources = keys(%{$Registered_Sources{1}}))
16110 {
16111 $TestResults .= " <sources>\n";
16112 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
16113 {
16114 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
16115 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
16116 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
16117 }
16118 $TestResults .= " </sources>\n";
16119 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016120
16121 $TestResults .= " <libs>\n";
16122 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
16123 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016124 # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016125 $TestResults .= " <name>$Library</name>\n";
16126 }
16127 $TestResults .= " </libs>\n";
16128
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016129 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016130 $TestResults .= " <types>".$TotalTypes."</types>\n";
16131
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016132 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
16133 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016134 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
16135
16136 # problem summary
16137 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
16138 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
16139
16140 $Problem_Summary .= " <problems_with_types>\n";
16141 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
16142 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
16143 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
16144 $Problem_Summary .= " <safe>$T_Other</safe>\n";
16145 $Problem_Summary .= " </problems_with_types>\n";
16146
16147 $Problem_Summary .= " <problems_with_symbols>\n";
16148 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
16149 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
16150 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016151 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016152 $Problem_Summary .= " </problems_with_symbols>\n";
16153
16154 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016155 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016156 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016157
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016158 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
16159
16160 return ($TestInfo.$TestResults.$Problem_Summary, "");
16161 }
16162 else
16163 { # HTML
16164 # test info
16165 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016166 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016167
16168 if($TargetComponent eq "library") {
16169 $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
16170 }
16171 else {
16172 $TestInfo .= "<tr><th>Module Name</th><td>$TargetTitle</td></tr>\n";
16173 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016174
16175 my (@VInf1, @VInf2, $AddTestInfo) = ();
16176 if($Arch1 ne "unknown"
16177 and $Arch2 ne "unknown")
16178 { # CPU arch
16179 if($Arch1 eq $Arch2)
16180 { # go to the separate section
Andrey Ponomarenko19b61de2016-08-31 19:45:06 +030016181 $AddTestInfo .= "<tr><th>Arch</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016182 }
16183 else
16184 { # go to the version number
16185 push(@VInf1, showArch($Arch1));
16186 push(@VInf2, showArch($Arch2));
16187 }
16188 }
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030016189 if($Level eq "Binary"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016190 and $OStarget ne "windows")
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016191 {
16192 if($GccV1 ne "unknown"
16193 and $GccV2 ne "unknown")
16194 { # GCC version
16195 if($GccV1 eq $GccV2)
16196 { # go to the separate section
16197 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
16198 }
16199 else
16200 { # go to the version number
16201 push(@VInf1, "gcc ".$GccV1);
16202 push(@VInf2, "gcc ".$GccV2);
16203 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016204 }
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016205 elsif($ClangV1
16206 and $ClangV2)
16207 { # Clang version
16208 if($ClangV1 eq $ClangV2)
16209 { # go to the separate section
16210 $AddTestInfo .= "<tr><th>Clang Version</th><td>$ClangV1</td></tr>\n";
16211 }
16212 else
16213 { # go to the version number
16214 push(@VInf1, "clang ".$ClangV1);
16215 push(@VInf2, "clang ".$ClangV2);
16216 }
16217 }
16218 elsif($GccV1 ne "unknown" and $ClangV2)
16219 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016220 push(@VInf1, "gcc ".$GccV1);
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016221 push(@VInf2, "clang ".$ClangV2);
16222 }
16223 elsif($ClangV1 and $GccV2 ne "unknown")
16224 {
16225 push(@VInf1, "clang ".$ClangV1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016226 push(@VInf2, "gcc ".$GccV2);
16227 }
16228 }
16229 # show long version names with GCC version and CPU architecture name (if different)
16230 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
16231 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
16232 $TestInfo .= $AddTestInfo;
16233 #if($COMMON_LANGUAGE{1}) {
16234 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
16235 #}
16236 if($ExtendedCheck) {
16237 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
16238 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016239 if($JoinReport)
16240 {
16241 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016242 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016243 }
Andrey Ponomarenkodd172162016-10-04 19:41:25 +030016244 elsif($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016245 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016246 }
16247 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016248 $TestInfo .= "</table>\n";
16249
16250 # test results
16251 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016252 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016253
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030016254 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016255 {
16256 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
16257 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
16258 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016259
16260 if(my @Sources = keys(%{$Registered_Sources{1}}))
16261 {
16262 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16263 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16264 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016265
16266 if(not $ExtendedCheck)
16267 {
16268 my $Libs_Link = "0";
16269 $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 +040016270 $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 +040016271 }
16272
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016273 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016274
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016275 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016276 if($JoinReport) {
16277 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16278 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016279
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030016280 my $BC_Rate = show_number(100 - $RESULT{$Level}{"Affected"});
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016281
16282 $TestResults .= "<tr><th>Compatibility</th>\n";
16283 if($RESULT{$Level}{"Verdict"} eq "incompatible")
16284 {
16285 my $Cl = "incompatible";
16286 if($BC_Rate>=90) {
16287 $Cl = "warning";
16288 }
16289 elsif($BC_Rate>=80) {
16290 $Cl = "almost_compatible";
16291 }
16292
16293 $TestResults .= "<td class=\'$Cl\'>".$BC_Rate."%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016294 }
16295 else {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016296 $TestResults .= "<td class=\'compatible\'>100%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016297 }
16298 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016299 $TestResults .= "</table>\n";
16300
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016301 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016302 # problem summary
16303 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016304 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016305 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16306
16307 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016308 if($Added>0)
16309 {
16310 if($JoinReport) {
16311 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16312 }
16313 else {
16314 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16315 }
16316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016317 $META_DATA .= "added:$Added;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016318 $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 +040016319
16320 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016321 if($Removed>0)
16322 {
16323 if($JoinReport) {
16324 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16325 }
16326 else {
16327 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16328 }
16329 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016330 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016331 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016332 $Problem_Summary .= "<td>High</td><td".getStyle("I", "Removed", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016333
16334 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016335 $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 +040016336 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016337 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016338 $Problem_Summary .= "<td>High</td><td".getStyle("T", "High", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016339
16340 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016341 $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 +040016342 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016343 $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 +040016344
16345 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016346 $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 +040016347 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016348 $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 +040016349
16350 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016351 $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 +040016352 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016353 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016354 $Problem_Summary .= "<td>High</td><td".getStyle("I", "High", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016355
16356 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016357 $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 +040016358 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016359 $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 +040016360
16361 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016362 $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 +040016363 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016364 $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 +040016365
16366 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016367 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16368 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016369 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016370 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016371 $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 +040016372
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016373 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016374 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016375 {
16376 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016377 $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 +030016378 $META_DATA .= "type_changes_other:$T_Other;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016379 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016380
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016381 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016382 {
16383 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016384 $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 +030016385 $META_DATA .= "interface_changes_other:$I_Other;";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016386 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016387
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016388 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016389 {
16390 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016391 $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 +030016392 $META_DATA .= "constant_changes_other:$C_Other;";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016393 }
16394
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016395 $META_DATA .= "tool_version:$TOOL_VERSION";
16396 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016397
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016398 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16399 }
16400}
16401
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016402sub getStyle($$$)
16403{
16404 my ($Subj, $Act, $Num) = @_;
16405 my %Style = (
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016406 "Added"=>"new",
16407 "Removed"=>"failed",
16408 "Safe"=>"passed",
16409 "Low"=>"warning",
16410 "Medium"=>"failed",
16411 "High"=>"failed"
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016412 );
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016413
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016414 if($Num>0) {
16415 return " class='".$Style{$Act}."'";
16416 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016417
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016418 return "";
16419}
16420
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016421sub show_number($)
16422{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016423 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016424 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016425 my $Num = cut_off_number($_[0], 2, 0);
16426 if($Num eq "0")
16427 {
16428 foreach my $P (3 .. 7)
16429 {
16430 $Num = cut_off_number($_[0], $P, 1);
16431 if($Num ne "0") {
16432 last;
16433 }
16434 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016435 }
16436 if($Num eq "0") {
16437 $Num = $_[0];
16438 }
16439 return $Num;
16440 }
16441 return $_[0];
16442}
16443
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016444sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016445{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016446 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016447 if($num!~/\./)
16448 {
16449 $num .= ".";
16450 foreach (1 .. $digs_to_cut-1) {
16451 $num .= "0";
16452 }
16453 }
16454 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16455 {
16456 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16457 $num .= "0";
16458 }
16459 }
16460 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16461 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16462 }
16463 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016464 if($z) {
16465 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16466 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016467 return $num;
16468}
16469
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016470sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016471{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016472 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016473 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016474
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016475 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016476 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16477 {
16478 my $Header = $Constants{1}{$Constant}{"Header"};
16479 if(not $Header)
16480 { # added
16481 $Header = $Constants{2}{$Constant}{"Header"}
16482 }
16483
16484 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16485 {
16486 if(not defined $CompatRules{$Level}{$Kind}) {
16487 next;
16488 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016489 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016490 next;
16491 }
16492 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16493 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016494 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016495
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016496 if($ReportFormat eq "xml")
16497 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016498 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016499 {
16500 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016501 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016502 {
16503 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016504 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16505 {
16506 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16507 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16508 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016509
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016510 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16511 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16512 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016513 if($Overcome) {
16514 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16515 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016516 $CHANGED_CONSTANTS .= " </problem>\n";
16517 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016518 $CHANGED_CONSTANTS .= " </constant>\n";
16519 }
16520 $CHANGED_CONSTANTS .= " </header>\n";
16521 }
16522 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16523 }
16524 else
16525 { # HTML
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016526 my $ProblemsNum = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016527 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016528 {
16529 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016530 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016531 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016532 my $Report = "";
16533
16534 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16535 {
16536 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16537 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016538 $Report .= "<tr>\n<th>1</th>\n<td>".$Change."</td>\n<td>$Effect</td>\n</tr>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016539 $ProblemsNum += 1;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016540 }
16541 if($Report)
16542 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016543 $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 +030016544 $Report = $ContentSpanStart."<span class='ext'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016545 $Report = insertIDs($Report);
16546 }
16547 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016548 }
16549 $CHANGED_CONSTANTS .= "<br/>\n";
16550 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016551 if($CHANGED_CONSTANTS)
16552 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016553 my $Title = "Problems with Constants, $TargetSeverity Severity";
16554 if($TargetSeverity eq "Safe")
16555 { # Safe Changes
16556 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016557 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016558 if($OldStyle) {
16559 $CHANGED_CONSTANTS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$CHANGED_CONSTANTS;
16560 }
16561 else {
16562 $CHANGED_CONSTANTS = "<h2>$Title <span".getStyle("C", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$CHANGED_CONSTANTS;
16563 }
16564 $CHANGED_CONSTANTS = "<a name='".get_Anchor("Constant", $Level, $TargetSeverity)."'></a>\n".$CHANGED_CONSTANTS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016565 }
16566 }
16567 return $CHANGED_CONSTANTS;
16568}
16569
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016570sub getTitle($$$)
16571{
16572 my ($Header, $Library, $NameSpace) = @_;
16573 my $Title = "";
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016574
16575 # if($Library and $Library!~/\.\w+\Z/) {
16576 # $Library .= " (.$LIB_EXT)";
16577 # }
16578
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016579 if($Header and $Library)
16580 {
16581 $Title .= "<span class='h_name'>$Header</span>";
16582 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16583 }
16584 elsif($Library) {
16585 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16586 }
16587 elsif($Header) {
16588 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16589 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016590
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016591 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016592 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016593 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016594
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016595 return $Title;
16596}
16597
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016598sub get_Report_Added($)
16599{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016600 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016601 my $ADDED_INTERFACES = "";
16602 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016603 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016604 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016605 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016606 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016607 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016608 {
16609 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16610 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016611 if($Level eq "Source" and $ReportFormat eq "html")
16612 { # do not show library name in HTML report
16613 $DyLib = "";
16614 }
16615 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016616 }
16617 }
16618 }
16619 if($ReportFormat eq "xml")
16620 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016621 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016622 {
16623 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016624 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016625 {
16626 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016627 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016628 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16629 }
16630 $ADDED_INTERFACES .= " </library>\n";
16631 }
16632 $ADDED_INTERFACES .= " </header>\n";
16633 }
16634 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16635 }
16636 else
16637 { # HTML
16638 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016639 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016640 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016641 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016642 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016643 my %NameSpaceSymbols = ();
16644 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016645 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016646 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016647 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016648 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016649 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16650 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016651 foreach my $Interface (@SortedInterfaces)
16652 {
16653 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016654 my $Signature = get_Signature($Interface, 2);
16655 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016656 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016657 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016658 if($Interface=~/\A(_Z|\?)/)
16659 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016660 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016661 $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 +040016662 }
16663 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016664 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016665 }
16666 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016667 else
16668 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016669 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016670 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016671 }
16672 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016673 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016674 }
16675 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016676 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016677 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016678 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016679 }
16680 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016681 if($ADDED_INTERFACES)
16682 {
16683 my $Anchor = "<a name='Added'></a>";
16684 if($JoinReport) {
16685 $Anchor = "<a name='".$Level."_Added'></a>";
16686 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016687 if($OldStyle) {
16688 $ADDED_INTERFACES = "<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES;
16689 }
16690 else {
16691 $ADDED_INTERFACES = "<h2>Added Symbols <span".getStyle("I", "Added", $Added_Number).">&nbsp;$Added_Number&nbsp;</span></h2><hr/>\n".$ADDED_INTERFACES;
16692 }
16693 $ADDED_INTERFACES = $Anchor.$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016694 }
16695 }
16696 return $ADDED_INTERFACES;
16697}
16698
16699sub get_Report_Removed($)
16700{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016701 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016702 my $REMOVED_INTERFACES = "";
16703 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016704 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016705 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016706 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016707 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016708 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016709 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016710 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16711 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016712 if($Level eq "Source" and $ReportFormat eq "html")
16713 { # do not show library name in HTML report
16714 $DyLib = "";
16715 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016716 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016717 }
16718 }
16719 }
16720 if($ReportFormat eq "xml")
16721 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016722 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016723 {
16724 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016725 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016726 {
16727 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016728 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16729 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016730 }
16731 $REMOVED_INTERFACES .= " </library>\n";
16732 }
16733 $REMOVED_INTERFACES .= " </header>\n";
16734 }
16735 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16736 }
16737 else
16738 { # HTML
16739 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016740 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016741 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016742 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016743 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016744 my %NameSpaceSymbols = ();
16745 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016746 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016747 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016748 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016749 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016750 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16751 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016752 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016753 {
16754 $Removed_Number += 1;
16755 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016756 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016757 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016758 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016759 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016760 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016761 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016762 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016763 $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 +040016764 }
16765 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016766 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016767 }
16768 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016769 else
16770 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016771 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016772 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016773 }
16774 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016775 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016776 }
16777 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016778 }
16779 }
16780 $REMOVED_INTERFACES .= "<br/>\n";
16781 }
16782 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016783 if($REMOVED_INTERFACES)
16784 {
16785 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16786 if($JoinReport) {
16787 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16788 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016789 if($OldStyle) {
16790 $REMOVED_INTERFACES = "<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES;
16791 }
16792 else {
16793 $REMOVED_INTERFACES = "<h2>Removed Symbols <span".getStyle("I", "Removed", $Removed_Number).">&nbsp;$Removed_Number&nbsp;</span></h2><hr/>\n".$REMOVED_INTERFACES;
16794 }
16795
16796 $REMOVED_INTERFACES = $Anchor.$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016797 }
16798 }
16799 return $REMOVED_INTERFACES;
16800}
16801
16802sub getXmlParams($$)
16803{
16804 my ($Content, $Problem) = @_;
16805 return "" if(not $Content or not $Problem);
16806 my %XMLparams = ();
16807 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16808 {
16809 my $Macro = "\@".lc($Attr);
16810 if($Content=~/\Q$Macro\E/) {
16811 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16812 }
16813 }
16814 my @PString = ();
16815 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016816 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016817 }
16818 if(@PString) {
16819 return " ".join(" ", @PString);
16820 }
16821 else {
16822 return "";
16823 }
16824}
16825
16826sub addMarkup($)
16827{
16828 my $Content = $_[0];
16829 # auto-markup
16830 $Content=~s/\n[ ]*//; # spaces
16831 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16832 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016833 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016834 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16835 if($Content=~/\ANOTE:/)
16836 { # notes
16837 $Content=~s!(NOTE):!<b>$1</b>:!g;
16838 }
16839 else {
16840 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16841 }
16842 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16843 my @Keywords = (
16844 "void",
16845 "const",
16846 "static",
16847 "restrict",
16848 "volatile",
16849 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016850 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016851 );
16852 my $MKeys = join("|", @Keywords);
16853 foreach (@Keywords) {
16854 $MKeys .= "|non-".$_;
16855 }
16856 $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 +040016857
16858 # Markdown
16859 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16860 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016861 return $Content;
16862}
16863
16864sub applyMacroses($$$$)
16865{
16866 my ($Level, $Kind, $Content, $Problem) = @_;
16867 return "" if(not $Content or not $Problem);
16868 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16869 $Content = addMarkup($Content);
16870 # macros
16871 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16872 {
16873 my $Macro = "\@".lc($Attr);
16874 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016875 if(not defined $Value
16876 or $Value eq "") {
16877 next;
16878 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016879
16880 if(index($Content, $Macro)==-1) {
16881 next;
16882 }
16883
16884 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16885 and $Kind!~/_Type_/
16886 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016887 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016888 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016889 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016890 $Value = black_name($Value);
16891 }
16892 elsif($Value=~/\s/) {
16893 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16894 }
16895 elsif($Value=~/\A\d+\Z/
16896 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16897 { # bits to bytes
16898 if($Value % $BYTE_SIZE)
16899 { # bits
16900 if($Value==1) {
16901 $Value = "<b>".$Value."</b> bit";
16902 }
16903 else {
16904 $Value = "<b>".$Value."</b> bits";
16905 }
16906 }
16907 else
16908 { # bytes
16909 $Value /= $BYTE_SIZE;
16910 if($Value==1) {
16911 $Value = "<b>".$Value."</b> byte";
16912 }
16913 else {
16914 $Value = "<b>".$Value."</b> bytes";
16915 }
16916 }
16917 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016918 else
16919 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016920 $Value = "<b>".htmlSpecChars($Value)."</b>";
16921 }
16922 $Content=~s/\Q$Macro\E/$Value/g;
16923 }
16924
16925 if($Content=~/(\A|[^\@\w])\@\w/)
16926 {
16927 if(not $IncompleteRules{$Level}{$Kind})
16928 { # only one warning
16929 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16930 $IncompleteRules{$Level}{$Kind} = 1;
16931 }
16932 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016933 return $Content;
16934}
16935
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016936sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016937{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016938 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016939 my $INTERFACE_PROBLEMS = "";
16940 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016941
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016942 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016943 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016944 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16945 if($SV and defined $CompatProblems{$Level}{$SN}) {
16946 next;
16947 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016948 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16949 my $DyLib = $Symbol_Library{1}{$Symbol};
16950 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
16951 { # Symbol with Version
16952 $DyLib = $Symbol_Library{1}{$VSym};
16953 }
16954 if(not $DyLib)
16955 { # const global data
16956 $DyLib = "";
16957 }
16958 if($Level eq "Source" and $ReportFormat eq "html")
16959 { # do not show library name in HTML report
16960 $DyLib = "";
16961 }
16962
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016963 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016964 {
16965 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016966 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016967 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016968 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16969 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016970 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016971 if($Severity eq $TargetSeverity)
16972 {
16973 $SymbolChanges{$Symbol}{$Kind} = $CompatProblems{$Level}{$Symbol}{$Kind};
16974 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016975 }
16976 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016977 }
16978 }
16979 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016980
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016981 if($ReportFormat eq "xml")
16982 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016983 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016984 {
16985 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016986 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016987 {
16988 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016989 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16990 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016991 {
16992 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016993 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016994 {
16995 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16996 {
16997 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016998 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016999
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017000 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
17001 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
17002 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
17003 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
17004 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017005 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
17006 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
17007 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017008 $INTERFACE_PROBLEMS .= " </problem>\n";
17009 }
17010 }
17011 $INTERFACE_PROBLEMS .= " </symbol>\n";
17012 }
17013 $INTERFACE_PROBLEMS .= " </library>\n";
17014 }
17015 $INTERFACE_PROBLEMS .= " </header>\n";
17016 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017017 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017018 }
17019 else
17020 { # HTML
17021 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017022 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017023 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017024 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017025 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017026 my (%NameSpaceSymbols, %NewSignature) = ();
17027 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017028 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017029 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017030 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017031 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017032 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030017033 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 +040017034 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017035 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017036 my $Signature = get_Signature($Symbol, 1);
17037 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017038 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030017039 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017040 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017041 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017042 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017043 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017044 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017045 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017046 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017047 }
17048 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17049 {
17050 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017051 $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 +040017052 $ProblemNum += 1;
17053 $ProblemsNum += 1;
17054 }
17055 }
17056 }
17057 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017058 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017059 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017060 my $ShowSymbol = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017061 if($Signature) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017062 $ShowSymbol = highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017063 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017064
17065 if($NameSpace)
17066 {
17067 $SYMBOL_REPORT = cut_Namespace($SYMBOL_REPORT, $NameSpace);
17068 $ShowSymbol = cut_Namespace($ShowSymbol, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017069 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017070
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017071 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowSymbol;
17072 if($OldStyle) {
17073 $INTERFACE_PROBLEMS .= " ($ProblemNum)";
17074 }
17075 else {
17076 $INTERFACE_PROBLEMS .= " <span".getStyle("I", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>";
17077 }
17078 $INTERFACE_PROBLEMS .= $ContentSpanEnd."<br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017079 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017080
17081 if(my $NSign = $NewSignature{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017082 { # argument list changed to
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017083 if($NameSpace) {
17084 $NSign = cut_Namespace($NSign, $NameSpace);
17085 }
17086 $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 +040017087 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017088
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017089 if($Symbol=~/\A(_Z|\?)/) {
17090 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
17091 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017092
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017093 $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 +040017094 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017095 }
17096 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017097 $INTERFACE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017098 }
17099 }
17100 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017101
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017102 if($INTERFACE_PROBLEMS)
17103 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017104 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
17105 my $Title = "Problems with Symbols, $TargetSeverity Severity";
17106 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017107 { # Safe Changes
17108 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017109 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017110 if($OldStyle) {
17111 $INTERFACE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$INTERFACE_PROBLEMS;
17112 }
17113 else {
17114 $INTERFACE_PROBLEMS = "<h2>$Title <span".getStyle("I", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$INTERFACE_PROBLEMS;
17115 }
17116 $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 +040017117 }
17118 }
17119 return $INTERFACE_PROBLEMS;
17120}
17121
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017122sub cut_Namespace($$)
17123{
17124 my ($N, $Ns) = @_;
17125 $N=~s/\b\Q$Ns\E:://g;
17126 return $N;
17127}
17128
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017129sub get_Report_TypeProblems($$)
17130{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017131 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017132 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017133
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017134 my %ReportMap = ();
17135 my %TypeChanges_Sev = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017136
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017137 foreach my $TypeName (keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017138 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017139 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
17140
17141 foreach my $Kind (keys(%{$TypeChanges{$Level}{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017142 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017143 foreach my $Location (keys(%{$TypeChanges{$Level}{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017144 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017145 my $Target = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017146 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017147
17148 if($Severity eq $TargetSeverity)
17149 {
17150 $ReportMap{$HeaderName}{$TypeName} = 1;
17151 $TypeChanges_Sev{$TypeName}{$Kind}{$Location} = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017152 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017153 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017154 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017155 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017156
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017157 if($ReportFormat eq "xml")
17158 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017159 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017160 {
17161 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017162 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017163 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017164 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017165 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017166 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017167 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017168 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017169 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017170 $Kinds_Locations{$Kind}{$Location} = 1;
17171
17172 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17173 if($Kinds_Target{$Kind}{$Target}) {
17174 next;
17175 }
17176 $Kinds_Target{$Kind}{$Target} = 1;
17177
17178 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017179 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
17180 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
17181 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
17182 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
17183 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017184 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
17185 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
17186 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017187 $TYPE_PROBLEMS .= " </problem>\n";
17188 }
17189 }
Andrey Ponomarenkof9f25c92016-07-26 17:20:17 +030017190 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
17191 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017192 $TYPE_PROBLEMS .= showVTables($TypeName);
17193 }
17194 $TYPE_PROBLEMS .= " </type>\n";
17195 }
17196 $TYPE_PROBLEMS .= " </header>\n";
17197 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017198 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017199 }
17200 else
17201 { # HTML
17202 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017203 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017204 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017205 my (%NameSpace_Type) = ();
17206 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017207 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017208 }
17209 foreach my $NameSpace (sort keys(%NameSpace_Type))
17210 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017211 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017212 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 +040017213 foreach my $TypeName (@SortedTypes)
17214 {
17215 my $ProblemNum = 1;
17216 my $TYPE_REPORT = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017217 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017218
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017219 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017220 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017221 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017222 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017223 $Kinds_Locations{$Kind}{$Location} = 1;
17224
17225 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17226 if($Kinds_Target{$Kind}{$Target}) {
17227 next;
17228 }
17229 $Kinds_Target{$Kind}{$Target} = 1;
17230
17231 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017232 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17233 {
17234 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017235 $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 +040017236 $ProblemNum += 1;
17237 $ProblemsNum += 1;
17238 }
17239 }
17240 }
17241 $ProblemNum -= 1;
17242 if($TYPE_REPORT)
17243 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017244 my $Affected = getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017245 my $ShowVTables = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017246 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017247 $ShowVTables = showVTables($TypeName);
17248 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017249
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017250 my $ShowType = show_Type($TypeName, 1, 1);
17251
17252 if($NameSpace)
17253 {
17254 $TYPE_REPORT = cut_Namespace($TYPE_REPORT, $NameSpace);
17255 $ShowType = cut_Namespace($ShowType, $NameSpace);
17256 $Affected = cut_Namespace($Affected, $NameSpace);
17257 $ShowVTables = cut_Namespace($ShowVTables, $NameSpace);
17258 }
17259
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017260 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowType;
17261 if($OldStyle) {
17262 $TYPE_PROBLEMS .= " ($ProblemNum)";
17263 }
17264 else {
17265 $TYPE_PROBLEMS .= " <span".getStyle("T", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>";
17266 }
17267 $TYPE_PROBLEMS .= $ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017268 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
17269 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
17270 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
17271 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017272 }
17273 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017274 $TYPE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017275 }
17276 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017277
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017278 if($TYPE_PROBLEMS)
17279 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017280 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
17281 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017282 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017283 { # Safe Changes
17284 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017285 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017286 if($OldStyle) {
17287 $TYPE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$TYPE_PROBLEMS;
17288 }
17289 else {
17290 $TYPE_PROBLEMS = "<h2>$Title <span".getStyle("T", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$TYPE_PROBLEMS;
17291 }
17292 $TYPE_PROBLEMS = "<a name=\'".get_Anchor("Type", $Level, $TargetSeverity)."\'></a>\n".$TYPE_PROBLEMS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017293 }
17294 }
17295 return $TYPE_PROBLEMS;
17296}
17297
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017298sub show_Type($$$)
17299{
17300 my ($Name, $Html, $LibVersion) = @_;
17301 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
17302 $TType = lc($TType);
17303 if($TType=~/struct|union|enum/) {
17304 $Name=~s/\A\Q$TType\E //g;
17305 }
17306 if($Html) {
17307 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
17308 }
17309 else {
17310 $Name = $TType." ".$Name;
17311 }
17312 return $Name;
17313}
17314
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017315sub get_Anchor($$$)
17316{
17317 my ($Kind, $Level, $Severity) = @_;
17318 if($JoinReport)
17319 {
17320 if($Severity eq "Safe") {
17321 return "Other_".$Level."_Changes_In_".$Kind."s";
17322 }
17323 else {
17324 return $Kind."_".$Level."_Problems_".$Severity;
17325 }
17326 }
17327 else
17328 {
17329 if($Severity eq "Safe") {
17330 return "Other_Changes_In_".$Kind."s";
17331 }
17332 else {
17333 return $Kind."_Problems_".$Severity;
17334 }
17335 }
17336}
17337
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017338sub showVTables($)
17339{
17340 my $TypeName = $_[0];
17341 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017342 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017343 if(defined $Type1{"VTable"}
17344 and keys(%{$Type1{"VTable"}}))
17345 {
17346 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017347 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017348 if(defined $Type2{"VTable"}
17349 and keys(%{$Type2{"VTable"}}))
17350 {
17351 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17352 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017353 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017354 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017355 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17356 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017357 }
17358 my $VTABLES = "";
17359 if($ReportFormat eq "xml")
17360 { # XML
17361 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017362 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017363 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017364 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017365 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17366 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017367 $VTABLES .= " </entry>\n";
17368 }
17369 $VTABLES .= " </vtable>\n\n";
17370 }
17371 else
17372 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017373 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017374 $VTABLES .= "<tr><th>Offset</th>";
17375 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017376 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017377 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017378 {
17379 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017380
17381 my $E1 = $Entries{$Index}{"E1"};
17382 my $E2 = $Entries{$Index}{"E2"};
17383
17384 if($E1 ne $E2
17385 and $E1!~/ 0x/
17386 and $E2!~/ 0x/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017387 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017388 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017389 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017390 $Color1 = " class='failed'";
17391 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017392 }
17393 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017394 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017395 }
17396 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017397 $VTABLES .= "<tr><th>".$Index."</th>\n";
17398 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17399 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017400 }
17401 $VTABLES .= "</table><br/>\n";
17402 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017403 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017404 }
17405 return $VTABLES;
17406 }
17407 }
17408 return "";
17409}
17410
17411sub simpleVEntry($)
17412{
17413 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017414 if(not defined $VEntry
17415 or $VEntry eq "") {
17416 return "";
17417 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017418
17419 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017420 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17421 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17422 if($VEntry=~/\A_ZThn.+\Z/) {
17423 $VEntry = "non-virtual thunk";
17424 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017425 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017426 # support for old GCC versions
17427 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17428 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17429 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017430 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17431 return $VEntry;
17432}
17433
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017434sub adjustParamPos($$$)
17435{
17436 my ($Pos, $Symbol, $LibVersion) = @_;
17437 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17438 {
17439 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17440 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17441 {
17442 return $Pos-1;
17443 }
17444
17445 return $Pos;
17446 }
17447
17448 return undef;
17449}
17450
17451sub getParamPos($$$)
17452{
17453 my ($Name, $Symbol, $LibVersion) = @_;
17454
17455 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17456 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17457 {
17458 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17459 foreach (keys(%{$Info->{"Param"}}))
17460 {
17461 if($Info->{"Param"}{$_}{"name"} eq $Name)
17462 {
17463 return $_;
17464 }
17465 }
17466 }
17467
17468 return undef;
17469}
17470
17471sub getParamName($)
17472{
17473 my $Loc = $_[0];
17474 $Loc=~s/\->.*//g;
17475 return $Loc;
17476}
17477
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017478sub getAffectedSymbols($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017479{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017480 my ($Level, $Target_TypeName, $Kinds_Locations) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017481
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017482 my $LIMIT = 10;
17483 if(defined $AffectLimit) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017484 $LIMIT = $AffectLimit;
17485 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017486
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017487 my @Kinds = sort keys(%{$Kinds_Locations});
17488 my %KLocs = ();
17489 foreach my $Kind (@Kinds)
17490 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017491 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 +030017492 $KLocs{$Kind} = \@Locs;
17493 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017494
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017495 my %SymLocKind = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017496 foreach my $Symbol (sort keys(%{$TypeProblemsIndex{$Level}{$Target_TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017497 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017498 if(index($Symbol, "_Z")==0
17499 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017500 { # duplicated problems for C2 constructors, D2 and D0 destructors
17501 next;
17502 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017503
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017504 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017505 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017506 foreach my $Loc (@{$KLocs{$Kind}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017507 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017508 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017509 next;
17510 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017511
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017512 if(index($Symbol, "\@")!=-1
17513 or index($Symbol, "\$")!=-1)
17514 {
17515 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17516
17517 if($Level eq "Source")
17518 { # remove symbol version
17519 $Symbol = $SN;
17520 }
17521
17522 if($SV and defined $CompatProblems{$Level}{$SN}
17523 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
17524 { # duplicated problems for versioned symbols
17525 next;
17526 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017527 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017528
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017529 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017530 if($Type_Name ne $Target_TypeName) {
17531 next;
17532 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017533
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017534 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017535 last;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017536 }
17537 }
17538 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017539
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017540 %KLocs = (); # clear
17541
17542 my %SymSel = ();
17543 my $Num = 0;
17544 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymLocKind))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017545 {
17546 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17547 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017548 foreach my $Kind (sort keys(%{$SymLocKind{$Symbol}{$Loc}}))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017549 {
17550 $SymSel{$Symbol}{"Loc"} = $Loc;
17551 $SymSel{$Symbol}{"Kind"} = $Kind;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017552 last LOOP;
17553 }
17554 }
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017555
17556 $Num += 1;
17557
17558 if($Num>=$LIMIT) {
17559 last;
17560 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017561 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017562
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017563 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017564
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017565 if($ReportFormat eq "xml")
17566 { # XML
17567 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017568
17569 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017570 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017571 my $Kind = $SymSel{$Symbol}{"Kind"};
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017572 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017573
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017574 my $PName = getParamName($Loc);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017575 my $Desc = getAffectDesc($Level, $Symbol, $Kind, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017576
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017577 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017578 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017579 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017580 $Target .= " param=\"$PName\"";
17581 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017582 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017583 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017584 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017585 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017586 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017587 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017588 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017589
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017590 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017591 $Target .= " field=\"$1\"";
17592 }
17593
17594 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017595 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017596 $Affected .= " </symbol>\n";
17597 }
17598 $Affected .= " </affected>\n";
17599 }
17600 else
17601 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017602 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017603 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017604 my $Kind = $SymSel{$Symbol}{"Kind"};
17605 my $Loc = $SymSel{$Symbol}{"Loc"};
17606
17607 my $Desc = getAffectDesc($Level, $Symbol, $Kind, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017608 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017609 my $PName = getParamName($Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017610 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17611
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017612 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017613 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017614 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017615
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017616 if(keys(%SymLocKind)>$LIMIT) {
17617 $Affected .= " <b>...</b>\n<br/>\n"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017618 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017619
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017620 $Affected = "<div class='affected'>".$Affected."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017621 if($Affected)
17622 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017623 my $Num = keys(%SymLocKind);
17624 my $Per = show_number($Num*100/keys(%{$CheckedSymbols{$Level}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017625 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017626 $Affected = $ContentSpanStart_Affected."[+] affected symbols: $Num ($Per\%)".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017627 }
17628 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017629
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017630 return $Affected;
17631}
17632
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017633sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017634{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017635 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017636 if($L2=~/\A(retval|this)\b/
17637 and $L1!~/\A(retval|this)\b/)
17638 {
17639 if($L1!~/\-\>/) {
17640 return 1;
17641 }
17642 elsif($L2=~/\-\>/) {
17643 return 1;
17644 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017645 }
17646 return 0;
17647}
17648
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017649sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017650{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017651 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017652
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017653 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017654
17655 my $Location_I = $Location;
17656 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17657
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017658 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017659
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017660 if($Kind eq "Overridden_Virtual_Method"
17661 or $Kind eq "Overridden_Virtual_Method_B") {
17662 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17663 }
17664 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17665 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017666 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17667
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017668 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17669 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017670 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17671 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17672
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017673 if($ClassName eq $Problem{"Type_Name"}) {
17674 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17675 }
17676 else {
17677 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17678 }
17679 }
17680 else
17681 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017682 my $TypeID = undef;
17683
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017684 if($Location=~/retval/)
17685 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017686 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017687 push(@Sentence, "Field \'".$Location."\' in return value");
17688 }
17689 else {
17690 push(@Sentence, "Return value");
17691 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017692
17693 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017694 }
17695 elsif($Location=~/this/)
17696 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017697 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017698 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17699 }
17700 else {
17701 push(@Sentence, "\'this\' pointer");
17702 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017703
17704 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017705 }
17706 else
17707 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017708
17709 my $PName = getParamName($Location);
17710 my $PPos = getParamPos($PName, $Symbol, 1);
17711
17712 if(index($Location, "->")!=-1) {
17713 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017714 }
17715 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017716 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017717 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017718 if($PName) {
17719 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017720 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017721
17722 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17723 }
17724
17725 if($Location!~/this/)
17726 {
17727 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017728 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017729 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017730 push(@Sentence, "(pointer)");
17731 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017732 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017733 push(@Sentence, "(reference)");
17734 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017735 }
17736 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017737
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017738 if($Location eq "this") {
17739 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17740 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017741 else
17742 {
17743 my $Location_T = $Location;
17744 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17745
17746 my $TypeID_Problem = $TypeID;
17747 if($Location_T) {
17748 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17749 }
17750
17751 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17752 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17753 }
17754 else {
17755 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17756 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017757 }
17758 }
17759 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017760 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017761 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 +040017762 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017763
17764 my $Sent = join(" ", @Sentence);
17765
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017766 $Sent=~s/->/./g;
17767
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017768 if($ReportFormat eq "xml")
17769 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017770 $Sent=~s/'//g;
17771 }
17772
17773 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017774}
17775
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017776sub getFieldType($$$)
17777{
17778 my ($Location, $TypeId, $LibVersion) = @_;
17779
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017780 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017781
17782 foreach my $Name (@Fields)
17783 {
17784 my %Info = get_BaseType($TypeId, $LibVersion);
17785
17786 foreach my $Pos (keys(%{$Info{"Memb"}}))
17787 {
17788 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17789 {
17790 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17791 last;
17792 }
17793 }
17794 }
17795
17796 return $TypeId;
17797}
17798
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017799sub get_XmlSign($$)
17800{
17801 my ($Symbol, $LibVersion) = @_;
17802 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17803 my $Report = "";
17804 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17805 {
17806 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017807 my $Type = $Info->{"Param"}{$Pos}{"type"};
17808 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017809 foreach my $Typedef (keys(%ChangedTypedef))
17810 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017811 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17812 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17813 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017814 }
17815 $Report .= " <param pos=\"$Pos\">\n";
17816 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017817 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017818 $Report .= " </param>\n";
17819 }
17820 if(my $Return = $Info->{"Return"})
17821 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017822 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017823 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017824 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017825 $Report .= " </retval>\n";
17826 }
17827 return $Report;
17828}
17829
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017830sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017831{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017832 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017833 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017834 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017835 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017836 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17837 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017838 next;
17839 }
17840 $Report .= " <symbol name=\"$Symbol\">\n";
17841 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017842 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017843 {
17844 if(defined $CompleteSignature{1}{$Symbol}
17845 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17846 {
17847 $P1 = get_XmlSign($Symbol, 1);
17848 $S1 = get_Signature($Symbol, 1);
17849 }
17850 elsif($Symbol=~/\A(_Z|\?)/) {
17851 $S1 = $tr_name{$Symbol};
17852 }
17853 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017854 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017855 {
17856 if(defined $CompleteSignature{2}{$Symbol}
17857 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17858 {
17859 $P2 = get_XmlSign($Symbol, 2);
17860 $S2 = get_Signature($Symbol, 2);
17861 }
17862 elsif($Symbol=~/\A(_Z|\?)/) {
17863 $S2 = $tr_name{$Symbol};
17864 }
17865 }
17866 if($S1)
17867 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017868 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017869 $Report .= $P1;
17870 $Report .= " </old>\n";
17871 }
17872 if($S2 and $S2 ne $S1)
17873 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017874 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017875 $Report .= $P2;
17876 $Report .= " </new>\n";
17877 }
17878 $Report .= " </symbol>\n";
17879 }
17880 $Report .= "</symbols_info>\n";
17881 return $Report;
17882}
17883
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017884sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017885{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017886 my ($Level, $Report) = @_;
17887 if($ReportFormat eq "xml") {
17888 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017889 }
17890 if($StdOut)
17891 { # --stdout option
17892 print STDOUT $Report;
17893 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017894 else
17895 {
17896 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017897 mkpath(get_dirname($RPath));
17898
17899 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17900 print REPORT $Report;
17901 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017902 }
17903}
17904
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017905sub getReport($)
17906{
17907 my $Level = $_[0];
17908 if($ReportFormat eq "xml")
17909 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017910 if($Level eq "Join")
17911 {
17912 my $Report = "<reports>\n";
17913 $Report .= getReport("Binary");
17914 $Report .= getReport("Source");
17915 $Report .= "</reports>\n";
17916 return $Report;
17917 }
17918 else
17919 {
17920 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17921 my ($Summary, $MetaData) = get_Summary($Level);
17922 $Report .= $Summary."\n";
17923 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17924 $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 +040017925
17926 # additional symbols info (if needed)
17927 # $Report .= get_Report_SymbolsInfo($Level);
17928
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017929 $Report .= "</report>\n";
17930 return $Report;
17931 }
17932 }
17933 else
17934 { # HTML
17935 my $CssStyles = readModule("Styles", "Report.css");
17936 my $JScripts = readModule("Scripts", "Sections.js");
17937 if($Level eq "Join")
17938 {
17939 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17940 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017941 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017942 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17943 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 +040017944 my ($BSummary, $BMetaData) = get_Summary("Binary");
17945 my ($SSummary, $SMetaData) = get_Summary("Source");
17946 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 +030017947 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017948 <br/>
17949 <div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017950 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17951 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017952 </div>";
17953 $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>";
17954 $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 +030017955 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017956 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017957 return $Report;
17958 }
17959 else
17960 {
17961 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017962 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17963 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17964 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 +040017965 if($Level eq "Binary")
17966 {
17967 if(getArch(1) eq getArch(2)
17968 and getArch(1) ne "unknown") {
17969 $Description .= " on ".showArch(getArch(1));
17970 }
17971 }
17972 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 +030017973 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017974 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17975 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17976 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017977 $Report .= "</div>\n<br/><br/><br/>\n";
17978 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017979 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017980 return $Report;
17981 }
17982 }
17983}
17984
17985sub createReport()
17986{
17987 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017988 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017989 writeReport("Join", getReport("Join"));
17990 }
17991 elsif($DoubleReport)
17992 { # default
17993 writeReport("Binary", getReport("Binary"));
17994 writeReport("Source", getReport("Source"));
17995 }
17996 elsif($BinaryOnly)
17997 { # --binary
17998 writeReport("Binary", getReport("Binary"));
17999 }
18000 elsif($SourceOnly)
18001 { # --source
18002 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018003 }
18004}
18005
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030018006sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018007{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030018008 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030018009
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030018010 $Footer .= "<hr/>\n";
18011 $Footer .= "<div class='footer' align='right'>";
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030018012 $Footer .= "<i>Generated by <a href='".$HomePage{"Dev"}."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;</i>\n";
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030018013 $Footer .= "</div>\n";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030018014 $Footer .= "<br/>\n";
18015
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018016 return $Footer;
18017}
18018
18019sub get_Report_Problems($$)
18020{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040018021 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030018022
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040018023 my $Report = get_Report_TypeProblems($Severity, $Level);
18024 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018025 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018026 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030018027
18028 if($Severity eq "Low" or $Severity eq "Safe") {
18029 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018030 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030018031
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018032 if($ReportFormat eq "html")
18033 {
18034 if($Report)
18035 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018036 if($JoinReport)
18037 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040018038 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018039 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
18040 }
18041 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040018042 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018043 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018044 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018045 else
18046 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040018047 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018048 $Report = "<a name=\'Other_Changes\'></a>".$Report;
18049 }
18050 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040018051 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018052 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018053 }
18054 }
18055 }
18056 return $Report;
18057}
18058
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018059sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018060{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018061 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +030018062
18063 my $Head = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
18064 $Head .= "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n";
18065 $Head .= "<head>\n";
18066 $Head .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
18067 $Head .= "<meta name=\"keywords\" content=\"$Keywords\" />\n";
18068 $Head .= "<meta name=\"description\" content=\"$Description\" />\n";
18069 $Head .= "<title>$Title</title>\n";
18070 $Head .= "<style type=\"text/css\">\n$Styles</style>\n";
18071 $Head .= "<script type=\"text/javascript\" language=\"JavaScript\">\n<!--\n$Scripts\n-->\n</script>\n";
18072 $Head .= "</head>\n";
18073
18074 return $Head;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018075}
18076
18077sub insertIDs($)
18078{
18079 my $Text = $_[0];
18080 while($Text=~/CONTENT_ID/)
18081 {
18082 if(int($Content_Counter)%2) {
18083 $ContentID -= 1;
18084 }
18085 $Text=~s/CONTENT_ID/c_$ContentID/;
18086 $ContentID += 1;
18087 $Content_Counter += 1;
18088 }
18089 return $Text;
18090}
18091
18092sub checkPreprocessedUnit($)
18093{
18094 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018095 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018096 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018097 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018098
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018099 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018100 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018101 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018102 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018103 chomp($Line);
18104 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018105 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018106 $CurHeader = path_format($1, $OSgroup);
18107 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018108 $CurClass = "";
18109
18110 if(index($CurHeader, $TMP_DIR)==0) {
18111 next;
18112 }
18113
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018114 if(substr($CurHeaderName, 0, 1) eq "<")
18115 { # <built-in>, <command-line>, etc.
18116 $CurHeaderName = "";
18117 $CurHeader = "";
18118 }
18119
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018120 if($ExtraInfo)
18121 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018122 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018123 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
18124 }
18125 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018126 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018127 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018128 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018129 if($CurHeaderName)
18130 {
18131 if(not $Include_Neighbors{$Version}{$CurHeaderName}
18132 and not $Registered_Headers{$Version}{$CurHeader})
18133 { # not a target
18134 next;
18135 }
18136 if(not is_target_header($CurHeaderName, 1)
18137 and not is_target_header($CurHeaderName, 2))
18138 { # user-defined header
18139 next;
18140 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018141 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018142 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018143
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018144 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018145 {
18146 my ($Name, $Value) = ($1, $2);
18147 if(not $Constants{$Version}{$Name}{"Access"})
18148 {
18149 $Constants{$Version}{$Name}{"Access"} = "public";
18150 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018151 if($CurHeaderName) {
18152 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
18153 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018154 }
18155 }
18156 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
18157 $Constants{$Version}{$1}{"Access"} = "private";
18158 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018159 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018160 else
18161 {
18162 if(defined $ExtraDump)
18163 {
18164 if($Line=~/(\w+)\s*\(/)
18165 { # functions
18166 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18167 }
18168 #elsif($Line=~/(\w+)\s*;/)
18169 #{ # data
18170 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18171 #}
18172 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
18173 $CurClass = $2;
18174 }
18175 }
18176 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018177 }
18178 close(PREPROC);
18179 foreach my $Constant (keys(%{$Constants{$Version}}))
18180 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018181 if($Constants{$Version}{$Constant}{"Access"} eq "private")
18182 {
18183 delete($Constants{$Version}{$Constant});
18184 next;
18185 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040018186 if(not $ExtraDump and ($Constant=~/_h\Z/i
18187 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018188 { # skip
18189 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018190 }
18191 else {
18192 delete($Constants{$Version}{$Constant}{"Access"});
18193 }
18194 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018195 if($Debug)
18196 {
18197 mkpath($DEBUG_PATH{$Version});
18198 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
18199 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018200}
18201
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018202sub uncoverConstant($$)
18203{
18204 my ($LibVersion, $Constant) = @_;
18205 return "" if(not $LibVersion or not $Constant);
18206 return $Constant if(isCyclical(\@RecurConstant, $Constant));
18207 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
18208 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
18209 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018210
18211 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018212 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018213 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
18214 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018215 {
18216 push(@RecurConstant, $Constant);
18217 my $Uncovered = uncoverConstant($LibVersion, $Value);
18218 if($Uncovered ne "") {
18219 $Value = $Uncovered;
18220 }
18221 pop(@RecurConstant);
18222 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018223
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018224 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018225 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018226 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
18227 }
18228 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
18229}
18230
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018231sub simpleConstant($$)
18232{
18233 my ($LibVersion, $Value) = @_;
18234 if($Value=~/\W/)
18235 {
18236 my $Value_Copy = $Value;
18237 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
18238 {
18239 my $Word = $1;
18240 if($Value!~/$Word\s*\(/)
18241 {
18242 my $Val = uncoverConstant($LibVersion, $Word);
18243 if($Val ne "")
18244 {
18245 $Value=~s/\b$Word\b/$Val/g;
18246 }
18247 }
18248 }
18249 }
18250 return $Value;
18251}
18252
18253sub computeValue($)
18254{
18255 my $Value = $_[0];
18256
18257 if($Value=~/\A\((-?[\d]+)\)\Z/) {
18258 return $1;
18259 }
18260
18261 if($Value=~/\A[\d\-\+()]+\Z/) {
18262 return eval($Value);
18263 }
18264
18265 return $Value;
18266}
18267
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018268my %IgnoreConstant = map {$_=>1} (
18269 "VERSION",
18270 "VERSIONCODE",
18271 "VERNUM",
18272 "VERS_INFO",
18273 "PATCHLEVEL",
18274 "INSTALLPREFIX",
18275 "VBUILD",
18276 "VPATCH",
18277 "VMINOR",
18278 "BUILD_STRING",
18279 "BUILD_TIME",
18280 "PACKAGE_STRING",
18281 "PRODUCTION",
18282 "CONFIGURE_COMMAND",
18283 "INSTALLDIR",
18284 "BINDIR",
18285 "CONFIG_FILE_PATH",
18286 "DATADIR",
18287 "EXTENSION_DIR",
18288 "INCLUDE_PATH",
18289 "LIBDIR",
18290 "LOCALSTATEDIR",
18291 "SBINDIR",
18292 "SYSCONFDIR",
18293 "RELEASE",
18294 "SOURCE_ID",
18295 "SUBMINOR",
18296 "MINOR",
18297 "MINNOR",
18298 "MINORVERSION",
18299 "MAJOR",
18300 "MAJORVERSION",
18301 "MICRO",
18302 "MICROVERSION",
18303 "BINARY_AGE",
18304 "INTERFACE_AGE",
18305 "CORE_ABI",
18306 "PATCH",
18307 "COPYRIGHT",
18308 "TIMESTAMP",
18309 "REVISION",
18310 "PACKAGE_TAG",
18311 "PACKAGEDATE",
18312 "NUMVERSION",
18313 "Release",
18314 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018315);
18316
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018317sub constantFilter($$$)
18318{
18319 my ($Name, $Value, $Level) = @_;
18320
18321 if($Level eq "Binary")
18322 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018323 if($Name=~/_t\Z/)
18324 { # __malloc_ptr_t
18325 return 1;
18326 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018327 foreach (keys(%IgnoreConstant))
18328 {
18329 if($Name=~/(\A|_)$_(_|\Z)/)
18330 { # version
18331 return 1;
18332 }
18333 if(/\A[A-Z].*[a-z]\Z/)
18334 {
18335 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18336 { # version
18337 return 1;
18338 }
18339 }
18340 }
18341 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18342 { # version
18343 return 1;
18344 }
18345 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18346 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18347 return 1;
18348 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018349
18350 if($Value=~/\A["'].*['"]/i)
18351 { # string
18352 return 0;
18353 }
18354
18355 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18356 { # static int gcry_pth_init
18357 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018358 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018359 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018360 return 1;
18361 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018362 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018363 { # foo(p)
18364 return 1;
18365 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018366 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018367 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018368 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018369 return 1;
18370 }
18371 }
18372
18373 return 0;
18374}
18375
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018376sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018377{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018378 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018379 foreach my $Constant (keys(%{$Constants{1}}))
18380 {
18381 if($SkipConstants{1}{$Constant})
18382 { # skipped by the user
18383 next;
18384 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018385
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018386 if(my $Header = $Constants{1}{$Constant}{"Header"})
18387 {
18388 if(not is_target_header($Header, 1)
18389 and not is_target_header($Header, 2))
18390 { # user-defined header
18391 next;
18392 }
18393 }
18394 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018395 next;
18396 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018397
18398 my $Old_Value = uncoverConstant(1, $Constant);
18399
18400 if(constantFilter($Constant, $Old_Value, $Level))
18401 { # separate binary and source problems
18402 next;
18403 }
18404
18405 if(not defined $Constants{2}{$Constant}{"Value"})
18406 { # removed
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030018407 if(not defined $SkipRemovedConstants)
18408 {
18409 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18410 "Target"=>$Constant,
18411 "Old_Value"=>$Old_Value );
18412 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018413 next;
18414 }
18415
18416 if($Constants{2}{$Constant}{"Value"} eq "")
18417 { # empty value
18418 # TODO: implement a rule
18419 next;
18420 }
18421
18422 my $New_Value = uncoverConstant(2, $Constant);
18423
18424 my $Old_Value_Pure = $Old_Value;
18425 my $New_Value_Pure = $New_Value;
18426
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018427 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18428 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18429 $New_Value_Pure=~s/(\W)\s+/$1/g;
18430 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018431
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018432 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018433
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018434 if($New_Value_Pure ne $Old_Value_Pure)
18435 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018436 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18437 { # complex values
18438 next;
18439 }
18440 if(computeValue($Old_Value) eq computeValue($New_Value))
18441 { # expressions
18442 next;
18443 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018444 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18445 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18446 next;
18447 }
18448 if($Old_Value eq "0" and $New_Value eq "NULL")
18449 { # 0 => NULL
18450 next;
18451 }
18452 if($Old_Value eq "NULL" and $New_Value eq "0")
18453 { # NULL => 0
18454 next;
18455 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018456 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018457 "Target"=>$Constant,
18458 "Old_Value"=>$Old_Value,
18459 "New_Value"=>$New_Value );
18460 }
18461 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018462
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030018463 if(defined $SkipAddedConstants) {
18464 return;
18465 }
18466
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018467 foreach my $Constant (keys(%{$Constants{2}}))
18468 {
18469 if(not defined $Constants{1}{$Constant}{"Value"})
18470 {
18471 if($SkipConstants{2}{$Constant})
18472 { # skipped by the user
18473 next;
18474 }
18475
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018476 if(my $Header = $Constants{2}{$Constant}{"Header"})
18477 {
18478 if(not is_target_header($Header, 1)
18479 and not is_target_header($Header, 2))
18480 { # user-defined header
18481 next;
18482 }
18483 }
18484 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018485 next;
18486 }
18487
18488 my $New_Value = uncoverConstant(2, $Constant);
18489 if(not defined $New_Value or $New_Value eq "") {
18490 next;
18491 }
18492
18493 if(constantFilter($Constant, $New_Value, $Level))
18494 { # separate binary and source problems
18495 next;
18496 }
18497
18498 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18499 "Target"=>$Constant,
18500 "New_Value"=>$New_Value );
18501 }
18502 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018503}
18504
18505sub convert_integer($)
18506{
18507 my $Value = $_[0];
18508 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018509 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018510 return hex($Value);
18511 }
18512 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018513 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018514 return oct($Value);
18515 }
18516 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018517 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018518 return oct($Value);
18519 }
18520 else {
18521 return $Value;
18522 }
18523}
18524
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018525sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018526{
18527 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018528 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018529 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018530 {
18531 if($LibVersion==1)
18532 {
18533 printMsg("WARNING", "checking headers only");
18534 $CheckHeadersOnly = 1;
18535 }
18536 else {
18537 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18538 }
18539 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018540
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018541 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018542 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018543 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018544
18545 if($CheckUndefined)
18546 {
18547 my %UndefinedLibs = ();
18548
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018549 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18550
18551 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018552 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018553 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018554 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018555 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018556 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018557 if($Symbol_Library{$LibVersion}{$Symbol}
18558 or $DepSymbol_Library{$LibVersion}{$Symbol})
18559 { # exported by target library
18560 next;
18561 }
18562 if(index($Symbol, '@')!=-1)
18563 { # exported default symbol version (@@)
18564 $Symbol=~s/\@/\@\@/;
18565 if($Symbol_Library{$LibVersion}{$Symbol}
18566 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18567 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018568 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018569 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018570 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18571 $UndefinedLibs{$Path} = 1;
18572 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018573 }
18574 }
18575 }
18576 if($ExtraInfo)
18577 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018578 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018579 {
18580 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018581 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018582 foreach (@Paths)
18583 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018584 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018585 my ($Dir, $Name) = separate_path($_);
18586
18587 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018588 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018589 }
18590
18591 $Name = parse_libname($Name, "name", $OStarget);
18592 $Name=~s/\Alib//;
18593
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018594 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018595 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018596
18597 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18598 {
18599 $LibString = " -L".esc($Dir).$LibString;
18600 }
18601
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018602 writeFile($ExtraInfo."/libs-string", $LibString);
18603 }
18604 }
18605 }
18606
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018607 if($ExtraInfo) {
18608 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18609 }
18610
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018611 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018612 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018613 if($#LibPaths!=-1)
18614 {
18615 if(not keys(%{$Symbol_Library{$LibVersion}}))
18616 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018617 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018618 printMsg("WARNING", "checking headers only");
18619 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018620 }
18621 }
18622 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018623
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018624 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018625 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018626}
18627
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018628my %Prefix_Lib_Map=(
18629 # symbols for autodetecting library dependencies (by prefix)
18630 "pthread_" => ["libpthread"],
18631 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18632 "cairo_" => ["libcairo"],
18633 "gtk_" => ["libgtk-x11-2.0"],
18634 "atk_" => ["libatk-1.0"],
18635 "gdk_" => ["libgdk-x11-2.0"],
18636 "gl" => ["libGL"],
18637 "glu" => ["libGLU"],
18638 "popt" => ["libpopt"],
18639 "Py" => ["libpython"],
18640 "jpeg_" => ["libjpeg"],
18641 "BZ2_" => ["libbz2"],
18642 "Fc" => ["libfontconfig"],
18643 "Xft" => ["libXft"],
18644 "SSL_" => ["libssl"],
18645 "sem_" => ["libpthread"],
18646 "snd_" => ["libasound"],
18647 "art_" => ["libart_lgpl_2"],
18648 "dbus_g" => ["libdbus-glib-1"],
18649 "GOMP_" => ["libgomp"],
18650 "omp_" => ["libgomp"],
18651 "cms" => ["liblcms"]
18652);
18653
18654my %Pattern_Lib_Map=(
18655 "SL[a-z]" => ["libslang"]
18656);
18657
18658my %Symbol_Lib_Map=(
18659 # symbols for autodetecting library dependencies (by name)
18660 "pow" => "libm",
18661 "fmod" => "libm",
18662 "sin" => "libm",
18663 "floor" => "libm",
18664 "cos" => "libm",
18665 "dlopen" => "libdl",
18666 "deflate" => "libz",
18667 "inflate" => "libz",
18668 "move_panel" => "libpanel",
18669 "XOpenDisplay" => "libX11",
18670 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018671 "clock_gettime" => "librt",
18672 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018673);
18674
18675sub find_SymbolLibs($$)
18676{
18677 my ($LibVersion, $Symbol) = @_;
18678
18679 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18680 { # debug symbols
18681 return ();
18682 }
18683
18684 my %Paths = ();
18685
18686 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18687 {
18688 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18689 $Paths{$Path} = 1;
18690 }
18691 }
18692
18693 if(my $SymbolPrefix = getPrefix($Symbol))
18694 {
18695 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18696 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18697 }
18698
18699 if(not keys(%Paths))
18700 {
18701 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18702 {
18703 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18704 {
18705 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18706 $Paths{$Path} = 1;
18707 }
18708 }
18709 }
18710 }
18711
18712 if(not keys(%Paths))
18713 {
18714 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18715 {
18716 if($Symbol=~/\A$Prefix/)
18717 {
18718 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18719 {
18720 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18721 $Paths{$Path} = 1;
18722 }
18723 }
18724 }
18725 }
18726 }
18727
18728 if(not keys(%Paths))
18729 {
18730 if($SymbolPrefix)
18731 { # try to find a library by symbol prefix
18732 if($SymbolPrefix eq "inotify" and
18733 index($Symbol, "\@GLIBC")!=-1)
18734 {
18735 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18736 $Paths{$Path} = 1;
18737 }
18738 }
18739 else
18740 {
18741 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18742 $Paths{$Path} = 1;
18743 }
18744 }
18745 }
18746 }
18747
18748 if(my @Paths = keys(%Paths)) {
18749 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18750 }
18751 }
18752 return keys(%Paths);
18753}
18754
18755sub get_LibPath_Prefix($$)
18756{
18757 my ($LibVersion, $Prefix) = @_;
18758
18759 $Prefix = lc($Prefix);
18760 $Prefix=~s/[_]+\Z//g;
18761
18762 foreach ("-2", "2", "-1", "1", "")
18763 { # libgnome-2.so
18764 # libxml2.so
18765 # libdbus-1.so
18766 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18767 return $Path;
18768 }
18769 }
18770 return "";
18771}
18772
18773sub getPrefix($)
18774{
18775 my $Str = $_[0];
18776 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18777 { # XmuValidArea: Xmu
18778 return $1;
18779 }
18780 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18781 { # snfReadFont: snf
18782 return $1;
18783 }
18784 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18785 { # XRRTimes: XRR
18786 return $1;
18787 }
18788 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18789 { # H5HF_delete: H5
18790 return $1;
18791 }
18792 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18793 { # alarm_event_add: alarm_
18794 return $1;
18795 }
18796 elsif($Str=~/\A(([a-z])\2{1,})/i)
18797 { # ffopen
18798 return $1;
18799 }
18800 return "";
18801}
18802
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018803sub getSymbolSize($$)
18804{ # size from the shared library
18805 my ($Symbol, $LibVersion) = @_;
18806 return 0 if(not $Symbol);
18807 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18808 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18809 {
18810 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18811 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18812 {
18813 if($Size<0) {
18814 return -$Size;
18815 }
18816 }
18817 }
18818 return 0;
18819}
18820
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018821sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018822{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18823 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018824 my ($Name, $Type) = @_;
18825
18826 # single
18827 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018828 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018829 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018830 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018831 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018832
18833 # double
18834 if($Name=~/$DEFAULT_STD_PARMS/)
18835 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018836 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018837 {
18838 my ($ShortName, $FuncParams) = split_Signature($Name);
18839
18840 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18841 {
18842 if(index($FParam, "<")!=-1)
18843 {
18844 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18845 my $FParam_N = canonifyName($FParam, "T");
18846 if($FParam_N ne $FParam) {
18847 $Name=~s/\Q$FParam\E/$FParam_N/g;
18848 }
18849 }
18850 }
18851 }
18852 elsif($Type eq "T")
18853 {
18854 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18855
18856 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018857 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018858 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018859 my $FParam = $TParams[0];
18860 foreach my $Pos (1 .. $#TParams)
18861 {
18862 my $TParam = $TParams[$Pos];
18863 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18864 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18865 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018866 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018867 }
18868 }
18869 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018870 if($Type eq "S") {
18871 return formatName($Name, "S");
18872 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018873 return $Name;
18874}
18875
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018876sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018877{
18878 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018879 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018880 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018881 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018882 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018883 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018884 next if($tr_name{$Symbol});
18885 $Symbol=~s/[\@\$]+(.*)\Z//;
18886 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018887 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018888 elsif(index($Symbol, "?")==0)
18889 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018890 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018891 }
18892 else
18893 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018894 $tr_name{$Symbol} = $Symbol;
18895 $mangled_name_gcc{$Symbol} = $Symbol;
18896 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018897 }
18898 }
18899 if($#MnglNames1 > -1)
18900 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018901 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018902 foreach my $MnglName (@MnglNames1)
18903 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018904 if(my $Unmangled = pop(@UnmangledNames))
18905 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018906 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018907 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18908 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18909 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018910 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018911 and $tr_name{$MnglName}=~/vtable for (.+)/)
18912 { # bind class name and v-table symbol
18913 my $ClassName = $1;
18914 $ClassVTable{$ClassName} = $MnglName;
18915 $VTableClass{$MnglName} = $ClassName;
18916 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018917 }
18918 }
18919 }
18920 if($#MnglNames2 > -1)
18921 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018922 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018923 foreach my $MnglName (@MnglNames2)
18924 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018925 if(my $Unmangled = pop(@UnmangledNames))
18926 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018927 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018928 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18929 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018930 }
18931 }
18932 return \%tr_name;
18933}
18934
18935sub link_symbol($$$)
18936{
18937 my ($Symbol, $RunWith, $Deps) = @_;
18938 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18939 return 1;
18940 }
18941 if($Deps eq "+Deps")
18942 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018943 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018944 return 1;
18945 }
18946 }
18947 return 0;
18948}
18949
18950sub link_symbol_internal($$$)
18951{
18952 my ($Symbol, $RunWith, $Where) = @_;
18953 return 0 if(not $Where or not $Symbol);
18954 if($Where->{$RunWith}{$Symbol})
18955 { # the exact match by symbol name
18956 return 1;
18957 }
18958 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18959 { # indirect symbol version, i.e.
18960 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018961 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018962 if($Where->{$RunWith}{$VSym}) {
18963 return 1;
18964 }
18965 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018966 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018967 if($Sym and $Ver)
18968 { # search for the symbol with the same version
18969 # or without version
18970 if($Where->{$RunWith}{$Sym})
18971 { # old: foo@v|foo@@v
18972 # new: foo
18973 return 1;
18974 }
18975 if($Where->{$RunWith}{$Sym."\@".$Ver})
18976 { # old: foo|foo@@v
18977 # new: foo@v
18978 return 1;
18979 }
18980 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18981 { # old: foo|foo@v
18982 # new: foo@@v
18983 return 1;
18984 }
18985 }
18986 return 0;
18987}
18988
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018989sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018990{
18991 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018992 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018993 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018994 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018995 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018996 my $NM = get_CmdPath("nm");
18997 if(not $NM) {
18998 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018999 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019000 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019001 while(<APP>)
19002 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019003 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019004 push(@Imported, $1);
19005 }
19006 }
19007 close(APP);
19008 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019009 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019010 {
19011 my $DumpBinCmd = get_CmdPath("dumpbin");
19012 if(not $DumpBinCmd) {
19013 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
19014 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019015 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019016 while(<APP>)
19017 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019018 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
19019 push(@Imported, $1);
19020 }
19021 }
19022 close(APP);
19023 }
19024 else
19025 {
19026 my $ReadelfCmd = get_CmdPath("readelf");
19027 if(not $ReadelfCmd) {
19028 exitStatus("Not_Found", "can't find \"readelf\"");
19029 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019030 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019031 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019032 while(<APP>)
19033 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019034 if(defined $symtab)
19035 { # do nothing with symtab
19036 if(index($_, "'.dynsym'")!=-1)
19037 { # dynamic table
19038 $symtab = undef;
19039 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019040 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019041 elsif(index($_, "'.symtab'")!=-1)
19042 { # symbol table
19043 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019044 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019045 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019046 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019047 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
19048 if($Ndx eq "UND")
19049 { # only imported symbols
19050 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019051 }
19052 }
19053 }
19054 close(APP);
19055 }
19056 return @Imported;
19057}
19058
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019059my %ELF_BIND = map {$_=>1} (
19060 "WEAK",
19061 "GLOBAL"
19062);
19063
19064my %ELF_TYPE = map {$_=>1} (
19065 "FUNC",
19066 "IFUNC",
19067 "OBJECT",
19068 "COMMON"
19069);
19070
19071my %ELF_VIS = map {$_=>1} (
19072 "DEFAULT",
19073 "PROTECTED"
19074);
19075
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019076sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019077{ # read the line of 'readelf' output corresponding to the symbol
19078 my @Info = split(/\s+/, $_[0]);
19079 # Num: Value Size Type Bind Vis Ndx Name
19080 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019081 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019082 shift(@Info); # spaces
19083 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019084
19085 if($#Info==7)
19086 { # UND SYMBOL (N)
19087 if($Info[7]=~/\(\d+\)/) {
19088 pop(@Info);
19089 }
19090 }
19091
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019092 if($#Info!=6)
19093 { # other lines
19094 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019095 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019096 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019097 return () if(not defined $ELF_BIND{$Info[3]});
19098 return () if(not defined $ELF_VIS{$Info[4]});
19099 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
19100 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
19101 return ();
19102 }
19103 if($OStarget eq "symbian")
19104 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
19105 if(index($Info[6], "_._.absent_export_")!=-1)
19106 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
19107 return ();
19108 }
19109 $Info[6]=~s/\@.+//g; # remove version
19110 }
19111 if(index($Info[2], "0x") == 0)
19112 { # size == 0x3d158
19113 $Info[2] = hex($Info[2]);
19114 }
19115 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019116}
19117
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019118sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019119{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019120 my ($LibVersion, $Name) = @_;
19121 return "" if(not $LibVersion or not $Name);
19122 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
19123 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019124 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019125 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
19126}
19127
19128sub get_LibPath_I($$)
19129{
19130 my ($LibVersion, $Name) = @_;
19131 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019132 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019133 if(-f $Name)
19134 { # absolute path
19135 return $Name;
19136 }
19137 else
19138 { # broken
19139 return "";
19140 }
19141 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019142 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019143 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019144 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019145 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019146 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019147 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019148 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019149 }
19150 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
19151 { # ldconfig default paths
19152 return $DefaultPath;
19153 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019154 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019155 { # search in default linker directories
19156 # and then in all system paths
19157 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019158 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019159 }
19160 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019161 if(not defined $Cache{"checkSystemFiles"}) {
19162 checkSystemFiles();
19163 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019164 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
19165 return $AllObjects[0];
19166 }
19167 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
19168 {
19169 if($ShortName ne $Name)
19170 { # FIXME: check this case
19171 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
19172 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019173 }
19174 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019175 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019176 # can't find
19177 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019178}
19179
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019180sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019181{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019182 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
19183 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019184
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019185 my $Real_Path = realpath_F($Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019186
19187 if(not $Real_Path)
19188 { # broken link
19189 return ();
19190 }
19191
19192 my $Lib_Name = get_filename($Real_Path);
19193
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019194 if($ExtraInfo)
19195 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019196 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019197 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019198 }
19199
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019200 if($IsNeededLib)
19201 {
19202 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
19203 return ();
19204 }
19205 }
19206 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019207 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019208
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019209 push(@RecurLib, $Lib_Name);
19210 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019211 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
19212
19213 if(not $IsNeededLib)
19214 { # special cases: libstdc++ and libc
19215 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
19216 {
19217 if($ShortName eq "libstdc++")
19218 { # libstdc++.so.6
19219 $STDCXX_TESTING = 1;
19220 }
19221 elsif($ShortName eq "libc")
19222 { # libc-2.11.3.so
19223 $GLIBC_TESTING = 1;
19224 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019225 }
19226 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019227 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019228 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019229 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019230 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019231 mkpath(get_dirname($DebugPath));
19232 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019233 if($OStarget eq "macos")
19234 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019235 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019236 if(not $NM) {
19237 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019238 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019239 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019240 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019241 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019242 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019243 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019244 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019245 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019246 else
19247 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019248 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019249 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019250 while(<LIB>)
19251 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019252 if($CheckUndefined)
19253 {
19254 if(not $IsNeededLib)
19255 {
19256 if(/ U _([\w\$]+)\s*\Z/)
19257 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019258 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019259 next;
19260 }
19261 }
19262 }
19263
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019264 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019265 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019266 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019267 if($IsNeededLib)
19268 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019269 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019270 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019271 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19272 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019273 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019274 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019275 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019276 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019277 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19278 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019279 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19280 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019281 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019282 setLanguage($LibVersion, "C++");
19283 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019284 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019285 }
19286 }
19287 }
19288 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019289
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019290 if($Deps)
19291 {
19292 if($LIB_TYPE eq "dynamic")
19293 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019294
19295 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019296 if(not $OtoolCmd) {
19297 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019298 }
19299
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019300 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19301 while(<LIB>)
19302 {
19303 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
19304 and $1 ne $Lib_Path) {
19305 $NeededLib{$1} = 1;
19306 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019307 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019308 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019309 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019310 }
19311 }
19312 elsif($OStarget eq "windows")
19313 { # Windows *.dll, *.lib
19314 my $DumpBinCmd = get_CmdPath("dumpbin");
19315 if(not $DumpBinCmd) {
19316 exitStatus("Not_Found", "can't find \"dumpbin\"");
19317 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019318 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019319 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019320 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019321 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019322 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019323 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019324 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019325 else
19326 { # write to pipe
19327 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019328 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019329 while(<LIB>)
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019330 {
19331 my $realname = undef;
19332 if($LIB_TYPE eq "dynamic")
19333 {
19334 # 1197 4AC 0000A620 SetThreadStackGuarantee
19335 # 1198 4AD SetThreadToken (forwarded to ...)
19336 # 3368 _o2i_ECPublicKey
19337 # 1 0 00005B30 ??0?N = ... (with pdb)
19338 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
19339 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
19340 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
19341 { # dynamic, static and forwarded symbols
19342 $realname = $1;
19343 }
19344 }
19345 else
19346 { # static
19347 if(/\A\s{10,}\d*\s+([\w\?\@]+)\s*\Z/i)
19348 {
19349 # 16 IID_ISecurityInformation
19350 $realname = $1;
19351 }
19352 }
19353
19354 if($realname)
19355 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019356 if($IsNeededLib)
19357 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019358 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019359 {
19360 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19361 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19362 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019363 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019364 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019365 {
19366 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19367 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019368 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19369 {
19370 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19371 setLanguage($LibVersion, "C++");
19372 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019373 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019374 }
19375 }
19376 }
19377 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019378
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019379 if($Deps)
19380 {
19381 if($LIB_TYPE eq "dynamic")
19382 { # dependencies
19383 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19384 while(<LIB>)
19385 {
19386 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19387 and $1 ne $Lib_Path) {
19388 $NeededLib{path_format($1, $OSgroup)} = 1;
19389 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019390 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019391 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019392 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019393 }
19394 }
19395 else
19396 { # Unix; *.so, *.a
19397 # Symbian: *.dso, *.lib
19398 my $ReadelfCmd = get_CmdPath("readelf");
19399 if(not $ReadelfCmd) {
19400 exitStatus("Not_Found", "can't find \"readelf\"");
19401 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019402 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019403 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019404 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019405 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019406 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019407 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019408 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019409 else
19410 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019411 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019412 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019413 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019414 while(<LIB>)
19415 {
19416 if($LIB_TYPE eq "dynamic")
19417 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019418 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019419 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019420 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019421 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019422 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019423 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019424 # do nothing with symtab
19425 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019426 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019427 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019428 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019429 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019430 next;
19431 }
19432 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019433 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019434 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019435 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019436 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019437 if($CheckUndefined)
19438 {
19439 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019440 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019441 }
19442 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019443 next;
19444 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019445 if($Bind eq "WEAK")
19446 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019447 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019448 if($Weak eq "-Weak")
19449 { # skip WEAK symbols
19450 next;
19451 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019452 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019453 my $Short = $Symbol;
19454 $Short=~s/\@.+//g;
19455 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019456 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019457 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19458 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019459 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019460 if($IsNeededLib)
19461 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019462 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019463 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019464 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19465 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019466 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019467 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019468 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019469 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019470 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19471 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19472 if($Vers)
19473 {
19474 if($LIB_EXT eq "so")
19475 { # value
19476 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19477 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19478 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019479 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019480 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19481 {
19482 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19483 setLanguage($LibVersion, "C++");
19484 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019485 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019486 }
19487 }
19488 }
19489 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019490
19491 if($Deps and $LIB_TYPE eq "dynamic")
19492 { # dynamic library specifics
19493 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19494 open(LIB, $Cmd." |");
19495
19496 while(<LIB>)
19497 {
19498 if(/NEEDED.+\[([^\[\]]+)\]/)
19499 { # dependencies:
19500 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19501 $NeededLib{$1} = 1;
19502 }
19503 }
19504
19505 close(LIB);
19506 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019507 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019508 if($Vers)
19509 {
19510 if(not $IsNeededLib and $LIB_EXT eq "so")
19511 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019512 my %Found = ();
19513
19514 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019515 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019516 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019517 next if(index($Symbol,"\@")==-1);
19518 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019519 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019520 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019521 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019522 if($Symbol_SameValue ne $Symbol
19523 and index($Symbol_SameValue,"\@")==-1)
19524 {
19525 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019526 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019527 last;
19528 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019529 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019530 }
19531 }
19532
19533 # default
19534 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19535 {
19536 next if(defined $Found{$Symbol});
19537 next if(index($Symbol,"\@\@")==-1);
19538
19539 if($Symbol=~/\A([^\@]*)\@\@/
19540 and not $SymVer{$LibVersion}{$1})
19541 {
19542 $SymVer{$LibVersion}{$1} = $Symbol;
19543 $Found{$Symbol} = 1;
19544 }
19545 }
19546
19547 # non-default
19548 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19549 {
19550 next if(defined $Found{$Symbol});
19551 next if(index($Symbol,"\@")==-1);
19552
19553 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19554 and not $SymVer{$LibVersion}{$1})
19555 {
19556 $SymVer{$LibVersion}{$1} = $Symbol;
19557 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019558 }
19559 }
19560 }
19561 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019562 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019563 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019564 foreach my $DyLib (sort keys(%NeededLib))
19565 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019566 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19567
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019568 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19569 {
19570 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19571 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19572 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019573 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019574 }
19575 }
19576 pop(@RecurLib);
19577 return $Library_Symbol{$LibVersion};
19578}
19579
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019580sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019581{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019582 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019583 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019584 return keys(%Prefixes);
19585}
19586
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019587sub get_prefixes_I($$)
19588{
19589 foreach my $P (@{$_[0]})
19590 {
19591 my @Parts = reverse(split(/[\/\\]+/, $P));
19592 my $Name = $Parts[0];
19593 foreach (1 .. $#Parts)
19594 {
19595 $_[1]->{$Name}{$P} = 1;
19596 last if($_>4 or $Parts[$_] eq "include");
19597 $Name = $Parts[$_].$SLASH.$Name;
19598 }
19599 }
19600}
19601
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019602sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019603{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019604 $Cache{"checkSystemFiles"} = 1;
19605
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019606 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019607
19608 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019609 {
19610 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019611
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019612 my @Files = cmd_find($DevelPath,"f");
19613 foreach my $Link (cmd_find($DevelPath,"l"))
19614 { # add symbolic links
19615 if(-f $Link) {
19616 push(@Files, $Link);
19617 }
19618 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019619
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019620 # search for headers in /usr/lib
19621 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19622 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19623 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019624
19625 # search for libraries in /usr/lib (including symbolic links)
19626 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19627 foreach my $Path (@Libs)
19628 {
19629 my $N = get_filename($Path);
19630 $SystemObjects{$N}{$Path} = 1;
19631 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019632 }
19633 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019634
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019635 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019636 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019637 next if(not -d $DevelPath);
19638 # search for all header files in the /usr/include
19639 # with or without extension (ncurses.h, QtCore, ...)
19640 push(@SysHeaders, cmd_find($DevelPath,"f"));
19641 foreach my $Link (cmd_find($DevelPath,"l"))
19642 { # add symbolic links
19643 if(-f $Link) {
19644 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019645 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019646 }
19647 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019648 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019649}
19650
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019651sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019652{
19653 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019654 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019655 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19656 {
19657 if(not -e $Dest) {
19658 exitStatus("Access_Error", "can't access \'$Dest\'");
19659 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019660 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019661 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19662 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019663 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019664 }
19665 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019666 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019667}
19668
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019669sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019670{
19671 my ($Path, $LibVersion) = @_;
19672 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019673 my $Name = get_filename($Path);
19674 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019675 return 1;
19676 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019677 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019678 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19679 return 1;
19680 }
19681 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19682 {
19683 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19684 return 1;
19685 }
19686 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019687 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019688 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019689 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019690 return 1;
19691 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019692 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019693 return 1;
19694 }
19695 }
19696 return 0;
19697}
19698
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019699sub specificHeader($$)
19700{
19701 my ($Header, $Spec) = @_;
19702 my $Name = get_filename($Header);
19703
19704 if($Spec eq "windows")
19705 {# MS Windows
19706 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19707 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19708 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19709 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19710 my @Dirs = (
19711 "win32",
19712 "win64",
19713 "win",
19714 "windows",
19715 "msvcrt"
19716 ); # /gsf-win32/
19717 if(my $DIRs = join("|", @Dirs)) {
19718 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19719 }
19720 }
19721 elsif($Spec eq "macos")
19722 { # Mac OS
19723 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19724 }
19725
19726 return 0;
19727}
19728
19729sub skipAlienHeader($)
19730{
19731 my $Path = $_[0];
19732 my $Name = get_filename($Path);
19733 my $Dir = get_dirname($Path);
19734
19735 if($Tolerance=~/2/)
19736 { # 2 - skip internal headers
19737 my @Terms = (
19738 "p",
19739 "priv",
19740 "int",
19741 "impl",
19742 "implementation",
19743 "internal",
19744 "private",
19745 "old",
19746 "compat",
19747 "debug",
19748 "test",
19749 "gen"
19750 );
19751
19752 my @Dirs = (
19753 "private",
19754 "priv",
19755 "port",
19756 "impl",
19757 "internal",
19758 "detail",
19759 "details",
19760 "old",
19761 "compat",
19762 "debug",
19763 "config",
19764 "compiler",
19765 "platform",
19766 "test"
19767 );
19768
19769 if(my $TERMs = join("|", @Terms)) {
19770 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19771 }
19772 if(my $DIRs = join("|", @Dirs)) {
19773 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19774 }
19775
19776 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19777 }
19778
19779 if($Tolerance=~/1/)
19780 { # 1 - skip non-Linux headers
19781 if($OSgroup ne "windows")
19782 {
19783 if(specificHeader($Path, "windows")) {
19784 return 1;
19785 }
19786 }
19787 if($OSgroup ne "macos")
19788 {
19789 if(specificHeader($Path, "macos")) {
19790 return 1;
19791 }
19792 }
19793 }
19794
19795 # valid
19796 return 0;
19797}
19798
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019799sub skipHeader($$)
19800{
19801 my ($Path, $LibVersion) = @_;
19802 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019803 if(defined $Cache{"skipHeader"}{$Path}) {
19804 return $Cache{"skipHeader"}{$Path};
19805 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019806 if(defined $Tolerance and $Tolerance=~/1|2/)
19807 { # --tolerant
19808 if(skipAlienHeader($Path)) {
19809 return ($Cache{"skipHeader"}{$Path} = 1);
19810 }
19811 }
19812 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19813 return 0;
19814 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019815 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19816}
19817
19818sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019819{ # returns:
19820 # 1 - if header should NOT be included and checked
19821 # 2 - if header should NOT be included, but should be checked
19822 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019823 my $Name = get_filename($Path);
19824 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019825 return $Kind;
19826 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019827 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19828 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019829 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019830 if(index($Path, $D)!=-1)
19831 {
19832 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19833 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19834 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019835 }
19836 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019837 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19838 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019839 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019840 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19841 {
19842 if($Name=~/$P/) {
19843 return $Kind;
19844 }
19845 if($P=~/[\/\\]/ and $Path=~/$P/) {
19846 return $Kind;
19847 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019848 }
19849 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019850
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019851 return 0;
19852}
19853
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019854sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019855{
19856 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019857 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019858 { # system directory
19859 return;
19860 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019861 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019862 { # already registered
19863 return;
19864 }
19865 foreach my $Path (find_libs($Dir,"",1))
19866 {
19867 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019868 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019869 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019870 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019871 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19872}
19873
19874sub registerObject($$)
19875{
19876 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019877
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019878 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019879 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko9c87bdb2016-10-20 18:15:38 +030019880 if($OStarget=~/linux|bsd|gnu|solaris/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019881 {
19882 if(my $SONAME = getSONAME($Path)) {
19883 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19884 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019885 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019886 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19887 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019888 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019889
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019890 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019891 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019892 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019893 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019894 if($ObjArch ne getArch_GCC($LibVersion))
19895 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19896 $CheckedArch{$LibVersion} = 1;
19897 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 +040019898 }
19899 }
19900 }
19901}
19902
19903sub getArch_Object($)
19904{
19905 my $Path = $_[0];
19906
19907 my %MachineType = (
19908 "14C" => "x86",
19909 "8664" => "x86_64",
19910 "1C0" => "arm",
19911 "200" => "ia64"
19912 );
19913
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019914 my %ArchName = (
19915 "s390:31-bit" => "s390",
19916 "s390:64-bit" => "s390x",
19917 "powerpc:common" => "ppc32",
19918 "powerpc:common64" => "ppc64",
19919 "i386:x86-64" => "x86_64",
19920 "mips:3000" => "mips",
19921 "sparc:v8plus" => "sparcv9"
19922 );
19923
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019924 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019925 {
19926 my $DumpbinCmd = get_CmdPath("dumpbin");
19927 if(not $DumpbinCmd) {
19928 exitStatus("Not_Found", "can't find \"dumpbin\"");
19929 }
19930
19931 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19932 my $Out = `$Cmd`;
19933
19934 if($Out=~/(\w+)\smachine/)
19935 {
19936 if(my $Type = $MachineType{uc($1)})
19937 {
19938 return $Type;
19939 }
19940 }
19941 }
Andrey Ponomarenko9c87bdb2016-10-20 18:15:38 +030019942 elsif($OStarget=~/macos/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019943 {
Andrey Ponomarenko9c87bdb2016-10-20 18:15:38 +030019944 my $OtoolCmd = get_CmdPath("otool");
19945 if(not $OtoolCmd) {
19946 exitStatus("Not_Found", "can't find \"otool\"");
19947 }
19948
19949 my $Cmd = $OtoolCmd." -hv -arch all \"$Path\"";
19950 my $Out = qx/$Cmd/;
19951
19952 if($Out=~/X86_64/i) {
19953 return "x86_64";
19954 }
19955 elsif($Out=~/X86/i) {
19956 return "x86";
19957 }
19958 }
19959 else
19960 { # linux, bsd, gnu, solaris, ...
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019961 my $ObjdumpCmd = get_CmdPath("objdump");
19962 if(not $ObjdumpCmd) {
19963 exitStatus("Not_Found", "can't find \"objdump\"");
19964 }
19965
19966 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019967
19968 if($OSgroup eq "windows") {
19969 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19970 }
19971 else {
19972 $Cmd = "LANG=$LOCALE ".$Cmd;
19973 }
19974 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019975
19976 if($Out=~/architecture:\s+([\w\-\:]+)/)
19977 {
19978 my $Arch = $1;
19979 if($Arch=~s/\:(.+)//)
19980 {
19981 my $Suffix = $1;
19982
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019983 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019984 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019985 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019986 }
19987 }
19988
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019989 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019990 $Arch = "x86";
19991 }
19992
19993 if($Arch eq "x86-64") {
19994 $Arch = "x86_64";
19995 }
19996
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019997 if($Arch eq "ia64-elf64") {
19998 $Arch = "ia64";
19999 }
20000
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020001 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020002 }
20003 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020004
20005 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020006}
20007
20008sub getSONAME($)
20009{
20010 my $Path = $_[0];
20011 return if(not $Path);
20012 if(defined $Cache{"getSONAME"}{$Path}) {
20013 return $Cache{"getSONAME"}{$Path};
20014 }
20015 my $ObjdumpCmd = get_CmdPath("objdump");
20016 if(not $ObjdumpCmd) {
20017 exitStatus("Not_Found", "can't find \"objdump\"");
20018 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010020019 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020020 if($OSgroup eq "windows") {
20021 $SonameCmd .= " | find \"SONAME\"";
20022 }
20023 else {
20024 $SonameCmd .= " | grep SONAME";
20025 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020026 if(my $SonameInfo = `$SonameCmd`)
20027 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020028 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
20029 return ($Cache{"getSONAME"}{$Path} = $1);
20030 }
20031 }
20032 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020033}
20034
20035sub getSOPaths_Dest($$)
20036{
20037 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020038 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020039 return ();
20040 }
20041 if(-f $Dest)
20042 {
20043 if(not parse_libname($Dest, "name", $OStarget)) {
20044 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
20045 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020046 registerObject($Dest, $LibVersion);
20047 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020048 return ($Dest);
20049 }
20050 elsif(-d $Dest)
20051 {
20052 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020053 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020054 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020055 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
20056 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020057 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020058 { # all files and symlinks that match the name of a library
20059 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
20060 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020061 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020062 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020063 }
20064 }
20065 }
20066 else
20067 { # search for all files and symlinks
20068 foreach my $Path (find_libs($Dest,"",""))
20069 {
20070 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020071 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020072 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020073 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020074 }
20075 if($OSgroup eq "macos")
20076 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020077 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020078 {
20079 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020080 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020081 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020082 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
20083 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020084 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020085 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020086 }
20087 }
20088 }
20089 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020090 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020091 }
20092 else {
20093 return ();
20094 }
20095}
20096
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020097sub realpath_F($)
20098{
20099 my $Path = $_[0];
20100 return path_format(realpath($Path), $OSgroup);
20101}
20102
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020103sub isCyclical($$)
20104{
20105 my ($Stack, $Value) = @_;
20106 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020107}
20108
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020109sub getGCC_Opts($)
20110{ # to use in module
20111 my $LibVersion = $_[0];
20112
20113 my @Opts = ();
20114
20115 if($CompilerOptions{$LibVersion})
20116 { # user-defined options
20117 push(@Opts, $CompilerOptions{$LibVersion});
20118 }
20119 if($GccOptions)
20120 { # additional
20121 push(@Opts, $GccOptions);
20122 }
20123
20124 if(@Opts) {
20125 return join(" ", @Opts);
20126 }
20127
20128 return undef;
20129}
20130
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040020131sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020132{
20133 my $LibVersion = $_[0];
20134
20135 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
20136 return $Cache{"getArch_GCC"}{$LibVersion};
20137 }
20138
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030020139 if(not $GCC_PATH) {
20140 return undef;
20141 }
20142
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020143 my $Arch = undef;
20144
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030020145 if(my $Target = get_dumpmachine($GCC_PATH))
20146 {
20147 if($Target=~/x86_64/) {
20148 $Arch = "x86_64";
20149 }
20150 elsif($Target=~/i[3-6]86/) {
20151 $Arch = "x86";
20152 }
20153 elsif($Target=~/\Aarm/i) {
20154 $Arch = "arm";
20155 }
20156 }
20157
20158 if(not $Arch)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020159 {
20160 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
20161
20162 my $Cmd = $GCC_PATH." test.c -o test";
20163 if(my $Opts = getGCC_Opts($LibVersion))
20164 { # user-defined options
20165 $Cmd .= " ".$Opts;
20166 }
20167
20168 chdir($TMP_DIR);
20169 system($Cmd);
20170 chdir($ORIG_DIR);
20171
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020172 my $EX = join_P($TMP_DIR, "test");
20173
20174 if($OSgroup eq "windows") {
20175 $EX = join_P($TMP_DIR, "test.exe");
20176 }
20177
20178 $Arch = getArch_Object($EX);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020179
20180 unlink("$TMP_DIR/test.c");
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020181 unlink($EX);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020182 }
20183
20184 if(not $Arch) {
20185 exitStatus("Error", "can't check ARCH type");
20186 }
20187
20188 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
20189}
20190
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020191sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020192{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020193 my $LibVersion = $_[0];
20194
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020195 my $Size = undef;
20196
20197 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020198 if(my $Arch = getArch($LibVersion))
20199 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040020200 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020201 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020202 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020203 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
20204 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020205 }
20206 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020207
20208 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020209 {
20210 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020211
20212 my $Cmd = $GCC_PATH." -E -dD empty.h";
20213 if(my $Opts = getGCC_Opts($LibVersion))
20214 { # user-defined options
20215 $Cmd .= " ".$Opts;
20216 }
20217
20218 chdir($TMP_DIR);
20219 my $Defines = `$Cmd`;
20220 chdir($ORIG_DIR);
20221
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020222 unlink("$TMP_DIR/empty.h");
20223
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020224 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
20225 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020226 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020227 }
20228 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
20229 { # GCC 3
20230 my $PTRDIFF = $1;
20231 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020232 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020233 }
20234 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020235 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020236 }
20237 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020238 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020239
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020240 if(not $Size) {
20241 exitStatus("Error", "can't check WORD size");
20242 }
20243
20244 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020245}
20246
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020247sub getWordSize($)
20248{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020249 return $WORD_SIZE{$_[0]};
20250}
20251
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020252sub majorVersion($)
20253{
20254 my $V = $_[0];
20255 return 0 if(not $V);
20256 my @VParts = split(/\./, $V);
20257 return $VParts[0];
20258}
20259
20260sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020261{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020262 my ($V1, $V2) = @_;
20263 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020264 my @V1Parts = split(/\./, $V1);
20265 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020266 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
20267 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020268 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
20269 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
20270 }
20271 return -1 if($#V1Parts < $#V2Parts);
20272 return 1 if($#V1Parts > $#V2Parts);
20273 return 0;
20274}
20275
20276sub read_ABI_Dump($$)
20277{
20278 my ($LibVersion, $Path) = @_;
20279 return if(not $LibVersion or not -e $Path);
20280 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020281 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020282 { # input *.abi
20283 $FilePath = $Path;
20284 }
20285 else
20286 { # input *.abi.tar.gz
20287 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020288 if(not isDump_U($FilePath)) {
20289 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20290 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020291 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020292
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020293 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020294
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020295 my $Line = readLineNum($FilePath, 0);
20296 if($Line=~/xml/)
20297 { # XML format
20298 loadModule("XmlDump");
20299 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020300 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020301 else
20302 { # Perl Data::Dumper format (default)
20303 open(DUMP, $FilePath);
20304 local $/ = undef;
20305 my $Content = <DUMP>;
20306 close(DUMP);
20307
20308 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
20309 { # remove temp file
20310 unlink($FilePath);
20311 }
20312 if($Content!~/};\s*\Z/) {
20313 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20314 }
20315 $ABI = eval($Content);
20316 if(not $ABI) {
20317 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
20318 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020319 }
20320 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020321 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020322 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020323 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020324 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020325 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020326 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020327 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030020328 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020329
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020330 if($ABI->{"PublicABI"}) {
20331 $UsedDump{$LibVersion}{"Public"} = 1;
20332 }
20333
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020334 if($ABI->{"ABI_DUMP_VERSION"})
20335 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020336 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020337 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020338 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020339 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020340 }
20341 else
20342 { # support for old ABI dumps
20343 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020344 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020345 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020346 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020347 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020348
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020349 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020350 {
20351 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 +040020352 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020353
20354 if(defined $ABI->{"ABI_DUMPER_VERSION"})
20355 { # DWARF ABI Dump
20356 $UseConv_Real{$LibVersion}{"P"} = 1;
20357 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
20358
20359 $UsedDump{$LibVersion}{"DWARF"} = 1;
20360
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030020361 if(not $TargetComponent_Opt)
20362 {
20363 if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
20364 $TargetComponent = "module";
20365 }
20366 else {
20367 $TargetComponent = "object";
20368 }
20369 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020370 }
20371
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020372 if(not checkDump($LibVersion, "2.11"))
20373 { # old ABI dumps
20374 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020375 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020376 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020377 { # ABI dump created with --binary option
20378 $UsedDump{$LibVersion}{"BinOnly"} = 1;
20379 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020380 else
20381 { # default
20382 $UsedDump{$LibVersion}{"SrcBin"} = 1;
20383 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020384
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020385 if(defined $ABI->{"Mode"}
20386 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020387 { # --ext option
20388 $ExtendedCheck = 1;
20389 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020390 if($ABI->{"Extra"}) {
20391 $ExtraDump = 1;
20392 }
20393
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020394 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020395 {
20396 $UsedDump{$LibVersion}{"L"} = $Lang;
20397 setLanguage($LibVersion, $Lang);
20398 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020399 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020400 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020401 }
20402 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020403 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020404 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020405 if(not $TInfo)
20406 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020407 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020408 }
20409 my %Tid_TDid = ();
20410 foreach my $TDid (keys(%{$TInfo}))
20411 {
20412 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
20413 {
20414 $MAX_ID = $Tid if($Tid>$MAX_ID);
20415 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020416 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020417 }
20418 }
20419 my %NewID = ();
20420 foreach my $Tid (keys(%Tid_TDid))
20421 {
20422 my @TDids = keys(%{$Tid_TDid{$Tid}});
20423 if($#TDids>=1)
20424 {
20425 foreach my $TDid (@TDids)
20426 {
20427 if($TDid) {
20428 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20429 }
20430 else
20431 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020432 my $ID = ++$MAX_ID;
20433
20434 $NewID{$TDid}{$Tid} = $ID;
20435 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20436 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020437 }
20438 }
20439 }
20440 else
20441 {
20442 my $TDid = $TDids[0];
20443 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20444 }
20445 }
20446 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20447 {
20448 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20449 if(defined $Info{"BaseType"})
20450 {
20451 my $Bid = $Info{"BaseType"}{"Tid"};
20452 my $BDid = $Info{"BaseType"}{"TDid"};
20453 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020454 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020455 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20456 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20457 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020458 }
20459 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20460 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020461 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020462 read_Machine_DumpInfo($ABI, $LibVersion);
20463 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020464 if(not $SymbolInfo{$LibVersion})
20465 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020466 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020467 }
20468 if(not keys(%{$SymbolInfo{$LibVersion}}))
20469 { # validation of old-version dumps
20470 if(not $ExtendedCheck) {
20471 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20472 }
20473 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020474 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020475 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020476 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020477 else
20478 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020479 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020480 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020481 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020482 }
20483 if(not $DepSymbols)
20484 { # Cannot reconstruct DepSymbols. This may result in false
20485 # positives if the old dump is for library 2. Not a problem if
20486 # old dumps are only from old libraries.
20487 $DepSymbols = {};
20488 }
20489 foreach my $Symbol (keys(%{$DepSymbols})) {
20490 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20491 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020492 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020493 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020494
20495 if(my $V = $TargetVersion{$LibVersion}) {
20496 $Descriptor{$LibVersion}{"Version"} = $V;
20497 }
20498 else {
20499 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20500 }
20501
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020502 if(not keys(%{$SkipTypes{$LibVersion}}))
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020503 { # if not defined by -skip-types option
20504 if(defined $ABI->{"SkipTypes"})
20505 {
20506 foreach my $TName (keys(%{$ABI->{"SkipTypes"}}))
20507 {
20508 $SkipTypes{$LibVersion}{$TName} = 1;
20509 }
20510 }
20511 if(defined $ABI->{"OpaqueTypes"})
20512 { # support for old dumps
20513 foreach my $TName (keys(%{$ABI->{"OpaqueTypes"}}))
20514 {
20515 $SkipTypes{$LibVersion}{$TName} = 1;
20516 }
20517 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020518 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020519
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020520 if(not keys(%{$SkipSymbols{$LibVersion}}))
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020521 { # if not defined by -skip-symbols option
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020522 if(defined $ABI->{"SkipSymbols"}) {
20523 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20524 }
20525 if(defined $ABI->{"SkipInterfaces"})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020526 { # support for old dumps
20527 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20528 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020529 if(defined $ABI->{"InternalInterfaces"})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020530 { # support for old dumps
20531 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20532 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020533 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020534 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020535
20536 if(not $TargetHeaders{$LibVersion})
20537 { # if not defined by -headers-list option
20538 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20539 }
20540
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020541 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020542 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020543 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030020544
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020545 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020546 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020547 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020548
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020549 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020550 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020551
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020552 if(not checkDump($LibVersion, "2.10.1")
20553 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020554 { # support for old ABI dumps: added target headers
20555 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020556 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020557 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020558
20559 if(not $ABI->{"PublicABI"})
20560 {
20561 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20562 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20563 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020564 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020565 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020566 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020567 if(defined $ABI->{"GccConstants"})
20568 { # 3.0
20569 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20570 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20571 }
20572 }
20573
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020574 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020575 if(not $NestedNameSpaces{$LibVersion})
20576 { # support for old dumps
20577 # Cannot reconstruct NameSpaces. This may affect design
20578 # of the compatibility report.
20579 $NestedNameSpaces{$LibVersion} = {};
20580 }
20581 # target system type
20582 # needed to adopt HTML report
20583 if(not $DumpSystem)
20584 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020585 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020586 }
20587 # recreate environment
20588 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20589 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020590 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020591 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020592 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20593 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020594 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020595 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020596 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020597 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20598 {
20599 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20600 setLanguage($LibVersion, "C++");
20601 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020602 }
20603 }
20604 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020605 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20606 {
20607 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20608 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20609 }
20610 }
20611
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020612 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020613 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020614 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020615 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020616 {
20617 if(not $Symbol_Library{$LibVersion}{$MnglName}
20618 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20619 push(@VFunc, $MnglName);
20620 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020621 }
20622 }
20623 translateSymbols(@VFunc, $LibVersion);
20624 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020625 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20626
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020627 if(not checkDump($LibVersion, "3.0"))
20628 { # support for old ABI dumps
20629 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20630 {
20631 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20632 {
20633 if(ref($BaseType) eq "HASH") {
20634 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20635 }
20636 }
20637 }
20638 }
20639
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020640 if(not checkDump($LibVersion, "3.2"))
20641 { # support for old ABI dumps
20642 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20643 {
20644 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20645 {
20646 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20647 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20648 }
20649 }
20650 }
20651
20652 # repair target headers list
20653 delete($TargetHeaders{$LibVersion});
20654 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020655 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20656 }
20657 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20658 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020659 }
20660
20661 # non-target constants from anon enums
20662 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20663 {
20664 if(not $ExtraDump
20665 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20666 {
20667 delete($Constants{$LibVersion}{$Name});
20668 }
20669 }
20670 }
20671
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020672 if(not checkDump($LibVersion, "2.20"))
20673 { # support for old ABI dumps
20674 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20675 {
20676 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20677
20678 if($TType=~/Struct|Union|Enum|Typedef/)
20679 { # repair complex types first
20680 next;
20681 }
20682
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020683 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020684 {
20685 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20686 if($BType=~/Struct|Union|Enum/i)
20687 {
20688 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20689 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20690 }
20691 }
20692 }
20693 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20694 {
20695 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20696 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20697 if($TType=~/Struct|Union|Enum/) {
20698 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20699 }
20700 }
20701 }
20702
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020703 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020704 { # NOTE: order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020705 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20706 { # support for old ABI dumps < 2.0 (ACC 1.22)
20707 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20708 {
20709 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20710 {
20711 if($Access ne "public") {
20712 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20713 }
20714 }
20715 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20716 }
20717 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20718 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020719 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20720 { # support for old ABI dumps
20721 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20722 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020723 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20724 { # DWARF ABI Dumps
20725 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20726 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020727 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20728 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20729 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020730
20731 # support for old formatting of type names
20732 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = formatName($TypeInfo{$LibVersion}{$TypeId}{"Name"}, "T");
20733
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020734 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20735 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020736 {
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +030020737 foreach my $SubId (keys(%{$TInfo{"Base"}}))
20738 {
20739 if($SubId eq $TypeId)
20740 { # Fix erroneus ABI dump
20741 delete($TypeInfo{$LibVersion}{$TypeId}{"Base"}{$SubId});
20742 next;
20743 }
20744
20745 $Class_SubClasses{$LibVersion}{$SubId}{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020746 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020747 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020748 if($TInfo{"Type"} eq "MethodPtr")
20749 {
20750 if(defined $TInfo{"Param"})
20751 { # support for old ABI dumps <= 1.17
20752 if(not defined $TInfo{"Param"}{"0"})
20753 {
20754 my $Max = keys(%{$TInfo{"Param"}});
20755 foreach my $Pos (1 .. $Max) {
20756 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20757 }
20758 delete($TInfo{"Param"}{$Max});
20759 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20760 }
20761 }
20762 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020763 if($TInfo{"BaseType"} eq $TypeId)
20764 { # fix ABI dump
20765 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20766 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020767
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020768 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020769 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020770 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020771 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020772 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20773 if(not $BName)
20774 { # broken type
20775 next;
20776 }
20777 if($TInfo{"Name"} eq $BName)
20778 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020779 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020780 next;
20781 }
20782 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20783 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020784 }
20785 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020786 }
20787 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20788 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020789 $TName_Tid{$LibVersion}{$TInfo{"Name"}} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020790 }
20791 }
20792
20793 if(not checkDump($LibVersion, "2.15"))
20794 { # support for old ABI dumps
20795 my %Dups = ();
20796 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20797 {
20798 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020799 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020800 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20801 { # remove template decls
20802 delete($SymbolInfo{$LibVersion}{$InfoId});
20803 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020804 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020805 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020806 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20807 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020808 { # templates
20809 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020810 }
20811 }
20812 }
20813
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020814 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20815 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020816 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20817 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20818 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20819 { # support for old ABI dumps (< 3.1)
20820 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20821 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20822 { # add "this" first parameter
20823 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20824 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20825
20826 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20827 {
20828 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20829 foreach my $Pos (reverse(0 .. $#Pos)) {
20830 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20831 }
20832 }
20833 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20834 }
20835 }
20836
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020837 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20838 { # ABI dumps have no mangled names for C-functions
20839 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20840 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020841 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20842 { # support for old ABI dumps
20843 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20844 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020845 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20846 { # DWARF ABI Dumps
20847 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20848 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020849 }
20850
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020851 $Descriptor{$LibVersion}{"Dump"} = 1;
20852}
20853
20854sub read_Machine_DumpInfo($$)
20855{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020856 my ($ABI, $LibVersion) = @_;
20857 if($ABI->{"Arch"}) {
20858 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020859 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020860 if($ABI->{"WordSize"}) {
20861 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020862 }
20863 else
20864 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020865 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020866 }
20867 if(not $WORD_SIZE{$LibVersion})
20868 { # support for old dumps (<1.23)
20869 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20870 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020871 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020872 }
20873 else
20874 {
20875 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020876 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020877 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020878 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20879 { # any "pointer"-type
20880 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020881 last;
20882 }
20883 }
20884 if($PSize)
20885 { # a pointer type size
20886 $WORD_SIZE{$LibVersion} = $PSize;
20887 }
20888 else {
20889 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20890 }
20891 }
20892 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020893 if($ABI->{"GccVersion"}) {
20894 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020895 }
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030020896 elsif($ABI->{"ClangVersion"}) {
20897 $CLANG_VERSION{$LibVersion} = $ABI->{"ClangVersion"};
20898 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020899}
20900
20901sub read_Libs_DumpInfo($$)
20902{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020903 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020904 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20905 if(not $Library_Symbol{$LibVersion})
20906 { # support for old dumps
20907 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20908 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020909 if(keys(%{$Library_Symbol{$LibVersion}})
20910 and not $DumpAPI) {
20911 $Descriptor{$LibVersion}{"Libs"} = "OK";
20912 }
20913}
20914
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020915sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020916{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020917 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020918
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020919 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020920 and not $DumpAPI) {
20921 $Descriptor{$LibVersion}{"Headers"} = "OK";
20922 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020923 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020924 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020925 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020926 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020927 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020928
20929 if(keys(%{$ABI->{"Sources"}})
20930 and not $DumpAPI) {
20931 $Descriptor{$LibVersion}{"Sources"} = "OK";
20932 }
20933 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020934 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020935 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20936 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20937 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020938}
20939
20940sub find_libs($$$)
20941{
20942 my ($Path, $Type, $MaxDepth) = @_;
20943 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020944 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020945}
20946
20947sub createDescriptor($$)
20948{
20949 my ($LibVersion, $Path) = @_;
20950 if(not $LibVersion or not $Path
20951 or not -e $Path) {
20952 return "";
20953 }
20954 if(-d $Path)
20955 { # directory with headers files and shared objects
20956 return "
20957 <version>
20958 ".$TargetVersion{$LibVersion}."
20959 </version>
20960
20961 <headers>
20962 $Path
20963 </headers>
20964
20965 <libs>
20966 $Path
20967 </libs>";
20968 }
20969 else
20970 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020971 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020972 { # standard XML-descriptor
20973 return readFile($Path);
20974 }
20975 elsif(is_header($Path, 2, $LibVersion))
20976 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020977 $CheckHeadersOnly = 1;
20978
20979 if($LibVersion==1) {
20980 $TargetVersion{$LibVersion} = "X";
20981 }
20982
20983 if($LibVersion==2) {
20984 $TargetVersion{$LibVersion} = "Y";
20985 }
20986
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020987 return "
20988 <version>
20989 ".$TargetVersion{$LibVersion}."
20990 </version>
20991
20992 <headers>
20993 $Path
20994 </headers>
20995
20996 <libs>
20997 none
20998 </libs>";
20999 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021000 else
21001 { # standard XML-descriptor
21002 return readFile($Path);
21003 }
21004 }
21005}
21006
21007sub detect_lib_default_paths()
21008{
21009 my %LPaths = ();
21010 if($OSgroup eq "bsd")
21011 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021012 if(my $LdConfig = get_CmdPath("ldconfig"))
21013 {
21014 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
21015 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021016 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
21017 {
21018 my $Name = "lib".$1;
21019 if(not defined $LPaths{$Name}) {
21020 $LPaths{$Name} = $2;
21021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021022 }
21023 }
21024 }
21025 else {
21026 printMsg("WARNING", "can't find ldconfig");
21027 }
21028 }
21029 else
21030 {
21031 if(my $LdConfig = get_CmdPath("ldconfig"))
21032 {
21033 if($SystemRoot and $OSgroup eq "linux")
21034 { # use host (x86) ldconfig with the target (arm) ld.so.conf
21035 if(-e $SystemRoot."/etc/ld.so.conf") {
21036 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
21037 }
21038 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021039 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
21040 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021041 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
21042 {
21043 my ($Name, $Path) = ($1, $2);
21044 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021045 if(not defined $LPaths{$Name})
21046 { # get first element from the list of available paths
21047
21048 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
21049 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
21050 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
21051
21052 $LPaths{$Name} = $Path;
21053 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021054 }
21055 }
21056 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040021057 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021058 printMsg("WARNING", "can't find ldconfig");
21059 }
21060 }
21061 return \%LPaths;
21062}
21063
21064sub detect_bin_default_paths()
21065{
21066 my $EnvPaths = $ENV{"PATH"};
21067 if($OSgroup eq "beos") {
21068 $EnvPaths.=":".$ENV{"BETOOLS"};
21069 }
21070 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021071 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021072 {
21073 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021074 next if(not $Path);
21075 if($SystemRoot
21076 and $Path=~/\A\Q$SystemRoot\E\//)
21077 { # do NOT use binaries from target system
21078 next;
21079 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021080 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021081 }
21082}
21083
21084sub detect_inc_default_paths()
21085{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021086 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021087 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021088 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021089 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021090 next if(index($Line, "/cc1plus ")!=-1);
21091
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021092 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
21093 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030021094 my $Path = realpath_F($1);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021095 if(index($Path, "c++")!=-1
21096 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021097 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021098 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021099 if(not defined $MAIN_CPP_DIR
21100 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
21101 $MAIN_CPP_DIR = $Path;
21102 }
21103 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021104 elsif(index($Path, "gcc")!=-1) {
21105 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021106 }
21107 else
21108 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021109 if($Path=~/local[\/\\]+include/)
21110 { # local paths
21111 next;
21112 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021113 if($SystemRoot
21114 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
21115 { # The GCC include path for user headers is not a part of the system root
21116 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
21117 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
21118 next;
21119 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021120 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021121 }
21122 }
21123 }
21124 unlink("$TMP_DIR/empty.h");
21125 return %DPaths;
21126}
21127
21128sub detect_default_paths($)
21129{
21130 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
21131 my $Search = $_[0];
21132 if($Search!~/inc/) {
21133 $HSearch = 0;
21134 }
21135 if($Search!~/lib/) {
21136 $LSearch = 0;
21137 }
21138 if($Search!~/bin/) {
21139 $BSearch = 0;
21140 }
21141 if($Search!~/gcc/) {
21142 $GSearch = 0;
21143 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021144 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021145 { # <search_headers> section of the XML descriptor
21146 # do NOT search for systems headers
21147 $HSearch = 0;
21148 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021149 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030021150 { # <search_libs> section of the XML descriptor
21151 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021152 $LSearch = 0;
21153 }
21154 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
21155 { # additional search paths
21156 next if($Type eq "include" and not $HSearch);
21157 next if($Type eq "lib" and not $LSearch);
21158 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021159 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021160 }
21161 if($OSgroup ne "windows")
21162 { # unix-like
21163 foreach my $Type ("include", "lib", "bin")
21164 { # automatic detection of system "devel" directories
21165 next if($Type eq "include" and not $HSearch);
21166 next if($Type eq "lib" and not $LSearch);
21167 next if($Type eq "bin" and not $BSearch);
21168 my ($UsrDir, $RootDir) = ("/usr", "/");
21169 if($SystemRoot and $Type ne "bin")
21170 { # 1. search for target headers and libraries
21171 # 2. use host commands: ldconfig, readelf, etc.
21172 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
21173 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021174 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021175 if(-d $RootDir."/".$Type)
21176 { # if "/lib" is symbolic link
21177 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021178 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021179 }
21180 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021181 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021182 }
21183 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021184 if(-d $UsrDir)
21185 {
21186 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021187 if(-d $UsrDir."/".$Type)
21188 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021189 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021190 }
21191 }
21192 }
21193 }
21194 if($BSearch)
21195 {
21196 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021197 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021198 }
21199 # check environment variables
21200 if($OSgroup eq "beos")
21201 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021202 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021203 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021204 if($_ eq ".") {
21205 next;
21206 }
21207 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
21208 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
21209 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021210 }
21211 }
21212 if($HSearch)
21213 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021214 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
21215 split(/:|;/, $ENV{"BEINCLUDES"})
21216 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021217 }
21218 if($LSearch)
21219 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021220 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
21221 split(/:|;/, $ENV{"BELIBRARIES"}),
21222 split(/:|;/, $ENV{"LIBRARY_PATH"})
21223 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021224 }
21225 }
21226 if($LSearch)
21227 { # using linker to get system paths
21228 if(my $LPaths = detect_lib_default_paths())
21229 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021230 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021231 foreach my $Name (keys(%{$LPaths}))
21232 {
21233 if($SystemRoot
21234 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
21235 { # wrong ldconfig configuration
21236 # check your <sysroot>/etc/ld.so.conf
21237 next;
21238 }
21239 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021240 if(my $Dir = get_dirname($LPaths->{$Name})) {
21241 $Dirs{$Dir} = 1;
21242 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021243 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021244 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021245 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021246 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021247 }
21248 if($BSearch)
21249 {
21250 if($CrossGcc)
21251 { # --cross-gcc=arm-linux-gcc
21252 if(-e $CrossGcc)
21253 { # absolute or relative path
21254 $GCC_PATH = get_abs_path($CrossGcc);
21255 }
21256 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
21257 { # command name
21258 $GCC_PATH = $CrossGcc;
21259 }
21260 else {
21261 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
21262 }
21263 if($GCC_PATH=~/\s/) {
21264 $GCC_PATH = "\"".$GCC_PATH."\"";
21265 }
21266 }
21267 }
21268 if($GSearch)
21269 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021270 if(not $CrossGcc)
21271 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021272 $GCC_PATH = get_CmdPath("gcc");
21273 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021274 if(not $GCC_PATH)
21275 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021276 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021277 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021278 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021279 { # select the latest version
21280 @GCCs = sort {$b cmp $a} @GCCs;
21281 if(check_gcc($GCCs[0], "3"))
21282 {
21283 $GCC_PATH = $GCCs[0];
21284 last;
21285 }
21286 }
21287 }
21288 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021289 if(not $GCC_PATH) {
21290 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
21291 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021292
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021293 my $GCC_Ver = get_dumpversion($GCC_PATH);
21294 if($GCC_Ver eq "4.8")
21295 { # on Ubuntu -dumpversion returns 4.8 for gcc 4.8.4
21296 my $Info = `$GCC_PATH --version`;
21297
21298 if($Info=~/gcc\s+(|\([^()]+\)\s+)(\d+\.\d+\.\d+)/)
21299 { # gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
21300 # gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)
21301 $GCC_Ver = $2;
21302 }
21303 }
21304
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030021305 if($OStarget=~/macos/)
21306 {
21307 my $Info = `$GCC_PATH --version`;
21308
21309 if($Info=~/clang/i) {
21310 printMsg("WARNING", "doesn't work with clang, please install GCC instead (and select it by -gcc-path option)");
21311 }
21312 }
21313
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021314 if($GCC_Ver)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021315 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021316 my $GccTarget = get_dumpmachine($GCC_PATH);
21317
21318 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021319 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021320 $OStarget = "linux";
21321 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021322 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021323 elsif($GccTarget=~/symbian/)
21324 {
21325 $OStarget = "symbian";
21326 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
21327 }
21328
21329 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
21330
21331 # check GCC version
Andrey Ponomarenko9c87bdb2016-10-20 18:15:38 +030021332 if($GCC_Ver=~/\A4\.8(|\.[012])|6\.[12]\.0\Z/)
21333 { # GCC 4.8.[0-2]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
21334 # GCC 6.[1-2].0: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78040
21335
21336 printMsg("ERROR", "Not working properly with GCC $GCC_Ver. Please use other GCC version with the help of --gcc-path=PATH option. Not supported GCC versions: 4.8.0, 4.8.1, 4.8.2, 6.1.0, 6.2.0");
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021337
Andrey Ponomarenko9c87bdb2016-10-20 18:15:38 +030021338 $GCC_MISSED_MNGL = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021339 }
21340 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021341 else {
21342 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021343 }
21344 }
21345 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021346 {
21347 # GCC standard paths
21348 if($GCC_PATH and not $NoStdInc)
21349 {
21350 my %DPaths = detect_inc_default_paths();
21351 @DefaultCppPaths = @{$DPaths{"Cpp"}};
21352 @DefaultGccPaths = @{$DPaths{"Gcc"}};
21353 @DefaultIncPaths = @{$DPaths{"Inc"}};
21354 push_U($SystemPaths{"include"}, @DefaultIncPaths);
21355 }
21356
21357 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021358 my $IncPath = "/usr/include";
21359 if($SystemRoot) {
21360 $IncPath = $SystemRoot.$IncPath;
21361 }
21362 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021363 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021364 }
21365 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021366
21367 if($ExtraInfo)
21368 {
21369 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
21370 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
21371 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021372}
21373
21374sub getLIB_EXT($)
21375{
21376 my $Target = $_[0];
21377 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
21378 return $Ext;
21379 }
21380 return $OS_LibExt{$LIB_TYPE}{"default"};
21381}
21382
21383sub getAR_EXT($)
21384{
21385 my $Target = $_[0];
21386 if(my $Ext = $OS_Archive{$Target}) {
21387 return $Ext;
21388 }
21389 return $OS_Archive{"default"};
21390}
21391
21392sub get_dumpversion($)
21393{
21394 my $Cmd = $_[0];
21395 return "" if(not $Cmd);
21396 if($Cache{"get_dumpversion"}{$Cmd}) {
21397 return $Cache{"get_dumpversion"}{$Cmd};
21398 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021399 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021400 chomp($V);
21401 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
21402}
21403
21404sub get_dumpmachine($)
21405{
21406 my $Cmd = $_[0];
21407 return "" if(not $Cmd);
21408 if($Cache{"get_dumpmachine"}{$Cmd}) {
21409 return $Cache{"get_dumpmachine"}{$Cmd};
21410 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021411 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021412 chomp($Machine);
21413 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
21414}
21415
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021416sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021417{
21418 my $Cmd = $_[0];
21419 return "" if(not $Cmd);
21420 my @Options = (
21421 "--version",
21422 "-help"
21423 );
21424 foreach my $Opt (@Options)
21425 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021426 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021427 if($Info) {
21428 return 1;
21429 }
21430 }
21431 return 0;
21432}
21433
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021434sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021435{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021436 my ($Cmd, $ReqVer) = @_;
21437 return 0 if(not $Cmd or not $ReqVer);
21438 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
21439 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021440 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021441 if(my $GccVer = get_dumpversion($Cmd))
21442 {
21443 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
21444 if(cmpVersions($GccVer, $ReqVer)>=0) {
21445 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
21446 }
21447 }
21448 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021449}
21450
21451sub get_depth($)
21452{
21453 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021454 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021455 }
21456 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
21457}
21458
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021459sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021460{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021461 return if($Cache{"registerGccHeaders"}); # this function should be called once
21462
21463 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021464 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021465 my @Headers = cmd_find($Path,"f");
21466 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21467 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021468 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021469 my $FileName = get_filename($HPath);
21470 if(not defined $DefaultGccHeader{$FileName})
21471 { # skip duplicated
21472 $DefaultGccHeader{$FileName} = $HPath;
21473 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021474 }
21475 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021476 $Cache{"registerGccHeaders"} = 1;
21477}
21478
21479sub registerCppHeaders()
21480{
21481 return if($Cache{"registerCppHeaders"}); # this function should be called once
21482
21483 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021484 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021485 my @Headers = cmd_find($CppDir,"f");
21486 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21487 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021488 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021489 my $FileName = get_filename($Path);
21490 if(not defined $DefaultCppHeader{$FileName})
21491 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021492 $DefaultCppHeader{$FileName} = $Path;
21493 }
21494 }
21495 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021496 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021497}
21498
21499sub parse_libname($$$)
21500{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021501 return "" if(not $_[0]);
21502 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21503 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021504 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021505 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21506}
21507
21508sub parse_libname_I($$$)
21509{
21510 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021511
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021512 if($Target eq "symbian") {
21513 return parse_libname_symbian($Name, $Type);
21514 }
21515 elsif($Target eq "windows") {
21516 return parse_libname_windows($Name, $Type);
21517 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021518
21519 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021520 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021521 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021522 { # libSDL-1.2.so.0.7.1
21523 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021524 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021525 if($Type eq "name")
21526 { # libSDL-1.2
21527 # libwbxml2
21528 return $2;
21529 }
21530 elsif($Type eq "name+ext")
21531 { # libSDL-1.2.so
21532 # libwbxml2.so
21533 return $1;
21534 }
21535 elsif($Type eq "version")
21536 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021537 if(defined $7
21538 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021539 { # 0.7.1
21540 return $7;
21541 }
21542 else
21543 { # libc-2.5.so (=>2.5 version)
21544 my $MV = $5;
21545 $MV=~s/\A[\-\_]+//g;
21546 return $MV;
21547 }
21548 }
21549 elsif($Type eq "short")
21550 { # libSDL
21551 # libwbxml2
21552 return $3;
21553 }
21554 elsif($Type eq "shortest")
21555 { # SDL
21556 # wbxml
21557 return shortest_name($3);
21558 }
21559 }
21560 return "";# error
21561}
21562
21563sub parse_libname_symbian($$)
21564{
21565 my ($Name, $Type) = @_;
21566 my $Ext = getLIB_EXT("symbian");
21567 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21568 { # libpthread{00010001}.dso
21569 if($Type eq "name")
21570 { # libpthread{00010001}
21571 return $2;
21572 }
21573 elsif($Type eq "name+ext")
21574 { # libpthread{00010001}.dso
21575 return $1;
21576 }
21577 elsif($Type eq "version")
21578 { # 00010001
21579 my $V = $4;
21580 $V=~s/\{(.+)\}/$1/;
21581 return $V;
21582 }
21583 elsif($Type eq "short")
21584 { # libpthread
21585 return $3;
21586 }
21587 elsif($Type eq "shortest")
21588 { # pthread
21589 return shortest_name($3);
21590 }
21591 }
21592 return "";# error
21593}
21594
21595sub parse_libname_windows($$)
21596{
21597 my ($Name, $Type) = @_;
21598 my $Ext = getLIB_EXT("windows");
21599 if($Name=~/((.+?)\.$Ext)\Z/)
21600 { # netapi32.dll
21601 if($Type eq "name")
21602 { # netapi32
21603 return $2;
21604 }
21605 elsif($Type eq "name+ext")
21606 { # netapi32.dll
21607 return $1;
21608 }
21609 elsif($Type eq "version")
21610 { # DLL version embedded
21611 # at binary-level
21612 return "";
21613 }
21614 elsif($Type eq "short")
21615 { # netapi32
21616 return $2;
21617 }
21618 elsif($Type eq "shortest")
21619 { # netapi
21620 return shortest_name($2);
21621 }
21622 }
21623 return "";# error
21624}
21625
21626sub shortest_name($)
21627{
21628 my $Name = $_[0];
21629 # remove prefix
21630 $Name=~s/\A(lib|open)//;
21631 # remove suffix
21632 $Name=~s/[\W\d_]+\Z//i;
21633 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21634 return $Name;
21635}
21636
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021637sub createSymbolsList($$$$$)
21638{
21639 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021640
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021641 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021642 prepareSymbols(1);
21643
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021644 my %SymbolHeaderLib = ();
21645 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021646
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021647 # Get List
21648 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21649 {
21650 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021651 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021652 next;
21653 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021654 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021655 { # skip other symbols
21656 next;
21657 }
21658 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21659 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021660 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021661 next;
21662 }
21663 my $DyLib = $Symbol_Library{1}{$Symbol};
21664 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021665 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021666 next;
21667 }
21668 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21669 $Total+=1;
21670 }
21671 # Draw List
21672 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21673 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21674 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21675 {
21676 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21677 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021678 my %NS_Symbol = ();
21679 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021680 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021681 }
21682 foreach my $NameSpace (sort keys(%NS_Symbol))
21683 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021684 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021685 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21686 foreach my $Symbol (@SortedInterfaces)
21687 {
21688 my $SubReport = "";
21689 my $Signature = get_Signature($Symbol, 1);
21690 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021691 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021692 }
21693 if($Symbol=~/\A(_Z|\?)/)
21694 {
21695 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021696 $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 +040021697 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021698 else {
21699 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21700 }
21701 }
21702 else
21703 {
21704 if($Signature) {
21705 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21706 }
21707 else {
21708 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21709 }
21710 }
21711 $SYMBOLS_LIST .= $SubReport;
21712 }
21713 }
21714 $SYMBOLS_LIST .= "<br/>\n";
21715 }
21716 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021717 # clear info
21718 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21719 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21720 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21721 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021722 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021723 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021724 my $CssStyles = readModule("Styles", "SymbolsList.css");
21725 my $JScripts = readModule("Scripts", "Sections.js");
21726 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021727 my $Title = "$LName: public symbols";
21728 my $Keywords = "$LName, API, symbols";
21729 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021730 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021731 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021732 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021733 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021734 writeFile($SaveTo, $SYMBOLS_LIST);
21735}
21736
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021737sub add_target_libs($)
21738{
21739 foreach (@{$_[0]}) {
21740 $TargetLibs{$_} = 1;
21741 }
21742}
21743
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021744sub is_target_lib($)
21745{
21746 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021747 if(not $LName) {
21748 return 0;
21749 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030021750 if($OSgroup eq "windows") {
21751 $LName = lc($LName);
21752 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021753 if($TargetLibraryName
21754 and $LName!~/\Q$TargetLibraryName\E/) {
21755 return 0;
21756 }
21757 if(keys(%TargetLibs)
21758 and not $TargetLibs{$LName}
21759 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21760 return 0;
21761 }
21762 return 1;
21763}
21764
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021765sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021766{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021767 my ($H, $V) = @_;
21768 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021769 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021770 if($TargetHeaders{$V}{$H}) {
21771 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021772 }
21773 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021774 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021775}
21776
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021777sub readLibs($)
21778{
21779 my $LibVersion = $_[0];
21780 if($OStarget eq "windows")
21781 { # dumpbin.exe will crash
21782 # without VS Environment
21783 check_win32_env();
21784 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021785 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021786 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021787 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021788}
21789
21790sub dump_sorting($)
21791{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021792 my $Hash = $_[0];
21793 return [] if(not $Hash);
21794 my @Keys = keys(%{$Hash});
21795 return [] if($#Keys<0);
21796 if($Keys[0]=~/\A\d+\Z/)
21797 { # numbers
21798 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021799 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021800 else
21801 { # strings
21802 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021803 }
21804}
21805
21806sub printMsg($$)
21807{
21808 my ($Type, $Msg) = @_;
21809 if($Type!~/\AINFO/) {
21810 $Msg = $Type.": ".$Msg;
21811 }
21812 if($Type!~/_C\Z/) {
21813 $Msg .= "\n";
21814 }
21815 if($Quiet)
21816 { # --quiet option
21817 appendFile($COMMON_LOG_PATH, $Msg);
21818 }
21819 else
21820 {
21821 if($Type eq "ERROR") {
21822 print STDERR $Msg;
21823 }
21824 else {
21825 print $Msg;
21826 }
21827 }
21828}
21829
21830sub exitStatus($$)
21831{
21832 my ($Code, $Msg) = @_;
21833 printMsg("ERROR", $Msg);
21834 exit($ERROR_CODE{$Code});
21835}
21836
21837sub exitReport()
21838{ # the tool has run without any errors
21839 printReport();
21840 if($COMPILE_ERRORS)
21841 { # errors in headers may add false positives/negatives
21842 exit($ERROR_CODE{"Compile_Error"});
21843 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021844 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21845 { # --binary
21846 exit($ERROR_CODE{"Incompatible"});
21847 }
21848 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21849 { # --source
21850 exit($ERROR_CODE{"Incompatible"});
21851 }
21852 elsif($RESULT{"Source"}{"Problems"}
21853 or $RESULT{"Binary"}{"Problems"})
21854 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021855 exit($ERROR_CODE{"Incompatible"});
21856 }
21857 else {
21858 exit($ERROR_CODE{"Compatible"});
21859 }
21860}
21861
21862sub readRules($)
21863{
21864 my $Kind = $_[0];
21865 if(not -f $RULES_PATH{$Kind}) {
21866 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21867 }
21868 my $Content = readFile($RULES_PATH{$Kind});
21869 while(my $Rule = parseTag(\$Content, "rule"))
21870 {
21871 my $RId = parseTag(\$Rule, "id");
21872 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21873 foreach my $Prop (@Properties) {
21874 if(my $Value = parseTag(\$Rule, lc($Prop)))
21875 {
21876 $Value=~s/\n[ ]*//;
21877 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21878 }
21879 }
21880 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21881 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21882 }
21883 else {
21884 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21885 }
21886 }
21887}
21888
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021889sub getReportPath($)
21890{
21891 my $Level = $_[0];
21892 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21893 if($Level eq "Binary")
21894 {
21895 if($BinaryReportPath)
21896 { # --bin-report-path
21897 return $BinaryReportPath;
21898 }
21899 elsif($OutputReportPath)
21900 { # --report-path
21901 return $OutputReportPath;
21902 }
21903 else
21904 { # default
21905 return $Dir."/abi_compat_report.$ReportFormat";
21906 }
21907 }
21908 elsif($Level eq "Source")
21909 {
21910 if($SourceReportPath)
21911 { # --src-report-path
21912 return $SourceReportPath;
21913 }
21914 elsif($OutputReportPath)
21915 { # --report-path
21916 return $OutputReportPath;
21917 }
21918 else
21919 { # default
21920 return $Dir."/src_compat_report.$ReportFormat";
21921 }
21922 }
21923 else
21924 {
21925 if($OutputReportPath)
21926 { # --report-path
21927 return $OutputReportPath;
21928 }
21929 else
21930 { # default
21931 return $Dir."/compat_report.$ReportFormat";
21932 }
21933 }
21934}
21935
21936sub printStatMsg($)
21937{
21938 my $Level = $_[0];
21939 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21940}
21941
21942sub listAffected($)
21943{
21944 my $Level = $_[0];
21945 my $List = "";
21946 foreach (keys(%{$TotalAffected{$Level}}))
21947 {
21948 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21949 { # skip "Low"-severity problems
21950 next;
21951 }
21952 $List .= "$_\n";
21953 }
21954 my $Dir = get_dirname(getReportPath($Level));
21955 if($Level eq "Binary") {
21956 writeFile($Dir."/abi_affected.txt", $List);
21957 }
21958 elsif($Level eq "Source") {
21959 writeFile($Dir."/src_affected.txt", $List);
21960 }
21961}
21962
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021963sub printReport()
21964{
21965 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021966 createReport();
21967 if($JoinReport or $DoubleReport)
21968 {
21969 if($RESULT{"Binary"}{"Problems"}
21970 or $RESULT{"Source"}{"Problems"}) {
21971 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021972 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021973 else {
21974 printMsg("INFO", "result: COMPATIBLE");
21975 }
21976 printStatMsg("Binary");
21977 printStatMsg("Source");
21978 if($ListAffected)
21979 { # --list-affected
21980 listAffected("Binary");
21981 listAffected("Source");
21982 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021983 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021984 elsif($BinaryOnly)
21985 {
21986 if($RESULT{"Binary"}{"Problems"}) {
21987 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21988 }
21989 else {
21990 printMsg("INFO", "result: COMPATIBLE");
21991 }
21992 printStatMsg("Binary");
21993 if($ListAffected)
21994 { # --list-affected
21995 listAffected("Binary");
21996 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021997 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021998 elsif($SourceOnly)
21999 {
22000 if($RESULT{"Source"}{"Problems"}) {
22001 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
22002 }
22003 else {
22004 printMsg("INFO", "result: COMPATIBLE");
22005 }
22006 printStatMsg("Source");
22007 if($ListAffected)
22008 { # --list-affected
22009 listAffected("Source");
22010 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022011 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022012 if($StdOut)
22013 {
22014 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022015 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022016 printMsg("INFO", "compatibility report has been generated to stdout");
22017 }
22018 else
22019 { # default
22020 printMsg("INFO", "compatibility reports have been generated to stdout");
22021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022022 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022023 else
22024 {
22025 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022026 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022027 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
22028 }
22029 elsif($DoubleReport)
22030 { # default
22031 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
22032 }
22033 elsif($BinaryOnly)
22034 { # --binary
22035 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
22036 }
22037 elsif($SourceOnly)
22038 { # --source
22039 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
22040 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022041 }
22042}
22043
22044sub check_win32_env()
22045{
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022046 if(not $ENV{"VCINSTALLDIR"}
22047 or not $ENV{"INCLUDE"}) {
22048 exitStatus("Error", "can't start without VC environment (vcvars64.bat)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022049 }
22050}
22051
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022052sub diffSets($$)
22053{
22054 my ($S1, $S2) = @_;
22055 my @SK1 = keys(%{$S1});
22056 my @SK2 = keys(%{$S2});
22057 if($#SK1!=$#SK2) {
22058 return 1;
22059 }
22060 foreach my $K1 (@SK1)
22061 {
22062 if(not defined $S2->{$K1}) {
22063 return 1;
22064 }
22065 }
22066 return 0;
22067}
22068
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022069sub defaultDumpPath($$)
22070{
22071 my ($N, $V) = @_;
22072 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
22073}
22074
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022075sub create_ABI_Dump()
22076{
22077 if(not -e $DumpAPI) {
22078 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
22079 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022080
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022081 if(isDump($DumpAPI)) {
22082 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022083 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022084 else {
22085 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022086 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022087
22088 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022089 { # set to default: N
22090 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022091 }
22092
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022093 initLogging(1);
22094 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022095
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022096 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022097 if($OutputDumpPath)
22098 { # user defined path
22099 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022100 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022101 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
22102
22103 if(not $Archive and not $StdOut)
22104 { # check archive utilities
22105 if($OSgroup eq "windows")
22106 { # using zip
22107 my $ZipCmd = get_CmdPath("zip");
22108 if(not $ZipCmd) {
22109 exitStatus("Not_Found", "can't find \"zip\"");
22110 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022111 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022112 else
22113 { # using tar and gzip
22114 my $TarCmd = get_CmdPath("tar");
22115 if(not $TarCmd) {
22116 exitStatus("Not_Found", "can't find \"tar\"");
22117 }
22118 my $GzipCmd = get_CmdPath("gzip");
22119 if(not $GzipCmd) {
22120 exitStatus("Not_Found", "can't find \"gzip\"");
22121 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022122 }
22123 }
22124
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022125 if(not $Descriptor{1}{"Dump"})
22126 {
22127 if(not $CheckHeadersOnly) {
22128 readLibs(1);
22129 }
22130 if($CheckHeadersOnly) {
22131 setLanguage(1, "C++");
22132 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022133 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022134 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022135 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022136 if(not $Descriptor{1}{"Dump"})
22137 {
22138 if($Descriptor{1}{"Headers"}) {
22139 readHeaders(1);
22140 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022141 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022142 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022143 if(not keys(%{$SymbolInfo{1}}))
22144 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022145 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022146 {
22147 if($CheckHeadersOnly) {
22148 exitStatus("Empty_Set", "the set of public symbols is empty");
22149 }
22150 else {
22151 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
22152 }
22153 }
22154 }
22155 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022156 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022157 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
22158 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022159 if($ExtraDump)
22160 { # add unmangled names to the ABI dump
22161 my @Names = ();
22162 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
22163 {
22164 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
22165 push(@Names, $MnglName);
22166 }
22167 }
22168 translateSymbols(@Names, 1);
22169 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
22170 {
22171 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
22172 {
22173 if(my $Unmangled = $tr_name{$MnglName})
22174 {
22175 if($MnglName ne $Unmangled) {
22176 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
22177 }
22178 }
22179 }
22180 }
22181 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022182
22183 my %GccConstants = (); # built-in GCC constants
22184 foreach my $Name (keys(%{$Constants{1}}))
22185 {
22186 if(not defined $Constants{1}{$Name}{"Header"})
22187 {
22188 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
22189 delete($Constants{1}{$Name});
22190 }
22191 }
22192
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022193 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022194 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022195 "TypeInfo" => $TypeInfo{1},
22196 "SymbolInfo" => $SymbolInfo{1},
22197 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022198 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022199 "SymbolVersion" => $SymVer{1},
22200 "LibraryVersion" => $Descriptor{1}{"Version"},
22201 "LibraryName" => $TargetLibraryName,
22202 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022203 "SkipTypes" => $SkipTypes{1},
22204 "SkipSymbols" => $SkipSymbols{1},
22205 "SkipNameSpaces" => $SkipNameSpaces{1},
22206 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022207 "Headers" => \%HeadersInfo,
22208 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022209 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022210 "NameSpaces" => $NestedNameSpaces{1},
22211 "Target" => $OStarget,
22212 "Arch" => getArch(1),
22213 "WordSize" => $WORD_SIZE{1},
22214 "GccVersion" => get_dumpversion($GCC_PATH),
22215 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
22216 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
22217 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022218 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022219 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022220 }
22221 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022222 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022223 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022224 if($ExtendedCheck)
22225 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022226 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022227 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022228 if($BinaryOnly)
22229 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022230 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022231 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022232 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022233 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022234 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022235 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
22236 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022237 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022238
22239 my $ABI_DUMP = "";
22240 if($UseXML)
22241 {
22242 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022243 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022244 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022245 else
22246 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022247 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022248 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022249 if($StdOut)
22250 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022251 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022252 printMsg("INFO", "ABI dump has been generated to stdout");
22253 return;
22254 }
22255 else
22256 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022257 my ($DDir, $DName) = separate_path($DumpPath);
22258 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022259 if(not $Archive) {
22260 $DPath = $DumpPath;
22261 }
22262
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022263 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022264
22265 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022266 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022267 close(DUMP);
22268
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022269 if(not -s $DPath) {
22270 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
22271 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022272 if($Archive) {
22273 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022274 }
22275
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022276 if($OutputDumpPath) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022277 printMsg("INFO", "dump path: $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022278 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022279 else {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022280 printMsg("INFO", "dump path: $DumpPath");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022281 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022282 # 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 +040022283 }
22284}
22285
22286sub quickEmptyReports()
22287{ # Quick "empty" reports
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022288 # ~4 times faster than merging equal dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022289 # NOTE: the dump contains the "LibraryVersion" attribute
22290 # if you change the version, then your dump will be different
22291 # OVERCOME: use -v1 and v2 options for comparing dumps
22292 # and don't change version in the XML descriptor (and dumps)
22293 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022294 if($Descriptor{1}{"Path"} eq $Descriptor{2}{"Path"}
22295 or -s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022296 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022297 my $FilePath1 = $Descriptor{1}{"Path"};
22298 my $FilePath2 = $Descriptor{2}{"Path"};
22299
22300 if(not isDump_U($FilePath1)) {
22301 $FilePath1 = unpackDump($FilePath1);
22302 }
22303
22304 if(not isDump_U($FilePath2)) {
22305 $FilePath2 = unpackDump($FilePath2);
22306 }
22307
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022308 if($FilePath1 and $FilePath2)
22309 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022310 my $Line = readLineNum($FilePath1, 0);
22311 if($Line=~/xml/)
22312 { # XML format
22313 # is not supported yet
22314 return;
22315 }
22316
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022317 local $/ = undef;
22318
22319 open(DUMP1, $FilePath1);
22320 my $Content1 = <DUMP1>;
22321 close(DUMP1);
22322
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022323 my $Eq = 0;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022324
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022325 if($FilePath1 eq $FilePath2) {
22326 $Eq = 1;
22327 }
22328
22329 if(not $Eq)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022330 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022331 open(DUMP2, $FilePath2);
22332 my $Content2 = <DUMP2>;
22333 close(DUMP2);
22334
22335 if($Content1 eq $Content2) {
22336 $Eq = 1;
22337 }
22338
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022339 # clean memory
22340 undef $Content2;
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022341 }
22342
22343 if($Eq)
22344 {
22345 printMsg("INFO", "Input ABI dumps are equal, so generating quick empty report");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022346 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022347 my $ABIdump = eval($Content1);
22348
22349 # clean memory
22350 undef $Content1;
22351
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022352 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022353 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 +040022354 }
22355 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022356 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022357 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
22358 }
22359 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022360 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022361 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
22362 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022363 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022364
22365 foreach (keys(%{$Registered_Headers{1}})) {
22366 $TargetHeaders{1}{$_} = 1;
22367 }
22368
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022369 read_Libs_DumpInfo($ABIdump, 1);
22370 read_Machine_DumpInfo($ABIdump, 1);
22371 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022372
22373 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
22374 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
22375
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022376 foreach my $S (keys(%{$ABIdump->{"SymbolInfo"}}))
22377 {
22378 if(my $Class = $ABIdump->{"SymbolInfo"}{$S}{"Class"})
22379 {
22380 if(defined $ABIdump->{"TypeInfo"}{$Class}{"PrivateABI"}) {
22381 next;
22382 }
22383 }
22384
22385 my $Access = $ABIdump->{"SymbolInfo"}{$S}{"Access"};
22386 if($Access ne "private")
22387 {
22388 $CheckedSymbols{"Binary"}{$S} = 1;
22389 $CheckedSymbols{"Source"}{$S} = 1;
22390 }
22391 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022392
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022393 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
22394 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022395
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030022396 if(not defined $Descriptor{1}{"Version"}) {
22397 $Descriptor{1}{"Version"} = "X";
22398 }
22399
22400 if(not defined $Descriptor{2}{"Version"}) {
22401 $Descriptor{2}{"Version"} = "Y";
22402 }
22403
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022404 if(defined $ABIdump->{"ABI_DUMPER_VERSION"})
22405 {
22406 $UsedDump{1}{"DWARF"} = 1;
22407 $UsedDump{2}{"DWARF"} = 1;
22408
22409 $UsedDump{1}{"M"} = $ABIdump->{"LibraryName"};
22410 $UsedDump{2}{"M"} = $ABIdump->{"LibraryName"};
22411 }
22412
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022413 exitReport();
22414 }
22415 }
22416 }
22417}
22418
22419sub initLogging($)
22420{
22421 my $LibVersion = $_[0];
22422 # create log directory
22423 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
22424 if($OutputLogPath{$LibVersion})
22425 { # user-defined by -log-path option
22426 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
22427 }
22428 if($LogMode ne "n") {
22429 mkpath($LOG_DIR);
22430 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022431 $LOG_PATH{$LibVersion} = join_P(get_abs_path($LOG_DIR), $LOG_FILE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022432 if($Debug)
22433 { # debug directory
22434 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022435
22436 if(not $ExtraInfo)
22437 { # enable --extra-info
22438 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
22439 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022440 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022441 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022442}
22443
22444sub writeLog($$)
22445{
22446 my ($LibVersion, $Msg) = @_;
22447 if($LogMode ne "n") {
22448 appendFile($LOG_PATH{$LibVersion}, $Msg);
22449 }
22450}
22451
22452sub resetLogging($)
22453{
22454 my $LibVersion = $_[0];
22455 if($LogMode!~/a|n/)
22456 { # remove old log
22457 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022458 if($Debug) {
22459 rmtree($DEBUG_PATH{$LibVersion});
22460 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022461 }
22462}
22463
22464sub printErrorLog($)
22465{
22466 my $LibVersion = $_[0];
22467 if($LogMode ne "n") {
22468 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
22469 }
22470}
22471
22472sub isDump($)
Jayant Chowdharyd334f9a2017-02-09 22:28:11 -080022473{ # Modified to include "bdump" - binary dump.
22474 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump|bdump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022475 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022476 return $1;
22477 }
22478 return 0;
22479}
22480
22481sub isDump_U($)
Jayant Chowdharyd334f9a2017-02-09 22:28:11 -080022482{ # Modified to include "bdump" - binary dump.
22483 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump|bdump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022484 return $1;
22485 }
22486 return 0;
22487}
22488
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022489sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022490{
22491 # read input XML descriptors or ABI dumps
22492 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022493 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022494 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022495 if(not -e $Descriptor{1}{"Path"}) {
22496 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022497 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022498
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022499 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022500 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022501 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022502 if(not -e $Descriptor{2}{"Path"}) {
22503 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022504 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022505
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022506 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022507
22508 if(not defined $DisableQuickEmptyReport)
22509 {
22510 if(isDump($Descriptor{1}{"Path"})
22511 and isDump($Descriptor{2}{"Path"}))
22512 { # optimization: equal ABI dumps
22513 quickEmptyReports();
22514 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022515 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022516
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022517 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022518
22519 if(isDump($Descriptor{1}{"Path"})) {
22520 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022521 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022522 else {
22523 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
22524 }
22525
22526 if(isDump($Descriptor{2}{"Path"})) {
22527 read_ABI_Dump(2, $Descriptor{2}{"Path"});
22528 }
22529 else {
22530 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022531 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022532
22533 if(not $Descriptor{1}{"Version"})
22534 { # set to default: X
22535 $Descriptor{1}{"Version"} = "X";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022536 print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022537 }
22538
22539 if(not $Descriptor{2}{"Version"})
22540 { # set to default: Y
22541 $Descriptor{2}{"Version"} = "Y";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022542 print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022543 }
22544
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030022545 if(not $UsedDump{1}{"V"}) {
22546 initLogging(1);
22547 }
22548
22549 if(not $UsedDump{2}{"V"}) {
22550 initLogging(2);
22551 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022552
22553 # check input data
22554 if(not $Descriptor{1}{"Headers"}) {
22555 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022556 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022557 if(not $Descriptor{2}{"Headers"}) {
22558 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022559 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022560
22561 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022562 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022563 if(not $Descriptor{1}{"Libs"}) {
22564 exitStatus("Error", "can't find libraries info in descriptor d1");
22565 }
22566 if(not $Descriptor{2}{"Libs"}) {
22567 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022568 }
22569 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022570
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022571 if($UseDumps)
22572 { # --use-dumps
22573 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022574 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
22575 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022576
22577 unlink($DumpPath1);
22578 unlink($DumpPath2);
22579
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022580 my $pid = fork();
22581 if($pid)
22582 { # dump on two CPU cores
22583 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22584 if($RelativeDirectory{1}) {
22585 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22586 }
22587 if($OutputLogPath{1}) {
22588 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22589 }
22590 if($CrossGcc) {
22591 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22592 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022593 if($Quiet)
22594 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022595 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022596 @PARAMS = (@PARAMS, "-logging-mode", "a");
22597 }
22598 elsif($LogMode and $LogMode ne "w")
22599 { # "w" is default
22600 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022601 }
22602 if($ExtendedCheck) {
22603 @PARAMS = (@PARAMS, "-extended");
22604 }
22605 if($UserLang) {
22606 @PARAMS = (@PARAMS, "-lang", $UserLang);
22607 }
22608 if($TargetVersion{1}) {
22609 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22610 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022611 if($BinaryOnly) {
22612 @PARAMS = (@PARAMS, "-binary");
22613 }
22614 if($SourceOnly) {
22615 @PARAMS = (@PARAMS, "-source");
22616 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022617 if($SortDump) {
22618 @PARAMS = (@PARAMS, "-sort");
22619 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022620 if($DumpFormat and $DumpFormat ne "perl") {
22621 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22622 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022623 if($CheckHeadersOnly) {
22624 @PARAMS = (@PARAMS, "-headers-only");
22625 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022626 if($Debug)
22627 {
22628 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022629 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022630 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022631 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022632 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022633 exit(1);
22634 }
22635 }
22636 else
22637 { # child
22638 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22639 if($RelativeDirectory{2}) {
22640 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22641 }
22642 if($OutputLogPath{2}) {
22643 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22644 }
22645 if($CrossGcc) {
22646 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22647 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022648 if($Quiet)
22649 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022650 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022651 @PARAMS = (@PARAMS, "-logging-mode", "a");
22652 }
22653 elsif($LogMode and $LogMode ne "w")
22654 { # "w" is default
22655 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022656 }
22657 if($ExtendedCheck) {
22658 @PARAMS = (@PARAMS, "-extended");
22659 }
22660 if($UserLang) {
22661 @PARAMS = (@PARAMS, "-lang", $UserLang);
22662 }
22663 if($TargetVersion{2}) {
22664 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22665 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022666 if($BinaryOnly) {
22667 @PARAMS = (@PARAMS, "-binary");
22668 }
22669 if($SourceOnly) {
22670 @PARAMS = (@PARAMS, "-source");
22671 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022672 if($SortDump) {
22673 @PARAMS = (@PARAMS, "-sort");
22674 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022675 if($DumpFormat and $DumpFormat ne "perl") {
22676 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22677 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022678 if($CheckHeadersOnly) {
22679 @PARAMS = (@PARAMS, "-headers-only");
22680 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022681 if($Debug)
22682 {
22683 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022684 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022685 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022686 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022687 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022688 exit(1);
22689 }
22690 else {
22691 exit(0);
22692 }
22693 }
22694 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022695
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022696 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022697 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22698 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022699 if($TargetTitle ne $TargetLibraryName) {
22700 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022701 }
22702 if($ShowRetVal) {
22703 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22704 }
22705 if($CrossGcc) {
22706 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22707 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022708 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22709 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022710 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022711 }
22712 if($ReportFormat and $ReportFormat ne "html")
22713 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022714 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22715 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022716 if($OutputReportPath) {
22717 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22718 }
22719 if($BinaryReportPath) {
22720 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22721 }
22722 if($SourceReportPath) {
22723 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22724 }
22725 if($LoggingPath) {
22726 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22727 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022728 if($CheckHeadersOnly) {
22729 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22730 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022731 if($BinaryOnly) {
22732 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22733 }
22734 if($SourceOnly) {
22735 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22736 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022737 if($Debug)
22738 {
22739 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22740 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022741 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022742 system("perl", $0, @CMP_PARAMS);
22743 exit($?>>8);
22744 }
22745 if(not $Descriptor{1}{"Dump"}
22746 or not $Descriptor{2}{"Dump"})
22747 { # need GCC toolchain to analyze
22748 # header files and libraries
22749 detect_default_paths("inc|lib|gcc");
22750 }
22751 if(not $Descriptor{1}{"Dump"})
22752 {
22753 if(not $CheckHeadersOnly) {
22754 readLibs(1);
22755 }
22756 if($CheckHeadersOnly) {
22757 setLanguage(1, "C++");
22758 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022759 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022760 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022761 }
22762 if(not $Descriptor{2}{"Dump"})
22763 {
22764 if(not $CheckHeadersOnly) {
22765 readLibs(2);
22766 }
22767 if($CheckHeadersOnly) {
22768 setLanguage(2, "C++");
22769 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022770 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022771 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022772 }
22773 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22774 { # support for old ABI dumps
22775 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022776 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022777 {
22778 $WORD_SIZE{1} = $WORD_SIZE{2};
22779 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22780 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022781 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022782 {
22783 $WORD_SIZE{2} = $WORD_SIZE{1};
22784 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22785 }
22786 }
22787 elsif(not $WORD_SIZE{1}
22788 and not $WORD_SIZE{2})
22789 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022790 $WORD_SIZE{1} = "4";
22791 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022792 }
22793 if($Descriptor{1}{"Dump"})
22794 { # support for old ABI dumps
22795 prepareTypes(1);
22796 }
22797 if($Descriptor{2}{"Dump"})
22798 { # support for old ABI dumps
22799 prepareTypes(2);
22800 }
22801 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22802 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22803 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022804 # process input data
22805 if($Descriptor{1}{"Headers"}
22806 and not $Descriptor{1}{"Dump"}) {
22807 readHeaders(1);
22808 }
22809 if($Descriptor{2}{"Headers"}
22810 and not $Descriptor{2}{"Dump"}) {
22811 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022812 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022813
22814 # clean memory
22815 %SystemHeaders = ();
22816 %mangled_name_gcc = ();
22817
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022818 prepareSymbols(1);
22819 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022820
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022821 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022822 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022823
22824 # Virtual Tables
22825 registerVTable(1);
22826 registerVTable(2);
22827
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022828 if(not checkDump(1, "1.22")
22829 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022830 { # support for old ABI dumps
22831 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22832 {
22833 if($ClassName=~/</)
22834 { # templates
22835 if(not defined $VirtualTable{1}{$ClassName})
22836 { # synchronize
22837 delete($VirtualTable{2}{$ClassName});
22838 }
22839 }
22840 }
22841 }
22842
22843 registerOverriding(1);
22844 registerOverriding(2);
22845
22846 setVirtFuncPositions(1);
22847 setVirtFuncPositions(2);
22848
22849 # Other
22850 addParamNames(1);
22851 addParamNames(2);
22852
22853 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022854}
22855
22856sub compareAPIs($)
22857{
22858 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022859
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022860 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022861 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022862
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022863 if($Level eq "Binary") {
22864 printMsg("INFO", "comparing ABIs ...");
22865 }
22866 else {
22867 printMsg("INFO", "comparing APIs ...");
22868 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022869
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022870 if($CheckHeadersOnly
22871 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022872 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022873 detectAdded_H($Level);
22874 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022875 }
22876 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022877 { # added/removed in libs
22878 detectAdded($Level);
22879 detectRemoved($Level);
22880 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022881
22882 mergeSymbols($Level);
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030022883
22884 if(not defined $DisableConstantsCheck)
22885 {
22886 if(keys(%{$CheckedSymbols{$Level}})) {
22887 mergeConstants($Level);
22888 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022889 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022890
22891 $Cache{"mergeTypes"} = (); # free memory
22892
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022893 if($CheckHeadersOnly
22894 or $Level eq "Source")
22895 { # added/removed in headers
22896 mergeHeaders($Level);
22897 }
22898 else
22899 { # added/removed in libs
22900 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022901 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022902
22903 foreach my $S (keys(%{$CompatProblems{$Level}}))
22904 {
22905 foreach my $K (keys(%{$CompatProblems{$Level}{$S}}))
22906 {
22907 foreach my $L (keys(%{$CompatProblems{$Level}{$S}{$K}}))
22908 {
22909 if(my $T = $CompatProblems{$Level}{$S}{$K}{$L}{"Type_Name"}) {
22910 $TypeProblemsIndex{$Level}{$T}{$S} = 1;
22911 }
22912 }
22913 }
22914 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022915}
22916
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022917sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022918{
22919 my %Opts = (
22920 "OStarget"=>$OStarget,
22921 "Debug"=>$Debug,
22922 "Quiet"=>$Quiet,
22923 "LogMode"=>$LogMode,
22924 "CheckHeadersOnly"=>$CheckHeadersOnly,
22925
22926 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022927 "GCC_PATH"=>$GCC_PATH,
22928 "TargetSysInfo"=>$TargetSysInfo,
22929 "CrossPrefix"=>$CrossPrefix,
22930 "TargetLibraryName"=>$TargetLibraryName,
22931 "CrossGcc"=>$CrossGcc,
22932 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022933 "NoStdInc"=>$NoStdInc,
Andrey Ponomarenko991da682016-09-07 19:09:50 +030022934 "CxxIncompat"=>$CxxIncompat,
22935 "SkipUnidentified"=>$SkipUnidentified,
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030022936 "DisableConstantsCheck"=>$DisableConstantsCheck,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022937
22938 "BinaryOnly" => $BinaryOnly,
22939 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022940 );
22941 return \%Opts;
22942}
22943
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022944sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022945{
22946 my %CODE_ERROR = reverse(%ERROR_CODE);
22947 return $CODE_ERROR{$_[0]};
22948}
22949
22950sub scenario()
22951{
22952 if($StdOut)
22953 { # enable quiet mode
22954 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022955 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022956 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022957 if(not $LogMode)
22958 { # default
22959 $LogMode = "w";
22960 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022961 if($UserLang)
22962 { # --lang=C++
22963 $UserLang = uc($UserLang);
22964 $COMMON_LANGUAGE{1}=$UserLang;
22965 $COMMON_LANGUAGE{2}=$UserLang;
22966 }
22967 if($LoggingPath)
22968 {
22969 $OutputLogPath{1} = $LoggingPath;
22970 $OutputLogPath{2} = $LoggingPath;
22971 if($Quiet) {
22972 $COMMON_LOG_PATH = $LoggingPath;
22973 }
22974 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022975
Andrey Ponomarenko9c87bdb2016-10-20 18:15:38 +030022976 if($Force) {
22977 $GCC_MISSED_MNGL = 1;
22978 }
22979
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022980 if($Quick) {
22981 $ADD_TMPL_INSTANCES = 0;
22982 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022983 if($OutputDumpPath)
22984 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022985 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022986 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22987 }
22988 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022989 if($BinaryOnly and $SourceOnly)
22990 { # both --binary and --source
22991 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022992 if(not $CmpSystems)
22993 {
22994 $BinaryOnly = 0;
22995 $SourceOnly = 0;
22996 }
22997
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022998 $DoubleReport = 1;
22999 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030023000
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023001 if($OutputReportPath)
23002 { # --report-path
23003 $DoubleReport = 0;
23004 $JoinReport = 1;
23005 }
23006 }
23007 elsif($BinaryOnly or $SourceOnly)
23008 { # --binary or --source
23009 $DoubleReport = 0;
23010 $JoinReport = 0;
23011 }
23012 if($UseXML)
23013 { # --xml option
23014 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040023015 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023016 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023017 if($ReportFormat)
23018 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023019 $ReportFormat = lc($ReportFormat);
23020 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040023021 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023022 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023023 if($ReportFormat eq "htm")
23024 { # HTM == HTML
23025 $ReportFormat = "html";
23026 }
23027 elsif($ReportFormat eq "xml")
23028 { # --report-format=XML equal to --xml
23029 $UseXML = 1;
23030 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023031 }
23032 else
23033 { # default: HTML
23034 $ReportFormat = "html";
23035 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040023036 if($DumpFormat)
23037 { # validate
23038 $DumpFormat = lc($DumpFormat);
23039 if($DumpFormat!~/\A(xml|perl)\Z/) {
23040 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
23041 }
23042 if($DumpFormat eq "xml")
23043 { # --dump-format=XML equal to --xml
23044 $UseXML = 1;
23045 }
23046 }
23047 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040023048 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040023049 $DumpFormat = "perl";
23050 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023051 if($Quiet and $LogMode!~/a|n/)
23052 { # --quiet log
23053 if(-f $COMMON_LOG_PATH) {
23054 unlink($COMMON_LOG_PATH);
23055 }
23056 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040023057 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023058 $CheckUndefined = 1;
23059 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023060 if($TestTool and $UseDumps)
23061 { # --test && --use-dumps == --test-dump
23062 $TestDump = 1;
23063 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040023064 if($Tolerant)
23065 { # enable all
23066 $Tolerance = 1234;
23067 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023068 if($Help)
23069 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023070 HELP_MESSAGE();
23071 exit(0);
23072 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030023073 if($InfoMsg)
23074 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023075 INFO_MESSAGE();
23076 exit(0);
23077 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023078 if($ShowVersion)
23079 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030023080 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 +040023081 exit(0);
23082 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023083 if($DumpVersion)
23084 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023085 printMsg("INFO", $TOOL_VERSION);
23086 exit(0);
23087 }
23088 if($ExtendedCheck) {
23089 $CheckHeadersOnly = 1;
23090 }
23091 if($SystemRoot_Opt)
23092 { # user defined root
23093 if(not -e $SystemRoot_Opt) {
23094 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
23095 }
23096 $SystemRoot = $SystemRoot_Opt;
23097 $SystemRoot=~s/[\/]+\Z//g;
23098 if($SystemRoot) {
23099 $SystemRoot = get_abs_path($SystemRoot);
23100 }
23101 }
23102 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040023103
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023104 if($SortDump)
23105 {
23106 $Data::Dumper::Useperl = 1;
23107 $Data::Dumper::Sortkeys = \&dump_sorting;
23108 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040023109
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023110 if($TargetLibsPath)
23111 {
23112 if(not -f $TargetLibsPath) {
23113 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
23114 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030023115 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath)))
23116 {
23117 if($OSgroup eq "windows") {
23118 $TargetLibs{lc($Lib)} = 1;
23119 }
23120 else {
23121 $TargetLibs{$Lib} = 1;
23122 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023123 }
23124 }
23125 if($TargetHeadersPath)
23126 { # --headers-list
23127 if(not -f $TargetHeadersPath) {
23128 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
23129 }
23130 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
23131 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030023132 $TargetHeaders{1}{get_filename($Header)} = 1;
23133 $TargetHeaders{2}{get_filename($Header)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023134 }
23135 }
23136 if($TargetHeader)
23137 { # --header
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030023138 $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
23139 $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023140 }
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030023141 if($TestABIDumper)
23142 {
23143 if($OSgroup ne "linux") {
23144 exitStatus("Error", "-test-abi-dumper option is available on Linux only");
23145 }
23146 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023147 if($TestTool
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030023148 or $TestDump
23149 or $TestABIDumper)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023150 { # --test, --test-dump
23151 detect_default_paths("bin|gcc"); # to compile libs
23152 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040023153 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030023154 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly, $OldStyle, $TestABIDumper);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023155 exit(0);
23156 }
23157 if($DumpSystem)
23158 { # --dump-system
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030023159 if(-d $MODULES_DIR."/Targets/"
23160 and -d $MODULES_DIR."/Targets/".$OStarget) {
23161 $TargetSysInfo = $MODULES_DIR."/Targets/".$OStarget;
23162 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030023163 if(not $TargetSysInfo) {
23164 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
23165 }
23166
23167 if(not -d $TargetSysInfo) {
23168 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
23169 }
23170
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023171 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023172 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023173 { # system XML descriptor
23174 if(not -f $DumpSystem) {
23175 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
23176 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030023177
23178 my $SDesc = readFile($DumpSystem);
23179 if(my $RelDir = $RelativeDirectory{1}) {
23180 $SDesc =~ s/{RELPATH}/$RelDir/g;
23181 }
23182
23183 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023184 foreach (@{$Ret->{"Tools"}})
23185 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023186 push_U($SystemPaths{"bin"}, $_);
23187 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023188 }
23189 if($Ret->{"CrossPrefix"}) {
23190 $CrossPrefix = $Ret->{"CrossPrefix"};
23191 }
23192 }
23193 elsif($SystemRoot_Opt)
23194 { # -sysroot "/" option
23195 # default target: /usr/lib, /usr/include
23196 # search libs: /usr/lib and /lib
23197 if(not -e $SystemRoot."/usr/lib") {
23198 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
23199 }
23200 if(not -e $SystemRoot."/lib") {
23201 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
23202 }
23203 if(not -e $SystemRoot."/usr/include") {
23204 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
23205 }
23206 readSystemDescriptor("
23207 <name>
23208 $DumpSystem
23209 </name>
23210 <headers>
23211 $SystemRoot/usr/include
23212 </headers>
23213 <libs>
23214 $SystemRoot/usr/lib
23215 </libs>
23216 <search_libs>
23217 $SystemRoot/lib
23218 </search_libs>");
23219 }
23220 else {
23221 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
23222 }
23223 detect_default_paths("bin|gcc"); # to check symbols
23224 if($OStarget eq "windows")
23225 { # to run dumpbin.exe
23226 # and undname.exe
23227 check_win32_env();
23228 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023229 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023230 exit(0);
23231 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023232
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023233 if($CmpSystems)
23234 { # --cmp-systems
23235 detect_default_paths("bin"); # to extract dumps
23236 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023237 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023238 exit(0);
23239 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023240
23241 if(not $CountSymbols)
23242 {
23243 if(not $TargetLibraryName) {
23244 exitStatus("Error", "library name is not selected (-l option)");
23245 }
23246 else
23247 { # validate library name
23248 if($TargetLibraryName=~/[\*\/\\]/) {
23249 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
23250 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023251 }
23252 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023253
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030023254 if(not $TargetTitle) {
23255 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023256 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030023257
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023258 if($SymbolsListPath)
23259 {
23260 if(not -f $SymbolsListPath) {
23261 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
23262 }
23263 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
23264 $SymbolsList{$Interface} = 1;
23265 }
23266 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030023267 if($TypesListPath)
23268 {
23269 if(not -f $TypesListPath) {
23270 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
23271 }
23272 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
23273 $TypesList{$Type} = 1;
23274 }
23275 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023276 if($SkipSymbolsListPath)
23277 {
23278 if(not -f $SkipSymbolsListPath) {
23279 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
23280 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030023281 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
23282 {
23283 $SkipSymbols{1}{$Interface} = 1;
23284 $SkipSymbols{2}{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023285 }
23286 }
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030023287 if($SkipTypesListPath)
23288 {
23289 if(not -f $SkipTypesListPath) {
23290 exitStatus("Access_Error", "can't access file \'$SkipTypesListPath\'");
23291 }
23292 foreach my $Type (split(/\s*\n\s*/, readFile($SkipTypesListPath)))
23293 {
23294 $SkipTypes{1}{$Type} = 1;
23295 $SkipTypes{2}{$Type} = 1;
23296 }
23297 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023298 if($SkipHeadersPath)
23299 {
23300 if(not -f $SkipHeadersPath) {
23301 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
23302 }
23303 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023304 { # register for both versions
23305 $SkipHeadersList{1}{$Path} = 1;
23306 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030023307
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023308 my ($CPath, $Type) = classifyPath($Path);
23309 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023310 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023311 }
23312 }
23313 if($ParamNamesPath)
23314 {
23315 if(not -f $ParamNamesPath) {
23316 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
23317 }
23318 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
23319 {
23320 if($Line=~s/\A(\w+)\;//)
23321 {
23322 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023323 if($Line=~/;(\d+);/)
23324 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023325 while($Line=~s/(\d+);(\w+)//) {
23326 $AddIntParams{$Interface}{$1}=$2;
23327 }
23328 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023329 else
23330 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023331 my $Num = 0;
23332 foreach my $Name (split(/;/, $Line)) {
23333 $AddIntParams{$Interface}{$Num++}=$Name;
23334 }
23335 }
23336 }
23337 }
23338 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023339
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023340 if($AppPath)
23341 {
23342 if(not -f $AppPath) {
23343 exitStatus("Access_Error", "can't access file \'$AppPath\'");
23344 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030023345
23346 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040023347 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023348 $SymbolsList_App{$Interface} = 1;
23349 }
23350 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023351
23352 if($CountSymbols)
23353 {
23354 if(not -e $CountSymbols) {
23355 exitStatus("Access_Error", "can't access \'$CountSymbols\'");
23356 }
23357
23358 read_ABI_Dump(1, $CountSymbols);
23359
23360 foreach my $Id (keys(%{$SymbolInfo{1}}))
23361 {
23362 my $MnglName = $SymbolInfo{1}{$Id}{"MnglName"};
23363 if(not $MnglName) {
23364 $MnglName = $SymbolInfo{1}{$Id}{"ShortName"}
23365 }
23366
23367 if(my $SV = $SymVer{1}{$MnglName}) {
23368 $CompleteSignature{1}{$SV} = $SymbolInfo{1}{$Id};
23369 }
23370 else {
23371 $CompleteSignature{1}{$MnglName} = $SymbolInfo{1}{$Id};
23372 }
23373
23374 if(my $Alias = $CompleteSignature{1}{$MnglName}{"Alias"}) {
23375 $CompleteSignature{1}{$Alias} = $SymbolInfo{1}{$Id};
23376 }
23377 }
23378
23379 my $Count = 0;
23380 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
23381 {
23382 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
23383 next;
23384 }
23385 if($CompleteSignature{1}{$Symbol}{"Private"}) {
23386 next;
23387 }
23388 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
23389 next;
23390 }
23391
23392 $Count += symbolFilter($Symbol, 1, "Affected + InlineVirt", "Binary");
23393 }
23394
23395 printMsg("INFO", $Count);
23396 exit(0);
23397 }
23398
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023399 if($DumpAPI)
23400 { # --dump-abi
23401 # make an API dump
23402 create_ABI_Dump();
23403 exit($COMPILE_ERRORS);
23404 }
23405 # default: compare APIs
23406 # -d1 <path>
23407 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023408 compareInit();
23409 if($JoinReport or $DoubleReport)
23410 {
23411 compareAPIs("Binary");
23412 compareAPIs("Source");
23413 }
23414 elsif($BinaryOnly) {
23415 compareAPIs("Binary");
23416 }
23417 elsif($SourceOnly) {
23418 compareAPIs("Source");
23419 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023420 exitReport();
23421}
23422
23423scenario();